PluginProbe
Elementor Website Builder – more than just a page builder / 3.31.2
Elementor Website Builder – more than just a page builder v3.31.2
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.31.2, at modules/global-classes/global-classes-rest-api.php

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