262 lines
7.8 KiB
PHP
262 lines
7.8 KiB
PHP
<?php
|
|
/**
|
|
* This module is not considered part of the public API, only internal.
|
|
* Any data or functionality that it produces should be exported by the
|
|
* main FontAwesome class and the API documented and semantically versioned there.
|
|
*/
|
|
namespace FortAwesome;
|
|
|
|
require_once trailingslashit( FONTAWESOME_DIR_PATH ) . 'includes/class-fontawesome-api-settings.php';
|
|
require_once trailingslashit( FONTAWESOME_DIR_PATH ) . 'includes/class-fontawesome-exception.php';
|
|
require_once trailingslashit( FONTAWESOME_DIR_PATH ) . 'includes/class-fontawesome-rest-response.php';
|
|
|
|
use \WP_REST_Controller, \WP_Error, \Exception;
|
|
|
|
/**
|
|
* Controller class for REST endpoint
|
|
*
|
|
* @internal
|
|
* @ignore
|
|
*/
|
|
class FontAwesome_Config_Controller extends WP_REST_Controller {
|
|
|
|
// phpcs:ignore Generic.Commenting.DocComment.MissingShort
|
|
/**
|
|
* @ignore
|
|
*/
|
|
private $plugin_slug = null;
|
|
|
|
// phpcs:ignore Generic.Commenting.DocComment.MissingShort
|
|
/**
|
|
* @ignore
|
|
*/
|
|
protected $namespace = null;
|
|
|
|
|
|
// phpcs:ignore Generic.Commenting.DocComment.MissingShort
|
|
/**
|
|
* @ignore
|
|
*/
|
|
public function __construct( $plugin_slug, $namespace ) {
|
|
$this->plugin_slug = $plugin_slug;
|
|
$this->namespace = $namespace;
|
|
}
|
|
|
|
// phpcs:ignore Generic.Commenting.DocComment.MissingShort
|
|
/**
|
|
* @ignore
|
|
*/
|
|
public function register_routes() {
|
|
$route_base = 'config';
|
|
|
|
register_rest_route(
|
|
$this->namespace,
|
|
'/' . $route_base,
|
|
array(
|
|
array(
|
|
'methods' => 'POST',
|
|
'callback' => array( $this, 'update_item' ),
|
|
'permission_callback' => function() {
|
|
return current_user_can( 'manage_options' ); },
|
|
'args' => array(),
|
|
),
|
|
)
|
|
);
|
|
}
|
|
|
|
// phpcs:ignore Generic.Commenting.DocComment.MissingShort
|
|
/**
|
|
* @ignore
|
|
*/
|
|
protected function build_item( $fa ) {
|
|
$preference_registration_error = null;
|
|
|
|
try {
|
|
fa()->gather_preferences();
|
|
} catch ( PreferenceRegistrationException $e ) {
|
|
$preference_registration_error = wpe_fontawesome_server_exception( $e );
|
|
}
|
|
|
|
$item = array(
|
|
'options' => $fa->options(),
|
|
'conflicts' => $fa->conflicts_by_option(),
|
|
);
|
|
|
|
if ( ! is_null( $preference_registration_error ) ) {
|
|
$item['error'] = $preference_registration_error;
|
|
}
|
|
|
|
return $item;
|
|
}
|
|
|
|
/**
|
|
* Update the singleton resource.
|
|
*
|
|
* @param WP_REST_Request $request Full data about the request.
|
|
* @return FontAwesome_REST_Response
|
|
*/
|
|
public function update_item( $request ) {
|
|
try {
|
|
$body = $request->get_json_params();
|
|
|
|
$given_options = isset( $body['options'] ) ? $body['options'] : null;
|
|
|
|
if ( is_null( $given_options ) ) {
|
|
return new FontAwesome_REST_Response( new WP_Error( 'fontawesome_client_exception' ), 400 );
|
|
}
|
|
|
|
$api_token = isset( $given_options['apiToken'] ) ? $given_options['apiToken'] : null;
|
|
|
|
if ( is_string( $api_token ) ) {
|
|
// We're adding an api_token.
|
|
$api_settings = FontAwesome_API_Settings::reset();
|
|
$api_settings->set_api_token( $api_token );
|
|
$api_settings->request_access_token();
|
|
} elseif ( boolval( fa_api_settings()->api_token() ) && ! boolval( $api_token ) ) {
|
|
// We're removing an existing API Token.
|
|
fa_api_settings()->remove();
|
|
|
|
/**
|
|
* We also need to change the version to one that would be
|
|
* valid for a CDN configuration.
|
|
*/
|
|
$given_options['version'] = fa()->latest_version();
|
|
}
|
|
|
|
$db_item = $this->prepare_item_for_database( $given_options );
|
|
|
|
update_option(
|
|
FontAwesome::OPTIONS_KEY,
|
|
$db_item
|
|
);
|
|
|
|
$return_data = $this->build_item( fa() );
|
|
return new FontAwesome_REST_Response( $return_data, 200 );
|
|
} catch ( FontAwesome_ServerException $e ) {
|
|
return new FontAwesome_REST_Response( wpe_fontawesome_server_exception( $e ), 500 );
|
|
} catch ( FontAwesome_Exception $e ) {
|
|
return new FontAwesome_REST_Response( wpe_fontawesome_client_exception( $e ), 400 );
|
|
} catch ( Exception $e ) {
|
|
return new FontAwesome_REST_Response( wpe_fontawesome_unknown_error( $e ), 500 );
|
|
} catch ( Error $e ) {
|
|
return new FontAwesome_REST_Response( wpe_fontawesome_unknown_error( $e ), 500 );
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Filters the incoming data, determines what should actually
|
|
* be stored in the database, and ensures that it's valid.
|
|
*
|
|
* @internal
|
|
* @ignore
|
|
* @param array $given_options the options from the request body
|
|
* @throws ConfigSchemaException
|
|
* @return array The item to store on the options key
|
|
*/
|
|
protected function prepare_item_for_database( $given_options ) {
|
|
// start with a copy of the defaults and just override them indivually.
|
|
$item = array_merge( array(), FontAwesome::DEFAULT_USER_OPTIONS );
|
|
|
|
/**
|
|
* The apiToken is handled specially.
|
|
* We only store a boolean value indicating whether and apiToken
|
|
* has been stored. It's the responsibility of the calling code
|
|
* to store the actual API Token appropriately.
|
|
*/
|
|
$api_token = isset( $given_options['apiToken'] ) && boolval( $given_options['apiToken'] );
|
|
$item['apiToken'] = $api_token;
|
|
|
|
/**
|
|
* A kitToken is handled specially.
|
|
* If one is provided, but there's no API token, then that is invalid.
|
|
*/
|
|
if ( isset( $given_options['kitToken'] ) && is_string( $given_options['kitToken'] ) ) {
|
|
if ( $api_token ) {
|
|
$item['kitToken'] = $given_options['kitToken'];
|
|
} else {
|
|
throw ConfigSchemaException::kit_token_no_api_token();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* For the following options, if they are provided at all, we just
|
|
* use that to override the default.
|
|
*/
|
|
if ( isset( $given_options['usePro'] ) ) {
|
|
$item['usePro'] = $given_options['usePro'];
|
|
}
|
|
|
|
/**
|
|
* The new option key is "compat", overriding the old v4Compat key.
|
|
*/
|
|
if ( isset( $given_options['compat'] ) ) {
|
|
$item['compat'] = $given_options['compat'];
|
|
} elseif ( isset( $given_options['v4Compat'] ) ) {
|
|
$item['compat'] = $given_options['v4Compat'];
|
|
}
|
|
if ( isset( $given_options['technology'] ) ) {
|
|
$item['technology'] = $given_options['technology'];
|
|
}
|
|
if ( isset( $given_options['pseudoElements'] ) ) {
|
|
$item['pseudoElements'] = $given_options['pseudoElements'];
|
|
}
|
|
|
|
$version_is_symbolic_latest = isset( $given_options['version'] )
|
|
&& 'latest' === $given_options['version'];
|
|
|
|
$version_is_concrete = isset( $given_options['version'] )
|
|
&& 1 === preg_match( '/[0-9]+\.[0-9]+/', $given_options['version'] );
|
|
|
|
/**
|
|
* The pseudoElements option is handled specially. If technology
|
|
* is webfont, pseudoElements must be true.
|
|
*/
|
|
if ( 'webfont' === $item['technology'] && ! $item['pseudoElements'] ) {
|
|
throw ConfigSchemaException::webfont_always_enables_pseudo_elements();
|
|
}
|
|
|
|
/**
|
|
* The version is handled specially.
|
|
*
|
|
* If this is a non-kit config, then the version must be concrete,
|
|
* a major.minor.patch version like 5.12.0.
|
|
*
|
|
* If this is a kit-based config, then the version must either be
|
|
* concrete or one of the exact, case-sensitive, strings 'latest',
|
|
* '5.x', or '6.x'.
|
|
*/
|
|
if ( isset( $given_options['kitToken'] ) && is_string( $given_options['kitToken'] ) && $version_is_symbolic_latest ) {
|
|
$item['version'] = 'latest';
|
|
} elseif ( $version_is_concrete || '5.x' === $given_options['version'] || '6.x' === $given_options['version'] ) {
|
|
$item['version'] = $given_options['version'];
|
|
} else {
|
|
throw ConfigSchemaException::concrete_version_expected();
|
|
}
|
|
|
|
// V6 is not supported on Pro CDN.
|
|
if ( 1 === preg_match( '/^6\./', $item['version'] ) && boolval( $item['usePro'] ) && ! is_string( $given_options['kitToken'] ) ) {
|
|
throw ConfigSchemaException::v6_pro_cdn_not_supported();
|
|
}
|
|
|
|
if (
|
|
$version_is_concrete &&
|
|
version_compare( '5.1.0', $item['version'], '>' ) &&
|
|
boolval( $item['v4Compat'] ) &&
|
|
'webfont' === $item['technology']
|
|
) {
|
|
throw ConfigSchemaException::webfont_v4compat_introduced_later();
|
|
}
|
|
|
|
return $item;
|
|
}
|
|
|
|
/**
|
|
* Allows a test subclass to mock the release provider.
|
|
*
|
|
* @ignore
|
|
*/
|
|
protected function release_provider() {
|
|
return fa_release_provider();
|
|
}
|
|
}
|