Gestionnaire de fichiers - Editer - /home/wwgoat/public_html/blog/data.tar
Arrière
base/endpoint.php 0000644 00000021633 14720700115 0010011 0 ustar 00 <?php namespace Elementor\Data\Base; use Elementor\Data\Manager; use WP_REST_Server; abstract class Endpoint { const AVAILABLE_METHODS = [ WP_REST_Server::READABLE, WP_REST_Server::CREATABLE, WP_REST_Server::EDITABLE, WP_REST_Server::DELETABLE, WP_REST_Server::ALLMETHODS, ]; /** * Controller of current endpoint. * * @var \Elementor\Data\Base\Controller */ protected $controller; /** * Loaded sub endpoint(s). * * @var \Elementor\Data\Base\SubEndpoint[] */ private $sub_endpoints = []; /** * Get format suffix. * * Examples: * '{one_parameter_name}'. * '{one_parameter_name}/{two_parameter_name}/'. * '{one_parameter_name}/whatever/anything/{two_parameter_name}/' and so on for each endpoint or sub-endpoint. * * @return string current location will later be added automatically. */ public static function get_format() { return ''; } /** * Endpoint constructor. * * run `$this->>register()`. * * @param \Elementor\Data\Base\Controller $controller * * @throws \Exception */ public function __construct( $controller ) { if ( ! ( $controller instanceof Controller ) ) { throw new \Exception( 'Invalid controller.' ); } $this->controller = $controller; $this->register(); } /** * Get endpoint name. * * @return string */ abstract public function get_name(); /** * Get base route. * * Removing 'index' from endpoint. * * @return string */ public function get_base_route() { $endpoint_name = $this->get_name(); // TODO: Allow this only for internal routes. // TODO: Make difference between internal and external endpoints. if ( 'index' === $endpoint_name ) { $endpoint_name = ''; } return '/' . $this->controller->get_rest_base() . '/' . $endpoint_name; } /** * Register the endpoint. * * By default: register get items route. * * @throws \Exception */ protected function register() { $this->register_items_route(); } /** * Register sub endpoint. * * @param string $route * @param string $endpoint_class * * @return \Elementor\Data\Base\SubEndpoint * @throws \Exception */ protected function register_sub_endpoint( $route, $endpoint_class ) { $endpoint_instance = new $endpoint_class( $route, $this ); if ( ! ( $endpoint_instance instanceof SubEndpoint ) ) { throw new \Exception( 'Invalid endpoint instance.' ); } $endpoint_route = $route . '/' . $endpoint_instance->get_name(); $this->sub_endpoints[ $endpoint_route ] = $endpoint_instance; $component_name = $endpoint_instance->controller->get_rest_base(); $parent_instance = $endpoint_instance->get_parent(); $parent_name = $endpoint_instance->get_name(); $parent_format_suffix = $parent_instance::get_format(); $current_format_suffix = $endpoint_instance::get_format(); $command = $component_name . '/' . $parent_name; $format = $component_name . '/' . $parent_format_suffix . '/' . $parent_name . '/' . $current_format_suffix; Manager::instance()->register_endpoint_format( $command, $format ); return $endpoint_instance; } /** * Base callback. * * All reset requests from the client should pass this function. * * @param string $methods * @param \WP_REST_Request $request * @param bool $is_multi * * @return mixed|\WP_Error|\WP_HTTP_Response|\WP_REST_Response * @throws \Exception */ public function base_callback( $methods, $request, $is_multi = false ) { // TODO: Find better solution. $json_params = $request->get_json_params(); if ( $json_params ) { $request->set_body_params( $json_params ); } // TODO: Handle permission callback. switch ( $methods ) { case WP_REST_Server::READABLE: $result = $is_multi ? $this->get_items( $request ) : $this->get_item( $request->get_param( 'id' ), $request ); break; case WP_REST_Server::CREATABLE: $result = $is_multi ? $this->create_items( $request ) : $this->create_item( $request->get_param( 'id' ), $request ); break; case WP_REST_Server::EDITABLE: $result = $is_multi ? $this->update_items( $request ) : $this->update_item( $request->get_param( 'id' ), $request ); break; case WP_REST_Server::DELETABLE: $result = $is_multi ? $this->delete_items( $request ) : $this->delete_item( $request->get_param( 'id' ), $request ); break; default: throw new \Exception( 'Invalid method.' ); } return rest_ensure_response( $result ); } /** * Retrieves a collection of items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function get_items( $request ) { return $this->controller->get_items( $request ); } /** * Retrieves one item from the collection. * * @param string $id * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function get_item( $id, $request ) { return $this->controller->get_item( $request ); } /** * Get permission callback. * * By default get permission callback from the controller. * * @param \WP_REST_Request $request Full data about the request. * * @return boolean */ public function get_permission_callback( $request ) { return $this->controller->get_permission_callback( $request ); } /** * Creates one item. * * @param string $id id of request item. * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function create_item( $id, $request ) { return $this->controller->create_item( $request ); } /** * Creates multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function create_items( $request ) { return $this->controller->create_items( $request ); } /** * Updates one item. * * @param string $id id of request item. * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function update_item( $id, $request ) { return $this->controller->update_item( $request ); } /** * Updates multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function update_items( $request ) { return $this->controller->update_items( $request ); } /** * Delete one item. * * @param string $id id of request item. * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function delete_item( $id, $request ) { return $this->controller->delete_item( $request ); } /** * Delete multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function delete_items( $request ) { return $this->controller->delete_items( $request ); } /** * Register item route. * * @param array $args * @param string $route * @param string $methods * * @throws \Exception */ public function register_item_route( $methods = WP_REST_Server::READABLE, $args = [], $route = '/' ) { $args = array_merge( [ 'id' => [ 'description' => 'Unique identifier for the object.', 'type' => 'string', ], ], $args ); if ( isset( $args['id'] ) && $args['id'] ) { $route .= '(?P<id>[\w]+)/'; } $this->register_route( $route, $methods, function ( $request ) use ( $methods ) { return $this->base_callback( $methods, $request ); }, $args ); } /** * Register items route. * * @param string $methods * * @throws \Exception */ public function register_items_route( $methods = WP_REST_Server::READABLE ) { $this->register_route( '', $methods, function ( $request ) use ( $methods ) { return $this->base_callback( $methods, $request, true ); } ); } /** * Register route. * * @param string $route * @param string $methods * @param null $callback * @param array $args * * @return bool * @throws \Exception */ public function register_route( $route = '', $methods = WP_REST_Server::READABLE, $callback = null, $args = [] ) { if ( ! in_array( $methods, self::AVAILABLE_METHODS, true ) ) { throw new \Exception( 'Invalid method.' ); } $route = $this->get_base_route() . $route; return register_rest_route( $this->controller->get_namespace(), $route, [ [ 'args' => $args, 'methods' => $methods, 'callback' => $callback, 'permission_callback' => function ( $request ) { return $this->get_permission_callback( $request ); }, ], ] ); } } base/processor.php 0000644 00000000674 14720700115 0010212 0 ustar 00 <?php namespace Elementor\Data\Base; abstract class Processor { /** * Controller. * * @var \Elementor\Data\Base\Controller */ private $controller; /** * Processor constructor. * * @param \Elementor\Data\Base\Controller $controller */ public function __construct( $controller ) { $this->controller = $controller; } /** * Get processor command. * * @return string */ abstract public function get_command(); } base/processor/after.php 0000644 00000000724 14720700115 0011307 0 ustar 00 <?php namespace Elementor\Data\Base\Processor; use Elementor\Data\Base\Processor; abstract class After extends Processor { /** * Get conditions for running processor. * * @param array $args * @param mixed $result * * @return bool */ public function get_conditions( $args, $result ) { return true; } /** * Apply processor. * * @param $args * @param $result * * @return mixed */ abstract public function apply( $args, $result ); } base/processor/before.php 0000644 00000000631 14720700115 0011445 0 ustar 00 <?php namespace Elementor\Data\Base\Processor; use Elementor\Data\Base\Processor; abstract class Before extends Processor { /** * Get conditions for running processor. * @param array $args * * @return bool */ public function get_conditions( $args ) { return true; } /** * Apply processor. * * @param array $args * * @return mixed */ abstract public function apply( $args ); } base/controller.php 0000644 00000020153 14720700115 0010350 0 ustar 00 <?php namespace Elementor\Data\Base; use Elementor\Data\Manager; use Elementor\Plugin; use WP_REST_Controller; use WP_REST_Server; abstract class Controller extends WP_REST_Controller { /** * Loaded endpoint(s). * * @var \Elementor\Data\Base\Endpoint[] */ public $endpoints = []; /** * Loaded processor(s). * * @var \Elementor\Data\Base\Processor[][] */ public $processors = []; /** * Controller constructor. * * Register endpoints on 'rest_api_init'. * */ public function __construct() { // TODO: Controllers and endpoints can have common interface. // TODO: Uncomment when native 3rd plugins uses V2. //$this->deprecated(); $this->namespace = Manager::ROOT_NAMESPACE . '/v' . Manager::VERSION; $this->rest_base = Manager::REST_BASE . $this->get_name(); add_action( 'rest_api_init', function () { $this->register(); // Because 'register' is protected. } ); /** * Since all actions were removed for custom internal REST server. * Re-add the actions. */ add_action( 'elementor_rest_api_before_init', function () { add_action( 'rest_api_init', function() { $this->register(); } ); } ); } /** * Get controller name. * * @return string */ abstract public function get_name(); /** * Get controller namespace. * * @return string */ public function get_namespace() { return $this->namespace; } /** * Get controller reset base. * * @return string */ public function get_rest_base() { return $this->rest_base; } /** * Get controller route. * * @return string */ public function get_controller_route() { return $this->get_namespace() . '/' . $this->get_rest_base(); } /** * Retrieves the index for a controller. * * @return \WP_REST_Response|\WP_Error */ public function get_controller_index() { $server = rest_get_server(); $routes = $server->get_routes(); $endpoints = array_intersect_key( $server->get_routes(), $routes ); $controller_route = $this->get_controller_route(); array_walk( $endpoints, function ( &$item, $endpoint ) use ( &$endpoints, $controller_route ) { if ( ! strstr( $endpoint, $controller_route ) ) { unset( $endpoints[ $endpoint ] ); } } ); $data = [ 'namespace' => $this->get_namespace(), 'controller' => $controller_route, 'routes' => $server->get_data_for_routes( $endpoints ), ]; $response = rest_ensure_response( $data ); // Link to the root index. $response->add_link( 'up', rest_url( '/' ) ); return $response; } /** * Get processors. * * @param string $command * * @return \Elementor\Data\Base\Processor[] */ public function get_processors( $command ) { $result = []; if ( isset( $this->processors[ $command ] ) ) { $result = $this->processors[ $command ]; } return $result; } public function get_items( $request ) { return $this->get_controller_index(); } /** * Creates multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function create_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Updates multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function update_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Delete multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function delete_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Register endpoints. */ abstract public function register_endpoints(); /** * Register processors. */ public function register_processors() { } /** * Register internal endpoints. */ protected function register_internal_endpoints() { register_rest_route( $this->get_namespace(), '/' . $this->get_rest_base(), [ [ 'methods' => WP_REST_Server::READABLE, 'callback' => array( $this, 'get_items' ), 'args' => [], 'permission_callback' => function ( $request ) { return $this->get_permission_callback( $request ); }, ], ] ); } /** * Register endpoint. * * @param string $endpoint_class * * @return \Elementor\Data\Base\Endpoint */ protected function register_endpoint( $endpoint_class ) { $endpoint_instance = new $endpoint_class( $this ); // TODO: Validate instance like in register_sub_endpoint(). $endpoint_route = $this->get_name() . '/' . $endpoint_instance->get_name(); $this->endpoints[ $endpoint_route ] = $endpoint_instance; $command = $endpoint_route; $format = $endpoint_instance::get_format(); if ( $command ) { $format = $command . '/' . $format; } else { $format = $format . $command; } // `$e.data.registerFormat()`. Manager::instance()->register_endpoint_format( $command, $format ); return $endpoint_instance; } /** * Register a processor. * * That will be later attached to the endpoint class. * * @param string $processor_class * * @return \Elementor\Data\Base\Processor $processor_instance */ protected function register_processor( $processor_class ) { $processor_instance = new $processor_class( $this ); // TODO: Validate processor instance. $command = $processor_instance->get_command(); if ( ! isset( $this->processors[ $command ] ) ) { $this->processors[ $command ] = []; } $this->processors[ $command ] [] = $processor_instance; return $processor_instance; } /** * Register. * * Endpoints & processors. */ protected function register() { $this->register_internal_endpoints(); $this->register_endpoints(); // Aka hooks. $this->register_processors(); } /** * Retrieves a recursive collection of all endpoint(s), items. * * Get items recursive, will run overall endpoints of the current controller. * For each endpoint it will run `$endpoint->getItems( $request ) // the $request passed in get_items_recursive`. * Will skip $skip_endpoints endpoint(s). * * Example, scenario: * Controller 'test-controller'. * Controller endpoints: 'endpoint1', 'endpoint2'. * Endpoint2 get_items method: `get_items() { return 'test' }`. * Call `Controller.get_items_recursive( ['endpoint1'] )`, result: [ 'endpoint2' => 'test' ]; * * @param array $skip_endpoints * * @return array */ public function get_items_recursive( $skip_endpoints = [] ) { $response = []; foreach ( $this->endpoints as $endpoint ) { // Skip self. if ( in_array( $endpoint, $skip_endpoints, true ) ) { continue; } $response[ $endpoint->get_name() ] = $endpoint->get_items( null ); } return $response; } /** * Get permission callback. * * Default controller permission callback. * By default endpoint will inherit the permission callback from the controller. * By default permission is `current_user_can( 'administrator' );`. * * @param \WP_REST_Request $request * * @return bool */ public function get_permission_callback( $request ) { // The function is public since endpoint need to access it. switch ( $request->get_method() ) { case 'GET': case 'POST': case 'UPDATE': case 'PUT': case 'DELETE': case 'PATCH': return current_user_can( 'administrator' ); } return false; } private static $notify_deprecated = true; private function deprecated() { add_action( 'elementor/init', function () { if ( ! self::$notify_deprecated ) { return; } Plugin::$instance->modules_manager->get_modules( 'dev-tools' )->deprecation->deprecated_function( 'Elementor\Data\Manager', '3.5.0', 'Elementor\Data\V2\Manager' ); self::$notify_deprecated = false; } ); } } base/sub-endpoint.php 0000644 00000001361 14720700115 0010574 0 ustar 00 <?php namespace Elementor\Data\Base; // TODO: Add test. abstract class SubEndpoint extends Endpoint { /** * @var Endpoint */ protected $parent_endpoint; /** * @var string */ protected $parent_route = ''; public function __construct( $parent_route, $parent_endpoint ) { $this->parent_endpoint = $parent_endpoint; $this->parent_route = $parent_route; parent::__construct( $this->parent_endpoint->controller ); } /** * Get parent route. * * @return \Elementor\Data\Base\Endpoint */ public function get_parent() { return $this->parent_endpoint; } public function get_base_route() { $controller_name = $this->controller->get_name(); return $controller_name . '/' . $this->parent_route . $this->get_name(); } } manager.php 0000644 00000022274 14720700115 0006673 0 ustar 00 <?php namespace Elementor\Data; use Elementor\Core\Base\Module as BaseModule; use Elementor\Data\Base\Processor; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Manager extends BaseModule { const ROOT_NAMESPACE = 'elementor'; const REST_BASE = ''; const VERSION = '1'; /** * @var \WP_REST_Server */ private $server; /** * @var boolean */ private $is_internal = false; /** * @var array */ private $cache = []; /** * Loaded controllers. * * @var \Elementor\Data\Base\Controller[] */ public $controllers = []; /** * Loaded command(s) format. * * @var string[] */ public $command_formats = []; /** * Fix issue with 'Potentially polymorphic call. The code may be inoperable depending on the actual class instance passed as the argument.'. * * @return \Elementor\Core\Base\Module|\Elementor\Data\Manager */ public static function instance() { return ( parent::instance() ); } public function __construct() { add_action( 'rest_api_init', [ $this, 'register_rest_error_handler' ] ); } public function get_name() { return 'data-manager'; } /** * @return \Elementor\Data\Base\Controller[] */ public function get_controllers() { return $this->controllers; } private function get_cache( $key ) { return self::get_items( $this->cache, $key ); } private function set_cache( $key, $value ) { $this->cache[ $key ] = $value; } /** * Register controller. * * @param string $controller_class_name * * @return \Elementor\Data\Base\Controller */ public function register_controller( $controller_class_name ) { $controller_instance = new $controller_class_name(); return $this->register_controller_instance( $controller_instance ); } /** * Register controller instance. * * @param \Elementor\Data\Base\Controller $controller_instance * * @return \Elementor\Data\Base\Controller */ public function register_controller_instance( $controller_instance ) { // TODO: Validate instance. $this->controllers[ $controller_instance->get_name() ] = $controller_instance; return $controller_instance; } /** * Register endpoint format. * * @param string $command * @param string $format * */ public function register_endpoint_format( $command, $format ) { $this->command_formats[ $command ] = rtrim( $format, '/' ); } public function register_rest_error_handler() { if ( ! $this->is_internal() ) { $logger_manager = \Elementor\Core\Logger\Manager::instance(); $logger_manager->register_error_handler(); } } /** * Find controller instance. * * By given command name. * * @param string $command * * @return false|\Elementor\Data\Base\Controller */ public function find_controller_instance( $command ) { $command_parts = explode( '/', $command ); $assumed_command_parts = []; foreach ( $command_parts as $command_part ) { $assumed_command_parts [] = $command_part; foreach ( $this->controllers as $controller_name => $controller ) { $assumed_command = implode( '/', $assumed_command_parts ); if ( $assumed_command === $controller_name ) { return $controller; } } } return false; } /** * Command extract args. * * @param string $command * @param array $args * * @return \stdClass */ public function command_extract_args( $command, $args = [] ) { $result = new \stdClass(); $result->command = $command; $result->args = $args; if ( false !== strpos( $command, '?' ) ) { $command_parts = explode( '?', $command ); $pure_command = $command_parts[0]; $query_string = $command_parts[1]; parse_str( $query_string, $temp ); $result->command = rtrim( $pure_command, '/' ); $result->args = array_merge( $args, $temp ); } return $result; } /** * Command to endpoint. * * Format is required otherwise $command will returned. * * @param string $command * @param string $format * @param array $args * * @return string endpoint */ public function command_to_endpoint( $command, $format, $args ) { $endpoint = $command; if ( $format ) { $formatted = $format; array_walk( $args, function ( $val, $key ) use ( &$formatted ) { $formatted = str_replace( '{' . $key . '}', $val, $formatted ); } ); // Remove remaining format if not requested via `$args`. if ( strstr( $formatted, '/{' ) ) { /** * Example: * $command = 'example/documents'; * $format = 'example/documents/{document_id}/elements/{element_id}'; * $formatted = 'example/documents/1618/elements/{element_id}'; * Result: * $formatted = 'example/documents/1618/elements'; */ $formatted = substr( $formatted, 0, strpos( $formatted, '/{' ) ); } $endpoint = $formatted; } return $endpoint; } /** * Run server. * * Init WordPress reset api. * * @return \WP_REST_Server */ public function run_server() { /** * If run_server() called means, that rest api is simulated from the backend. */ $this->is_internal = true; if ( ! $this->server ) { // Remove all 'rest_api_init' actions. remove_all_actions( 'rest_api_init' ); // Call custom reset api loader. do_action( 'elementor_rest_api_before_init' ); $this->server = rest_get_server(); // Init API. } return $this->server; } /** * Kill server. * * Free server and controllers. */ public function kill_server() { global $wp_rest_server; $this->controllers = []; $this->command_formats = []; $this->server = false; $this->is_internal = false; $this->cache = []; $wp_rest_server = false; } /** * Run processor. * * @param \Elementor\Data\Base\Processor $processor * @param array $data * * @return mixed */ public function run_processor( $processor, $data ) { if ( call_user_func_array( [ $processor, 'get_conditions' ], $data ) ) { return call_user_func_array( [ $processor, 'apply' ], $data ); } return null; } /** * Run processors. * * Filter them by class. * * @param \Elementor\Data\Base\Processor[] $processors * @param string $filter_by_class * @param array $data * * @return false|array */ public function run_processors( $processors, $filter_by_class, $data ) { foreach ( $processors as $processor ) { if ( $processor instanceof $filter_by_class ) { if ( Processor\Before::class === $filter_by_class ) { $this->run_processor( $processor, $data ); } elseif ( Processor\After::class === $filter_by_class ) { $result = $this->run_processor( $processor, $data ); if ( $result ) { $data[1] = $result; } } else { // TODO: error break; } } } return isset( $data[1] ) ? $data[1] : false; } /** * Run request. * * Simulate rest API from within the backend. * Use args as query. * * @param string $endpoint * @param array $args * @param string $method * * @return \WP_REST_Response */ private function run_request( $endpoint, $args, $method ) { $this->run_server(); $endpoint = '/' . self::ROOT_NAMESPACE . '/v' . self::VERSION . '/' . $endpoint; // Run reset api. $request = new \WP_REST_Request( $method, $endpoint ); if ( 'GET' === $method ) { $request->set_query_params( $args ); } else { $request->set_body_params( $args ); } return rest_do_request( $request ); } /** * Run endpoint. * * Wrapper for `$this->run_request` return `$response->getData()` instead of `$response`. * * @param string $endpoint * @param array $args * @param string $method * * @return array */ public function run_endpoint( $endpoint, $args = [], $method = 'GET' ) { $response = $this->run_request( $endpoint, $args, $method ); return $response->get_data(); } /** * Run ( simulated reset api ). * * Do: * Init reset server. * Run before processors. * Run command as reset api endpoint from internal. * Run after processors. * * @param string $command * @param array $args * @param string $method * * @return array|false processed result */ public function run( $command, $args = [], $method = 'GET' ) { $key = crc32( $command . '-' . wp_json_encode( $args ) . '-' . $method ); $cache = $this->get_cache( $key ); if ( $cache ) { return $cache; } $this->run_server(); $controller_instance = $this->find_controller_instance( $command ); if ( ! $controller_instance ) { $this->set_cache( $key, [] ); return []; } $extracted_command = $this->command_extract_args( $command, $args ); $command = $extracted_command->command; $args = $extracted_command->args; $format = isset( $this->command_formats[ $command ] ) ? $this->command_formats[ $command ] : false; $command_processors = $controller_instance->get_processors( $command ); $endpoint = $this->command_to_endpoint( $command, $format, $args ); $this->run_processors( $command_processors, Processor\Before::class, [ $args ] ); $response = $this->run_request( $endpoint, $args, $method ); $result = $response->get_data(); if ( $response->is_error() ) { $this->set_cache( $key, [] ); return []; } $result = $this->run_processors( $command_processors, Processor\After::class, [ $args, $result ] ); $this->set_cache( $key, $result ); return $result; } public function is_internal() { return $this->is_internal; } } v2/base/endpoint/index.php 0000644 00000003172 14720700115 0011445 0 ustar 00 <?php namespace Elementor\Data\V2\Base\Endpoint; use Elementor\Data\V2\Base\Endpoint; use WP_REST_Server; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Index extends Endpoint { public function get_name() { return 'index'; } public function get_format() { return "{$this->controller->get_full_name()}/{id}"; } public function get_public_name() { return ''; } public function get_items( $request ) { return $this->controller->get_items( $request ); } public function get_item( $id, $request ) { return $this->controller->get_item( $request ); } public function create_items( $request ) { return $this->controller->create_items( $request ); } public function create_item( $id, $request ) { return $this->controller->create_item( $request ); } public function update_items( $request ) { return $this->controller->update_items( $request ); } public function update_item( $id, $request ) { return $this->controller->update_item( $request ); } public function delete_items( $request ) { return $this->controller->delete_items( $request ); } public function delete_item( $id, $request ) { return $this->controller->delete_item( $request ); } public function register_items_route( $methods = WP_REST_Server::READABLE, $args = [] ) { parent::register_items_route( $methods, array_merge( $this->controller->get_items_args( $methods ), $args ) ); } public function register_item_route( $methods = WP_REST_Server::READABLE, $args = [], $route = '/' ) { parent::register_item_route( $methods, array_merge( $this->controller->get_item_args( $methods ), $args ), $route ); } } v2/base/endpoint/index/all-children.php 0000644 00000003570 14720700115 0014005 0 ustar 00 <?php namespace Elementor\Data\V2\Base\Endpoint\Index; use Elementor\Data\V2\Base\Endpoint\Index; use Elementor\Data\V2\Manager; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * class AllChildren, is optional endpoint. * Used in cases where the endpoints are static & there no use of dynamic endpoints( alpha/{id} ), eg: * 'settings' - controller * 'settings/products' - endpoint * 'settings/partners' - endpoint * * When 'settings' is requested, it should return results of all endpoints ( except it self ): * 'settings/products * 'settings/partners' * By running 'get_items' of each endpoint. */ class AllChildren extends Index { public function get_format() { return $this->controller->get_name() . '/index'; } /* * Retrieves a result(s) of all controller endpoint(s), items. * * Run overall endpoints of the current controller. * * Example, scenario: * 'settings' - controller * 'settings/products' - endpoint * 'settings/partners' - endpoint * Result: * [ * 'products' => [ * 0 => ... * 1 => ... * ], * 'partners' => [ * 0 => ... * 1 => ... * ], * ] */ public function get_items( $request ) { $response = []; foreach ( $this->controller->get_sub_controllers() as $controller ) { $controller_route = $this->get_controller()->get_base_route() . '/' . $controller->get_name(); $result = Manager::instance()->run_request( $controller_route ); if ( ! $result->is_error() ) { $response[ $controller->get_name() ] = $result->get_data(); } } foreach ( $this->controller->endpoints as $endpoint ) { // Skip self. if ( $endpoint === $this ) { continue; } $result = Manager::instance()->run_request( $endpoint->get_base_route() ); if ( ! $result->is_error() ) { $response[ $endpoint->get_name() ] = $result->get_data(); } } return $response; } } v2/base/endpoint/index/sub-index-endpoint.php 0000644 00000002740 14720700115 0015161 0 ustar 00 <?php namespace Elementor\Data\V2\Base\Endpoint\Index; use Elementor\Data\V2\Base\Endpoint\Index; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * Class SubIndexEndpoint is default `Base\Endpoint\Index` of `SubController`, * it was created to handle base_route and format for child controller, index endpoint. * In case `SubController` were used and the default method of `Controller::register_index_endpoint` ain't overridden. * this class will give support to have such routes, eg: 'alpha/{id}/beta/{sub_id}' without using additional endpoints. */ final class Sub_Index_Endpoint extends Index { /*** * @var \Elementor\Data\V2\Base\Controller */ public $controller; public function get_format() { return $this->controller->get_parent()->get_name() . '/{id}/' . $this->controller->get_name() . '/{sub_id}'; } public function get_base_route() { $parent_controller = $this->controller->get_parent(); $parent_index_endpoint = $parent_controller->index_endpoint; $parent_controller_route = ''; // In case `$parent_index_endpoint` is AllChildren, it cannot support id_arg_name. if ( ! $parent_index_endpoint instanceof AllChildren ) { $parent_controller_route = "(?P<{$parent_index_endpoint->id_arg_name}>[\w]+)"; } return untrailingslashit('/' . implode( '/', array_filter( [ trim( $parent_index_endpoint->get_base_route(), '/' ), $parent_controller_route, $this->controller->get_name(), $this->get_public_name(), ] ) ) ); } } v2/base/endpoint.php 0000644 00000005741 14720700115 0010342 0 ustar 00 <?php namespace Elementor\Data\V2\Base; use Elementor\Data\V2\Manager; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } abstract class Endpoint extends Base_Route { /** * Current parent. * * @var \Elementor\Data\V2\Base\Controller|\Elementor\Data\V2\Base\Endpoint */ protected $parent; /** * Loaded sub endpoint(s). * * @var \Elementor\Data\V2\Base\Endpoint[] */ protected $sub_endpoints = []; /** * Get endpoint name. * * @return string */ abstract public function get_name(); /** * * Get endpoint format. * The formats that generated using this function, will be used only be `Data\Manager::run()`. * * @return string */ abstract public function get_format(); /** * Get controller. * * @return \Elementor\Data\V2\Base\Controller */ public function get_controller() { return $this->controller; } /** * Get current parent. * * @return \Elementor\Data\V2\Base\Controller|\Elementor\Data\V2\Base\Endpoint */ public function get_parent() { return $this->parent; } /** * Get public name. * * @return string */ public function get_public_name() { return $this->get_name(); } /** * Get full command name ( including index ). * * @return string */ public function get_full_command() { $parent = $this->get_parent(); if ( $parent instanceof Controller ) { return $this->controller->get_full_name() . '/' . $this->get_name(); } return $this->get_name_ancestry(); } /** * Get name ancestry format, example: 'alpha/beta/delta'. * * @return string */ public function get_name_ancestry() { $ancestors = $this->get_ancestors(); $ancestors_names = []; foreach ( $ancestors as $ancestor ) { $ancestors_names [] = $ancestor->get_name(); } return implode( '/', $ancestors_names ); } /** * Register sub endpoint. * * @param \Elementor\Data\V2\Base\Endpoint $endpoint * * @return \Elementor\Data\V2\Base\Endpoint */ public function register_sub_endpoint( Endpoint $endpoint ) { $command = $endpoint->get_full_command(); $format = $endpoint->get_format(); $this->sub_endpoints[ $command ] = $endpoint; Manager::instance()->register_endpoint_format( $command, $format ); return $endpoint; } /** * Get ancestors. * * @return \Elementor\Data\V2\Base\Endpoint[] */ private function get_ancestors() { $ancestors = []; $current = $this; do { if ( $current ) { $ancestors [] = $current; } $current = $current->get_parent(); } while ( $current ); return array_reverse( $ancestors ); } /** * Endpoint constructor. * * @param \Elementor\Data\V2\Base\Controller|\Elementor\Data\V2\Base\Endpoint $parent * @param string $route */ public function __construct( $parent, $route = '/' ) { $controller = $parent; $this->parent = $parent; // In case, its behave like sub-endpoint. if ( ! ( $parent instanceof Controller ) ) { $controller = $parent->get_controller(); } parent::__construct( $controller, $route ); } } v2/base/processor.php 0000644 00000001547 14720700115 0010541 0 ustar 00 <?php namespace Elementor\Data\V2\Base; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * Processor is just typically HOOK, who called before or after a command runs. * It exist to simulate frontend ($e.data) like mechanism with commands and hooks, since each * controller or endpoint is reachable via command (get_format). * The `Elementor\Data\V2\Manager::run` is able to run them with the ability to reach the endpoint. */ abstract class Processor { /** * Controller. * * @var \Elementor\Data\V2\Base\Controller */ private $controller; /** * Get processor command. * * @return string */ abstract public function get_command(); /** * Processor constructor. * * @param \Elementor\Data\V2\Base\Controller $controller */ public function __construct( $controller ) { $this->controller = $controller; } } v2/base/base-route.php 0000644 00000024422 14720700115 0010565 0 ustar 00 <?php namespace Elementor\Data\V2\Base; use Elementor\Data\V2\Base\Exceptions\Data_Exception; use Elementor\Data\V2\Base\Exceptions\Error_500; use WP_REST_Server; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * Class purpose is to separate routing logic into one file. */ abstract class Base_Route { const AVAILABLE_METHODS = [ WP_REST_Server::READABLE, WP_REST_Server::CREATABLE, WP_REST_Server::EDITABLE, WP_REST_Server::DELETABLE, WP_REST_Server::ALLMETHODS, ]; /** * Controller of current endpoint. * * @var \Elementor\Data\V2\Base\Controller */ protected $controller; /** * Current route, effect only in case the endpoint behave like sub-endpoint. * * @var string */ protected $route; /** * All register routes. * * @var array */ protected $routes = []; /** * Registered item route. * * @var array|null */ protected $item_route = null; protected $id_arg_name = 'id'; protected $id_arg_type_regex = '[\d]+'; /** * Ensure start-with and end-with slashes. * * '/' => '/' * 'abc' => '/abc/' * '/abc' => '/abc/' * 'abc/' => '/abc/' * '/abc/' => '/abc/' * * @param string $route * * @return string */ private function ensure_slashes( $route ) { if ( '/' !== $route[0] ) { $route = '/' . $route; } return trailingslashit( $route ); } /** * Get base route. * This method should always return the base route starts with '/' and ends without '/'. * * @return string */ public function get_base_route() { $name = $this->get_public_name(); $parent = $this->get_parent(); $parent_base = $parent->get_base_route(); $route = '/'; if ( ! ( $parent instanceof Controller ) ) { $route = $parent->item_route ? $parent->item_route['route'] . '/' : $this->route; } return untrailingslashit( '/' . trim( $parent_base . $route . $name, '/' ) ); } /** * Get permission callback. * * By default get permission callback from the controller. * * @param \WP_REST_Request $request Full data about the request. * * @return boolean */ public function get_permission_callback( $request ) { return $this->controller->get_permission_callback( $request ); } /** * Retrieves a collection of items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function get_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Retrieves one item from the collection. * * @param string $id * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function get_item( $id, $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Creates multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function create_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Creates one item. * * @param string $id id of request item. * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function create_item( $id, $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Updates multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function update_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Updates one item. * * @param string $id id of request item. * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function update_item( $id, $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Delete multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function delete_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Delete one item. * * @param string $id id of request item. * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ protected function delete_item( $id, $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Register the endpoint. * * By default: register get items route. */ protected function register() { $this->register_items_route(); } protected function register_route( $route = '', $methods = WP_REST_Server::READABLE, $args = [] ) { if ( ! in_array( $methods, self::AVAILABLE_METHODS, true ) ) { trigger_error( "Invalid method: '$methods'.", E_USER_ERROR ); // phpcs:ignore } $route = $this->get_base_route() . $route; $this->routes [] = [ 'args' => $args, 'route' => $route, ]; /** * Determine behaviour of `base_callback()` and `get_permission_callback()`: * For `base_callback()` which applying the action. * Whether it's a one item request and should call `get_item_permission_callback()` or it's mutil items request and should call `get_items_permission_callback()`. */ $is_multi = ! empty( $args['is_multi'] ); if ( $is_multi ) { unset( $args['is_multi'] ); } $callback = function ( $request ) use ( $methods, $args, $is_multi ) { return $this->base_callback( $methods, $request, $is_multi ); }; return register_rest_route( $this->controller->get_namespace(), $route, [ [ 'args' => $args, 'methods' => $methods, 'callback' => $callback, 'permission_callback' => function ( $request ) { return $this->get_permission_callback( $request ); }, ], ] ); } /** * Register items route. * * @param string $methods * @param array $args */ public function register_items_route( $methods = WP_REST_Server::READABLE, $args = [] ) { $args['is_multi'] = true; $this->register_route( '', $methods, $args ); } /** * Register item route. * * @param string $route * @param array $args * @param string $methods */ public function register_item_route( $methods = WP_REST_Server::READABLE, $args = [], $route = '/' ) { if ( ! empty( $args['id_arg_name'] ) ) { $this->id_arg_name = $args['id_arg_name']; unset( $args['id_arg_name'] ); } if ( ! empty( $args['id_arg_type_regex'] ) ) { $this->id_arg_type_regex = $args['id_arg_type_regex']; unset( $args['id_arg_type_regex'] ); } $args = array_merge( [ $this->id_arg_name => [ 'description' => 'Unique identifier for the object.', 'type' => 'string', 'required' => true, ], ], $args ); $route .= '(?P<' . $this->id_arg_name . '>' . $this->id_arg_type_regex . ')'; $this->item_route = [ 'args' => $args, 'route' => $route, ]; $this->register_route( $route, $methods, $args ); } /** * Base callback. * All reset requests from the client should pass this function. * * @param string $methods * @param \WP_REST_Request $request * @param bool $is_multi * @param array $args * * @return mixed|\WP_Error|\WP_HTTP_Response|\WP_REST_Response */ public function base_callback( $methods, $request, $is_multi = false, $args = [] ) { if ( $request ) { $json_params = $request->get_json_params(); if ( $json_params ) { $request->set_body_params( $json_params ); } } $args = wp_parse_args( $args, [ 'is_debug' => ( defined( 'WP_DEBUG' ) && WP_DEBUG ), ] ); $result = new \WP_Error( 'invalid_methods', 'route not supported.' ); $request->set_param( 'is_multi', $is_multi ); try { switch ( $methods ) { case WP_REST_Server::READABLE: $result = $is_multi ? $this->get_items( $request ) : $this->get_item( $request->get_param( 'id' ), $request ); break; case WP_REST_Server::CREATABLE: $result = $is_multi ? $this->create_items( $request ) : $this->create_item( $request->get_param( 'id' ), $request ); break; case WP_REST_Server::EDITABLE: $result = $is_multi ? $this->update_items( $request ) : $this->update_item( $request->get_param( 'id' ), $request ); break; case WP_REST_Server::DELETABLE: $result = $is_multi ? $this->delete_items( $request ) : $this->delete_item( $request->get_param( 'id' ), $request ); break; } } catch ( Data_Exception $e ) { $result = $e->to_wp_error(); } catch ( \Exception $e ) { if ( empty( $args['is_debug'] ) ) { $result = ( new Error_500() )->to_wp_error(); } else { // For frontend. $exception_mapping = [ 'trace' => $e->getTrace(), 'file' => $e->getFile(), 'line' => $e->getLine(), ]; $e->debug = $exception_mapping; $result = ( new Data_Exception( $e->getMessage(), $e->getCode(), $e ) )->to_wp_error(); } } return rest_ensure_response( $result ); } /** * Constructor. * * run `$this->register()`. * * @param \Elementor\Data\V2\Base\Controller $controller * @param string $route */ protected function __construct( Controller $controller, $route ) { $this->controller = $controller; $this->route = $this->ensure_slashes( $route ); $this->register(); } } v2/base/processor/after.php 0000644 00000001041 14720700115 0011627 0 ustar 00 <?php namespace Elementor\Data\V2\Base\Processor; use Elementor\Data\V2\Base\Processor; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } abstract class After extends Processor { /** * Get conditions for running processor. * * @param array $args * @param mixed $result * * @return bool */ public function get_conditions( $args, $result ) { return true; } /** * Apply processor. * * @param $args * @param $result * * @return mixed */ abstract public function apply( $args, $result ); } v2/base/processor/before.php 0000644 00000000746 14720700115 0012003 0 ustar 00 <?php namespace Elementor\Data\V2\Base\Processor; use Elementor\Data\V2\Base\Processor; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } abstract class Before extends Processor { /** * Get conditions for running processor. * @param array $args * * @return bool */ public function get_conditions( $args ) { return true; } /** * Apply processor. * * @param array $args * * @return mixed */ abstract public function apply( $args ); } v2/base/controller.php 0000644 00000027211 14720700115 0010701 0 ustar 00 <?php namespace Elementor\Data\V2\Base; use Elementor\Data\V2\Base\Exceptions\WP_Error_Exception; use Elementor\Data\V2\Manager; use WP_REST_Controller; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * TODO: Utilize 'WP_REST_Controller' as much as possible. */ abstract class Controller extends WP_REST_Controller { /** * Loaded endpoint(s). * * @var \Elementor\Data\V2\Base\Endpoint[] */ public $endpoints = []; /** * Index endpoint. * * @var \Elementor\Data\V2\Base\Endpoint\Index */ public $index_endpoint = null; /** * Loaded processor(s). * * @var \Elementor\Data\V2\Base\Processor[][] */ public $processors = []; /** * @var \Elementor\Data\V2\Base\Controller|null */ private $parent = null; /** * @var \Elementor\Data\V2\Base\Controller[] */ private $sub_controllers = []; public static function get_default_namespace() { return Manager::ROOT_NAMESPACE; } public static function get_default_version() { return Manager::VERSION; } /** * Get controller name. * * @return string */ abstract public function get_name(); /** * Register endpoints. */ public function register_endpoints() { } public function register_routes() { _doing_it_wrong( 'Elementor\Data\V2\Controller::register_routes', sprintf( "Method '%s' deprecated. use `register_endpoints()`.", __METHOD__ ), '3.5.0' ); } /** * Get parent controller name. * * @note: If `get_parent_name()` provided, controller will work as sub-controller. * * @returns null|string */ public function get_parent_name() { return null; } /** * Get full controller name. * * The method exist to handle situations when parent exist, to include the parent name. * * @return string */ public function get_full_name() { if ( ! $this->parent ) { return $this->get_name(); } return $this->parent->get_name() . '/' . $this->get_name(); } /** * Get controller namespace. * * @return string */ public function get_namespace() { return $this->namespace; } /** * Get controller reset base. * * @return string */ public function get_base_route() { if ( ! $this->parent ) { return $this->rest_base; } return $this->parent->get_base_route() . '/' . $this->get_name(); } /** * Get controller route. * * @return string */ public function get_controller_route() { return $this->get_namespace() . '/' . $this->get_base_route(); } /** * Retrieves rest route(s) index for current controller. * * @return \WP_REST_Response|\WP_Error */ public function get_controller_index() { $server = rest_get_server(); $routes = $server->get_routes(); $endpoints = array_intersect_key( $server->get_routes(), $routes ); $controller_route = $this->get_controller_route(); array_walk( $endpoints, function ( &$item, $endpoint ) use ( &$endpoints, $controller_route ) { if ( ! strstr( $endpoint, $controller_route ) ) { unset( $endpoints[ $endpoint ] ); } } ); $data = [ 'namespace' => $this->get_namespace(), 'controller' => $controller_route, 'routes' => $server->get_data_for_routes( $endpoints ), ]; $response = rest_ensure_response( $data ); // Link to the root index. $response->add_link( 'up', rest_url( '/' ) ); return $response; } /** * Get items args of index endpoint. * * Is method is used when `get_collection_params()` is not enough, and need of knowing the methods is required. * * @param string $methods * * @return array */ public function get_items_args( $methods ) { if ( \WP_REST_Server::READABLE === $methods ) { return $this->get_collection_params(); } return []; } /** * Get item args of index endpoint. * * @param string $methods * * @return array */ public function get_item_args( $methods ) { return []; } /** * Get permission callback. * * Default controller permission callback. * By default endpoint will inherit the permission callback from the controller. * * @param \WP_REST_Request $request * * @return bool */ public function get_permission_callback( $request ) { $is_multi = (bool) $request->get_param( 'is_multi' ); $result = false; // The function is public since endpoint need to access it. // Utilize 'WP_REST_Controller' get_permission_check methods. switch ( $request->get_method() ) { case 'GET': $result = $is_multi ? $this->get_items_permissions_check( $request ) : $this->get_item_permissions_check( $request ); break; case 'POST': $result = $is_multi ? $this->create_items_permissions_check( $request ) : $this->create_item_permissions_check( $request ); break; case 'UPDATE': case 'PUT': case 'PATCH': $result = $is_multi ? $this->update_items_permissions_check( $request ) : $this->update_item_permissions_check( $request ); break; case 'DELETE': $result = $is_multi ? $this->delete_items_permissions_check( $request ) : $this->delete_item_permissions_check( $request ); break; } if ( $result instanceof \WP_Error ) { throw new WP_Error_Exception( $result ); } return $result; } /** * Checks if a given request has access to create items. ** * * @param \WP_REST_Request $request Full details about the request. * * @return true|\WP_Error True if the request has access to create items, WP_Error object otherwise. */ public function create_items_permissions_check( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Checks if a given request has access to update items. * * @param \WP_REST_Request $request Full details about the request. * * @return true|\WP_Error True if the request has access to update the item, WP_Error object otherwise. */ public function update_items_permissions_check( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Checks if a given request has access to delete items. * * @param \WP_REST_Request $request Full details about the request. * * @return true|\WP_Error True if the request has access to delete the item, WP_Error object otherwise. */ public function delete_items_permissions_check( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } public function get_items( $request ) { return $this->get_controller_index(); } /** * Creates multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function create_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Updates multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function update_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Delete multiple items. * * @param \WP_REST_Request $request Full data about the request. * * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. */ public function delete_items( $request ) { return new \WP_Error( 'invalid-method', sprintf( "Method '%s' not implemented. Must be overridden in subclass.", __METHOD__ ), [ 'status' => 405 ] ); } /** * Get the parent controller. * * @return \Elementor\Data\V2\Base\Controller|null */ public function get_parent() { return $this->parent; } /** * Get sub controller(s). * * @return \Elementor\Data\V2\Base\Controller[] */ public function get_sub_controllers() { return $this->sub_controllers; } /** * Get processors. * * @param string $command * * @return \Elementor\Data\V2\Base\Processor[] */ public function get_processors( $command ) { $result = []; if ( isset( $this->processors[ $command ] ) ) { $result = $this->processors[ $command ]; } return $result; } /** * Register processors. */ public function register_processors() { } /** * Register index endpoint. */ protected function register_index_endpoint() { if ( ! $this->parent ) { $this->register_endpoint( new Endpoint\Index( $this ) ); return; } $this->register_endpoint( new Endpoint\Index\Sub_Index_Endpoint( $this ) ); } /** * Register endpoint. * * @param \Elementor\Data\V2\Base\Endpoint $endpoint * * @return \Elementor\Data\V2\Base\Endpoint */ protected function register_endpoint( Endpoint $endpoint ) { $command = $endpoint->get_full_command(); if ( $endpoint instanceof Endpoint\Index ) { $this->index_endpoint = $endpoint; } else { $this->endpoints[ $command ] = $endpoint; } $format = $endpoint->get_format(); // `$e.data.registerFormat()`. Manager::instance()->register_endpoint_format( $command, $format ); return $endpoint; } /** * Register a processor. * * That will be later attached to the endpoint class. * * @param Processor $processor * * @return \Elementor\Data\V2\Base\Processor $processor_instance */ protected function register_processor( Processor $processor ) { $command = $processor->get_command(); if ( ! isset( $this->processors[ $command ] ) ) { $this->processors[ $command ] = []; } $this->processors[ $command ] [] = $processor; return $processor; } /** * Register. * * Endpoints & processors. */ protected function register() { $this->register_index_endpoint(); $this->register_endpoints(); // Aka hooks. $this->register_processors(); } /** * Get collection params by 'additionalProperties' context. * * @param string $context * * @return array */ protected function get_collection_params_by_additional_props_context( $context ) { $result = []; $collection_params = $this->get_collection_params(); foreach ( $collection_params as $collection_param_key => $collection_param ) { if ( isset( $collection_param['additionalProperties']['context'] ) && $context === $collection_param['additionalProperties']['context'] ) { $result[ $collection_param_key ] = $collection_param; } } return $result; } /** * When `$this->get_parent_name` is extended, the controller will have a parent, and will know to behave like a sub-controller. * * @param string $parent_name */ private function act_as_sub_controller( $parent_name ) { $this->parent = Manager::instance()->get_controller( $parent_name ); if ( ! $this->parent ) { trigger_error( "Cannot find parent controller: '$parent_name'", E_USER_ERROR ); // phpcs:ignore } $this->parent->sub_controllers [] = $this; } /** * Controller constructor. * * Register endpoints on 'rest_api_init'. */ public function __construct() { $this->namespace = static::get_default_namespace() . '/v' . static::get_default_version(); $this->rest_base = $this->get_name(); add_action( 'rest_api_init', function () { $this->register(); // Because 'register' is protected. } ); /** * Since all actions were removed for custom internal REST server. * Re-add the actions. */ add_action( 'elementor_rest_api_before_init', function () { add_action( 'rest_api_init', function () { $this->register(); } ); } ); $parent_name = $this->get_parent_name(); if ( $parent_name ) { $this->act_as_sub_controller( $parent_name ); } } } v2/base/exceptions/error-404.php 0000644 00000000533 14720700115 0012333 0 ustar 00 <?php namespace Elementor\Data\V2\Base\Exceptions; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Error_404 extends Data_Exception { protected function get_http_error_code() { return 404; } public function get_code() { return 'not-found'; } public function get_message() { return '404 not found'; } } v2/base/exceptions/wp-error-exception.php 0000644 00000000561 14720700115 0014447 0 ustar 00 <?php namespace Elementor\Data\V2\Base\Exceptions; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class WP_Error_Exception extends Data_Exception { public function __construct( \WP_Error $wp_error ) { parent::__construct( $wp_error->get_error_message(), $wp_error->get_error_code(), [ 'status' => $wp_error->get_error_code(), ] ); } } v2/base/exceptions/data-exception.php 0000644 00000002155 14720700115 0013604 0 ustar 00 <?php namespace Elementor\Data\V2\Base\Exceptions; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Data_Exception extends \Exception { protected $custom_data = [ 'code' => '', 'data' => [], ]; public function get_code() { return 'reset-http-error'; } public function get_message() { return '501 Not Implemented'; } public function get_data() { return [ 'status' => $this->get_http_error_code(), // 'status' is used by WP to pass the http error code. ]; } public function to_wp_error() { return new \WP_Error( $this->custom_data['code'], $this->message, $this->custom_data['data'] ); } protected function get_http_error_code() { return 501; // 501 Not Implemented } protected function apply() {} public function __construct( $message = '', $code = '', $data = [] ) { $this->message = empty( $message ) ? $this->get_message() : $message; $this->custom_data['code'] = empty( $code ) ? $this->get_code() : $code; $this->custom_data['data'] = empty( $data ) ? $this->get_data() : $data; parent::__construct( $this->message, 0, null ); $this->apply(); } } v2/base/exceptions/error-500.php 0000644 00000000556 14720700115 0012335 0 ustar 00 <?php namespace Elementor\Data\V2\Base\Exceptions; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } class Error_500 extends Data_Exception { protected function get_http_error_code() { return 500; } public function get_code() { return 'internal-server-error'; } public function get_message() { return 'Something went wrong'; } } v2/manager.php 0000644 00000021640 14720700115 0007216 0 ustar 00 <?php namespace Elementor\Data\V2; use Elementor\Core\Base\Module as BaseModule; use Elementor\Data\V2\Base\Processor; use Elementor\Data\V2\Base\Controller; if ( ! defined( 'ABSPATH' ) ) { exit; // Exit if accessed directly } /** * @method static \Elementor\Data\V2\Manager instance() */ class Manager extends BaseModule { const ROOT_NAMESPACE = 'elementor'; const VERSION = '1'; /** * @var \WP_REST_Server */ private $server; /** * @var boolean */ private $is_internal = false; /** * @var array */ private $cache = []; /** * Loaded controllers. * * @var \Elementor\Data\V2\Base\Controller[] */ public $controllers = []; /** * Loaded command(s) format. * * @var string[] */ public $command_formats = []; public function get_name() { return 'data-manager-v2'; } /** * @return \Elementor\Data\V2\Base\Controller[] */ public function get_controllers() { return $this->controllers; } /** * @param string $name * * @return \Elementor\Data\V2\Base\Controller|false */ public function get_controller( $name ) { if ( isset( $this->controllers[ $name ] ) ) { return $this->controllers[ $name ]; } return false; } private function get_cache( $key ) { return self::get_items( $this->cache, $key ); } private function set_cache( $key, $value ) { $this->cache[ $key ] = $value; } /** * Register controller. * * @param \Elementor\Data\V2\Base\Controller $controller_instance * * @return \Elementor\Data\V2\Base\Controller */ public function register_controller( Controller $controller_instance ) { $this->controllers[ $controller_instance->get_name() ] = $controller_instance; return $controller_instance; } /** * Register endpoint format. * * @param string $command * @param string $format * */ public function register_endpoint_format( $command, $format ) { $this->command_formats[ $command ] = untrailingslashit( $format ); } /** * Find controller instance. * * By given command name. * * @param string $command * * @return false|\Elementor\Data\V2\Base\Controller */ public function find_controller_instance( $command ) { $command_parts = explode( '/', $command ); $assumed_command_parts = []; foreach ( $command_parts as $command_part ) { $assumed_command_parts [] = $command_part; foreach ( $this->controllers as $controller_name => $controller ) { $assumed_command = implode( '/', $assumed_command_parts ); if ( $assumed_command === $controller_name ) { return $controller; } } } return false; } /** * Command extract args. * * @param string $command * @param array $args * * @return \stdClass */ public function command_extract_args( $command, $args = [] ) { $result = new \stdClass(); $result->command = $command; $result->args = $args; if ( false !== strpos( $command, '?' ) ) { $command_parts = explode( '?', $command ); $pure_command = $command_parts[0]; $query_string = $command_parts[1]; parse_str( $query_string, $temp ); $result->command = untrailingslashit( $pure_command ); $result->args = array_merge( $args, $temp ); } return $result; } /** * Command to endpoint. * * Format is required otherwise $command will returned. * * @param string $command * @param string $format * @param array $args * * @return string endpoint */ public function command_to_endpoint( $command, $format, $args ) { $endpoint = $command; if ( $format ) { $formatted = $format; array_walk( $args, function ( $val, $key ) use ( &$formatted ) { $formatted = str_replace( '{' . $key . '}', $val, $formatted ); } ); // Remove remaining format if not requested via `$args`. if ( strstr( $formatted, '/{' ) ) { /** * Example: * $command = 'example/documents'; * $format = 'example/documents/{document_id}/elements/{element_id}'; * $formatted = 'example/documents/1618/elements/{element_id}'; * Result: * $formatted = 'example/documents/1618/elements'; */ $formatted = substr( $formatted, 0, strpos( $formatted, '/{' ) ); } $endpoint = $formatted; } return $endpoint; } /** * Run server. * * Init WordPress reset api. * * @return \WP_REST_Server */ public function run_server() { /** * If run_server() called means, that rest api is simulated from the backend. */ $this->is_internal = true; if ( ! $this->server ) { // Remove all 'rest_api_init' actions. remove_all_actions( 'rest_api_init' ); // Call custom reset api loader. do_action( 'elementor_rest_api_before_init' ); $this->server = rest_get_server(); // Init API. } return $this->server; } /** * Kill server. * * Free server and controllers. */ public function kill_server() { global $wp_rest_server; $this->controllers = []; $this->command_formats = []; $this->server = false; $this->is_internal = false; $this->cache = []; $wp_rest_server = false; } /** * Run processor. * * @param \Elementor\Data\V2\Base\Processor $processor * @param array $data * * @return mixed */ public function run_processor( $processor, $data ) { if ( call_user_func_array( [ $processor, 'get_conditions' ], $data ) ) { return call_user_func_array( [ $processor, 'apply' ], $data ); } return null; } /** * Run processors. * * Filter them by class. * * @param \Elementor\Data\V2\Base\Processor[] $processors * @param string $filter_by_class * @param array $data * * @return false|array */ public function run_processors( $processors, $filter_by_class, $data ) { foreach ( $processors as $processor ) { if ( $processor instanceof $filter_by_class ) { if ( Processor\Before::class === $filter_by_class ) { $this->run_processor( $processor, $data ); } elseif ( Processor\After::class === $filter_by_class ) { $result = $this->run_processor( $processor, $data ); if ( $result ) { $data[1] = $result; } } else { trigger_error( "Invalid processor filter: '\${ $filter_by_class }'" ); // phpcs:ignore break; } } } return isset( $data[1] ) ? $data[1] : false; } /** * Run request. * * Simulate rest API from within the backend. * Use args as query. * * @param string $endpoint * @param array $args * @param string $method * @param string $namespace (optional) * @param string $version (optional) * * @return \WP_REST_Response */ public function run_request( $endpoint, $args = [], $method = \WP_REST_Server::READABLE, $namespace = self::ROOT_NAMESPACE, $version = self::VERSION ) { $this->run_server(); $endpoint = '/' . $namespace . '/v' . $version . '/' . trim( $endpoint, '/' ); // Run reset api. $request = new \WP_REST_Request( $method, $endpoint ); if ( 'GET' === $method ) { $request->set_query_params( $args ); } else { $request->set_body_params( $args ); } return rest_do_request( $request ); } /** * Run endpoint. * * Wrapper for `$this->run_request` return `$response->getData()` instead of `$response`. * * @param string $endpoint * @param array $args * @param string $method * * @return array */ public function run_endpoint( $endpoint, $args = [], $method = 'GET' ) { // The method become public since it used in `Elementor\Data\V2\Base\Endpoint\Index\AllChildren`. $response = $this->run_request( $endpoint, $args, $method ); return $response->get_data(); } /** * Run ( simulated reset api ). * * Do: * Init reset server. * Run before processors. * Run command as reset api endpoint from internal. * Run after processors. * * @param string $command * @param array $args * @param string $method * * @return array|false processed result */ public function run( $command, $args = [], $method = 'GET' ) { $key = crc32( $command . '-' . wp_json_encode( $args ) . '-' . $method ); $cache = $this->get_cache( $key ); if ( $cache ) { return $cache; } $this->run_server(); $controller_instance = $this->find_controller_instance( $command ); if ( ! $controller_instance ) { $this->set_cache( $key, [] ); return []; } $extracted_command = $this->command_extract_args( $command, $args ); $command = $extracted_command->command; $args = $extracted_command->args; $format = isset( $this->command_formats[ $command ] ) ? $this->command_formats[ $command ] : false; $command_processors = $controller_instance->get_processors( $command ); $endpoint = $this->command_to_endpoint( $command, $format, $args ); $this->run_processors( $command_processors, Processor\Before::class, [ $args ] ); $response = $this->run_request( $endpoint, $args, $method ); $result = $response->get_data(); if ( $response->is_error() ) { $this->set_cache( $key, [] ); return []; } $result = $this->run_processors( $command_processors, Processor\After::class, [ $args, $result ] ); $this->set_cache( $key, $result ); return $result; } public function is_internal() { return $this->is_internal; } }
| ver. 1.4 |
Github
|
.
| PHP 8.0.30 | Génération de la page: 0 |
proxy
|
phpinfo
|
Réglages