PluginProbe
Elementor Website Builder – more than just a page builder / 3.30.0-dev3
Elementor Website Builder – more than just a page builder v3.30.0-dev3
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 / global-classes / global-classes-rest-api.php

global-classes-rest-api.php in Elementor Website Builder – more than just a page builder 3.30.0-dev3, at modules/global-classes/global-classes-rest-api.php

204 lines 5.1 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\GlobalClasses;
4
5 use Elementor\Modules\GlobalClasses\Utils\Error_Builder;
6 use Elementor\Modules\GlobalClasses\Utils\Response_Builder;
7 use Elementor\Modules\GlobalClasses\Database\Migrations\Add_Capabilities;
8
9 if ( ! defined( 'ABSPATH' ) ) {
10 exit; // Exit if accessed directly.
11 }
12
13 class Global_Classes_REST_API {
14 const API_NAMESPACE = 'elementor/v1';
15 const API_BASE = 'global-classes';
16
17 const MAX_ITEMS = 50;
18
19 private $repository = null;
20
21 public function register_hooks() {
22 add_action( 'rest_api_init', fn() => $this->register_routes() );
23 }
24
25 private function get_repository() {
26 if ( ! $this->repository ) {
27 $this->repository = new Global_Classes_Repository();
28 }
29
30 return $this->repository;
31 }
32
33 private function register_routes() {
34 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE, [
35 [
36 'methods' => 'GET',
37 'callback' => fn( $request ) => $this->route_wrapper( fn() => $this->all( $request ) ),
38 'permission_callback' => fn() => true,
39 'args' => [
40 'context' => [
41 'type' => 'string',
42 'required' => false,
43 'default' => Global_Classes_Repository::CONTEXT_FRONTEND,
44 'enum' => [
45 Global_Classes_Repository::CONTEXT_FRONTEND,
46 Global_Classes_Repository::CONTEXT_PREVIEW,
47 ],
48 ],
49 ],
50 ],
51 ] );
52
53 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE, [
54 [
55 'methods' => 'PUT',
56 'callback' => fn( $request ) => $this->route_wrapper( fn() => $this->put( $request ) ),
57 'permission_callback' => fn() => current_user_can( Add_Capabilities::UPDATE_CLASS ),
58 'args' => [
59 'context' => [
60 'type' => 'string',
61 'required' => false,
62 'default' => Global_Classes_Repository::CONTEXT_FRONTEND,
63 'enum' => [
64 Global_Classes_Repository::CONTEXT_FRONTEND,
65 Global_Classes_Repository::CONTEXT_PREVIEW,
66 ],
67 ],
68 'changes' => [
69 'type' => 'object',
70 'required' => true,
71 'additionalProperties' => false,
72 'properties' => [
73 'added' => [
74 'type' => 'array',
75 'required' => true,
76 'items' => [ 'type' => 'string' ],
77 ],
78 'deleted' => [
79 'type' => 'array',
80 'required' => true,
81 'items' => [ 'type' => 'string' ],
82 ],
83 'modified' => [
84 'type' => 'array',
85 'required' => true,
86 'items' => [ 'type' => 'string' ],
87 ],
88 ],
89 ],
90 'items' => [
91 'required' => true,
92 'type' => 'object',
93 'additionalProperties' => [
94 'type' => 'object',
95 'properties' => [
96 'id' => [
97 'type' => 'string',
98 'required' => true,
99 ],
100 'variants' => [
101 'type' => 'array',
102 'required' => true,
103 ],
104 'type' => [
105 'type' => 'string',
106 'enum' => [ 'class' ],
107 'required' => true,
108 ],
109 'label' => [
110 'type' => 'string',
111 'required' => true,
112 ],
113 ],
114 ],
115 ],
116 'order' => [
117 'required' => true,
118 'type' => 'array',
119 'items' => [
120 'type' => 'string',
121 ],
122 ],
123 ],
124 ],
125 ] );
126 }
127
128 private function all( \WP_REST_Request $request ) {
129 $context = $request->get_param( 'context' );
130
131 $classes = $this->get_repository()->context( $context )->all();
132
133 return Response_Builder::make( (object) $classes->get_items()->all() )
134 ->set_meta( [ 'order' => $classes->get_order()->all() ] )
135 ->build();
136 }
137
138 private function put( \WP_REST_Request $request ) {
139 $parser = Global_Classes_Parser::make();
140
141 $items_result = $parser->parse_items(
142 $request->get_param( 'items' )
143 );
144
145 $items_count = count( $items_result->unwrap() );
146
147 if ( $items_count >= static::MAX_ITEMS ) {
148 return Error_Builder::make( 'global_classes_limit_exceeded' )
149 ->set_status( 400 )
150 ->set_message( sprintf(
151 __( 'Global classes limit exceeded. Maximum allowed: %d', 'elementor' ),
152 static::MAX_ITEMS
153 ) )
154 ->build();
155 }
156
157 if ( ! $items_result->is_valid() ) {
158 return Error_Builder::make( 'invalid_items' )
159 ->set_status( 400 )
160 ->set_message( 'Invalid items: ' . $items_result->errors()->to_string() )
161 ->build();
162 }
163
164 $order_result = $parser->parse_order(
165 $request->get_param( 'order' ),
166 $items_result->unwrap()
167 );
168
169 if ( ! $order_result->is_valid() ) {
170 return Error_Builder::make( 'invalid_order' )
171 ->set_status( 400 )
172 ->set_message( 'Invalid order: ' . $order_result->errors()->to_string() )
173 ->build();
174 }
175
176 $repository = $this->get_repository()
177 ->context( $request->get_param( 'context' ) );
178
179 $changes_resolver = Global_Classes_Changes_Resolver::make(
180 $repository,
181 $request->get_param( 'changes' ) ?? [],
182 );
183
184 $repository->put(
185 $changes_resolver->resolve_items( $items_result->unwrap() ),
186 $changes_resolver->resolve_order( $order_result->unwrap() ),
187 );
188
189 return Response_Builder::make()->no_content()->build();
190 }
191
192 private function route_wrapper( callable $cb ) {
193 try {
194 $response = $cb();
195 } catch ( \Exception $e ) {
196 return Error_Builder::make( 'unexpected_error' )
197 ->set_message( __( 'Something went wrong', 'elementor' ) )
198 ->build();
199 }
200
201 return $response;
202 }
203 }
204