580 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			580 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * Rest API functions.
 | |
|  *
 | |
|  * @since 2.5.0
 | |
|  *
 | |
|  * @package GP Premium
 | |
|  */
 | |
| 
 | |
| if ( ! defined( 'ABSPATH' ) ) {
 | |
| 	exit; // No direct access, please.
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Font library REST API endpoints class.
 | |
|  */
 | |
| class GeneratePress_Pro_Font_Library_Rest extends WP_REST_Controller {
 | |
| 	/**
 | |
| 	 * Instance.
 | |
| 	 *
 | |
| 	 * @access private
 | |
| 	 * @var object Instance
 | |
| 	 */
 | |
| 	private static $instance;
 | |
| 
 | |
| 	/**
 | |
| 	 * Namespace.
 | |
| 	 *
 | |
| 	 * @var string
 | |
| 	 */
 | |
| 	protected $namespace = 'generatepress-font-library/v';
 | |
| 
 | |
| 	/**
 | |
| 	 * Version.
 | |
| 	 *
 | |
| 	 * @var string
 | |
| 	 */
 | |
| 	protected $version = '1';
 | |
| 
 | |
| 	/**
 | |
| 	 * Initiator.
 | |
| 	 *
 | |
| 	 * @return object initialized object of class.
 | |
| 	 */
 | |
| 	public static function get_instance() {
 | |
| 		if ( ! isset( self::$instance ) ) {
 | |
| 			self::$instance = new self();
 | |
| 		}
 | |
| 
 | |
| 		return self::$instance;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * GenerateBlocks_Rest constructor.
 | |
| 	 */
 | |
| 	public function __construct() {
 | |
| 		add_action( 'rest_api_init', array( $this, 'register_routes' ) );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Register rest routes.
 | |
| 	 */
 | |
| 	public function register_routes() {
 | |
| 		$namespace = $this->namespace . $this->version;
 | |
| 
 | |
| 		// Get fonts from CPT.
 | |
| 		register_rest_route(
 | |
| 			$namespace,
 | |
| 			'/get-fonts/',
 | |
| 			array(
 | |
| 				'methods'  => WP_REST_Server::READABLE,
 | |
| 				'callback' => array( $this, 'get_fonts' ),
 | |
| 				'permission_callback' => array( $this, 'edit_posts_permission' ),
 | |
| 			)
 | |
| 		);
 | |
| 
 | |
| 		// Download a Google font.
 | |
| 		register_rest_route(
 | |
| 			$namespace,
 | |
| 			'/download-google-font/',
 | |
| 			array(
 | |
| 				'methods'             => WP_REST_Server::EDITABLE,
 | |
| 				'callback'            => array( $this, 'download_google_font' ),
 | |
| 				'permission_callback' => array( $this, 'edit_posts_permission' ),
 | |
| 			)
 | |
| 		);
 | |
| 
 | |
| 		// Upload a font.
 | |
| 		register_rest_route(
 | |
| 			$namespace,
 | |
| 			'/upload-fonts/',
 | |
| 			array(
 | |
| 				'methods'             => WP_REST_Server::EDITABLE,
 | |
| 				'callback'            => array( $this, 'upload_fonts' ),
 | |
| 				'permission_callback' => array( $this, 'edit_posts_permission' ),
 | |
| 			)
 | |
| 		);
 | |
| 
 | |
| 		// Delete a font family.
 | |
| 		register_rest_route(
 | |
| 			$namespace,
 | |
| 			'/delete-font/',
 | |
| 			array(
 | |
| 				'methods'             => WP_REST_Server::EDITABLE,
 | |
| 				'callback'            => array( $this, 'delete_font' ),
 | |
| 				'permission_callback' => array( $this, 'edit_posts_permission' ),
 | |
| 			)
 | |
| 		);
 | |
| 
 | |
| 		// Get font library settings.
 | |
| 		register_rest_route(
 | |
| 			$namespace,
 | |
| 			'/get-settings/',
 | |
| 			array(
 | |
| 				'methods'  => WP_REST_Server::READABLE,
 | |
| 				'callback' => array( $this, 'get_settings' ),
 | |
| 				'permission_callback' => array( $this, 'edit_posts_permission' ),
 | |
| 			)
 | |
| 		);
 | |
| 
 | |
| 		// Set font library settings.
 | |
| 		register_rest_route(
 | |
| 			$namespace,
 | |
| 			'/set-settings/',
 | |
| 			array(
 | |
| 				'methods'             => WP_REST_Server::EDITABLE,
 | |
| 				'callback'            => array( $this, 'set_settings' ),
 | |
| 				'permission_callback' => array( $this, 'edit_posts_permission' ),
 | |
| 			)
 | |
| 		);
 | |
| 
 | |
| 		register_rest_route(
 | |
| 			$namespace,
 | |
| 			'/optimize-google-fonts/',
 | |
| 			array(
 | |
| 				'methods'             => WP_REST_Server::EDITABLE,
 | |
| 				'callback'            => array( $this, 'optimize_google_fonts' ),
 | |
| 				'permission_callback' => array( $this, 'edit_posts_permission' ),
 | |
| 			)
 | |
| 		);
 | |
| 
 | |
| 		register_rest_route(
 | |
| 			$namespace,
 | |
| 			'/update-font-post/',
 | |
| 			array(
 | |
| 				'methods'             => WP_REST_Server::EDITABLE,
 | |
| 				'callback'            => array( $this, 'update_font_post' ),
 | |
| 				'permission_callback' => array( $this, 'edit_posts_permission' ),
 | |
| 			)
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get font posts.
 | |
| 	 *
 | |
| 	 * @param WP_REST_Request $request The request object.
 | |
| 	 *
 | |
| 	 * @return array The response.
 | |
| 	 */
 | |
| 	public function get_fonts( WP_REST_Request $request ) {
 | |
| 		$name     = $request->get_param( 'name' );
 | |
| 		$response = GeneratePress_Pro_Font_Library::get_fonts( $name );
 | |
| 
 | |
| 		return $this->success( $response );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Generate font CSS.
 | |
| 	 *
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public function build_css_file() {
 | |
| 
 | |
| 		$result = GeneratePress_Pro_Font_Library::build_css_file();
 | |
| 
 | |
| 		if ( is_wp_error( $result ) ) {
 | |
| 			return $this->error( 'font_css_generation_failed', __( 'Failed to generate font CSS.', 'gp-premium' ) );
 | |
| 		}
 | |
| 
 | |
| 		return $this->success( $result );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Delete a specific font from the library and the associated CPT post.
 | |
| 	 *
 | |
| 	 * @param WP_REST_Request $request request object.
 | |
| 	 *
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public function delete_font( WP_REST_Request $request ) {
 | |
| 		$font_id        = $request->get_param( 'fontId' );
 | |
| 		$slug           = get_post_field( 'post_name', $font_id );
 | |
| 		$upload_dir     = wp_get_upload_dir();
 | |
| 		$font_base_path = trailingslashit( $upload_dir['basedir'] ) . 'generatepress/fonts/' . $slug . '/';
 | |
| 
 | |
| 		// Delete the font post.
 | |
| 		$success = wp_delete_post( $font_id, true );
 | |
| 
 | |
| 		if ( ! $success ) {
 | |
| 			return $this->error(
 | |
| 				'font_post_delete_failed',
 | |
| 				__( 'Failed to delete font post.', 'gp-premium' )
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		// Delete the font sub folder if it exists.
 | |
| 		if ( file_exists( $font_base_path ) ) {
 | |
| 			GeneratePress_Pro_Font_Library::delete_directory( $font_base_path );
 | |
| 		}
 | |
| 
 | |
| 		// Regenerate the font CSS.
 | |
| 		$this->build_css_file();
 | |
| 
 | |
| 		// Return success.
 | |
| 		return $this->success( __( 'Font successfully deleted!', 'gp-premium' ) );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Download a specific Google font and update the CPT.
 | |
| 	 *
 | |
| 	 * @param WP_REST_Request $request request object.
 | |
| 	 *
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public function optimize_google_fonts( WP_REST_Request $request ) {
 | |
| 		$font     = $request->get_param( 'font' ) ?? array();
 | |
| 		$variants = $request->get_param( 'variants' ) ?? array();
 | |
| 
 | |
| 		if ( ! $font || ! $variants ) {
 | |
| 			return $this->failed( 'No font or variants provided' );
 | |
| 		}
 | |
| 
 | |
| 		$optimized_variants = GeneratePress_Pro_Font_Library_Optimize::get_variants( $font, $variants );
 | |
| 
 | |
| 		if ( $optimized_variants ) {
 | |
| 			foreach ( $optimized_variants as $key => $optimized_variant ) {
 | |
| 				foreach ( $variants as &$variant ) {
 | |
| 					$style_match  = $variant['fontStyle'] === $optimized_variant['fontStyle'];
 | |
| 					$weight_match = $variant['fontWeight'] === $optimized_variant['fontWeight'];
 | |
| 
 | |
| 					if ( $style_match && $weight_match ) {
 | |
| 						$variant['src'] = $optimized_variant['src'];
 | |
| 						break;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return $this->success( $variants );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Check if a font post exists by slug and create it if it doesn't exist.
 | |
| 	 *
 | |
| 	 * @param array $variant The font variant to check.
 | |
| 	 * @param array $slug    The font slug.
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public static function get_font_post( $variant, $slug ) {
 | |
| 		global $wpdb;
 | |
| 
 | |
| 		$font_post = $wpdb->get_row(
 | |
| 			$wpdb->prepare(
 | |
| 				"SELECT ID FROM $wpdb->posts WHERE post_name = %s AND post_type = %s",
 | |
| 				$slug,
 | |
| 				GeneratePress_Pro_Font_Library::FONT_LIBRARY_CPT
 | |
| 			)
 | |
| 		);
 | |
| 
 | |
| 		if ( $font_post ) {
 | |
| 			return $font_post->ID;
 | |
| 		}
 | |
| 
 | |
| 		$font_post = wp_insert_post(
 | |
| 			array(
 | |
| 				'post_title'  => $variant['fontFamily'],
 | |
| 				'post_name'   => $slug,
 | |
| 				'post_type'   => GeneratePress_Pro_Font_Library::FONT_LIBRARY_CPT,
 | |
| 				'post_status' => 'publish',
 | |
| 				'wp_error'    => true,
 | |
| 				'meta_input'  => array(
 | |
| 					'gp_font_family_alias' => '',
 | |
| 					'gp_font_variants'     => array(),
 | |
| 					'gp_font_display'      => 'auto',
 | |
| 					'gp_font_fallback'     => '',
 | |
| 					'gp_font_variable'     => GeneratePress_Pro_Font_Library::CSS_VAR_PREFIX . $slug,
 | |
| 				),
 | |
| 			)
 | |
| 		);
 | |
| 
 | |
| 		return $font_post;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Upload a specific custom font and update the CPT.
 | |
| 	 *
 | |
| 	 * @param WP_REST_Request $request request object.
 | |
| 	 *
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public function upload_fonts( WP_REST_Request $request ) {
 | |
| 		$font     = $request->get_param( 'font' ) ?? array();
 | |
| 		$variants = $request->get_param( 'variants' );
 | |
| 		$source   = $request->get_param( 'source' );
 | |
| 		$slug     = $request->get_param( 'slug' ) ?? $font['slug'] ?? '';
 | |
| 		$results  = array(
 | |
| 			'ID'       => null,
 | |
| 			'variants' => array(),
 | |
| 		);
 | |
| 
 | |
| 		// Tweaks variants based on the source if needed.
 | |
| 		if ( 'custom' === $source ) {
 | |
| 			// Decode the FormData sent via POST.
 | |
| 			$variants = json_decode( $variants, true );
 | |
| 		}
 | |
| 
 | |
| 		foreach ( $variants as $variant ) {
 | |
| 			// Move the uploaded font asset from the temp folder to the fonts directory.
 | |
| 			if ( ! function_exists( 'wp_handle_upload' ) ) {
 | |
| 				require_once ABSPATH . 'wp-admin/includes/file.php';
 | |
| 			}
 | |
| 
 | |
| 			$file = $variant['src'];
 | |
| 
 | |
| 			// If custom assume the font is being uploaded.
 | |
| 			if ( 'custom' === $source ) {
 | |
| 				$file_params = $request->get_file_params();
 | |
| 				$file        = $file_params[ $variant['src'] ] ?? $variant['src'];
 | |
| 			}
 | |
| 
 | |
| 			$font_file = GeneratePress_Pro_Font_Library::handle_font_file_upload( $variant, $slug, $file );
 | |
| 
 | |
| 			if ( is_wp_error( $font_file ) ) {
 | |
| 				$results['error'][] = array(
 | |
| 					'font'    => $variant,
 | |
| 					'message' => $font_file->get_error_message(),
 | |
| 				);
 | |
| 
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			// Get the font post for this variant.
 | |
| 			$font_post = self::get_font_post( $variant, $slug );
 | |
| 
 | |
| 			if ( is_wp_error( $font_post ) ) {
 | |
| 				return $this->error( 500, __( 'Failed to create font post.', 'gp-premium' ) );
 | |
| 			}
 | |
| 
 | |
| 			if ( 'google' === $source ) {
 | |
| 				$font_family = explode( ', ', $font['fontFamily'] ?? '' );
 | |
| 				// Remove the main font-family.
 | |
| 				array_shift( $font_family );
 | |
| 
 | |
| 				// Set the fallback if we can infer one.
 | |
| 				if ( $font_family ) {
 | |
| 					$fallback = implode( ', ', $font_family );
 | |
| 					update_post_meta( $font_post, 'gp_font_fallback', $fallback );
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			$existing_variants = get_post_meta( $font_post, 'gp_font_variants', true );
 | |
| 
 | |
| 			if ( ! is_array( $variants ) ) {
 | |
| 				$existing_variants = array();
 | |
| 			}
 | |
| 
 | |
| 			$checked_variants = GeneratePress_Pro_Font_Library::check_variants(
 | |
| 				$existing_variants,
 | |
| 				array(
 | |
| 					'src'        => $font_file['url'],
 | |
| 					'fontFamily' => $variant['fontFamily'],
 | |
| 					'fontStyle'  => $variant['fontStyle'],
 | |
| 					'fontWeight' => $variant['fontWeight'],
 | |
| 					'name'       => GeneratePress_Pro_Font_Library::get_variant_name( $variant ),
 | |
| 					'isVariable' => $variant['isVariable'] ?? false,
 | |
| 					'source'     => 'custom',
 | |
| 					'disabled'   => false,
 | |
| 					'preview'    => '',
 | |
| 				)
 | |
| 			);
 | |
| 
 | |
| 			// Update the font post meta with merged variants.
 | |
| 			update_post_meta( $font_post, 'gp_font_variants', $checked_variants );
 | |
| 
 | |
| 			// Generate the font CSS.
 | |
| 			$generate_css = $this->build_css_file();
 | |
| 
 | |
| 			if ( false === $generate_css->success ) {
 | |
| 				return $this->error( 500, __( 'CSS Generation failed', 'gp-premium' ) );
 | |
| 			}
 | |
| 
 | |
| 			$results['ID']       = $font_post;
 | |
| 			$results['variants'] = $checked_variants;
 | |
| 		}
 | |
| 
 | |
| 		return $this->success( $results );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get font library settings.
 | |
| 	 *
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public function get_settings() {
 | |
| 		return $this->success( get_option( 'gp_font_library_settings', array() ) );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Update font library settings.
 | |
| 	 *
 | |
| 	 * @param WP_REST_Request $request request object.
 | |
| 	 *
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public function set_settings( WP_REST_Request $request ) {
 | |
| 		$settings = $request->get_param( 'settings' );
 | |
| 		$sanitized_settings = array();
 | |
| 
 | |
| 		foreach ( $settings as $setting => $value ) {
 | |
| 			if ( 'google_gdpr' === $setting ) {
 | |
| 				$sanitized_settings[ $setting ] = (bool) $value;
 | |
| 			} elseif ( 'preferred_subset' === $setting ) {
 | |
| 				// Stored as an array to support multiple preferred subsets in the future.
 | |
| 				$sanitized_settings[ $setting ] = array( sanitize_text_field( $value ) );
 | |
| 			} else {
 | |
| 				$sanitized_settings[ $setting ] = sanitize_text_field( $value );
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		$updated = update_option(
 | |
| 			GeneratePress_Pro_Font_Library::SETTINGS_OPTION,
 | |
| 			$sanitized_settings,
 | |
| 			false
 | |
| 		);
 | |
| 
 | |
| 		if ( $updated ) {
 | |
| 			// Return success.
 | |
| 			return $this->success(
 | |
| 				array(
 | |
| 					'message' => __( 'Font settings successfully updated!', 'gp-premium' ),
 | |
| 					'response' => $updated,
 | |
| 					'settings' => $sanitized_settings,
 | |
| 				)
 | |
| 			);
 | |
| 		}
 | |
| 
 | |
| 		return $this->failed(
 | |
| 			array(
 | |
| 				'message'  => __( 'Failed to update font settings.', 'gp-premium' ),
 | |
| 				'settings' => $sanitized_settings,
 | |
| 			)
 | |
| 		);
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Update a font post.
 | |
| 	 *
 | |
| 	 * @param WP_REST_Request $request request object.
 | |
| 	 *
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public function update_font_post( WP_REST_Request $request ) {
 | |
| 		$font_id           = $request->get_param( 'id' );
 | |
| 		$status            = $request->get_param( 'status' );
 | |
| 		$font_family_alias = $request->get_param( 'alias' );
 | |
| 		$new_variants      = $request->get_param( 'newVariants' );
 | |
| 		$delete_variants   = $request->get_param( 'deleteVariants' );
 | |
| 		$font_display      = $request->get_param( 'fontDisplay' );
 | |
| 		$fallback          = $request->get_param( 'fallback' );
 | |
| 		$css_variable      = $request->get_param( 'cssVariable' );
 | |
| 		$slug              = get_post_field( 'post_name', $font_id );
 | |
| 
 | |
| 		// Update the font post.
 | |
| 		wp_update_post(
 | |
| 			array(
 | |
| 				'ID'          => $font_id,
 | |
| 				'post_status' => $status,
 | |
| 				'meta_input'  => array(
 | |
| 					'gp_font_family_alias' => $font_family_alias,
 | |
| 					'gp_font_variants'     => $new_variants,
 | |
| 					'gp_font_display'      => $font_display,
 | |
| 					'gp_font_fallback'     => $fallback,
 | |
| 					'gp_font_variable'     => $css_variable,
 | |
| 				),
 | |
| 			)
 | |
| 		);
 | |
| 
 | |
| 		$upload_dir = wp_get_upload_dir();
 | |
| 		$base_path  = trailingslashit( $upload_dir['basedir'] ) . 'generatepress/fonts/' . $slug . '/';
 | |
| 		foreach ( $delete_variants as $variant ) {
 | |
| 			if ( isset( $variant['deleteStatus'] ) && $variant['deleteStatus'] ) {
 | |
| 				$file_path = $base_path . basename( $variant['src'] );
 | |
| 				if ( file_exists( $file_path ) ) {
 | |
| 					unlink( $file_path );
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		// Regenerate the font CSS.
 | |
| 		$this->build_css_file();
 | |
| 
 | |
| 		// Return success.
 | |
| 		return $this->success( __( 'Font post successfully updated!', 'gp-premium' ) );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get edit options permissions.
 | |
| 	 *
 | |
| 	 * @return bool
 | |
| 	 */
 | |
| 	public function update_settings_permission() {
 | |
| 		return current_user_can( 'manage_options' );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get edit posts permissions.
 | |
| 	 *
 | |
| 	 * @return bool
 | |
| 	 */
 | |
| 	public function edit_posts_permission() {
 | |
| 		return current_user_can( 'edit_posts' );
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Success rest.
 | |
| 	 *
 | |
| 	 * @param mixed $response response data.
 | |
| 	 * @param mixed $data     data.
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public function success( $response, $data = null ) {
 | |
| 		return new WP_REST_Response(
 | |
| 			array(
 | |
| 				'success'  => true,
 | |
| 				'response' => $response,
 | |
| 				'data'     => $data,
 | |
| 			),
 | |
| 			200
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Failed rest.
 | |
| 	 *
 | |
| 	 * @param mixed $response response data.
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public function failed( $response ) {
 | |
| 		return new WP_REST_Response(
 | |
| 			array(
 | |
| 				'success'  => false,
 | |
| 				'response' => $response,
 | |
| 			),
 | |
| 			200
 | |
| 		);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Error rest.
 | |
| 	 *
 | |
| 	 * @param mixed $code     error code.
 | |
| 	 * @param mixed $response response data.
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	public function error( $code, $response ) {
 | |
| 		return new WP_REST_Response(
 | |
| 			array(
 | |
| 				'error'      => true,
 | |
| 				'success'    => false,
 | |
| 				'error_code' => $code,
 | |
| 				'response'   => $response,
 | |
| 			),
 | |
| 			500
 | |
| 		);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| GeneratePress_Pro_Font_Library_Rest::get_instance();
 |