PluginProbe ʕ •ᴥ•ʔ
Elementor Website Builder – more than just a page builder / 3.32.0-dev3
Elementor Website Builder – more than just a page builder v3.32.0-dev3
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 4.0.6 4.0.5 4.0.4 4.0.3 3.22.0-dev1 4.0.0-beta3 3.22.0-dev2 4.0.0-beta4 3.22.0-dev3 4.0.0-beta5 3.22.0-dev4 4.0.0-dev1 3.22.0-dev5 4.0.0-dev2 3.22.0-dev6 4.0.0-dev3 3.22.1 4.0.0-dev4 3.22.2 4.0.0-dev5 3.22.3 4.0.1 3.23.0 4.0.2 3.23.0-beta1 3.23.0-beta2 3.23.0-beta3 3.23.0-beta4 3.23.0-beta5 3.23.0-beta6 3.23.0-dev1 3.23.0-dev2 3.23.0-dev3 3.23.0-dev4 3.23.0-dev5 3.23.0-dev6 3.23.1 3.23.2 3.23.3 3.23.4 3.24.0 3.24.0-beta1 3.24.0-beta2 3.24.0-beta3 3.24.0-dev1 3.24.0-dev2 3.24.0-dev3 3.24.1 3.24.2 3.24.3 3.24.4 3.24.5 3.24.6 3.24.7 3.24.8 3.25.0 3.25.0-beta1 3.25.0-beta2 3.25.0-beta3 3.25.0-dev1 3.25.0-dev2 3.25.0-dev3 3.25.1 3.25.10 3.25.11 3.25.2 3.25.3 3.25.4 3.25.5 3.25.6 3.25.7 3.25.8 3.25.9 3.26.0 3.26.0-beta1 3.26.0-beta2 3.26.0-beta3 3.26.0-beta4 3.26.0-beta5 3.26.0-dev1 3.26.0-dev2 3.26.0-dev3 3.26.0-dev4 3.26.0-dev5 3.26.1 3.26.2 3.26.3 3.26.4 3.26.5 3.27.0 3.27.0-beta1 3.27.0-beta2 3.27.0-dev1 3.27.0-dev2 3.27.1 3.27.2 3.27.3 3.27.4 3.27.5 3.27.6 3.27.7 3.28.0 3.28.0-beta1 3.28.0-beta2 3.28.0-beta3 3.28.0-dev1 3.28.0-dev2 3.28.0-dev3 3.28.1 3.28.2 3.28.3 3.28.4 3.29.0 3.29.0-beta1 trunk 3.29.0-beta2 3.0.0 3.29.0-beta3 3.0.1 3.29.0-beta4 3.0.10 3.29.0-dev1 3.0.11 3.29.0-dev2 3.0.12 3.29.0-dev3 3.0.13 3.29.0-dev4 3.0.14 3.29.1 3.0.15 3.29.2 3.0.16 3.3.0 3.0.2 3.3.1 3.0.3 3.30.0 3.0.4 3.30.0-beta1 3.0.5 3.30.0-beta2 3.0.6 3.30.0-beta3 3.0.7 3.30.0-dev1 3.0.8 3.30.0-dev2 3.0.8.1 3.30.0-dev3 3.0.9 3.30.1 3.1.0 3.30.2 3.1.0-beta1 3.30.3 3.1.0-beta2 3.30.4 3.1.0-beta3 3.31.0 3.1.0-beta4 3.31.0-beta1 3.1.0-dev1 3.31.0-beta2 3.1.0-dev2 3.31.0-dev1 3.1.0-dev3 3.31.0-dev2 3.1.1 3.31.1 3.1.2 3.31.2 3.1.3 3.31.3 3.1.4 3.31.4 3.10.0 3.31.5 3.10.0-dev1 3.32.0 3.10.1 3.32.0-beta1 3.10.2 3.32.0-beta2 3.11.0 3.32.0-beta3 3.11.0-beta1 3.32.0-dev1 3.11.0-beta2 3.32.0-dev2 3.11.0-beta3 3.32.0-dev3 3.11.0-dev1 3.32.1 3.11.0-dev2 3.32.2 3.11.0-dev3 3.32.3 3.11.1 3.32.4 3.11.2 3.32.5 3.11.3 3.33.0 3.11.4 3.33.0-beta1 3.11.5 3.33.0-beta2 3.12.0 3.33.0-beta3 3.12.1 3.33.0-beta4 3.12.2 3.33.0-dev1 3.13.0 3.33.0-dev2 3.13.0-beta1 3.33.0-dev3 3.13.0-beta2 3.33.0-dev4 3.13.0-beta3 3.33.1 3.13.0-dev3 3.33.2 3.13.0-dev4 3.33.3 3.13.1 3.33.4 3.13.2 3.33.5 3.13.3 3.33.6 3.13.4 3.34.0 3.14.0 3.34.0-beta1 3.14.0-beta1 3.34.0-beta2 3.14.0-beta2 3.34.0-beta3 3.14.0-beta3 3.34.0-dev1 3.14.0-beta4 3.34.0-dev2 3.14.0-beta5 3.34.1 3.14.1 3.34.2 3.15.0 3.34.3 3.15.1 3.34.4 3.15.2 3.35.0 3.15.3 3.35.0-beta1 3.16.0 3.35.0-beta2 3.16.0-beta3 3.35.0-beta3 3.16.0-beta4 3.35.0-beta4 3.16.0-dev1 3.35.0-dev1 3.16.0-dev2 3.35.0-dev2 3.16.1 3.35.0-dev3 3.16.2 3.35.0-dev4 3.16.3 3.35.1 3.16.4 3.35.2 3.16.5 3.35.3 3.16.6 3.35.4 3.17.0 3.35.5 3.17.0-dev2 3.35.6 3.17.0-dev3 3.35.7 3.17.0-dev4 3.35.8 3.17.1 3.35.9 3.17.2 3.4.0 3.17.3 3.4.0-dev7 3.18.0 3.4.0-dev8 3.18.0-beta1 3.4.0-dev9 3.18.0-beta2 3.4.1 3.18.0-beta3 3.4.2 3.18.0-beta4 3.4.3 3.18.0-dev1 3.4.4 3.18.1 3.4.5 3.18.2 3.4.6 3.18.3 3.4.7 3.19.0 3.4.8 3.19.0-beta1 3.5.0 3.19.0-beta2 3.5.0-beta1 3.19.0-beta3 3.5.0-beta2 3.19.0-beta4 3.5.0-beta3 3.19.0-beta5 3.5.0-beta4 3.19.0-beta6 3.5.0-beta5 3.19.0-dev1 3.5.0-beta7 3.19.0-dev2 3.5.0-beta8 3.19.0-dev3 3.5.0-dev8 3.19.0-dev4 3.5.0-dev9 3.19.0-dev5 3.5.1 3.19.0-dev6 3.5.2 3.19.1 3.5.3 3.19.2 3.5.4 3.19.3 3.5.5 3.19.4 3.5.6 3.2.0 3.6.0 3.2.1 3.6.0-beta1 3.2.2 3.6.0-beta2 3.2.3 3.6.0-beta3 3.2.4 3.6.0-beta4 3.2.5 3.6.0-beta5 3.20.0 3.6.0-dev1 3.20.0-beta1 3.6.0-dev10 3.20.0-beta2 3.6.1 3.20.0-beta3 3.6.2 3.20.0-beta4 3.6.3 3.20.0-dev1 3.6.4 3.20.0-dev2 3.6.5 3.20.0-dev3 3.6.6 3.20.0-dev4 3.6.7 3.20.1 3.6.8 3.20.2 3.7.0 3.20.3 3.7.0-beta1 3.20.4 3.7.0-beta2 3.21.0 3.7.0-beta3 3.21.0-beta1 3.7.0-beta4 3.21.0-beta2 3.7.0-dev1 3.21.0-beta3 3.7.1 3.21.0-dev1 3.7.2 3.21.0-dev2 3.7.3 3.21.0-dev3 3.7.4 3.21.1 3.7.5 3.21.2 3.7.6 3.21.3 3.7.7 3.21.4 3.7.8 3.21.5 3.8.0 3.21.6 3.8.0-beta1 3.21.7 3.8.0-beta2 3.21.8 3.8.0-beta3 3.22.0 3.8.1 3.22.0-beta1 3.9.0 3.22.0-beta2 3.9.1 3.22.0-beta3 3.9.2 3.22.0-beta4 4.0.0 3.22.0-beta5 4.0.0-beta1 3.22.0-beta6 4.0.0-beta2
elementor / modules / variables / classes / rest-api.php
elementor / modules / variables / classes Last commit date
css-renderer.php 9 months ago fonts.php 9 months ago rest-api.php 9 months ago style-schema.php 9 months ago style-transformers.php 9 months ago variable-types-registry.php 9 months ago variables.php 9 months ago
rest-api.php
498 lines
1 <?php
2
3 namespace Elementor\Modules\Variables\Classes;
4
5 use Exception;
6 use WP_Error;
7 use WP_REST_Response;
8 use WP_REST_Request;
9 use WP_REST_Server;
10 use Elementor\Plugin;
11 use Elementor\Modules\Variables\Module as Variables_Module;
12 use Elementor\Modules\Variables\Storage\Repository as Variables_Repository;
13 use Elementor\Modules\Variables\Storage\Exceptions\VariablesLimitReached;
14 use Elementor\Modules\Variables\Storage\Exceptions\RecordNotFound;
15 use Elementor\Modules\Variables\Storage\Exceptions\DuplicatedLabel;
16 use Elementor\Modules\Variables\Storage\Exceptions\BatchOperationFailed;
17
18 if ( ! defined( 'ABSPATH' ) ) {
19 exit; // Exit if accessed directly.
20 }
21
22 class Rest_Api {
23 const API_NAMESPACE = 'elementor/v1';
24 const API_BASE = 'variables';
25 const HTTP_OK = 200;
26 const HTTP_CREATED = 201;
27 const HTTP_BAD_REQUEST = 400;
28 const HTTP_NOT_FOUND = 404;
29 const HTTP_SERVER_ERROR = 500;
30 const MAX_ID_LENGTH = 64;
31 const MAX_LABEL_LENGTH = 50;
32 const MAX_VALUE_LENGTH = 512;
33 private Variables_Repository $variables_repository;
34
35 public function __construct( Variables_Repository $variables_repository ) {
36 $this->variables_repository = $variables_repository;
37 }
38
39 public function enough_permissions_to_perform_ro_action() {
40 return current_user_can( 'edit_posts' );
41 }
42
43 public function enough_permissions_to_perform_rw_action() {
44 return current_user_can( 'manage_options' );
45 }
46
47 public function register_routes() {
48 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE . '/list', [
49 'methods' => WP_REST_Server::READABLE,
50 'callback' => [ $this, 'get_variables' ],
51 'permission_callback' => [ $this, 'enough_permissions_to_perform_ro_action' ],
52 ] );
53
54 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE . '/create', [
55 'methods' => WP_REST_Server::CREATABLE,
56 'callback' => [ $this, 'create_variable' ],
57 'permission_callback' => [ $this, 'enough_permissions_to_perform_rw_action' ],
58 'args' => [
59 'type' => [
60 'required' => true,
61 'type' => 'string',
62 'validate_callback' => [ $this, 'is_valid_variable_type' ],
63 'sanitize_callback' => [ $this, 'trim_and_sanitize_text_field' ],
64 ],
65 'label' => [
66 'required' => true,
67 'type' => 'string',
68 'validate_callback' => [ $this, 'is_valid_variable_label' ],
69 'sanitize_callback' => [ $this, 'trim_and_sanitize_text_field' ],
70 ],
71 'value' => [
72 'required' => true,
73 'type' => 'string',
74 'validate_callback' => [ $this, 'is_valid_variable_value' ],
75 'sanitize_callback' => [ $this, 'trim_and_sanitize_text_field' ],
76 ],
77 ],
78 ] );
79
80 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE . '/update', [
81 'methods' => WP_REST_Server::EDITABLE,
82 'callback' => [ $this, 'update_variable' ],
83 'permission_callback' => [ $this, 'enough_permissions_to_perform_rw_action' ],
84 'args' => [
85 'id' => [
86 'required' => true,
87 'type' => 'string',
88 'validate_callback' => [ $this, 'is_valid_variable_id' ],
89 'sanitize_callback' => [ $this, 'trim_and_sanitize_text_field' ],
90 ],
91 'label' => [
92 'required' => true,
93 'type' => 'string',
94 'validate_callback' => [ $this, 'is_valid_variable_label' ],
95 'sanitize_callback' => [ $this, 'trim_and_sanitize_text_field' ],
96 ],
97 'value' => [
98 'required' => true,
99 'type' => 'string',
100 'validate_callback' => [ $this, 'is_valid_variable_value' ],
101 'sanitize_callback' => [ $this, 'trim_and_sanitize_text_field' ],
102 ],
103 ],
104 ] );
105
106 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE . '/delete', [
107 'methods' => WP_REST_Server::EDITABLE,
108 'callback' => [ $this, 'delete_variable' ],
109 'permission_callback' => [ $this, 'enough_permissions_to_perform_rw_action' ],
110 'args' => [
111 'id' => [
112 'required' => true,
113 'type' => 'string',
114 'validate_callback' => [ $this, 'is_valid_variable_id' ],
115 'sanitize_callback' => [ $this, 'trim_and_sanitize_text_field' ],
116 ],
117 ],
118 ] );
119
120 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE . '/restore', [
121 'methods' => WP_REST_Server::EDITABLE,
122 'callback' => [ $this, 'restore_variable' ],
123 'permission_callback' => [ $this, 'enough_permissions_to_perform_rw_action' ],
124 'args' => [
125 'id' => [
126 'required' => true,
127 'type' => 'string',
128 'validate_callback' => [ $this, 'is_valid_variable_id' ],
129 'sanitize_callback' => [ $this, 'trim_and_sanitize_text_field' ],
130 ],
131 'label' => [
132 'required' => false,
133 'type' => 'string',
134 'validate_callback' => [ $this, 'is_valid_variable_label' ],
135 'sanitize_callback' => [ $this, 'trim_and_sanitize_text_field' ],
136 ],
137 'value' => [
138 'required' => false,
139 'type' => 'string',
140 'validate_callback' => [ $this, 'is_valid_variable_value' ],
141 'sanitize_callback' => [ $this, 'trim_and_sanitize_text_field' ],
142 ],
143 ],
144 ] );
145
146 register_rest_route( self::API_NAMESPACE, '/' . self::API_BASE . '/batch', [
147 'methods' => WP_REST_Server::CREATABLE,
148 'callback' => [ $this, 'process_batch' ],
149 'permission_callback' => [ $this, 'enough_permissions_to_perform_rw_action' ],
150 'args' => [
151 'watermark' => [
152 'required' => true,
153 'type' => 'integer',
154 'validate_callback' => [ $this, 'is_valid_watermark' ],
155 ],
156 'operations' => [
157 'required' => true,
158 'type' => 'array',
159 'validate_callback' => [ $this, 'is_valid_operations_array' ],
160 ],
161 ],
162 ] );
163 }
164
165 public function trim_and_sanitize_text_field( $value ) {
166 return trim( sanitize_text_field( $value ) );
167 }
168
169 public function is_valid_variable_id( $id ) {
170 $id = trim( $id );
171
172 if ( empty( $id ) ) {
173 return new WP_Error(
174 'invalid_variable_id_empty',
175 __( 'ID cannot be empty', 'elementor' )
176 );
177 }
178
179 if ( self::MAX_ID_LENGTH < strlen( $id ) ) {
180 return new WP_Error( 'invalid_variable_id_length', sprintf(
181 /* translators: %d: Maximum ID length. */
182 __( 'ID cannot exceed %d characters', 'elementor' ),
183 self::MAX_ID_LENGTH
184 ) );
185 }
186
187 return true;
188 }
189
190 public function is_valid_variable_type( $type ) {
191 $allowed_types = array_keys( Variables_Module::instance()->get_variable_types_registry()->all() );
192
193 return in_array( $type, $allowed_types, true );
194 }
195
196 public function is_valid_variable_label( $label ) {
197 $label = trim( $label );
198
199 if ( empty( $label ) ) {
200 return new WP_Error(
201 'invalid_variable_label_empty',
202 __( 'Label cannot be empty', 'elementor' )
203 );
204 }
205
206 if ( self::MAX_LABEL_LENGTH < strlen( $label ) ) {
207 return new WP_Error( 'invalid_variable_label_length', sprintf(
208 /* translators: %d: Maximum label length. */
209 __( 'Label cannot exceed %d characters', 'elementor' ),
210 self::MAX_LABEL_LENGTH
211 ) );
212 }
213
214 return true;
215 }
216
217 public function is_valid_variable_value( $value ) {
218 $value = trim( $value );
219
220 if ( empty( $value ) ) {
221 return new WP_Error(
222 'invalid_variable_value_empty',
223 __( 'Value cannot be empty', 'elementor' )
224 );
225 }
226
227 if ( self::MAX_VALUE_LENGTH < strlen( $value ) ) {
228 return new WP_Error( 'invalid_variable_value_length', sprintf(
229 /* translators: %d: Maximum value length. */
230 __( 'Value cannot exceed %d characters', 'elementor' ),
231 self::MAX_VALUE_LENGTH
232 ) );
233 }
234
235 return true;
236 }
237
238 public function create_variable( WP_REST_Request $request ) {
239 try {
240 return $this->create_new_variable( $request );
241 } catch ( Exception $e ) {
242 return $this->error_response( $e );
243 }
244 }
245
246 protected function clear_cache() {
247 Plugin::$instance->files_manager->clear_cache();
248 }
249
250 private function create_new_variable( WP_REST_Request $request ) {
251 $type = $request->get_param( 'type' );
252 $label = $request->get_param( 'label' );
253 $value = $request->get_param( 'value' );
254
255 $result = $this->variables_repository->create( [
256 'type' => $type,
257 'label' => $label,
258 'value' => $value,
259 ] );
260
261 $this->clear_cache();
262
263 return $this->success_response( [
264 'variable' => $result['variable'],
265 'watermark' => $result['watermark'],
266 ], self::HTTP_CREATED );
267 }
268
269 public function update_variable( WP_REST_Request $request ) {
270 try {
271 return $this->update_existing_variable( $request );
272 } catch ( Exception $e ) {
273 return $this->error_response( $e );
274 }
275 }
276
277 private function update_existing_variable( WP_REST_Request $request ) {
278 $id = $request->get_param( 'id' );
279 $label = $request->get_param( 'label' );
280 $value = $request->get_param( 'value' );
281
282 $result = $this->variables_repository->update( $id, [
283 'label' => $label,
284 'value' => $value,
285 ] );
286
287 $this->clear_cache();
288
289 return $this->success_response( [
290 'variable' => $result['variable'],
291 'watermark' => $result['watermark'],
292 ] );
293 }
294
295 public function delete_variable( WP_REST_Request $request ) {
296 try {
297 return $this->delete_existing_variable( $request );
298 } catch ( Exception $e ) {
299 return $this->error_response( $e );
300 }
301 }
302
303 private function delete_existing_variable( WP_REST_Request $request ) {
304 $id = $request->get_param( 'id' );
305
306 $result = $this->variables_repository->delete( $id );
307
308 $this->clear_cache();
309
310 return $this->success_response( [
311 'variable' => $result['variable'],
312 'watermark' => $result['watermark'],
313 ] );
314 }
315
316 public function restore_variable( WP_REST_Request $request ) {
317 try {
318 return $this->restore_existing_variable( $request );
319 } catch ( Exception $e ) {
320 return $this->error_response( $e );
321 }
322 }
323
324 private function restore_existing_variable( WP_REST_Request $request ) {
325 $id = $request->get_param( 'id' );
326
327 $overrides = [];
328
329 $label = $request->get_param( 'label' );
330
331 if ( $label ) {
332 $overrides['label'] = $label;
333 }
334
335 $value = $request->get_param( 'value' );
336
337 if ( $value ) {
338 $overrides['value'] = $value;
339 }
340
341 $result = $this->variables_repository->restore( $id, $overrides );
342
343 $this->clear_cache();
344
345 return $this->success_response( [
346 'variable' => $result['variable'],
347 'watermark' => $result['watermark'],
348 ] );
349 }
350
351 public function get_variables() {
352 try {
353 return $this->list_of_variables();
354 } catch ( Exception $e ) {
355 return $this->error_response( $e );
356 }
357 }
358
359 private function list_of_variables() {
360 $db_record = $this->variables_repository->load();
361
362 return $this->success_response( [
363 'variables' => $db_record['data'],
364 'total' => count( $db_record['data'] ),
365 'watermark' => $db_record['watermark'],
366 ] );
367 }
368
369 private function success_response( $payload, $status_code = null ) {
370 return new WP_REST_Response( [
371 'success' => true,
372 'data' => $payload,
373 ], $status_code ?? self::HTTP_OK );
374 }
375
376 private function error_response( Exception $e ) {
377 if ( $e instanceof VariablesLimitReached ) {
378 return $this->prepare_error_response(
379 self::HTTP_BAD_REQUEST,
380 'invalid_variable_limit_reached',
381 __( 'Reached the maximum number of variables', 'elementor' )
382 );
383 }
384
385 if ( $e instanceof DuplicatedLabel ) {
386 return $this->prepare_error_response(
387 self::HTTP_BAD_REQUEST,
388 'duplicated_label',
389 __( 'Variable label already exists', 'elementor' )
390 );
391 }
392
393 if ( $e instanceof RecordNotFound ) {
394 return $this->prepare_error_response(
395 self::HTTP_NOT_FOUND,
396 'variable_not_found',
397 __( 'Variable not found', 'elementor' )
398 );
399 }
400
401 return $this->prepare_error_response(
402 self::HTTP_SERVER_ERROR,
403 'unexpected_server_error',
404 __( 'Unexpected server error', 'elementor' )
405 );
406 }
407
408 private function prepare_error_response( $status_code, $error, $message ) {
409 return new WP_REST_Response( [
410 'code' => $error,
411 'message' => $message,
412 'data' => [
413 'status' => $status_code,
414 ],
415 ], $status_code );
416 }
417
418 public function is_valid_watermark( $watermark ) {
419 if ( ! is_numeric( $watermark ) || $watermark < 0 ) {
420 return new WP_Error(
421 'invalid_watermark',
422 __( 'Watermark must be a non-negative integer', 'elementor' )
423 );
424 }
425
426 return true;
427 }
428
429 public function is_valid_operations_array( $operations ) {
430 if ( ! is_array( $operations ) || empty( $operations ) ) {
431 return new WP_Error(
432 'invalid_operations_empty',
433 __( 'Operations array cannot be empty', 'elementor' )
434 );
435 }
436
437 foreach ( $operations as $index => $operation ) {
438 if ( ! is_array( $operation ) || ! isset( $operation['type'] ) ) {
439 return new WP_Error(
440 'invalid_operation_structure',
441 sprintf(
442 /* translators: %d: operation index */
443 __( 'Invalid operation structure at index %d', 'elementor' ),
444 $index
445 )
446 );
447 }
448
449 $allowed_types = [ 'create', 'update', 'delete', 'restore' ];
450
451 if ( ! in_array( $operation['type'], $allowed_types, true ) ) {
452 return new WP_Error(
453 'invalid_operation_type',
454 sprintf(
455 /* translators: %d: operation index */
456 __( 'Invalid operation type at index %d', 'elementor' ),
457 $index
458 )
459 );
460 }
461 }
462
463 return true;
464 }
465
466 public function process_batch( WP_REST_Request $request ) {
467 try {
468 return $this->process_batch_operations( $request );
469 } catch ( Exception $e ) {
470 return $this->batch_error_response( $e );
471 }
472 }
473
474 private function process_batch_operations( WP_REST_Request $request ) {
475 $watermark = $request->get_param( 'watermark' );
476 $operations = $request->get_param( 'operations' );
477
478 $result = $this->variables_repository->process_atomic_batch( $operations, $watermark );
479
480 $this->clear_cache();
481
482 return $this->success_response( $result );
483 }
484
485 private function batch_error_response( Exception $e ) {
486 if ( $e instanceof BatchOperationFailed ) {
487 return new WP_REST_Response( [
488 'success' => false,
489 'code' => 'atomic_operation_failed',
490 'message' => __( 'Batch operation failed', 'elementor' ),
491 'data' => $e->getErrorDetails(),
492 ], self::HTTP_BAD_REQUEST );
493 }
494
495 return $this->error_response( $e );
496 }
497 }
498