PluginProbe
Elementor Website Builder – more than just a page builder / 4.3.0-beta3
Elementor Website Builder – more than just a page builder v4.3.0-beta3
4.3.0-beta3 4.3.0-beta2 4.3.0-beta1 4.2.4 4.2.3 4.2.2 4.2.1 4.2.0 4.1.5 4.2.0-beta2 4.2.0-dev2 4.2.0-beta1 4.1.4 4.1.3 4.1.2 4.1.1 4.1.0 4.1.0-beta3 4.1.0-dev3 4.0.9 4.1.0-beta2 4.1.0-dev2 4.0.8 4.1.0-beta1 4.1.0-dev1 All 452 releases
elementor / modules / mcp / rest-api / mcp-proxy-rest-api.php

mcp-proxy-rest-api.php in Elementor Website Builder – more than just a page builder 4.3.0-beta3, at modules/mcp/rest-api/mcp-proxy-rest-api.php

164 lines 4.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Elementor\Modules\Mcp\RestApi;
4
5 use Elementor\Core\Utils\Api\Error_Builder;
6 use Elementor\Core\Utils\Api\Response_Builder;
7 use Elementor\Modules\Mcp\Module as Mcp_Module;
8 use Elementor\Modules\Mcp\Registry\Ability_Registry;
9 use Elementor\Plugin;
10
11 if ( ! defined( 'ABSPATH' ) ) {
12 exit;
13 }
14
15 class Mcp_Proxy_REST_API {
16 const API_NAMESPACE = 'elementor/v1';
17 const API_BASE = 'mcp-proxy';
18
19 private ?Ability_Registry $registry;
20
21 public function __construct( ?Ability_Registry $registry = null ) {
22 $this->registry = $registry;
23 }
24
25 public function register_hooks() {
26 add_action( 'rest_api_init', fn() => $this->register_routes() );
27 }
28
29 private function register_routes() {
30 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE, [
31 [
32 'methods' => 'POST',
33 'callback' => fn( $request ) => $this->route_wrapper( fn() => $this->handle_tool( $request ) ),
34 'permission_callback' => fn() => current_user_can( 'edit_posts' ),
35 'args' => [
36 'tool' => [
37 'type' => 'string',
38 'required' => true,
39 ],
40 'input' => [
41 'type' => 'object',
42 'required' => true,
43 ],
44 ],
45 ],
46 [
47 'methods' => 'GET',
48 'callback' => fn( $request ) => $this->route_wrapper( fn() => $this->handle_resource( $request ) ),
49 'permission_callback' => fn() => current_user_can( 'edit_posts' ),
50 'args' => [
51 'uri' => [
52 'type' => 'string',
53 'required' => true,
54 ],
55 ],
56 ],
57 ] );
58 }
59
60 private function handle_tool( \WP_REST_Request $request ) {
61 $tool = $request->get_param( 'tool' );
62 $input = $request->get_param( 'input' );
63
64 $ability = $this->resolve_registry()->find_by_proxy_slug( (string) $tool );
65
66 if ( null === $ability ) {
67 return Error_Builder::make( 'unknown_tool' )
68 ->set_status( 404 )
69 // translators: By tool name
70 ->set_message( sprintf( __( 'Unknown tool: %s', 'elementor' ), $tool ) )
71 ->build();
72 }
73
74 if ( ! $ability->check_permission() ) {
75 return $this->build_response( $this->forbidden_error() );
76 }
77
78 $result = $ability->execute_guarded( is_array( $input ) ? $input : [] );
79
80 return $this->build_response( $result );
81 }
82
83 private function handle_resource( \WP_REST_Request $request ) {
84 $uri = $request->get_param( 'uri' );
85
86 $ability = $this->resolve_registry()->find_resource_by_uri( (string) $uri );
87
88 if ( null === $ability ) {
89 return Error_Builder::make( 'unknown_resource' )
90 ->set_status( 404 )
91 // translators: By resource URI
92 ->set_message( sprintf( __( 'Unknown resource: %s', 'elementor' ), $uri ) )
93 ->build();
94 }
95
96 if ( ! $ability->check_permission() ) {
97 return $this->build_response( $this->forbidden_error() );
98 }
99
100 $result = $ability->execute();
101
102 return $this->build_response( $result );
103 }
104
105 private function resolve_registry(): Ability_Registry {
106 if ( $this->registry instanceof Ability_Registry ) {
107 return $this->registry;
108 }
109
110 $module = Plugin::$instance->modules_manager->get_modules( 'mcp' );
111
112 $this->registry = $module instanceof Mcp_Module
113 ? $module->registry()
114 : Mcp_Module::build_core_registry();
115
116 return $this->registry;
117 }
118
119 private function forbidden_error(): \WP_Error {
120 return new \WP_Error(
121 'rest_forbidden',
122 __( 'Sorry, you are not allowed to perform this action.', 'elementor' ),
123 [ 'status' => \WP_Http::FORBIDDEN ]
124 );
125 }
126
127 private function build_response( $result ) {
128 if ( is_wp_error( $result ) ) {
129 $data = $result->get_error_data();
130 $status = is_array( $data ) && isset( $data['status'] ) ? $data['status'] : 400;
131
132 return Error_Builder::make( $result->get_error_code() )
133 ->set_status( $status )
134 ->set_message( $result->get_error_message() )
135 ->build();
136 }
137
138 $http_status = $this->resolve_http_status( $result );
139
140 return Response_Builder::make( $result )->set_status( $http_status )->build();
141 }
142
143 private function resolve_http_status( $result ): int {
144 $status = is_array( $result ) ? ( $result['status'] ?? 'ok' ) : 'ok';
145
146 $status_map = [
147 'error' => 422,
148 'partial_error' => 207,
149 ];
150
151 return $status_map[ $status ] ?? 200;
152 }
153
154 private function route_wrapper( callable $cb ) {
155 try {
156 return $cb();
157 } catch ( \Exception $e ) {
158 return Error_Builder::make( 'unexpected_error' )
159 ->set_message( __( 'Something went wrong', 'elementor' ) )
160 ->build();
161 }
162 }
163 }
164