Commit realizado el 12:13:52 08-04-2024
This commit is contained in:
@@ -0,0 +1,707 @@
|
||||
<?php
|
||||
/**
|
||||
* Class Font_Controller
|
||||
*
|
||||
* @link https://github.com/googleforcreators/web-stories-wp
|
||||
*
|
||||
* @copyright 2021 Google LLC
|
||||
* @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright 2021 Google LLC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
declare(strict_types = 1);
|
||||
|
||||
namespace Google\Web_Stories\REST_API;
|
||||
|
||||
use stdClass;
|
||||
use WP_Error;
|
||||
use WP_Post;
|
||||
use WP_Query;
|
||||
use WP_REST_Posts_Controller;
|
||||
use WP_REST_Request;
|
||||
use WP_REST_Response;
|
||||
use WP_REST_Server;
|
||||
|
||||
/**
|
||||
* Font_Controller class.
|
||||
*
|
||||
* @phpstan-type Font array{
|
||||
* family: string,
|
||||
* fallbacks?: string[],
|
||||
* weights?: array<int, array{0: int, 1: int}>,
|
||||
* styles?: string[],
|
||||
* variants?: string[],
|
||||
* service?: string,
|
||||
* metrics?: mixed,
|
||||
* id?: string,
|
||||
* url?: string
|
||||
* }
|
||||
* @phpstan-type SchemaEntry array{
|
||||
* description: string,
|
||||
* type: string,
|
||||
* context: string[],
|
||||
* default?: mixed,
|
||||
* }
|
||||
* @phpstan-type Schema array{
|
||||
* properties: array{
|
||||
* family?: SchemaEntry,
|
||||
* fallbacks?: SchemaEntry,
|
||||
* weights?: SchemaEntry,
|
||||
* styles?: SchemaEntry,
|
||||
* variants?: SchemaEntry,
|
||||
* service?: SchemaEntry,
|
||||
* metrics?: SchemaEntry,
|
||||
* id?: SchemaEntry,
|
||||
* url?: SchemaEntry
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
class Font_Controller extends WP_REST_Posts_Controller {
|
||||
/**
|
||||
* Registers the routes for posts.
|
||||
*
|
||||
* @since 1.16.0
|
||||
*
|
||||
* @see register_rest_route()
|
||||
*/
|
||||
public function register_routes(): void {
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base,
|
||||
[
|
||||
[
|
||||
'methods' => WP_REST_Server::READABLE,
|
||||
'callback' => [ $this, 'get_items' ],
|
||||
'permission_callback' => [ $this, 'get_items_permissions_check' ],
|
||||
'args' => $this->get_collection_params(),
|
||||
],
|
||||
[
|
||||
'methods' => WP_REST_Server::CREATABLE,
|
||||
'callback' => [ $this, 'create_item' ],
|
||||
'permission_callback' => [ $this, 'create_item_permissions_check' ],
|
||||
'args' => $this->get_endpoint_args_for_item_schema( WP_REST_Server::CREATABLE ),
|
||||
],
|
||||
'schema' => [ $this, 'get_public_item_schema' ],
|
||||
]
|
||||
);
|
||||
|
||||
register_rest_route(
|
||||
$this->namespace,
|
||||
'/' . $this->rest_base . '/(?P<id>[\d]+)',
|
||||
[
|
||||
'args' => [
|
||||
'id' => [
|
||||
'description' => __( 'Unique identifier for the font.', 'web-stories' ),
|
||||
'type' => 'integer',
|
||||
],
|
||||
],
|
||||
[
|
||||
'methods' => WP_REST_Server::DELETABLE,
|
||||
'callback' => [ $this, 'delete_item' ],
|
||||
'permission_callback' => [ $this, 'delete_item_permissions_check' ],
|
||||
],
|
||||
'schema' => [ $this, 'get_public_item_schema' ],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a collection of fonts.
|
||||
*
|
||||
* @since 1.16.0
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function get_items( $request ) {
|
||||
/**
|
||||
* Fonts list.
|
||||
*
|
||||
* @phpstan-var Font[] $fonts
|
||||
*/
|
||||
$fonts = [];
|
||||
|
||||
// Retrieve the list of registered collection query parameters.
|
||||
$registered = $this->get_collection_params();
|
||||
|
||||
if ( isset( $registered['service'], $request['service'] ) ) {
|
||||
if ( 'all' === $request['service'] || 'builtin' === $request['service'] ) {
|
||||
array_push( $fonts, ...$this->get_builtin_fonts() );
|
||||
|
||||
// For custom fonts the searching will be done in WP_Query already.
|
||||
if ( isset( $registered['search'], $request['search'] ) && ! empty( $request['search'] ) ) {
|
||||
/**
|
||||
* Requested URL.
|
||||
*
|
||||
* @var string $search
|
||||
*/
|
||||
$search = $request['search'];
|
||||
$fonts = array_values(
|
||||
array_filter(
|
||||
$fonts,
|
||||
/**
|
||||
* Font data.
|
||||
*
|
||||
* @param array{family: string} $font
|
||||
* @return bool
|
||||
*/
|
||||
static fn( array $font ) => false !== stripos( $font['family'], $search )
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ( 'all' === $request['service'] || 'custom' === $request['service'] ) {
|
||||
array_push( $fonts, ...$this->get_custom_fonts( $request ) );
|
||||
}
|
||||
|
||||
// Filter before doing any sorting.
|
||||
if ( isset( $registered['include'], $request['include'] ) && ! empty( $request['include'] ) ) {
|
||||
/**
|
||||
* Include list.
|
||||
*
|
||||
* @var array{string} $include_list
|
||||
*/
|
||||
$include_list = $request['include'];
|
||||
$include_list = array_map( 'strtolower', $include_list );
|
||||
|
||||
$fonts = array_values(
|
||||
array_filter(
|
||||
$fonts,
|
||||
/**
|
||||
* Font data.
|
||||
*
|
||||
* @param array{family: string} $font
|
||||
* @return bool
|
||||
*/
|
||||
static fn( array $font ): bool => \in_array( strtolower( $font['family'] ), $include_list, true )
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( 'all' === $request['service'] ) {
|
||||
// Since the built-in fonts and custom fonts both are already sorted,
|
||||
// we only need to sort when including both.
|
||||
usort(
|
||||
$fonts,
|
||||
/**
|
||||
* Font A and Font B.
|
||||
*
|
||||
* @param Font $a
|
||||
* @param Font $b
|
||||
* @return int
|
||||
*/
|
||||
static fn( array $a, array $b ): int => strnatcasecmp( $a['family'], $b['family'] )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return rest_ensure_response( $fonts );
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a given request has access to read posts.
|
||||
*
|
||||
* @since 1.16.0
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return true|WP_Error True if the request has read access, WP_Error object otherwise.
|
||||
*/
|
||||
public function get_items_permissions_check( $request ) {
|
||||
$post_type = get_post_type_object( $this->post_type );
|
||||
|
||||
if (
|
||||
! $post_type ||
|
||||
! current_user_can( $post_type->cap->read_post ) // phpcs:ignore WordPress.WP.Capabilities.Undetermined
|
||||
) {
|
||||
return new \WP_Error(
|
||||
'rest_forbidden',
|
||||
__( 'Sorry, you are not allowed to list fonts.', 'web-stories' ),
|
||||
[ 'status' => rest_authorization_required_code() ]
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force-deletes a single font.
|
||||
*
|
||||
* @since 1.16.0
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return WP_REST_Response|WP_Error Response object on success, or WP_Error object on failure.
|
||||
*/
|
||||
public function delete_item( $request ) {
|
||||
$request->set_param( 'force', true );
|
||||
|
||||
return parent::delete_item( $request );
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a single post output for response.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.NPathComplexity)
|
||||
*
|
||||
* @since 1.16.0
|
||||
*
|
||||
* @param WP_Post $item Post object.
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return WP_REST_Response Response object.
|
||||
*/
|
||||
public function prepare_item_for_response( $item, $request ): WP_REST_Response {
|
||||
// Restores the more descriptive, specific name for use within this method.
|
||||
$post = $item;
|
||||
$GLOBALS['post'] = $post; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
|
||||
|
||||
setup_postdata( $post );
|
||||
|
||||
$fields = $this->get_fields_for_response( $request );
|
||||
|
||||
$data = [];
|
||||
|
||||
if ( rest_is_field_included( 'id', $fields ) ) {
|
||||
$data['id'] = $post->ID;
|
||||
}
|
||||
|
||||
if ( rest_is_field_included( 'family', $fields ) ) {
|
||||
$data['family'] = $post->post_title;
|
||||
}
|
||||
|
||||
if ( rest_is_field_included( 'service', $fields ) ) {
|
||||
$data['service'] = 'custom';
|
||||
}
|
||||
|
||||
/**
|
||||
* Font data.
|
||||
*
|
||||
* @var array<string, mixed>|null $font_data
|
||||
*/
|
||||
$font_data = json_decode( $post->post_content, true );
|
||||
|
||||
if ( $font_data ) {
|
||||
foreach ( $font_data as $key => $value ) {
|
||||
if ( rest_is_field_included( $key, $fields ) ) {
|
||||
$data[ $key ] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Request context.
|
||||
*
|
||||
* @var string $context
|
||||
*/
|
||||
$context = ! empty( $request['context'] ) ? $request['context'] : 'view';
|
||||
$data = $this->add_additional_fields_to_object( $data, $request );
|
||||
$data = $this->filter_response_by_context( $data, $context );
|
||||
|
||||
/**
|
||||
* Response object.
|
||||
*
|
||||
* @var WP_REST_Response $response
|
||||
*/
|
||||
$response = rest_ensure_response( $data );
|
||||
|
||||
if ( rest_is_field_included( '_links', $fields ) || rest_is_field_included( '_embedded', $fields ) ) {
|
||||
$links = $this->prepare_links( $post );
|
||||
$response->add_links( $links );
|
||||
|
||||
if ( ! empty( $links['self']['href'] ) ) {
|
||||
$actions = $this->get_available_actions( $post, $request );
|
||||
|
||||
$self = $links['self']['href'];
|
||||
|
||||
foreach ( $actions as $rel ) {
|
||||
$response->add_link( $rel, $self );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the query params for the fonts collection.
|
||||
*
|
||||
* @since 1.16.0
|
||||
*
|
||||
* @return array<string, array<string, mixed>> Collection parameters.
|
||||
*/
|
||||
public function get_collection_params(): array {
|
||||
$query_params = parent::get_collection_params();
|
||||
|
||||
$query_params['context']['default'] = 'view';
|
||||
|
||||
$query_params['search'] = [
|
||||
'description' => __( 'Limit results to those matching a string.', 'web-stories' ),
|
||||
'type' => 'string',
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
'validate_callback' => 'rest_validate_request_arg',
|
||||
];
|
||||
|
||||
$query_params['include'] = [
|
||||
'description' => __( 'Limit result set to specific fonts.', 'web-stories' ),
|
||||
'type' => 'array',
|
||||
'items' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
'default' => [],
|
||||
];
|
||||
|
||||
$query_params['service'] = [
|
||||
'description' => __( 'Filter fonts by service.', 'web-stories' ),
|
||||
'type' => 'string',
|
||||
'sanitize_callback' => 'sanitize_text_field',
|
||||
'default' => 'all',
|
||||
'enum' => [
|
||||
'all',
|
||||
'custom',
|
||||
'builtin', // system + fonts.google.com.
|
||||
],
|
||||
];
|
||||
|
||||
/** This filter is documented in wp-includes/rest-api/endpoints/class-wp-rest-posts-controller.php */
|
||||
return apply_filters( "rest_{$this->post_type}_collection_params", $query_params, $this->post_type );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the font's schema, conforming to JSON Schema.
|
||||
*
|
||||
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
|
||||
*
|
||||
* @since 1.16.0
|
||||
*
|
||||
* @return array Item schema data.
|
||||
*
|
||||
* @phpstan-return Schema
|
||||
*/
|
||||
public function get_item_schema(): array {
|
||||
if ( $this->schema ) {
|
||||
/**
|
||||
* Schema.
|
||||
*
|
||||
* @phpstan-var Schema $schema
|
||||
*/
|
||||
$schema = $this->add_additional_fields_schema( $this->schema );
|
||||
return $schema;
|
||||
}
|
||||
|
||||
$schema = [
|
||||
'$schema' => 'http://json-schema.org/draft-04/schema#',
|
||||
'title' => $this->post_type,
|
||||
'type' => 'object',
|
||||
// Base properties for every font.
|
||||
'properties' => [
|
||||
'family' => [
|
||||
'description' => __( 'The font family', 'web-stories' ),
|
||||
'type' => [ 'string', 'null' ],
|
||||
'context' => [ 'view', 'edit', 'embed' ],
|
||||
'required' => true,
|
||||
],
|
||||
'fallbacks' => [
|
||||
'description' => __( 'Fallback fonts', 'web-stories' ),
|
||||
'type' => 'array',
|
||||
'items' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'required' => true,
|
||||
],
|
||||
'weights' => [
|
||||
'description' => __( 'Font weights', 'web-stories' ),
|
||||
'type' => 'array',
|
||||
'items' => [
|
||||
'type' => 'integer',
|
||||
'minimum' => 0,
|
||||
'maximum' => 900,
|
||||
],
|
||||
'minimum' => 1,
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'required' => true,
|
||||
],
|
||||
'styles' => [
|
||||
'description' => __( 'Font styles', 'web-stories' ),
|
||||
'type' => 'array',
|
||||
'items' => [
|
||||
'type' => 'string',
|
||||
],
|
||||
'minimum' => 1,
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'required' => true,
|
||||
],
|
||||
'variants' => [
|
||||
'description' => __( 'Font variants', 'web-stories' ),
|
||||
'type' => 'array',
|
||||
'items' => [
|
||||
'type' => 'array',
|
||||
'items' => [
|
||||
'type' => 'integer',
|
||||
'minimum' => 0,
|
||||
'maximum' => 900,
|
||||
],
|
||||
'minimum' => 2,
|
||||
'maximum' => 2,
|
||||
],
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'required' => true,
|
||||
],
|
||||
'service' => [
|
||||
'description' => __( 'Font service', 'web-stories' ),
|
||||
'type' => 'string',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'metrics' => [
|
||||
'description' => __( 'Font metrics', 'web-stories' ),
|
||||
'type' => 'object',
|
||||
'context' => [ 'view', 'edit' ],
|
||||
'required' => true,
|
||||
],
|
||||
'id' => [
|
||||
'description' => __( 'Unique identifier for the font.', 'web-stories' ),
|
||||
'type' => 'integer',
|
||||
'context' => [ 'view', 'edit', 'embed' ],
|
||||
'readonly' => true,
|
||||
],
|
||||
'url' => [
|
||||
'description' => __( 'Font URL.', 'web-stories' ),
|
||||
'type' => 'string',
|
||||
'format' => 'uri',
|
||||
'context' => [ 'view', 'edit', 'embed' ],
|
||||
'required' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$this->schema = $schema;
|
||||
|
||||
/**
|
||||
* Schema.
|
||||
*
|
||||
* @phpstan-var Schema $schema
|
||||
*/
|
||||
$schema = $this->add_additional_fields_schema( $this->schema );
|
||||
return $schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of Google fonts.
|
||||
*
|
||||
* @since 1.16.0
|
||||
*
|
||||
* @return array<int, mixed> List of Google fonts.
|
||||
*
|
||||
* @phpstan-return Font[]
|
||||
*/
|
||||
protected function get_builtin_fonts(): array {
|
||||
$file = WEBSTORIES_PLUGIN_DIR_PATH . 'includes/data/fonts/fonts.json';
|
||||
|
||||
if ( ! is_readable( $file ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$content = file_get_contents( $file ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents, WordPressVIPMinimum.Performance.FetchingRemoteData.FileGetContentsUnknown
|
||||
|
||||
if ( ! $content ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* List of Google Fonts.
|
||||
*
|
||||
* @var array|null $fonts
|
||||
* @phpstan-var Font[]|null $fonts
|
||||
*/
|
||||
$fonts = json_decode( $content, true );
|
||||
|
||||
if ( ! $fonts ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return $fonts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of custom fonts.
|
||||
*
|
||||
* @since 1.16.0
|
||||
*
|
||||
* @param WP_REST_Request $request Full details about the request.
|
||||
* @return array<int, mixed> List of custom fonts.
|
||||
*
|
||||
* @phpstan-return Font[]
|
||||
*/
|
||||
protected function get_custom_fonts( $request ): array {
|
||||
// Retrieve the list of registered collection query parameters.
|
||||
$registered = $this->get_collection_params();
|
||||
$args = [
|
||||
'orderby' => 'title',
|
||||
'order' => 'ASC',
|
||||
];
|
||||
|
||||
/*
|
||||
* This array defines mappings between public API query parameters whose
|
||||
* values are accepted as-passed, and their internal WP_Query parameter
|
||||
* name equivalents (some are the same). Only values which are also
|
||||
* present in $registered will be set.
|
||||
*/
|
||||
$parameter_mappings = [
|
||||
'search' => 's',
|
||||
];
|
||||
|
||||
/*
|
||||
* For each known parameter which is both registered and present in the request,
|
||||
* set the parameter's value on the query $args.
|
||||
*/
|
||||
foreach ( $parameter_mappings as $api_param => $wp_param ) {
|
||||
if ( isset( $registered[ $api_param ], $request[ $api_param ] ) ) {
|
||||
$args[ $wp_param ] = $request[ $api_param ];
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure our per_page parameter overrides any provided posts_per_page filter.
|
||||
if ( isset( $registered['per_page'] ) ) {
|
||||
$args['posts_per_page'] = $request['per_page'];
|
||||
}
|
||||
|
||||
// Force search to be case-insensitive.
|
||||
|
||||
// Force the post_type argument, since it's not a user input variable.
|
||||
$args['post_type'] = $this->post_type;
|
||||
$query_args = $this->prepare_items_query( $args, $request );
|
||||
|
||||
$posts_query = new WP_Query();
|
||||
$query_result = $posts_query->query( $query_args );
|
||||
|
||||
/**
|
||||
* List of custom fonts.
|
||||
*
|
||||
* @var array $posts
|
||||
* @phpstan-var Font[] $posts
|
||||
*/
|
||||
$posts = [];
|
||||
|
||||
/**
|
||||
* We're expecting a post object.
|
||||
*
|
||||
* @var WP_Post $post
|
||||
*/
|
||||
foreach ( $query_result as $post ) {
|
||||
if ( ! $this->check_read_permission( $post ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$data = $this->prepare_item_for_response( $post, $request );
|
||||
$posts[] = $this->prepare_response_for_collection( $data );
|
||||
}
|
||||
|
||||
// Reset filter.
|
||||
if ( 'edit' === $request['context'] ) {
|
||||
remove_filter( 'post_password_required', [ $this, 'check_password_required' ] );
|
||||
}
|
||||
|
||||
return $posts;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares a single post for create.
|
||||
*
|
||||
* @since 1.16.0
|
||||
*
|
||||
* @param WP_REST_Request $request Request object.
|
||||
* @return stdClass|WP_Error Post object or WP_Error.
|
||||
*/
|
||||
protected function prepare_item_for_database( $request ) {
|
||||
$prepared_post = new stdClass();
|
||||
$prepared_post->post_status = 'publish';
|
||||
|
||||
$font_data = [];
|
||||
|
||||
$fields = [
|
||||
'family',
|
||||
'fallbacks',
|
||||
'weights',
|
||||
'styles',
|
||||
'variants',
|
||||
'metrics',
|
||||
'url',
|
||||
];
|
||||
|
||||
$schema = $this->get_item_schema();
|
||||
|
||||
foreach ( $fields as $field ) {
|
||||
if ( ! empty( $schema['properties'][ $field ] ) && ! empty( $request[ $field ] ) ) {
|
||||
$font_data[ $field ] = $request[ $field ];
|
||||
|
||||
if ( 'family' === $field ) {
|
||||
/**
|
||||
* Request data.
|
||||
*
|
||||
* @var array{family: string} $request
|
||||
*/
|
||||
$font_family = trim( $request['family'] );
|
||||
|
||||
$prepared_post->post_title = $font_family;
|
||||
|
||||
if ( $this->font_exists( $font_family ) ) {
|
||||
return new \WP_Error(
|
||||
'rest_invalid_field',
|
||||
__( 'A font with this name already exists', 'web-stories' ),
|
||||
[ 'status' => 400 ]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$prepared_post->post_content = wp_json_encode( $font_data );
|
||||
|
||||
return $prepared_post;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a font with the same name already exists.
|
||||
*
|
||||
* Performs a case-insensitive comparison.
|
||||
*
|
||||
* @since 1.16.0
|
||||
*
|
||||
* @param string $font_family Font family.
|
||||
* @return bool Whether a font with this exact name already exists.
|
||||
*/
|
||||
private function font_exists( string $font_family ): bool {
|
||||
$request = new WP_REST_Request(
|
||||
WP_REST_Server::READABLE,
|
||||
$this->namespace .
|
||||
'/' . $this->rest_base
|
||||
);
|
||||
$request->set_param( 'include', [ $font_family ] );
|
||||
$request->set_param( 'service', 'all' );
|
||||
|
||||
/**
|
||||
* Response object.
|
||||
*
|
||||
* @var WP_REST_Response $response
|
||||
*/
|
||||
$response = $this->get_items( $request );
|
||||
|
||||
return ! empty( $response->get_data() );
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user