endpoint.php (9114B)
1 <?php 2 3 namespace Elementor\Data\Base; 4 5 use Elementor\Data\Manager; 6 use WP_REST_Server; 7 8 abstract class Endpoint { 9 10 const AVAILABLE_METHODS = [ 11 WP_REST_Server::READABLE, 12 WP_REST_Server::CREATABLE, 13 WP_REST_Server::EDITABLE, 14 WP_REST_Server::DELETABLE, 15 WP_REST_Server::ALLMETHODS, 16 ]; 17 18 /** 19 * Controller of current endpoint. 20 * 21 * @var \Elementor\Data\Base\Controller 22 */ 23 protected $controller; 24 25 /** 26 * Loaded sub endpoint(s). 27 * 28 * @var \Elementor\Data\Base\SubEndpoint[] 29 */ 30 private $sub_endpoints = []; 31 32 /** 33 * Get format suffix. 34 * 35 * Examples: 36 * '{one_parameter_name}'. 37 * '{one_parameter_name}/{two_parameter_name}/'. 38 * '{one_parameter_name}/whatever/anything/{two_parameter_name}/' and so on for each endpoint or sub-endpoint. 39 * 40 * @return string current location will later be added automatically. 41 */ 42 public static function get_format() { 43 return ''; 44 } 45 46 /** 47 * Endpoint constructor. 48 * 49 * run `$this->>register()`. 50 * 51 * @param \Elementor\Data\Base\Controller $controller 52 * 53 * @throws \Exception 54 */ 55 public function __construct( $controller ) { 56 if ( ! ( $controller instanceof Controller ) ) { 57 throw new \Exception( 'Invalid controller' ); 58 } 59 60 $this->controller = $controller; 61 $this->register(); 62 } 63 64 /** 65 * Get endpoint name. 66 * 67 * @return string 68 */ 69 abstract public function get_name(); 70 71 /** 72 * Get base route. 73 * 74 * Removing 'index' from endpoint. 75 * 76 * @return string 77 */ 78 public function get_base_route() { 79 $endpoint_name = $this->get_name(); 80 81 // TODO: Allow this only for internal routes. 82 // TODO: Make difference between internal and external endpoints. 83 if ( 'index' === $endpoint_name ) { 84 $endpoint_name = ''; 85 } 86 87 return '/' . $this->controller->get_rest_base() . '/' . $endpoint_name; 88 } 89 90 /** 91 * Register the endpoint. 92 * 93 * By default: register get items route. 94 * 95 * @throws \Exception 96 */ 97 protected function register() { 98 $this->register_items_route(); 99 } 100 101 /** 102 * Register sub endpoint. 103 * 104 * @param string $route 105 * @param string $endpoint_class 106 * 107 * @return \Elementor\Data\Base\SubEndpoint 108 * @throws \Exception 109 */ 110 protected function register_sub_endpoint( $route, $endpoint_class ) { 111 $endpoint_instance = new $endpoint_class( $route, $this ); 112 113 if ( ! ( $endpoint_instance instanceof SubEndpoint ) ) { 114 throw new \Exception( 'Invalid endpoint instance.' ); 115 } 116 117 $endpoint_route = $route . '/' . $endpoint_instance->get_name(); 118 119 $this->sub_endpoints[ $endpoint_route ] = $endpoint_instance; 120 121 $component_name = $endpoint_instance->controller->get_rest_base(); 122 $parent_instance = $endpoint_instance->get_parent(); 123 $parent_name = $endpoint_instance->get_name(); 124 $parent_format_suffix = $parent_instance::get_format(); 125 $current_format_suffix = $endpoint_instance::get_format(); 126 127 $command = $component_name . '/' . $parent_name; 128 $format = $component_name . '/' . $parent_format_suffix . '/' . $parent_name . '/' . $current_format_suffix; 129 130 Manager::instance()->register_endpoint_format( $command, $format ); 131 132 return $endpoint_instance; 133 } 134 135 /** 136 * Base callback. 137 * 138 * All reset requests from the client should pass this function. 139 * 140 * @param string $methods 141 * @param \WP_REST_Request $request 142 * @param bool $is_multi 143 * 144 * @return mixed|\WP_Error|\WP_HTTP_Response|\WP_REST_Response 145 * @throws \Exception 146 */ 147 public function base_callback( $methods, $request, $is_multi = false ) { 148 // TODO: Find better solution. 149 $json_params = $request->get_json_params(); 150 151 if ( $json_params ) { 152 $request->set_body_params( $json_params ); 153 } 154 155 // TODO: Handle permission callback. 156 switch ( $methods ) { 157 case WP_REST_Server::READABLE: 158 $result = $is_multi ? $this->get_items( $request ) : $this->get_item( $request->get_param( 'id' ), $request ); 159 break; 160 161 case WP_REST_Server::CREATABLE: 162 $result = $is_multi ? $this->create_items( $request ) : $this->create_item( $request->get_param( 'id' ), $request ); 163 break; 164 165 case WP_REST_Server::EDITABLE: 166 $result = $is_multi ? $this->update_items( $request ) : $this->update_item( $request->get_param( 'id' ), $request ); 167 break; 168 169 case WP_REST_Server::DELETABLE: 170 $result = $is_multi ? $this->delete_items( $request ) : $this->delete_item( $request->get_param( 'id' ), $request ); 171 break; 172 173 default: 174 throw new \Exception( 'Invalid method.' ); 175 } 176 177 return rest_ensure_response( $result ); 178 } 179 180 /** 181 * Retrieves a collection of items. 182 * 183 * @param \WP_REST_Request $request Full data about the request. 184 * 185 * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. 186 */ 187 public function get_items( $request ) { 188 return $this->controller->get_items( $request ); 189 } 190 191 /** 192 * Retrieves one item from the collection. 193 * 194 * @param string $id 195 * @param \WP_REST_Request $request Full data about the request. 196 * 197 * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. 198 */ 199 public function get_item( $id, $request ) { 200 return $this->controller->get_item( $request ); 201 } 202 203 /** 204 * Get permission callback. 205 * 206 * By default get permission callback from the controller. 207 * 208 * @param \WP_REST_Request $request Full data about the request. 209 * 210 * @return boolean 211 */ 212 public function get_permission_callback( $request ) { 213 return $this->controller->get_permission_callback( $request ); 214 } 215 216 /** 217 * Creates one item. 218 * 219 * @param string $id id of request item. 220 * @param \WP_REST_Request $request Full data about the request. 221 * 222 * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. 223 */ 224 public function create_item( $id, $request ) { 225 return $this->controller->create_item( $request ); 226 } 227 228 /** 229 * Creates multiple items. 230 * 231 * @param \WP_REST_Request $request Full data about the request. 232 * 233 * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. 234 */ 235 public function create_items( $request ) { 236 return $this->controller->create_items( $request ); 237 } 238 239 /** 240 * Updates one item. 241 * 242 * @param string $id id of request item. 243 * @param \WP_REST_Request $request Full data about the request. 244 * 245 * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. 246 */ 247 public function update_item( $id, $request ) { 248 return $this->controller->update_item( $request ); 249 } 250 251 /** 252 * Updates multiple items. 253 * 254 * @param \WP_REST_Request $request Full data about the request. 255 * 256 * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. 257 */ 258 public function update_items( $request ) { 259 return $this->controller->update_items( $request ); 260 } 261 262 /** 263 * Delete one item. 264 * 265 * @param string $id id of request item. 266 * @param \WP_REST_Request $request Full data about the request. 267 * 268 * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. 269 */ 270 public function delete_item( $id, $request ) { 271 return $this->controller->delete_item( $request ); 272 } 273 274 /** 275 * Delete multiple items. 276 * 277 * @param \WP_REST_Request $request Full data about the request. 278 * 279 * @return \WP_Error|\WP_REST_Response Response object on success, or WP_Error object on failure. 280 */ 281 public function delete_items( $request ) { 282 return $this->controller->delete_items( $request ); 283 } 284 285 /** 286 * Register item route. 287 * 288 * @param array $args 289 * @param string $route 290 * @param string $methods 291 * 292 * @throws \Exception 293 */ 294 public function register_item_route( $methods = WP_REST_Server::READABLE, $args = [], $route = '/' ) { 295 $args = array_merge( [ 296 'id' => [ 297 'description' => 'Unique identifier for the object.', 298 'type' => 'string', 299 ], 300 ], $args ); 301 302 if ( isset( $args['id'] ) && $args['id'] ) { 303 $route .= '(?P<id>[\w]+)/'; 304 } 305 306 $this->register_route( $route, $methods, function ( $request ) use ( $methods ) { 307 return $this->base_callback( $methods, $request ); 308 }, $args ); 309 } 310 311 /** 312 * Register items route. 313 * 314 * @param string $methods 315 * 316 * @throws \Exception 317 */ 318 public function register_items_route( $methods = WP_REST_Server::READABLE ) { 319 $this->register_route( '', $methods, function ( $request ) use ( $methods ) { 320 return $this->base_callback( $methods, $request, true ); 321 } ); 322 } 323 324 /** 325 * Register route. 326 * 327 * @param string $route 328 * @param string $methods 329 * @param null $callback 330 * @param array $args 331 * 332 * @return bool 333 * @throws \Exception 334 */ 335 public function register_route( $route = '', $methods = WP_REST_Server::READABLE, $callback = null, $args = [] ) { 336 if ( ! in_array( $methods, self::AVAILABLE_METHODS, true ) ) { 337 throw new \Exception( 'Invalid method.' ); 338 } 339 340 $route = $this->get_base_route() . $route; 341 342 return register_rest_route( $this->controller->get_namespace(), $route, [ 343 [ 344 'args' => $args, 345 'methods' => $methods, 346 'callback' => $callback, 347 'permission_callback' => function ( $request ) { 348 return $this->get_permission_callback( $request ); 349 }, 350 ], 351 ] ); 352 } 353 }