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();
|