PluginProbe
Elementor Website Builder – more than just a page builder / 3.32.5
Elementor Website Builder – more than just a page builder v3.32.5
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 4.0.7 All 451 releases
elementor / modules / components / components-rest-api.php

components-rest-api.php in Elementor Website Builder – more than just a page builder 3.32.5, at modules/components/components-rest-api.php

156 lines 4.5 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\Components;
4
5 use Elementor\Core\Utils\Api\Error_Builder;
6 use Elementor\Core\Utils\Api\Response_Builder;
7
8 if ( ! defined( 'ABSPATH' ) ) {
9 exit; // Exit if accessed directly.
10 }
11
12 class Components_REST_API {
13 const API_NAMESPACE = 'elementor/v1';
14 const API_BASE = 'components';
15 const STYLES_ROUTE = 'styles';
16 const MAX_COMPONENTS = 50;
17
18 private $repository = null;
19
20 public function register_hooks() {
21 add_action( 'rest_api_init', fn() => $this->register_routes() );
22 }
23
24 private function get_repository() {
25 if ( ! $this->repository ) {
26 $this->repository = new Components_Repository();
27 }
28
29 return $this->repository;
30 }
31
32 private function register_routes() {
33 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE, [
34 [
35 'methods' => 'GET',
36 'callback' => fn() => $this->route_wrapper( fn() => $this->get_components() ),
37 'permission_callback' => fn() => is_user_logged_in(),
38 ],
39 ] );
40
41 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE . '/' . self::STYLES_ROUTE, [
42 [
43 'methods' => 'GET',
44 'callback' => fn() => $this->route_wrapper( fn() => $this->get_styles() ),
45 'permission_callback' => fn() => is_user_logged_in(),
46 ],
47 ] );
48
49 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE, [
50 [
51 'methods' => 'POST',
52 'callback' => fn( $request ) => $this->route_wrapper( fn() => $this->create_component( $request ) ),
53 'permission_callback' => fn() => current_user_can( 'manage_options' ),
54 'args' => [
55 'name' => [
56 'type' => 'string',
57 'required' => true,
58 ],
59 'content' => [
60 'type' => 'array',
61 'required' => true,
62 'items' => [
63 'type' => 'object',
64 ],
65 ],
66 ],
67 ],
68 ] );
69 }
70
71 private function get_components() {
72 $components = $this->get_repository()->all();
73
74 $components_list = $components->get_components()->map( fn( $component ) => [
75 'id' => $component['id'],
76 'name' => $component['name'],
77 ])->all();
78
79 return Response_Builder::make( $components_list )->build();
80 }
81
82 private function get_styles() {
83 $components = $this->get_repository()->all();
84
85 $styles = [];
86 $components->get_components()->each( function( $component ) use ( &$styles ) {
87 $styles[ $component['id'] ] = $component['styles'];
88 } );
89
90 return Response_Builder::make( $styles )->build();
91 }
92 private function create_component( \WP_REST_Request $request ) {
93 $components = $this->get_repository()->all();
94 $components_count = $components->get_components()->count();
95
96 if ( $components_count >= static::MAX_COMPONENTS ) {
97 return Error_Builder::make( 'components_limit_exceeded' )
98 ->set_status( 400 )
99 ->set_message( sprintf(
100 /* translators: %d: maximum components limit. */
101 __( 'Components limit exceeded. Maximum allowed: %d', 'elementor' ),
102 static::MAX_COMPONENTS
103 ) )
104 ->build();
105 }
106
107 $parser = Components_Parser::make();
108
109 $name_result = $parser->parse_name( $request->get_param( 'name' ), $components->get_components()->map( fn( $component ) => $component['name'] )->all() );
110
111 if ( ! $name_result->is_valid() ) {
112 return Error_Builder::make( 'invalid_name' )
113 ->set_status( 400 )
114 ->set_message( 'Invalid component name: ' . $name_result->errors()->to_string() )
115 ->build();
116 }
117
118 $name = $name_result->unwrap();
119 // The content is validated & sanitized in the document save process.
120 $content = $request->get_param( 'content' );
121
122 try {
123 $component_id = $this->get_repository()->create( $name, $content );
124
125 return Response_Builder::make( [ 'component_id' => $component_id ] )->set_status( 201 )->build();
126 } catch ( \Exception $e ) {
127 $error_message = $e->getMessage();
128
129 $invalid_elements_structure_error = str_contains( $error_message, 'Invalid data' );
130 $atomic_styles_validation_error = str_contains( $error_message, 'Styles validation failed' );
131 $atomic_settings_validation_error = str_contains( $error_message, 'Settings validation failed' );
132
133 if ( $invalid_elements_structure_error || $atomic_styles_validation_error || $atomic_settings_validation_error ) {
134 return Error_Builder::make( 'content_validation_failed' )
135 ->set_status( 400 )
136 ->set_message( $error_message )
137 ->build();
138 }
139
140 throw $e;
141 }
142 }
143
144 private function route_wrapper( callable $cb ) {
145 try {
146 $response = $cb();
147 } catch ( \Exception $e ) {
148 return Error_Builder::make( 'unexpected_error' )
149 ->set_message( __( 'Something went wrong', 'elementor' ) )
150 ->build();
151 }
152
153 return $response;
154 }
155 }
156