File "class-fontawesome-conflict-detection-controller.php"
Full Path: /home/vantageo/public_html/cache/cache/cache/cache/.wp-cli/wp-content/plugins/font-awesome/includes/class-fontawesome-conflict-detection-controller.php
File size: 14.07 KB
MIME-type: text/x-php
Charset: utf-8
<?php
namespace FortAwesome;
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, \Error, \Exception;
/**
* REST Controller for managing data on the FontAwesome::CONFLICT_DETECTION_OPTIONS_KEY.
*
* Internal use only, not part of this plugin's public API.
*
* @ignore
* @internal
*/
class FontAwesome_Conflict_Detection_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
*/
protected $valid_attrs = array( 'type', 'technology', 'href', 'src', 'innerText', 'tagName' );
// 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 = 'conflict-detection';
register_rest_route(
$this->namespace,
'/' . $route_base . '/until',
array(
array(
'methods' => 'POST',
'callback' => array( $this, 'update_detect_conflicts_until' ),
'permission_callback' => function() {
return current_user_can( 'manage_options' ); },
'args' => array(),
),
)
);
register_rest_route(
$this->namespace,
'/' . $route_base . '/conflicts',
array(
array(
'methods' => 'POST',
'callback' => array( $this, 'report_conflicts' ),
'permission_callback' => function() {
return current_user_can( 'manage_options' ); },
'args' => array(),
),
)
);
register_rest_route(
$this->namespace,
'/' . $route_base . '/conflicts',
array(
array(
'methods' => 'DELETE',
'callback' => array( $this, 'delete_conflicts' ),
'permission_callback' => function() {
return current_user_can( 'manage_options' ); },
'args' => array(),
),
)
);
/**
* The given blocklist, an array of md5s, will become the new blocklist,
* for each md5 in the given array that already exists as a key in
* the unregisteredClients array.
*/
register_rest_route(
$this->namespace,
'/' . $route_base . '/conflicts/blocklist',
array(
array(
'methods' => 'POST',
'callback' => array( $this, 'update_blocklist' ),
'permission_callback' => function() {
return current_user_can( 'manage_options' ); },
'args' => array(),
),
)
);
}
/**
* Report conflicts. Adds and/or updates unregisteredClients
*
* The response will have an HTTP 204 status if the request results in no changes.
* If changes are made, the response will have an HTTP 200 status, and
* the response body will include just the new status of the
* unregisteredClients (not the entire conflict-detection option data).
*
* If the plugin is not currently in conflict detection mode, this
* returns an HTTP 404 status.
*
* @param WP_REST_Request $request the request.
* @return FontAwesome_REST_Response
*/
// phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.Missing
public function report_conflicts( $request ) {
try {
if ( ! fa()->detecting_conflicts() ) {
return new FontAwesome_REST_Response( null, 404 );
}
$item = $this->prepare_unregistered_clients_for_database( $request );
$prev_option = get_option(
FontAwesome::CONFLICT_DETECTION_OPTIONS_KEY,
FontAwesome::DEFAULT_CONFLICT_DETECTION_OPTIONS
);
$prev_option_unregistered_clients = (
isset( $prev_option['unregisteredClients'] )
&& is_array( $prev_option['unregisteredClients'] )
)
? $prev_option['unregisteredClients']
: array();
$new_option_unregistered_clients = array_merge(
$prev_option_unregistered_clients,
$item
);
if ( $this->unregistered_clients_array_has_changes( $prev_option_unregistered_clients, $new_option_unregistered_clients ) ) {
// Update only the unregisteredClients key, leaving any other keys unchanged.
$new_option_value = array_merge(
$prev_option,
array(
'unregisteredClients' => $new_option_unregistered_clients,
)
);
if ( update_option( FontAwesome::CONFLICT_DETECTION_OPTIONS_KEY, $new_option_value ) ) {
return new FontAwesome_REST_Response( $new_option_unregistered_clients, 200 );
} else {
throw new ConflictDetectionStorageException();
}
} else {
// No change.
return new FontAwesome_REST_Response( null, 204 );
}
} 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 );
}
}
/**
* Remove (forget) some specified previously detected conflicts.
*
* The request body should contain an array of md5 values to be
* deleted. Any unrecognized md5s are ignored.
*
* The response will have an HTTP 204 status if the request results in no changes,
* otherwise it will include the new set of unregistered clients.
*
* If the plugin is not currently in conflict detection mode, this
* returns an HTTP 404 status.
*
* @param WP_REST_Request $request the request.
* @return FontAwesome_REST_Response
*/
// phpcs:ignore Squiz.Commenting.FunctionCommentThrowTag.Missing
public function delete_conflicts( $request ) {
try {
$body = $request->get_json_params();
if ( ! $this->is_array_of_md5( $body ) ) {
throw new ConflictDetectionSchemaException();
}
$prev_option = get_option(
FontAwesome::CONFLICT_DETECTION_OPTIONS_KEY,
FontAwesome::DEFAULT_CONFLICT_DETECTION_OPTIONS
);
$prev_option_unregistered_clients = (
isset( $prev_option['unregisteredClients'] )
&& is_array( $prev_option['unregisteredClients'] )
)
? $prev_option['unregisteredClients']
: array();
// Make a copy.
$new_option_unregistered_clients = array_merge(
array(),
$prev_option_unregistered_clients
);
foreach ( $body as $md5 ) {
unset( $new_option_unregistered_clients[ $md5 ] );
}
if ( $this->unregistered_clients_array_has_changes( $prev_option_unregistered_clients, $new_option_unregistered_clients ) ) {
// Update only the unregisteredClients key, leaving any other keys unchanged.
$new_option_value = array_merge(
$prev_option,
array(
'unregisteredClients' => $new_option_unregistered_clients,
)
);
if ( update_option( FontAwesome::CONFLICT_DETECTION_OPTIONS_KEY, $new_option_value ) ) {
return new FontAwesome_REST_Response( $new_option_unregistered_clients, 200 );
} else {
throw new ConflictDetectionStorageException();
}
} else {
// No change.
return new FontAwesome_REST_Response( null, 204 );
}
} 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 );
}
}
/**
* Update the value of detectConflictsUntil to start/stop conflict detection.
*
* @throws ConflictDetectionSchemaException
* @throws ConflictDetectionStorageException
* @param WP_REST_Request $request the request.
* @return FontAwesome_REST_Response
*/
public function update_detect_conflicts_until( $request ) {
try {
$body = $request->get_body();
$new_value = intval( $body );
if ( 0 === $new_value && '0' !== $body ) {
throw new ConflictDetectionSchemaException();
}
$prev_option = get_option(
FontAwesome::CONFLICT_DETECTION_OPTIONS_KEY,
FontAwesome::DEFAULT_CONFLICT_DETECTION_OPTIONS
);
$prev_option_detect_conflicts_until = (
isset( $prev_option['detectConflictsUntil'] ) &&
is_integer( $prev_option['detectConflictsUntil'] )
)
? $prev_option['detectConflictsUntil']
: null;
if ( $prev_option_detect_conflicts_until !== $new_value ) {
// Update only the detectConflictsUntil key, leaving any other keys unchanged.
$new_option_value = array_merge(
$prev_option,
array( 'detectConflictsUntil' => $new_value )
);
if ( update_option( FontAwesome::CONFLICT_DETECTION_OPTIONS_KEY, $new_option_value ) ) {
return new FontAwesome_REST_Response( array( 'detectConflictsUntil' => $new_value ), 200 );
} else {
throw new ConflictDetectionStorageException();
}
} else {
// No change.
return new FontAwesome_REST_Response( null, 204 );
}
} 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 );
}
}
/**
* Updates which unregistered will be blocked.
*
* The body of the request is an array of md5 values identifying those
* unregistered clients that will be blocked as a result of this request.
* Any unrecognized md5s will be ignored.
*
* Internal use only, not part of this plugin's public API.
*
* @throws ConflictDetectionSchemaException
* @throws ConflictDetectionStorageException
* @ignore
* @internal
*/
public function update_blocklist( $request ) {
try {
$body = $request->get_json_params();
if ( ! $this->is_array_of_md5( $body ) ) {
throw new ConflictDetectionSchemaException();
}
$prev_option = get_option(
FontAwesome::CONFLICT_DETECTION_OPTIONS_KEY,
FontAwesome::DEFAULT_CONFLICT_DETECTION_OPTIONS
);
$prev_option_unregistered_clients = (
isset( $prev_option['unregisteredClients'] )
&& is_array( $prev_option['unregisteredClients'] )
)
? $prev_option['unregisteredClients']
: array();
// Make a copy.
$new_option_unregistered_clients = array_merge(
array(),
$prev_option_unregistered_clients
);
foreach ( array_keys( $new_option_unregistered_clients ) as $md5 ) {
if ( in_array( $md5, $body, true ) ) {
$new_option_unregistered_clients[ $md5 ]['blocked'] = true;
} else {
$new_option_unregistered_clients[ $md5 ]['blocked'] = false;
}
}
if ( $this->unregistered_clients_array_has_changes( $prev_option_unregistered_clients, $new_option_unregistered_clients ) ) {
// Update only the unregisteredClients key, leaving any other keys unchanged.
$new_option_value = array_merge(
$prev_option,
array(
'unregisteredClients' => $new_option_unregistered_clients,
)
);
if ( update_option( FontAwesome::CONFLICT_DETECTION_OPTIONS_KEY, $new_option_value ) ) {
return new FontAwesome_REST_Response( fa()->blocklist(), 200 );
} else {
throw new ConflictDetectionStorageException();
}
} else {
// No change.
return new FontAwesome_REST_Response( null, 204 );
}
} 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 );
}
}
/**
* Reads a json body of the given Request, validates it, and turns it
* into a valid value for the unregisteredClients key of the conflict detection
* option.
*
* @internal
* @ignore
* @throws ConflictDetectionSchemaException
* @return array
*/
protected function prepare_unregistered_clients_for_database( $request ) {
$body = $request->get_json_params();
if ( ! \is_array( $body ) || count( $body ) === 0 ) {
throw new ConflictDetectionSchemaException();
}
$validated = array();
foreach ( $body as $md5 => $attrs ) {
if ( ! is_string( $md5 ) || ! strlen( $md5 ) === 32 ) {
throw new ConflictDetectionSchemaException();
}
if ( ! is_array( $attrs ) ) {
throw new ConflictDetectionSchemaException();
}
$validated[ $md5 ] = array();
foreach ( $attrs as $key => $value ) {
if ( in_array( $key, $this->valid_attrs, true ) ) {
$validated[ $md5 ][ $key ] = $value;
}
}
}
return $validated;
}
protected function unregistered_clients_array_has_changes( $old, $new ) {
if ( ! is_array( $old ) ) {
return true;
}
if ( count( array_diff_key( $old, $new ) ) > 0 || count( array_diff_key( $new, $old ) ) > 0 ) {
return true;
} else {
foreach ( $old as $key => $value ) {
if ( count( array_diff_assoc( $old[ $key ], $new[ $key ] ) ) > 0 ) {
return true;
}
}
foreach ( $new as $key => $value ) {
if ( count( array_diff_assoc( $new[ $key ], $old[ $key ] ) ) > 0 ) {
return true;
}
}
return false;
}
}
protected function is_array_of_md5( $data ) {
return \is_array( $data ) &&
count( $data ) === 0 ||
(
0 === count(
array_filter(
$data,
function( $md5 ) {
return ! is_string( $md5 ) || strlen( $md5 ) !== 32;
}
)
)
);
}
}