PluginProbe
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards / 5.5.77
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards v5.5.77
5.5.83 5.5.82 5.5.81 5.5.80 5.5.79 5.5.77 5.5.76 5.5.75 5.5.73 5.5.72 5.5.22 5.5.23 5.5.29 5.5.3 5.5.31 5.5.32 5.5.34 5.5.35 5.5.36 5.5.37 5.5.4 5.5.40 5.5.41 5.5.42 5.5.43 All 159 releases
wp-data-access / WPDataAccess / API / WPDA_Apps.php

WPDA_Apps.php in WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards 5.5.77, at WPDataAccess/API/WPDA_Apps.php

2,563 lines 105.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPDataAccess\API;
4
5 use stdClass;
6 use WPDataAccess\Connection\WPDADB;
7 use WPDataAccess\Data_Dictionary\WPDA_List_Columns_Cache;
8 use WPDataAccess\Plugin_Table_Models\WPDA_App_Container_Model;
9 use WPDataAccess\Plugin_Table_Models\WPDA_App_Apps_Model;
10 use WPDataAccess\Plugin_Table_Models\WPDA_App_Model;
11 use WPDataAccess\Plugin_Table_Models\WPDA_Table_Settings_Model;
12 use WPDataAccess\Utilities\WPDA_App_Localization;
13 use WPDataAccess\WPDA;
14 class WPDA_Apps extends WPDA_API_Core {
15 const METHODS = array('httpGet', 'httpPost', 'httpRequest');
16
17 const WPDA_APP_DEFAULT_LANG = 'wpda_app_default_lang';
18
19 private function sanitize_settings( $value ) {
20 if ( is_array( $value ) ) {
21 foreach ( $value as $index => $item ) {
22 $value[$index] = $this->sanitize_settings( $item );
23 }
24 } elseif ( is_object( $value ) ) {
25 $object_vars = get_object_vars( $value );
26 foreach ( $object_vars as $property_name => $property_value ) {
27 $value->{$property_name} = $this->sanitize_settings( $property_value );
28 }
29 } else {
30 // Allow HTML and onclick for computed fields
31 // phpcs:disable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
32 $value = apply_filters(
33 'wp_kses_post',
34 $value,
35 "",
36 ["onclick"]
37 );
38 // phpcs:enable WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
39 }
40 return $value;
41 }
42
43 public function register_rest_routes() {
44 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/init', array(
45 'methods' => array('POST'),
46 'callback' => array($this, 'app_init'),
47 'permission_callback' => '__return_true',
48 ) );
49 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/list', array(
50 'methods' => array('POST'),
51 'callback' => array($this, 'app_list'),
52 'permission_callback' => '__return_true',
53 ) );
54 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/meta', array(
55 'methods' => array('POST'),
56 'callback' => array($this, 'app_meta'),
57 'permission_callback' => '__return_true',
58 'args' => array(
59 'app_id' => $this->get_param( 'app_id' ),
60 ),
61 ) );
62 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/lang', array(
63 'methods' => array('POST'),
64 'callback' => array($this, 'app_lang'),
65 'permission_callback' => '__return_true',
66 'args' => array(
67 'lang' => array(
68 'required' => true,
69 'type' => 'string',
70 'description' => __( 'App default language', 'wp-data-access' ),
71 'sanitize_callback' => 'sanitize_text_field',
72 'validate_callback' => 'rest_validate_request_arg',
73 ),
74 ),
75 ) );
76 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/table/meta', array(
77 'methods' => array('POST'),
78 'callback' => array($this, 'app_table_meta'),
79 'permission_callback' => '__return_true',
80 'args' => array(
81 'dbs' => $this->get_param( 'dbs' ),
82 'tbl' => $this->get_param( 'tbl' ),
83 'waa' => array(
84 'required' => false,
85 'type' => 'boolean',
86 'description' => __( 'With admin actions (to support table exports)', 'wp-data-access' ),
87 ),
88 ),
89 ) );
90 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/create', array(
91 'methods' => array('POST'),
92 'callback' => array($this, 'app_create'),
93 'permission_callback' => '__return_true',
94 'args' => array(
95 'app_name' => $this->get_param( 'app_name' ),
96 'app_title' => $this->get_param( 'app_title' ),
97 'app_type' => $this->get_param( 'app_type' ),
98 'app_settings' => $this->get_param( 'app_settings' ),
99 'app_dbs' => $this->get_param( 'dbs' ),
100 'app_tbl' => $this->get_param( 'tbl' ),
101 'app_cls' => $this->get_param( 'app_cls' ),
102 'app_table' => array(
103 'required' => true,
104 'type' => 'string',
105 'description' => __( 'App table', 'wp-data-access' ),
106 'sanitize_callback' => 'sanitize_text_field',
107 'validate_callback' => 'rest_validate_request_arg',
108 ),
109 'app_query' => $this->get_param( 'app_query' ),
110 ),
111 ) );
112 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/createapp', array(
113 'methods' => array('POST'),
114 'callback' => array($this, 'app_createapp'),
115 'permission_callback' => '__return_true',
116 'args' => array(
117 'app_name' => $this->get_param( 'app_name' ),
118 'app_title' => $this->get_param( 'app_title' ),
119 'app_type' => $this->get_param( 'app_type' ),
120 'app_settings' => $this->get_param( 'app_settings' ),
121 'app_apps' => $this->get_param( 'app_apps' ),
122 ),
123 ) );
124 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/copy', array(
125 'methods' => array('POST'),
126 'callback' => array($this, 'app_copy'),
127 'permission_callback' => '__return_true',
128 'args' => array(
129 'app_id' => $this->get_param( 'app_id' ),
130 ),
131 ) );
132 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/export', array(
133 'methods' => array('POST'),
134 'callback' => array($this, 'app_export'),
135 'permission_callback' => '__return_true',
136 'args' => array(
137 'app_id' => $this->get_param( 'app_id' ),
138 ),
139 ) );
140 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/details', array(
141 'methods' => array('POST'),
142 'callback' => array($this, 'app_details'),
143 'permission_callback' => '__return_true',
144 'args' => array(
145 'app_id' => $this->get_param( 'app_id' ),
146 'cnt_id' => $this->get_param( 'cnt_id' ),
147 ),
148 ) );
149 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/detailmeta', array(
150 'methods' => array('POST'),
151 'callback' => array($this, 'app_detail_meta'),
152 'permission_callback' => '__return_true',
153 'args' => array(
154 'app_id' => $this->get_param( 'app_id' ),
155 'cnt_id' => $this->get_param( 'cnt_id' ),
156 'rel_tab' => $this->get_param( 'rel_tab' ),
157 ),
158 ) );
159 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/detailreorder', array(
160 'methods' => array('POST'),
161 'callback' => array($this, 'app_detail_reorder'),
162 'permission_callback' => '__return_true',
163 'args' => array(
164 'app_id' => $this->get_param( 'app_id' ),
165 'cnt_id_from' => $this->get_param( 'cnt_id' ),
166 'cnt_id_to' => $this->get_param( 'cnt_id' ),
167 ),
168 ) );
169 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/relationship/create', array(
170 'methods' => array('POST'),
171 'callback' => array($this, 'app_relationship_create'),
172 'permission_callback' => '__return_true',
173 'args' => array(
174 'app_id' => $this->get_param( 'app_id' ),
175 'app_title' => $this->get_param( 'app_title' ),
176 'app_dbs' => $this->get_param( 'dbs' ),
177 'app_tbl' => $this->get_param( 'tbl' ),
178 'app_cls' => $this->get_param( 'app_cls' ),
179 'app_relation' => array(
180 'required' => true,
181 'type' => 'string',
182 'description' => __( 'Table settings', 'wp-data-access' ),
183 'sanitize_callback' => 'sanitize_text_field',
184 'validate_callback' => 'rest_validate_request_arg',
185 ),
186 ),
187 ) );
188 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/relationship/update', array(
189 'methods' => array('POST'),
190 'callback' => array($this, 'app_relationship_update'),
191 'permission_callback' => '__return_true',
192 'args' => array(
193 'app_id' => $this->get_param( 'app_id' ),
194 'app_cnt' => $this->get_param( 'cnt_id' ),
195 'app_title' => $this->get_param( 'app_title' ),
196 'app_dbs' => $this->get_param( 'dbs' ),
197 'app_tbl' => $this->get_param( 'tbl' ),
198 'app_cls' => $this->get_param( 'app_cls' ),
199 'app_relation' => array(
200 'required' => true,
201 'type' => 'string',
202 'description' => __( 'Table settings', 'wp-data-access' ),
203 'sanitize_callback' => 'sanitize_text_field',
204 'validate_callback' => 'rest_validate_request_arg',
205 ),
206 ),
207 ) );
208 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/relationship/delete', array(
209 'methods' => array('POST'),
210 'callback' => array($this, 'app_relationship_delete'),
211 'permission_callback' => '__return_true',
212 'args' => array(
213 'cnt_id' => $this->get_param( 'cnt_id' ),
214 ),
215 ) );
216 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/save', array(
217 'methods' => array('POST'),
218 'callback' => array($this, 'app_save'),
219 'permission_callback' => '__return_true',
220 'args' => array(
221 'app_id' => $this->get_param( 'app_id' ),
222 'app_name' => $this->get_param( 'app_name' ),
223 'app_title' => $this->get_param( 'app_title' ),
224 'app_type' => $this->get_param( 'app_type' ),
225 'app_settings' => $this->get_param( 'app_settings' ),
226 'app_add_to_menu' => $this->get_param( 'app_add_to_menu' ),
227 'app_dbs' => $this->get_param( 'dbs' ),
228 'app_tbl' => $this->get_param( 'tbl' ),
229 'app_cls' => $this->get_param( 'app_cls' ),
230 'app_query' => $this->get_param( 'app_query' ),
231 ),
232 ) );
233 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/saveapp', array(
234 'methods' => array('POST'),
235 'callback' => array($this, 'app_saveapp'),
236 'permission_callback' => '__return_true',
237 'args' => array(
238 'app_id' => $this->get_param( 'app_id' ),
239 'app_name' => $this->get_param( 'app_name' ),
240 'app_title' => $this->get_param( 'app_title' ),
241 'app_type' => $this->get_param( 'app_type' ),
242 'app_settings' => $this->get_param( 'app_settings' ),
243 'app_add_to_menu' => $this->get_param( 'app_add_to_menu' ),
244 'app_apps' => $this->get_param( 'app_apps' ),
245 ),
246 ) );
247 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/remove', array(
248 'methods' => array('POST'),
249 'callback' => array($this, 'app_remove'),
250 'permission_callback' => '__return_true',
251 'args' => array(
252 'app_id' => $this->get_param( 'app_id' ),
253 ),
254 ) );
255 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/settings', array(
256 'methods' => array('POST'),
257 'callback' => array($this, 'app_settings'),
258 'permission_callback' => '__return_true',
259 'args' => array(
260 'app_id' => $this->get_param( 'app_id' ),
261 'cnt_id' => $this->get_param( 'cnt_id' ),
262 'target' => array(
263 'required' => true,
264 'type' => 'string',
265 'description' => __( 'Setting target', 'wp-data-access' ),
266 'sanitize_callback' => 'sanitize_text_field',
267 'validate_callback' => 'rest_validate_request_arg',
268 ),
269 'settings' => array(
270 'required' => false,
271 'type' => 'string',
272 'description' => __( 'App settings - JSON string', 'wp-data-access' ),
273 'sanitize_callback' => function ( $param ) {
274 $sanitized_settings = $this->sanitize_settings( json_decode( (string) $param, true ) );
275 // Save sanitized JSON as string
276 return json_encode( $sanitized_settings );
277 },
278 'validate_callback' => 'rest_validate_request_arg',
279 ),
280 'map' => array(
281 'required' => false,
282 'type' => 'string',
283 'description' => __( 'Map settings - JSON string', 'wp-data-access' ),
284 'sanitize_callback' => 'wp_kses_post',
285 'validate_callback' => 'rest_validate_request_arg',
286 ),
287 'chart' => array(
288 'required' => false,
289 'type' => 'string',
290 'description' => __( 'Chart settings - JSON string', 'wp-data-access' ),
291 'sanitize_callback' => 'sanitize_text_field',
292 'validate_callback' => 'rest_validate_request_arg',
293 ),
294 'theme' => array(
295 'required' => false,
296 'type' => 'string',
297 'description' => __( 'Theme settings - JSON string', 'wp-data-access' ),
298 'sanitize_callback' => 'sanitize_text_field',
299 'validate_callback' => 'rest_validate_request_arg',
300 ),
301 ),
302 ) );
303 // DML
304 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/select', array(
305 'methods' => array('POST'),
306 'callback' => array($this, 'app_select'),
307 'permission_callback' => '__return_true',
308 'args' => array(
309 'app_id' => $this->get_param( 'app_id' ),
310 'cnt_id' => $this->get_param( 'cnt_id' ),
311 'col' => $this->get_param( 'cols' ),
312 'page_index' => $this->get_param( 'page_index' ),
313 'page_size' => $this->get_param( 'page_size' ),
314 'search' => $this->get_param( 'search' ),
315 'search_columns' => $this->get_param( 'search_columns' ),
316 'search_column_fns' => $this->get_param( 'search_column_fns' ),
317 'search_column_lov' => $this->get_param( 'search_column_lov' ),
318 'search_data_types' => $this->get_param( 'search_data_types' ),
319 'search_custom' => $this->get_param( 'search_custom' ),
320 'search_params' => $this->get_param( 'search_params' ),
321 'shortcode_params' => $this->get_param( 'search_params' ),
322 'md' => $this->get_param( 'md' ),
323 'sorting' => $this->get_param( 'sorting' ),
324 'row_count' => $this->get_param( 'row_count' ),
325 'row_count_estimate' => $this->get_param( 'row_count_estimate' ),
326 'media' => $this->get_param( 'media' ),
327 'rel_tab' => $this->get_param( 'rel_tab' ),
328 'client_side' => $this->get_param( 'client_side' ),
329 'geo_radius' => array(
330 'required' => false,
331 'type' => 'mixed',
332 'description' => __( 'Geo radius segment', 'wp-data-access' ),
333 'sanitize_callback' => function ( $param ) {
334 $geo_radius = array();
335 if ( isset(
336 $param['col']['lat'],
337 $param['col']['lng'],
338 $param['loc']['lat'],
339 $param['loc']['lng'],
340 $param['radius'],
341 $param['unit']
342 ) && is_numeric( $param['loc']['lat'] ) && is_numeric( $param['loc']['lng'] ) && is_numeric( $param['radius'] ) && ('km' === $param['unit'] || 'miles' === $param['unit']) ) {
343 $geo_radius['col']['lat'] = WPDA::remove_backticks( sanitize_text_field( $param['col']['lat'] ) );
344 $geo_radius['col']['lng'] = WPDA::remove_backticks( sanitize_text_field( $param['col']['lng'] ) );
345 $geo_radius['loc']['lat'] = (float) sanitize_text_field( $param['loc']['lat'] );
346 $geo_radius['loc']['lng'] = (float) sanitize_text_field( $param['loc']['lng'] );
347 $geo_radius['radius'] = (float) sanitize_text_field( $param['radius'] );
348 $geo_radius['unit'] = sanitize_text_field( $param['unit'] );
349 }
350 return $geo_radius;
351 },
352 ),
353 ),
354 ) );
355 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/get', array(
356 'methods' => array('POST'),
357 'callback' => array($this, 'app_get'),
358 'permission_callback' => '__return_true',
359 'args' => array(
360 'app_id' => $this->get_param( 'app_id' ),
361 'cnt_id' => $this->get_param( 'cnt_id' ),
362 'key' => $this->get_param( 'key' ),
363 'media' => $this->get_param( 'media' ),
364 'rel_tab' => $this->get_param( 'rel_tab' ),
365 ),
366 ) );
367 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/insert', array(
368 'methods' => array('POST'),
369 'callback' => array($this, 'app_insert'),
370 'permission_callback' => '__return_true',
371 'args' => array(
372 'app_id' => $this->get_param( 'app_id' ),
373 'cnt_id' => $this->get_param( 'cnt_id' ),
374 'val' => $this->get_param( 'val' ),
375 'join_tab' => $this->get_param( 'join_tab' ),
376 'rel_tab' => $this->get_param( 'rel_tab' ),
377 ),
378 ) );
379 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/update', array(
380 'methods' => array('POST'),
381 'callback' => array($this, 'app_update'),
382 'permission_callback' => '__return_true',
383 'args' => array(
384 'app_id' => $this->get_param( 'app_id' ),
385 'cnt_id' => $this->get_param( 'cnt_id' ),
386 'key' => $this->get_param( 'key' ),
387 'val' => $this->get_param( 'val' ),
388 'join_tab' => $this->get_param( 'join_tab' ),
389 'rel_tab' => $this->get_param( 'rel_tab' ),
390 ),
391 ) );
392 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/update/inline', array(
393 'methods' => array('POST'),
394 'callback' => array($this, 'app_update_inline'),
395 'permission_callback' => '__return_true',
396 'args' => array(
397 'app_id' => $this->get_param( 'app_id' ),
398 'cnt_id' => $this->get_param( 'cnt_id' ),
399 'key' => $this->get_param( 'key' ),
400 'val' => $this->get_param( 'val' ),
401 ),
402 ) );
403 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/delete', array(
404 'methods' => array('POST'),
405 'callback' => array($this, 'app_delete'),
406 'permission_callback' => '__return_true',
407 'args' => array(
408 'app_id' => $this->get_param( 'app_id' ),
409 'cnt_id' => $this->get_param( 'cnt_id' ),
410 'key' => $this->get_param( 'key' ),
411 ),
412 ) );
413 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/lov', array(
414 'methods' => array('POST'),
415 'callback' => array($this, 'app_lov'),
416 'permission_callback' => '__return_true',
417 'args' => array(
418 'app_id' => $this->get_param( 'app_id' ),
419 'cnt_id' => $this->get_param( 'cnt_id' ),
420 'col' => $this->get_param( 'col' ),
421 'cols' => $this->get_param( 'cols' ),
422 'search' => $this->get_param( 'search' ),
423 'search_columns' => $this->get_param( 'search_columns' ),
424 'search_column_fns' => $this->get_param( 'search_column_fns' ),
425 'search_column_lov' => $this->get_param( 'search_column_lov' ),
426 'search_data_types' => $this->get_param( 'search_data_types' ),
427 'search_custom' => $this->get_param( 'search_custom' ),
428 'search_params' => $this->get_param( 'search_params' ),
429 'shortcode_params' => $this->get_param( 'search_params' ),
430 'md' => $this->get_param( 'md' ),
431 'cascade' => $this->get_param( 'cascade' ),
432 ),
433 ) );
434 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/lookup', array(
435 'methods' => array('POST'),
436 'callback' => array($this, 'app_lookup'),
437 'permission_callback' => '__return_true',
438 'args' => array(
439 'app_id' => $this->get_param( 'app_id' ),
440 'cnt_id' => $this->get_param( 'cnt_id' ),
441 'target' => array(
442 'required' => true,
443 'type' => 'string',
444 'description' => __( 'Target: table or (r)form', 'wp-data-access' ),
445 'sanitize_callback' => 'sanitize_text_field',
446 'validate_callback' => 'rest_validate_request_arg',
447 ),
448 'col' => $this->get_param( 'col' ),
449 'colk' => $this->get_param( 'col' ),
450 'colv' => $this->get_param( 'col' ),
451 'cold' => $this->get_param( 'key' ),
452 'cols' => $this->get_param( 'cols' ),
453 'search' => $this->get_param( 'search' ),
454 'search_columns' => $this->get_param( 'search_columns' ),
455 'search_column_fns' => $this->get_param( 'search_column_fns' ),
456 'search_column_lov' => $this->get_param( 'search_column_lov' ),
457 'search_data_types' => $this->get_param( 'search_data_types' ),
458 'search_custom' => $this->get_param( 'search_custom' ),
459 'search_params' => $this->get_param( 'search_params' ),
460 'shortcode_params' => $this->get_param( 'search_params' ),
461 'md' => $this->get_param( 'md' ),
462 'cascade' => $this->get_param( 'cascade' ),
463 'values' => $this->get_param( 'md' ),
464 ),
465 ) );
466 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/lookup/dbs', array(
467 'methods' => array('POST'),
468 'callback' => array($this, 'app_lookup_dbs'),
469 'permission_callback' => '__return_true',
470 'args' => array(
471 'app_id' => $this->get_param( 'app_id' ),
472 'cnt_id' => $this->get_param( 'cnt_id' ),
473 ),
474 ) );
475 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/lookup/tbl', array(
476 'methods' => array('POST'),
477 'callback' => array($this, 'app_lookup_tbl'),
478 'permission_callback' => '__return_true',
479 'args' => array(
480 'app_id' => $this->get_param( 'app_id' ),
481 'cnt_id' => $this->get_param( 'cnt_id' ),
482 'dbs' => $this->get_param( 'dbs' ),
483 ),
484 ) );
485 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/lookup/cls', array(
486 'methods' => array('POST'),
487 'callback' => array($this, 'app_lookup_cls'),
488 'permission_callback' => '__return_true',
489 'args' => array(
490 'app_id' => $this->get_param( 'app_id' ),
491 'cnt_id' => $this->get_param( 'cnt_id' ),
492 'dbs' => $this->get_param( 'dbs' ),
493 'tbl' => $this->get_param( 'tbl' ),
494 ),
495 ) );
496 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/qb/list', array(
497 'methods' => array('POST'),
498 'callback' => array($this, 'app_qb_list'),
499 'permission_callback' => '__return_true',
500 ) );
501 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/chart/data', array(
502 'methods' => array('POST'),
503 'callback' => array($this, 'app_chart_data'),
504 'permission_callback' => '__return_true',
505 'args' => array(
506 'app_id' => $this->get_param( 'app_id' ),
507 'search_custom' => $this->get_param( 'search_custom' ),
508 'shortcode_params' => $this->get_param( 'search_params' ),
509 ),
510 ) );
511 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/dbs/rename', array(
512 'methods' => array('POST'),
513 'callback' => array($this, 'app_dbs_rename'),
514 'permission_callback' => '__return_true',
515 'args' => array(
516 'dbs_source' => $this->get_param( 'dbs' ),
517 'dbs_destination' => $this->get_param( 'dbs' ),
518 ),
519 ) );
520 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/lang/get', array(
521 'methods' => array('POST'),
522 'callback' => array($this, 'app_lang_get'),
523 'permission_callback' => '__return_true',
524 ) );
525 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/lang/set', array(
526 'methods' => array('POST'),
527 'callback' => array($this, 'app_lang_set'),
528 'permission_callback' => '__return_true',
529 'args' => array(
530 'localizations' => array(
531 'required' => true,
532 'type' => 'mixed',
533 'description' => __( 'Custom side translations (JSON as string)', 'wp-data-access' ),
534 'sanitize_callback' => 'sanitize_text_field',
535 'validate_callback' => 'rest_validate_request_arg',
536 ),
537 ),
538 ) );
539 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/call', array(
540 'methods' => array('POST'),
541 'callback' => array($this, 'app_call'),
542 'permission_callback' => '__return_true',
543 'args' => array(
544 'app_id' => $this->get_param( 'app_id' ),
545 'cls' => array(
546 'required' => true,
547 'type' => 'string',
548 'description' => __( 'Class name', 'wp-data-access' ),
549 'sanitize_callback' => 'sanitize_text_field',
550 'validate_callback' => 'rest_validate_request_arg',
551 ),
552 'fnc' => array(
553 'required' => true,
554 'type' => 'string',
555 'description' => __( 'Function name', 'wp-data-access' ),
556 'sanitize_callback' => 'sanitize_text_field',
557 'validate_callback' => 'rest_validate_request_arg',
558 ),
559 'arg' => array(
560 'required' => true,
561 'type' => 'mixed',
562 'description' => __( 'Arguments', 'wp-data-access' ),
563 'sanitize_callback' => 'sanitize_text_field',
564 'validate_callback' => 'rest_validate_request_arg',
565 ),
566 ),
567 ) );
568 }
569
570 public function app_call( $request ) {
571 return $this->bad_request();
572 }
573
574 public function app_lang_get( $request ) {
575 if ( !$this->current_user_can_access() ) {
576 // Only admins
577 return $this->unauthorized();
578 }
579 if ( !$this->current_user_token_valid( $request ) ) {
580 return $this->invalid_nonce();
581 }
582 return $this->WPDA_Rest_Response( '', WPDA_App_Localization::get() );
583 }
584
585 public function app_lang_set( $request ) {
586 if ( !$this->current_user_can_access() ) {
587 // Only admins
588 return $this->unauthorized();
589 }
590 if ( !$this->current_user_token_valid( $request ) ) {
591 return $this->invalid_nonce();
592 }
593 $localizations = $request->get_param( 'localizations' );
594 WPDA_App_Localization::set( $localizations );
595 return $this->WPDA_Rest_Response( 'Translation successfully saved' );
596 }
597
598 private function get_app_columns( $columns ) {
599 if ( !is_array( $columns ) ) {
600 return false;
601 }
602 return array_map( function ( $value ) {
603 return $value['columnName'];
604 }, array_filter( $columns, function ( $column ) {
605 return $column['isSelected'];
606 } ) );
607 }
608
609 private function get_app_table_columns( $settings, $table_settings ) {
610 if ( !isset( $settings['columns'] ) ) {
611 return false;
612 }
613 $columns = $this->get_app_columns( $settings['columns'] );
614 if ( false === $columns ) {
615 return false;
616 }
617 $columns_available = array_flip( $columns );
618 if ( !isset( $settings['table'] ) ) {
619 return array_map( function () {
620 return true;
621 }, $columns_available );
622 }
623 if ( !is_array( $table_settings ) || !isset( $table_settings['columns'] ) ) {
624 return false;
625 }
626 $table_columns = $table_settings['columns'];
627 for ($i = 0; $i < count( $columns ); $i++) {
628 if ( isset( $columns_available[$columns[$i]] ) ) {
629 $column_name = $columns[$i];
630 $columns_available[$columns[$i]] = count( array_filter( $table_columns, function ( $column ) use($columns, $column_name) {
631 if ( !isset( $column['columnName'], $column['queryable'] ) ) {
632 return false;
633 }
634 $queryable = $column['queryable'];
635 return $column_name === $column['columnName'] && true === $queryable;
636 } ) ) > 0;
637 }
638 }
639 return $columns_available;
640 }
641
642 private function get_app_form_columns( $settings ) {
643 if ( !isset( $settings['columns'] ) ) {
644 return false;
645 }
646 return $this->get_app_columns( $settings['columns'] );
647 }
648
649 public function app_export( $request ) {
650 $app_id = $request->get_param( 'app_id' );
651 if ( !$this->main_app_access( $app_id, $msg ) ) {
652 if ( 'rest_cookie_invalid_nonce' === $msg ) {
653 return $this->invalid_nonce();
654 }
655 return $this->unauthorized();
656 }
657 if ( !$this->current_user_token_valid( $request ) ) {
658 return $this->invalid_nonce();
659 }
660 return $this->do_app_export( $app_id );
661 }
662
663 public function app_copy( $request ) {
664 $app_id = $request->get_param( 'app_id' );
665 if ( !$this->main_app_access( $app_id, $msg ) ) {
666 if ( 'rest_cookie_invalid_nonce' === $msg ) {
667 return $this->invalid_nonce();
668 }
669 return $this->unauthorized();
670 }
671 if ( !$this->current_user_token_valid( $request ) ) {
672 return $this->invalid_nonce();
673 }
674 return $this->do_app_copy( $app_id );
675 }
676
677 public function app_details( $request ) {
678 $app_id = $request->get_param( 'app_id' );
679 $cnt_id = $request->get_param( 'cnt_id' );
680 if ( $this->check_app_access(
681 $app_id,
682 $cnt_id,
683 'select',
684 $dbs,
685 $tbl,
686 $msg,
687 $settings
688 ) ) {
689 return $this->WPDA_Rest_Response( '', WPDA_App_Container_Model::select( $app_id, 1 ) );
690 } else {
691 if ( 'rest_cookie_invalid_nonce' === $msg ) {
692 return $this->invalid_nonce();
693 } else {
694 return new \WP_Error('error', $msg, array(
695 'status' => 401,
696 ));
697 }
698 }
699 }
700
701 public function app_detail_meta( $request ) {
702 $app_id = $request->get_param( 'app_id' );
703 $cnt_id = $request->get_param( 'cnt_id' );
704 $rel_tab = $request->get_param( 'rel_tab' );
705 if ( $this->check_app_access(
706 $app_id,
707 $cnt_id,
708 'select',
709 $dbs,
710 $tbl,
711 $msg,
712 $settings
713 ) ) {
714 $container = WPDA_App_Container_Model::get_container( $app_id, $cnt_id );
715 if ( !isset( $container[0] ) ) {
716 return $this->bad_request();
717 }
718 return $this->get_app_container_meta( $app_id, $container, $rel_tab );
719 } else {
720 if ( 'rest_cookie_invalid_nonce' === $msg ) {
721 return $this->invalid_nonce();
722 } else {
723 return new \WP_Error('error', $msg, array(
724 'status' => 401,
725 ));
726 }
727 }
728 }
729
730 public function app_detail_reorder( $request ) {
731 $app_id = $request->get_param( 'app_id' );
732 $cnt_id_from = $request->get_param( 'cnt_id_from' );
733 $cnt_id_to = $request->get_param( 'cnt_id_to' );
734 if ( $this->check_app_access(
735 $app_id,
736 $cnt_id_from,
737 'select',
738 $dbs,
739 $tbl,
740 $msg,
741 $settings
742 ) ) {
743 $container = WPDA_App_Container_Model::get_container( $app_id, $cnt_id_from );
744 if ( !isset( $container[0] ) ) {
745 return $this->bad_request();
746 }
747 $container = WPDA_App_Container_Model::get_container( $app_id, $cnt_id_to );
748 if ( !isset( $container[0] ) ) {
749 return $this->bad_request();
750 }
751 return $this->reorder_details( $app_id, $cnt_id_from, $cnt_id_to );
752 } else {
753 if ( 'rest_cookie_invalid_nonce' === $msg ) {
754 return $this->invalid_nonce();
755 } else {
756 return new \WP_Error('error', $msg, array(
757 'status' => 401,
758 ));
759 }
760 }
761 }
762
763 public function app_relationship_create( $request ) {
764 if ( !$this->current_user_can_access() ) {
765 return $this->unauthorized();
766 }
767 if ( !$this->current_user_token_valid( $request ) ) {
768 return $this->invalid_nonce();
769 }
770 $app_id = $request->get_param( 'app_id' );
771 $app_title = $request->get_param( 'app_title' );
772 $app_dbs = $request->get_param( 'app_dbs' );
773 $app_tbl = $request->get_param( 'app_tbl' );
774 $app_cls = $request->get_param( 'app_cls' );
775 $app_relation = $request->get_param( 'app_relation' );
776 return $this->WPDA_Rest_Response( '', WPDA_App_Container_Model::create(
777 $app_id,
778 $app_dbs,
779 $app_tbl,
780 json_encode( $app_cls ),
781 $app_title,
782 1,
783 null,
784 $app_relation
785 ) );
786 }
787
788 public function app_relationship_update( $request ) {
789 if ( !$this->current_user_can_access() ) {
790 return $this->unauthorized();
791 }
792 if ( !$this->current_user_token_valid( $request ) ) {
793 return $this->invalid_nonce();
794 }
795 $app_id = $request->get_param( 'app_id' );
796 $app_cnt = $request->get_param( 'app_cnt' );
797 $app_title = $request->get_param( 'app_title' );
798 $app_dbs = $request->get_param( 'app_dbs' );
799 $app_tbl = $request->get_param( 'app_tbl' );
800 $app_cls = $request->get_param( 'app_cls' );
801 $app_relation = $request->get_param( 'app_relation' );
802 return $this->WPDA_Rest_Response( '', WPDA_App_Container_Model::update(
803 $app_id,
804 $app_cnt,
805 $app_dbs,
806 $app_tbl,
807 json_encode( $app_cls ),
808 $app_title,
809 $app_relation
810 ) );
811 }
812
813 public function app_relationship_delete( $request ) {
814 if ( !$this->current_user_can_access() ) {
815 return $this->unauthorized();
816 }
817 if ( !$this->current_user_token_valid( $request ) ) {
818 return $this->invalid_nonce();
819 }
820 $cnt_id = $request->get_param( 'cnt_id' );
821 return $this->WPDA_Rest_Response( '', WPDA_App_Container_Model::delete_container( $cnt_id ) );
822 }
823
824 private function build_lookups(
825 $table_settings,
826 $dbs,
827 &$search_columns,
828 $search_column_lov,
829 $search_column_fns,
830 &$default_where,
831 &$lookups
832 ) {
833 return $this->bad_request();
834 }
835
836 private function build_relationships(
837 $container,
838 &$m2m_relationship,
839 $tbl,
840 &$default_where
841 ) {
842 return $this->bad_request();
843 }
844
845 public function app_select( $request ) {
846 $app_id = $request->get_param( 'app_id' );
847 $cnt_id = $request->get_param( 'cnt_id' );
848 $col = $request->get_param( 'col' );
849 $page_index = $request->get_param( 'page_index' );
850 $page_size = $request->get_param( 'page_size' );
851 $search = $request->get_param( 'search' );
852 $search_columns = $request->get_param( 'search_columns' );
853 $search_column_fns = $request->get_param( 'search_column_fns' );
854 $search_column_lov = $request->get_param( 'search_column_lov' );
855 $search_data_types = $request->get_param( 'search_data_types' );
856 $search_custom = $request->get_param( 'search_custom' );
857 $search_params = $request->get_param( 'search_params' );
858 $shortcode_params = $request->get_param( 'shortcode_params' );
859 $md = $request->get_param( 'md' );
860 $sorting = $request->get_param( 'sorting' );
861 $row_count = $request->get_param( 'row_count' );
862 $row_count_estimate = $request->get_param( 'row_count_estimate' );
863 $media = $request->get_param( 'media' );
864 $rel_tab = $request->get_param( 'rel_tab' );
865 $client_side = '1' === $request->get_param( 'client_side' );
866 $geo_radius = $request->get_param( 'geo_radius' );
867 $default_where = '';
868 $default_orderby = '';
869 $lookups = array();
870 $m2m_relationship = array();
871 if ( $client_side ) {
872 // Delete search values on refresh
873 $search = '';
874 $search_columns = array();
875 }
876 if ( $this->check_app_access(
877 $app_id,
878 $cnt_id,
879 'select',
880 $dbs,
881 $tbl,
882 $msg,
883 $settings
884 ) ) {
885 $container = WPDA_App_Container_Model::get_container( $app_id, $cnt_id );
886 $app = WPDA_App_Model::get_by_id( $app_id );
887 if ( isset( $app[0]['app_type'], $container[0]['cnt_map'] ) && '2' == $app[0]['app_type'] && null !== $container[0]['cnt_map'] ) {
888 // App = Map
889 // Get default where map
890 $map_json = json_decode( (string) $container[0]['cnt_map'], true );
891 if ( isset( $map_json['setup']['defaultWhere'] ) && null !== $map_json['setup']['defaultWhere'] && '' !== trim( $map_json['setup']['defaultWhere'] ) ) {
892 $default_where = $map_json['setup']['defaultWhere'];
893 }
894 } else {
895 // All other apps (not being a map)
896 if ( '1' === $rel_tab ) {
897 } else {
898 $table_settings = $settings['table'] ?? array();
899 // Get default where clause
900 if ( isset( $table_settings['table']['defaultWhere'] ) ) {
901 $default_where = $table_settings['table']['defaultWhere'];
902 }
903 // Get default order by
904 if ( isset( $table_settings['table']['defaultOrderBy'] ) ) {
905 $default_orderby_db = $table_settings['table']['defaultOrderBy'];
906 if ( is_array( $default_orderby_db ) ) {
907 foreach ( $default_orderby_db as $orderby ) {
908 if ( isset( $orderby['columnName'], $orderby['order'] ) && '' !== trim( $orderby['columnName'] ) ) {
909 $default_orderby .= (( '' === $default_orderby ? 'order by ' : ',' )) . '`' . WPDA::remove_backticks( $orderby['columnName'] ) . '` ' . (( 'desc' === $orderby['order'] ? 'desc' : 'asc' ));
910 }
911 }
912 }
913 }
914 }
915 }
916 $table_api = new WPDA_Table();
917 return $table_api->select(
918 $dbs,
919 $tbl,
920 $col,
921 $page_index,
922 $page_size,
923 $search,
924 $search_columns,
925 $search_column_fns,
926 $sorting,
927 $row_count,
928 $row_count_estimate,
929 $media,
930 $this->process_params(
931 $default_where,
932 $search_custom,
933 $search_params,
934 $shortcode_params
935 ),
936 $default_orderby,
937 $lookups,
938 $md,
939 $m2m_relationship,
940 $search_data_types,
941 $client_side,
942 $geo_radius
943 );
944 } else {
945 if ( 'rest_cookie_invalid_nonce' === $msg ) {
946 return $this->invalid_nonce();
947 } else {
948 return new \WP_Error('error', $msg, array(
949 'status' => 401,
950 ));
951 }
952 }
953 }
954
955 private function get_m2m_relationship( $relationship, $tbl, $cols ) {
956 return array();
957 }
958
959 private function get_lookup_lov( $column_lookup, $search_value, $search_type ) {
960 return null;
961 }
962
963 private function convert_relation_columns( $columns ) {
964 return array_map( function ( $value ) {
965 if ( true === $value['isSelected'] ) {
966 return $value['columnName'];
967 }
968 }, $columns );
969 }
970
971 public function app_get( $request ) {
972 $app_id = $request->get_param( 'app_id' );
973 $cnt_id = $request->get_param( 'cnt_id' );
974 $key = $request->get_param( 'key' );
975 $media = $request->get_param( 'media' );
976 $rel_tab = $request->get_param( 'rel_tab' );
977 if ( $this->check_app_access(
978 $app_id,
979 $cnt_id,
980 'select',
981 $dbs,
982 $tbl,
983 $msg,
984 $settings
985 ) ) {
986 $column_names = $this->get_app_form_columns( $settings );
987 if ( false === $column_names ) {
988 return $this->invalid_app_settings();
989 }
990 $default_where = '';
991 $table_api = new WPDA_Table();
992 return $table_api->get(
993 $dbs,
994 $tbl,
995 $key,
996 $media,
997 $column_names,
998 $default_where
999 );
1000 } else {
1001 if ( 'rest_cookie_invalid_nonce' === $msg ) {
1002 return $this->invalid_nonce();
1003 } else {
1004 return new \WP_Error('error', $msg, array(
1005 'status' => 401,
1006 ));
1007 }
1008 }
1009 }
1010
1011 public function app_insert( $request ) {
1012 $app_id = $request->get_param( 'app_id' );
1013 $cnt_id = $request->get_param( 'cnt_id' );
1014 $val = $request->get_param( 'val' );
1015 $join_tab = $request->get_param( 'join_tab' );
1016 $rel_tab = $request->get_param( 'rel_tab' );
1017 if ( $this->check_app_access(
1018 $app_id,
1019 $cnt_id,
1020 'insert',
1021 $dbs,
1022 $tbl,
1023 $msg
1024 ) ) {
1025 $table_api = new WPDA_Table();
1026 return $table_api->insert( $dbs, $tbl, $val );
1027 } else {
1028 if ( 'rest_cookie_invalid_nonce' === $msg ) {
1029 return $this->invalid_nonce();
1030 } else {
1031 return new \WP_Error('error', $msg, array(
1032 'status' => 401,
1033 ));
1034 }
1035 }
1036 }
1037
1038 public function app_update( $request ) {
1039 $app_id = $request->get_param( 'app_id' );
1040 $cnt_id = $request->get_param( 'cnt_id' );
1041 $key = $request->get_param( 'key' );
1042 $val = $request->get_param( 'val' );
1043 $join_tab = $request->get_param( 'join_tab' );
1044 $rel_tab = $request->get_param( 'rel_tab' );
1045 if ( $this->check_app_access(
1046 $app_id,
1047 $cnt_id,
1048 'update',
1049 $dbs,
1050 $tbl,
1051 $msg,
1052 $settings
1053 ) ) {
1054 $column_names = $this->get_app_form_columns( $settings );
1055 if ( false === $column_names ) {
1056 $column_names = array();
1057 }
1058 $code_columns = array();
1059 $html_columns = array();
1060 if ( isset( $settings['form']['columns'] ) ) {
1061 foreach ( $settings['form']['columns'] as $column ) {
1062 if ( isset( $column['allowHtml'] ) && false === $column['allowHtml'] ) {
1063 $html_columns[] = $column['columnName'];
1064 }
1065 }
1066 }
1067 $table_api = new WPDA_Table();
1068 return $table_api->update(
1069 $dbs,
1070 $tbl,
1071 $key,
1072 $val,
1073 $column_names,
1074 $code_columns,
1075 $html_columns
1076 );
1077 } else {
1078 if ( 'rest_cookie_invalid_nonce' === $msg ) {
1079 return $this->invalid_nonce();
1080 } else {
1081 return new \WP_Error('error', $msg, array(
1082 'status' => 401,
1083 ));
1084 }
1085 }
1086 }
1087
1088 public function app_update_inline( $request ) {
1089 return $this->bad_request();
1090 }
1091
1092 public function app_delete( $request ) {
1093 $app_id = $request->get_param( 'app_id' );
1094 $cnt_id = $request->get_param( 'cnt_id' );
1095 $key = $request->get_param( 'key' );
1096 if ( $this->check_app_access(
1097 $app_id,
1098 $cnt_id,
1099 'delete',
1100 $dbs,
1101 $tbl,
1102 $msg
1103 ) ) {
1104 $table_api = new WPDA_Table();
1105 return $table_api->delete( $dbs, $tbl, $key );
1106 } else {
1107 if ( 'rest_cookie_invalid_nonce' === $msg ) {
1108 return $this->invalid_nonce();
1109 } else {
1110 return new \WP_Error('error', $msg, array(
1111 'status' => 401,
1112 ));
1113 }
1114 }
1115 }
1116
1117 public function app_lov( $request ) {
1118 return $this->bad_request();
1119 }
1120
1121 public function app_lookup( $request ) {
1122 $app_id = $request->get_param( 'app_id' );
1123 $cnt_id = $request->get_param( 'cnt_id' );
1124 $target = $request->get_param( 'target' );
1125 $col = $request->get_param( 'col' );
1126 $colk = $request->get_param( 'colk' );
1127 $colv = $request->get_param( 'colv' );
1128 $cold = $request->get_param( 'cold' );
1129 $cols = $request->get_param( 'cols' );
1130 $search = $request->get_param( 'search' );
1131 $search_columns = $request->get_param( 'search_columns' );
1132 $search_column_fns = $request->get_param( 'search_column_fns' );
1133 $search_column_lov = $request->get_param( 'search_column_lov' );
1134 $search_data_types = $request->get_param( 'search_data_types' );
1135 $search_custom = $request->get_param( 'search_custom' );
1136 $search_params = $request->get_param( 'search_params' );
1137 $shortcode_params = $request->get_param( 'shortcode_params' );
1138 $md = $request->get_param( 'md' );
1139 $cascade = $request->get_param( 'cascade' );
1140 $values = $request->get_param( 'values' );
1141 $default_where = '';
1142 $default_where_lookup = '';
1143 $lookups = array();
1144 $m2m_relationship = array();
1145 if ( $this->check_app_access(
1146 $app_id,
1147 $cnt_id,
1148 'select',
1149 $dbs,
1150 $tbl,
1151 $msg,
1152 $settings
1153 ) ) {
1154 $container = WPDA_App_Container_Model::get_container( $app_id, $cnt_id );
1155 if ( !isset( $container[0] ) ) {
1156 return $this->bad_request();
1157 }
1158 $lookup = array();
1159 $lookup_dbs = "";
1160 $lookup_tbl = "";
1161 if ( 'form' === $target ) {
1162 // Handle form lookup
1163 if ( isset( $container[0]['cnt_form'] ) ) {
1164 $lookup = json_decode( (string) $container[0]['cnt_form'], true );
1165 }
1166 } else {
1167 if ( 'rform' === $target ) {
1168 // Handle form lookup
1169 if ( isset( $container[0]['cnt_rform'] ) ) {
1170 $lookup = json_decode( (string) $container[0]['cnt_rform'], true );
1171 }
1172 } else {
1173 // Handle table lookup
1174 if ( isset( $container[0]['cnt_table'] ) ) {
1175 $lookup = json_decode( (string) $container[0]['cnt_table'], true );
1176 }
1177 }
1178 }
1179 if ( isset( $lookup['columns'] ) && is_array( $lookup['columns'] ) ) {
1180 foreach ( $lookup['columns'] as $column ) {
1181 if ( $col === $column['columnName'] ) {
1182 if ( !isset( $column['lookup'] ) ) {
1183 return $this->WPDA_Rest_Response( '', [] );
1184 }
1185 $lookup_dbs = $column['lookup']['dbs'];
1186 $lookup_tbl = $column['lookup']['tbl'];
1187 if ( isset( $column['columnName'], $column['lookup']['defaultWhere'] ) ) {
1188 $default_where_lookup = $column['lookup']['defaultWhere'];
1189 }
1190 }
1191 }
1192 }
1193 if ( $lookup_dbs === null || $lookup_dbs === "" || $lookup_tbl === null || $lookup_tbl === "" ) {
1194 return $this->bad_request();
1195 }
1196 $table_api = new WPDA_Table();
1197 return $table_api->lookup(
1198 $lookup_dbs,
1199 $lookup_tbl,
1200 $colk,
1201 $colv,
1202 $cold,
1203 $this->process_params(
1204 $default_where_lookup,
1205 $search_custom,
1206 $search_params,
1207 $shortcode_params,
1208 $values
1209 ),
1210 '1' === $cascade,
1211 $tbl,
1212 $col,
1213 $this->process_params(
1214 $default_where,
1215 $search_custom,
1216 $search_params,
1217 $shortcode_params,
1218 $values
1219 ),
1220 $search,
1221 $cols,
1222 $search_columns,
1223 $search_column_fns,
1224 $lookups,
1225 $md,
1226 $m2m_relationship,
1227 $search_data_types
1228 );
1229 } else {
1230 if ( 'rest_cookie_invalid_nonce' === $msg ) {
1231 return $this->invalid_nonce();
1232 } else {
1233 return new \WP_Error('error', $msg, array(
1234 'status' => 401,
1235 ));
1236 }
1237 }
1238 }
1239
1240 public function app_lookup_dbs( $request ) {
1241 $app_id = $request->get_param( 'app_id' );
1242 $cnt_id = $request->get_param( 'cnt_id' );
1243 if ( $this->check_app_access(
1244 $app_id,
1245 $cnt_id,
1246 'select',
1247 $_dbs,
1248 $_tbl,
1249 $msg
1250 ) ) {
1251 $tree_api = new WPDA_Tree();
1252 return $tree_api->get_dbs();
1253 } else {
1254 if ( 'rest_cookie_invalid_nonce' === $msg ) {
1255 return $this->invalid_nonce();
1256 } else {
1257 return new \WP_Error('error', $msg, array(
1258 'status' => 401,
1259 ));
1260 }
1261 }
1262 }
1263
1264 public function app_lookup_tbl( $request ) {
1265 $app_id = $request->get_param( 'app_id' );
1266 $cnt_id = $request->get_param( 'cnt_id' );
1267 $dbs = $request->get_param( 'dbs' );
1268 if ( $this->check_app_access(
1269 $app_id,
1270 $cnt_id,
1271 'select',
1272 $_dbs,
1273 $_tbl,
1274 $msg
1275 ) ) {
1276 $tree_api = new WPDA_Tree();
1277 return $tree_api->get_tbl_vws( $dbs );
1278 } else {
1279 if ( 'rest_cookie_invalid_nonce' === $msg ) {
1280 return $this->invalid_nonce();
1281 } else {
1282 return new \WP_Error('error', $msg, array(
1283 'status' => 401,
1284 ));
1285 }
1286 }
1287 }
1288
1289 public function app_lookup_cls( $request ) {
1290 $app_id = $request->get_param( 'app_id' );
1291 $cnt_id = $request->get_param( 'cnt_id' );
1292 $dbs = $request->get_param( 'dbs' );
1293 $tbl = $request->get_param( 'tbl' );
1294 if ( $this->check_app_access(
1295 $app_id,
1296 $cnt_id,
1297 'select',
1298 $_dbs,
1299 $_tbl,
1300 $msg
1301 ) ) {
1302 $tree_api = new WPDA_Tree();
1303 return $tree_api->get_cls( $dbs, $tbl );
1304 } else {
1305 if ( 'rest_cookie_invalid_nonce' === $msg ) {
1306 return $this->invalid_nonce();
1307 } else {
1308 return new \WP_Error('error', $msg, array(
1309 'status' => 401,
1310 ));
1311 }
1312 }
1313 }
1314
1315 public function app_qb_list( $request ) {
1316 $qb = new WPDA_QB();
1317 return $qb->open( $request );
1318 }
1319
1320 public function app_dbs_rename( $request ) {
1321 if ( !$this->current_user_can_access() ) {
1322 // Only admins
1323 return $this->unauthorized();
1324 }
1325 if ( !$this->current_user_token_valid( $request ) ) {
1326 return $this->invalid_nonce();
1327 }
1328 $dbs_source = $request->get_param( 'dbs_source' );
1329 $dbs_destination = $request->get_param( 'dbs_destination' );
1330 if ( '' === trim( $dbs_source ) || '' === trim( $dbs_destination ) ) {
1331 return new \WP_Error('error', 'Invalid arguments', array(
1332 'status' => 401,
1333 ));
1334 }
1335 global $wpdb;
1336 $renamed = 0;
1337 $debug_mode = 'on' === WPDA::get_option( WPDA::OPTION_PLUGIN_DEBUG );
1338 $debug = array();
1339 $errors = array();
1340 // Rename all occurrences in repository tables and apps
1341 $sqls = array(
1342 "update `{$wpdb->prefix}wpda_publisher` set `pub_schema_name` = %s where `pub_schema_name` = %s",
1343 "update `{$wpdb->prefix}wpda_project_page` set `page_schema_name` = %s where `page_schema_name` = %s",
1344 "update `{$wpdb->prefix}wpda_project_table` set `wpda_schema_name` = %s where `wpda_schema_name` = %s",
1345 "update `{$wpdb->prefix}wpda_media` set `media_schema_name` = %s where `media_schema_name` = %s",
1346 "update `{$wpdb->prefix}wpda_menus` set `menu_schema_name` = %s where `menu_schema_name` = %s",
1347 "update `{$wpdb->prefix}wpda_table_design` set `wpda_schema_name` = %s where `wpda_schema_name` = %s",
1348 "update `{$wpdb->prefix}wpda_table_settings` set `wpda_schema_name` = %s where `wpda_schema_name` = %s",
1349 "update `{$wpdb->prefix}wpda_app_container` set `cnt_dbs` = %s where `cnt_dbs` = %s"
1350 );
1351 foreach ( $sqls as $sql ) {
1352 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared -- plugin table
1353 $result = $wpdb->query( $wpdb->prepare( $sql, array($dbs_destination, $dbs_source) ) );
1354 // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
1355 $renamed += $result;
1356 if ( $debug_mode ) {
1357 $debug[] = array(
1358 'sql' => $sql,
1359 'result' => $result,
1360 );
1361 }
1362 if ( '' !== $wpdb->last_error ) {
1363 $errors[] = array(
1364 'sql' => $sql,
1365 'error' => $wpdb->last_error,
1366 );
1367 }
1368 }
1369 $sql_content = array("update `{$wpdb->prefix}wpda_app_container` set `cnt_table` = replace(`cnt_table`, '\"dbs\":\"%1s\"', '\"dbs\":\"%1s\"') where `cnt_table` like '%\"dbs\":\"%1s\"%'", "update `{$wpdb->prefix}wpda_app_container` set `cnt_form` = replace(`cnt_form`, '\"dbs\":\"%1s\"', '\"dbs\":\"%1s\"') where `cnt_form` like '%\"dbs\":\"%1s\"%'");
1370 foreach ( $sql_content as $sql ) {
1371 // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared -- plugin table
1372 $result = $wpdb->query( $wpdb->prepare( $sql, array($dbs_source, $dbs_destination, $dbs_source) ) );
1373 $renamed += $result;
1374 if ( $debug_mode ) {
1375 $debug[] = array(
1376 'sql' => $sql,
1377 'result' => $result,
1378 );
1379 }
1380 if ( '' !== $wpdb->last_error ) {
1381 $errors[] = array(
1382 'sql' => $sql,
1383 'error' => $wpdb->last_error,
1384 );
1385 }
1386 }
1387 $context = array();
1388 if ( $debug_mode ) {
1389 $context['debug'] = $debug;
1390 }
1391 if ( 0 < count( $errors ) ) {
1392 $context['errors'] = $errors;
1393 return new \WP_Error('error', 'Failed renaming database', array(
1394 'status' => 401,
1395 'context' => $context,
1396 ));
1397 }
1398 return $this->WPDA_Rest_Response( sprintf(
1399 /* translators: %s = number of database substitutions */
1400 __( 'Successfully renamed %s database occurrences', 'wp-data-access' ),
1401 $renamed
1402 ), null, $context );
1403 }
1404
1405 public function app_chart_data( $request ) {
1406 $app_id = $request->get_param( 'app_id' );
1407 $search_custom = $request->get_param( 'search_custom' );
1408 $shortcode_params = $request->get_param( 'shortcode_params' );
1409 if ( !$this->main_app_access( $app_id, $msg ) ) {
1410 if ( 'rest_cookie_invalid_nonce' === $msg ) {
1411 return $this->invalid_nonce();
1412 }
1413 return $this->unauthorized();
1414 }
1415 if ( !$this->current_user_token_valid( $request ) ) {
1416 return $this->invalid_nonce();
1417 }
1418 $app_container = WPDA_App_Container_Model::select( $app_id, 0 );
1419 if ( 1 === count( $app_container ) && null !== $app_container[0]['cnt_query'] && '' !== trim( (string) $app_container[0]['cnt_query'] ) ) {
1420 $dbs = $app_container[0]['cnt_dbs'];
1421 $query = $app_container[0]['cnt_query'];
1422 // Process shortcode and url parameters
1423 $query = $this->process_params(
1424 $query,
1425 $search_custom,
1426 null,
1427 $shortcode_params
1428 );
1429 $wpdadb = WPDADB::get_db_connection( $dbs );
1430 if ( null === $wpdadb ) {
1431 // Error connecting.
1432 return new \WP_Error('error', "Error connecting to database {$dbs}", array(
1433 'status' => 420,
1434 ));
1435 }
1436 $suppress = $wpdadb->suppress_errors( true );
1437 $chart_data = $wpdadb->get_results( $query, 'ARRAY_A' );
1438 $wpdadb->get_results( "create temporary table `wpda_chart_data_types` as {$query}", 'ARRAY_A' );
1439 $explain = $wpdadb->get_results( "desc `wpda_chart_data_types`", 'ARRAY_A' );
1440 $wpdadb->get_results( "drop temporary table `wpda_chart_data_types`", 'ARRAY_A' );
1441 $wpdadb->suppress_errors( $suppress );
1442 return array(
1443 'data' => $chart_data,
1444 'explain' => $explain,
1445 );
1446 } else {
1447 return new \WP_Error('error', $msg, array(
1448 'status' => 401,
1449 ));
1450 }
1451 }
1452
1453 public function app_lang( $request ) {
1454 if ( !$this->current_user_can_access() ) {
1455 return $this->unauthorized();
1456 }
1457 if ( !$this->current_user_token_valid( $request ) ) {
1458 return $this->invalid_nonce();
1459 }
1460 $lang = $request->get_param( 'lang' );
1461 update_option( self::WPDA_APP_DEFAULT_LANG, $lang );
1462 return $this->WPDA_Rest_Response( __( 'Successfully saved changes', 'wp-data-access' ) );
1463 }
1464
1465 public function app_meta( $request ) {
1466 $app_id = $request->get_param( 'app_id' );
1467 if ( !$this->main_app_access( $app_id, $msg ) ) {
1468 if ( 'rest_cookie_invalid_nonce' === $msg ) {
1469 return $this->invalid_nonce();
1470 }
1471 return $this->unauthorized();
1472 }
1473 if ( !$this->current_user_token_valid( $request ) ) {
1474 return $this->invalid_nonce();
1475 }
1476 return $this->get_app_meta( $app_id );
1477 }
1478
1479 public function app_settings( $request ) {
1480 if ( !$this->current_user_can_access() ) {
1481 return $this->unauthorized();
1482 }
1483 if ( !$this->current_user_token_valid( $request ) ) {
1484 return $this->invalid_nonce();
1485 }
1486 $app_id = $request->get_param( 'app_id' );
1487 $cnt_id = $request->get_param( 'cnt_id' );
1488 $target = $request->get_param( 'target' );
1489 $settings = $request->get_param( 'settings' );
1490 $chart = $request->get_param( 'chart' );
1491 $map = $request->get_param( 'map' );
1492 $theme = $request->get_param( 'theme' );
1493 return $this->do_app_settings(
1494 $app_id,
1495 $cnt_id,
1496 $target,
1497 $settings,
1498 $chart,
1499 $map,
1500 $theme
1501 );
1502 }
1503
1504 public function app_init( $request ) {
1505 if ( !$this->current_user_can_access() ) {
1506 return $this->unauthorized();
1507 }
1508 if ( !$this->current_user_token_valid( $request ) ) {
1509 return $this->invalid_nonce();
1510 }
1511 return $this->get_app_init();
1512 }
1513
1514 public function app_list( $request ) {
1515 if ( !$this->current_user_can_access() ) {
1516 return $this->unauthorized();
1517 }
1518 if ( !$this->current_user_token_valid( $request ) ) {
1519 return $this->invalid_nonce();
1520 }
1521 return $this->get_app_list();
1522 }
1523
1524 public function app_table_meta( $request ) {
1525 $dbs = $request->get_param( 'dbs' );
1526 $tbl = $request->get_param( 'tbl' );
1527 $waa = $request->get_param( 'waa' );
1528 if ( !$this->current_user_can_access() ) {
1529 return $this->unauthorized();
1530 }
1531 if ( !$this->current_user_token_valid( $request ) ) {
1532 return $this->invalid_nonce();
1533 }
1534 $table_api = new WPDA_Table();
1535 return $this->WPDA_Rest_Response( '', $table_api->get_table_meta_data( $dbs, $tbl, $waa ) );
1536 }
1537
1538 public function app_create( $request ) {
1539 if ( !$this->current_user_can_access() ) {
1540 return $this->unauthorized();
1541 }
1542 if ( !$this->current_user_token_valid( $request ) ) {
1543 return $this->invalid_nonce();
1544 }
1545 // App details
1546 $app_name = $request->get_param( 'app_name' );
1547 $app_title = $request->get_param( 'app_title' );
1548 $app_type = $request->get_param( 'app_type' );
1549 $app_settings = $request->get_param( 'app_settings' );
1550 // App container
1551 $app_dbs = $request->get_param( 'app_dbs' );
1552 $app_tbl = $request->get_param( 'app_tbl' );
1553 $app_cls = $request->get_param( 'app_cls' );
1554 $app_table = $request->get_param( 'app_table' );
1555 $app_query = $request->get_param( 'app_query' );
1556 return $this->do_app_create(
1557 $app_name,
1558 $app_title,
1559 $app_type,
1560 $app_settings,
1561 $app_dbs,
1562 $app_tbl,
1563 $app_cls,
1564 $app_table,
1565 $app_query
1566 );
1567 }
1568
1569 public function app_createapp( $request ) {
1570 if ( !$this->current_user_can_access() ) {
1571 return $this->unauthorized();
1572 }
1573 if ( !$this->current_user_token_valid( $request ) ) {
1574 return $this->invalid_nonce();
1575 }
1576 $app_name = $request->get_param( 'app_name' );
1577 $app_title = $request->get_param( 'app_title' );
1578 $app_type = $request->get_param( 'app_type' );
1579 $app_settings = $request->get_param( 'app_settings' );
1580 $app_apps = $request->get_param( 'app_apps' );
1581 return $this->do_app_createapp(
1582 $app_name,
1583 $app_title,
1584 $app_type,
1585 $app_settings,
1586 $app_apps
1587 );
1588 }
1589
1590 public function app_remove( $request ) {
1591 if ( !$this->current_user_can_access() ) {
1592 return $this->unauthorized();
1593 }
1594 if ( !$this->current_user_token_valid( $request ) ) {
1595 return $this->invalid_nonce();
1596 }
1597 $app_id = $request->get_param( 'app_id' );
1598 return $this->do_app_remove( $app_id );
1599 }
1600
1601 public function app_save( $request ) {
1602 if ( !$this->current_user_can_access() ) {
1603 return $this->unauthorized();
1604 }
1605 if ( !$this->current_user_token_valid( $request ) ) {
1606 return $this->invalid_nonce();
1607 }
1608 // App details
1609 $app_id = $request->get_param( 'app_id' );
1610 $app_name = $request->get_param( 'app_name' );
1611 $app_title = $request->get_param( 'app_title' );
1612 $app_type = $request->get_param( 'app_type' );
1613 $app_settings = $request->get_param( 'app_settings' );
1614 $app_add_to_menu = $request->get_param( 'app_add_to_menu' );
1615 // App container
1616 $app_dbs = $request->get_param( 'app_dbs' );
1617 $app_tbl = $request->get_param( 'app_tbl' );
1618 $app_cls = $request->get_param( 'app_cls' );
1619 $app_query = $request->get_param( 'app_query' );
1620 return $this->do_app_save(
1621 $app_id,
1622 $app_name,
1623 $app_title,
1624 $app_type,
1625 $app_settings,
1626 $app_add_to_menu,
1627 $app_dbs,
1628 $app_tbl,
1629 $app_cls,
1630 $app_query
1631 );
1632 }
1633
1634 public function app_saveapp( $request ) {
1635 if ( !$this->current_user_can_access() ) {
1636 return $this->unauthorized();
1637 }
1638 if ( !$this->current_user_token_valid( $request ) ) {
1639 return $this->invalid_nonce();
1640 }
1641 $app_id = $request->get_param( 'app_id' );
1642 $app_name = $request->get_param( 'app_name' );
1643 $app_title = $request->get_param( 'app_title' );
1644 $app_type = $request->get_param( 'app_type' );
1645 $app_settings = $request->get_param( 'app_settings' );
1646 $app_add_to_menu = $request->get_param( 'app_add_to_menu' );
1647 $app_apps = $request->get_param( 'app_apps' );
1648 return $this->do_app_saveapp(
1649 $app_id,
1650 $app_name,
1651 $app_title,
1652 $app_type,
1653 $app_settings,
1654 $app_add_to_menu,
1655 $app_apps
1656 );
1657 }
1658
1659 private function do_app_settings(
1660 $app_id,
1661 $cnt_id,
1662 $target,
1663 $settings,
1664 $chart,
1665 $map,
1666 $theme
1667 ) {
1668 if ( 1 > $app_id || 1 > $cnt_id || 'table' !== $target && 'form' !== $target && 'rform' !== $target && 'theme' !== $target && 'chart' !== $target && 'map' !== $target && 'dashboard' !== $target ) {
1669 return $this->bad_request();
1670 }
1671 if ( null === $settings || '' === $settings ) {
1672 // Perform reset
1673 switch ( $target ) {
1674 case 'table':
1675 $error_msg = WPDA_App_Container_Model::update_table_settings( $cnt_id, null );
1676 if ( '' !== $error_msg ) {
1677 return new \WP_Error('error', $error_msg, array(
1678 'status' => 403,
1679 ));
1680 }
1681 break;
1682 case 'form':
1683 $error_msg = WPDA_App_Container_Model::update_form_settings( $cnt_id, null );
1684 if ( '' !== $error_msg ) {
1685 return new \WP_Error('error', $error_msg, array(
1686 'status' => 403,
1687 ));
1688 }
1689 break;
1690 case 'chart':
1691 $error_msg = WPDA_App_Container_Model::update_chart_settings( $cnt_id, null );
1692 if ( '' !== $error_msg ) {
1693 return new \WP_Error('error', $error_msg, array(
1694 'status' => 403,
1695 ));
1696 }
1697 break;
1698 case 'map':
1699 $error_msg = WPDA_App_Container_Model::update_map_settings( $cnt_id, null );
1700 if ( '' !== $error_msg ) {
1701 return new \WP_Error('error', $error_msg, array(
1702 'status' => 403,
1703 ));
1704 }
1705 break;
1706 case 'theme':
1707 $error_msg = WPDA_App_Model::update_theme( $app_id, null );
1708 if ( '' !== $error_msg ) {
1709 return new \WP_Error('error', $error_msg, array(
1710 'status' => 403,
1711 ));
1712 }
1713 break;
1714 case 'dashboard':
1715 $error_msg = WPDA_App_Container_Model::update_dashboard_settings( $app_id, null );
1716 if ( '' !== $error_msg ) {
1717 return new \WP_Error('error', $error_msg, array(
1718 'status' => 403,
1719 ));
1720 }
1721 break;
1722 default:
1723 return $this->bad_request();
1724 }
1725 return $this->WPDA_Rest_Response( __( 'Reset was successful', 'wp-data-access' ) );
1726 }
1727 if ( 'table' === $target ) {
1728 // Update table settings
1729 $error_msg = WPDA_App_Container_Model::update_table_settings( $cnt_id, $settings );
1730 if ( '' !== $error_msg ) {
1731 return new \WP_Error('error', $error_msg, array(
1732 'status' => 403,
1733 ));
1734 }
1735 // Update chart settings
1736 $error_msg = WPDA_App_Container_Model::update_chart_settings( $cnt_id, $chart );
1737 if ( '' !== $error_msg ) {
1738 return new \WP_Error('error', $error_msg, array(
1739 'status' => 403,
1740 ));
1741 }
1742 // Update map settings
1743 $error_msg = WPDA_App_Container_Model::update_map_settings( $cnt_id, $map );
1744 if ( '' !== $error_msg ) {
1745 return new \WP_Error('error', $error_msg, array(
1746 'status' => 403,
1747 ));
1748 }
1749 } else {
1750 if ( 'rform' === $target ) {
1751 // Update rform settings
1752 $error_msg = WPDA_App_Container_Model::update_rform_settings( $cnt_id, $settings );
1753 if ( '' !== $error_msg ) {
1754 return new \WP_Error('error', $error_msg, array(
1755 'status' => 403,
1756 ));
1757 }
1758 } else {
1759 if ( 'chart' === $target ) {
1760 // Update chart settings
1761 $error_msg = WPDA_App_Container_Model::update_chart_settings( $cnt_id, $settings );
1762 if ( '' !== $error_msg ) {
1763 return new \WP_Error('error', $error_msg, array(
1764 'status' => 403,
1765 ));
1766 }
1767 } else {
1768 if ( 'map' === $target ) {
1769 // Update chart settings
1770 $error_msg = WPDA_App_Container_Model::update_map_settings( $cnt_id, $settings );
1771 if ( '' !== $error_msg ) {
1772 return new \WP_Error('error', $error_msg, array(
1773 'status' => 403,
1774 ));
1775 }
1776 } else {
1777 if ( 'form' === $target ) {
1778 // Update form settings
1779 $error_msg = WPDA_App_Container_Model::update_form_settings( $cnt_id, $settings );
1780 if ( '' !== $error_msg ) {
1781 return new \WP_Error('error', $error_msg, array(
1782 'status' => 403,
1783 ));
1784 }
1785 } else {
1786 if ( 'dashboard' === $target ) {
1787 $error_msg = WPDA_App_Container_Model::update_dashboard_settings( $cnt_id, $settings );
1788 if ( '' !== $error_msg ) {
1789 return new \WP_Error('error', $error_msg, array(
1790 'status' => 403,
1791 ));
1792 }
1793 }
1794 }
1795 }
1796 }
1797 }
1798 }
1799 $error_msg = WPDA_App_Model::update_theme( $app_id, $theme );
1800 if ( '' !== $error_msg ) {
1801 return new \WP_Error('error', $error_msg, array(
1802 'status' => 403,
1803 ));
1804 }
1805 return $this->WPDA_Rest_Response( __( 'Successfully saved settings', 'wp-data-access' ) );
1806 }
1807
1808 private function do_app_remove( $app_id ) {
1809 WPDA_App_Apps_Model::delete( $app_id, true );
1810 WPDA_App_Container_Model::delete( $app_id );
1811 WPDA_App_Model::delete( $app_id );
1812 return $this->WPDA_Rest_Response( __( 'Successfully deleted app', 'wp-data-access' ) );
1813 }
1814
1815 private function do_app_create(
1816 $app_name,
1817 $app_title,
1818 $app_type,
1819 $app_settings,
1820 $app_dbs,
1821 $app_tbl,
1822 $app_cls,
1823 $app_table,
1824 $app_query
1825 ) {
1826 // Add app
1827 $insert = WPDA_App_Model::create(
1828 $app_name,
1829 $app_title,
1830 $app_type,
1831 $app_settings
1832 );
1833 if ( false !== $insert['app_id'] ) {
1834 $app_id = $insert['app_id'];
1835 // Add app container
1836 $container = WPDA_App_Container_Model::create(
1837 $app_id,
1838 $app_dbs,
1839 $app_tbl,
1840 json_encode( $app_cls ),
1841 $app_title,
1842 0,
1843 $app_table,
1844 null,
1845 $app_query
1846 );
1847 if ( false !== $container['cnt_id'] ) {
1848 // App and container successfully saved
1849 return $this->WPDA_Rest_Response( __( 'Successfully saved changes', 'wp-data-access' ) );
1850 } else {
1851 // Insert failed
1852 // Remove previously created app
1853 WPDA_App_Model::delete( $app_id );
1854 return new \WP_Error('error', $container['msg'], array(
1855 'status' => 403,
1856 ));
1857 }
1858 } else {
1859 // Insert failed
1860 return new \WP_Error('error', $insert['msg'], array(
1861 'status' => 403,
1862 ));
1863 }
1864 }
1865
1866 private function do_app_createapp(
1867 $app_name,
1868 $app_title,
1869 $app_type,
1870 $app_settings,
1871 $app_apps
1872 ) {
1873 // Add app
1874 $insert = WPDA_App_Model::create(
1875 $app_name,
1876 $app_title,
1877 $app_type,
1878 $app_settings
1879 );
1880 if ( false !== $insert['app_id'] ) {
1881 // Add apps
1882 if ( is_array( $app_apps ) ) {
1883 $app_id = $insert['app_id'];
1884 foreach ( $app_apps as $index => $app_id_detail ) {
1885 // Insert app
1886 WPDA_App_Apps_Model::create( $app_id, $app_id_detail, $index );
1887 }
1888 }
1889 // App and details successfully saved
1890 return $this->WPDA_Rest_Response( __( 'Successfully saved changes', 'wp-data-access' ) );
1891 } else {
1892 // Insert failed
1893 return new \WP_Error('error', $insert['msg'], array(
1894 'status' => 403,
1895 ));
1896 }
1897 }
1898
1899 private function get_app_init() {
1900 return $this->WPDA_Rest_Response( '', array(
1901 'roles' => $this->get_wp_roles(),
1902 'users' => $this->get_wp_users(),
1903 'lang' => get_option( self::WPDA_APP_DEFAULT_LANG ),
1904 ) );
1905 }
1906
1907 private function get_app_list() {
1908 $dataset = WPDA_App_Model::list();
1909 $context = WPDA_App_Apps_Model::list();
1910 return $this->WPDA_Rest_Response( '', $dataset, $context );
1911 }
1912
1913 private function get_relation_columns( $container ) {
1914 return null;
1915 }
1916
1917 private function reorder_details( $app_id, $cnt_id_from, $cnt_id_to ) {
1918 return $this->bad_request();
1919 }
1920
1921 private function get_app_apps_meta( $app, $apps ) {
1922 $app_id_details = array_map( function ( $e ) {
1923 if ( isset( $e['app_id_detail'] ) ) {
1924 return $e['app_id_detail'];
1925 }
1926 }, $apps );
1927 $app_titles = array();
1928 foreach ( $app_id_details as $app_id_detail ) {
1929 $app_detail = WPDA_App_Model::get_by_id( $app_id_detail );
1930 if ( isset( $app_detail[0]['app_title'] ) ) {
1931 $app_titles[$app_id_detail] = $app_detail[0]['app_title'];
1932 }
1933 }
1934 $response = array(
1935 'app' => array(
1936 'app' => $app,
1937 'container' => array(),
1938 'apps' => $app_id_details,
1939 'titles' => $app_titles,
1940 ),
1941 );
1942 $response['settings'] = $this->get_table_settings();
1943 return $this->WPDA_Rest_Response( '', $response );
1944 }
1945
1946 private function get_table_settings( $tbl = null, $dbs = null ) {
1947 $settings = new stdClass();
1948 if ( null !== $dbs && null !== $tbl ) {
1949 $settings_db = WPDA_Table_Settings_Model::query( $tbl, $dbs );
1950 if ( isset( $settings_db[0]['wpda_table_settings'] ) ) {
1951 $settings = json_decode( (string) $settings_db[0]['wpda_table_settings'] );
1952 // Remove old settings from response.
1953 unset($settings->form_labels);
1954 unset($settings->list_labels);
1955 unset($settings->custom_settings);
1956 unset($settings->search_settings);
1957 }
1958 }
1959 $settings->env = $this->get_env();
1960 global $wpdb;
1961 $settings->wp = [
1962 'roles' => $this->get_wp_roles(),
1963 'users' => $this->get_wp_users(),
1964 'home' => admin_url( 'admin.php' ),
1965 'tables' => array_values( $wpdb->tables() ),
1966 'date_format' => get_option( 'date_format' ),
1967 'time_format' => get_option( 'time_format' ),
1968 'scroll_offset' => WPDA::get_option( WPDA::OPTION_APPS_SCROLL_OFFSET ),
1969 ];
1970 return $settings;
1971 }
1972
1973 private function get_app_container_meta( $app_id, $container, $rel_tab = false ) {
1974 $app = WPDA_App_Model::get_by_id( $app_id );
1975 if ( false === $app ) {
1976 return $this->bad_request();
1977 }
1978 if ( !isset( $container[0]['cnt_dbs'], $container[0]['cnt_tbl'], $container[0]['cnt_cls'] ) ) {
1979 return $this->bad_request();
1980 }
1981 $dbs = $container[0]['cnt_dbs'];
1982 $tbl = $container[0]['cnt_tbl'];
1983 $response = array(
1984 'app' => array(
1985 'app' => $app,
1986 'container' => array_map( function ( $value ) {
1987 $show = WPDA::current_user_is_admin();
1988 if ( !$show ) {
1989 // Hide database and table name in responses for non admin users.
1990 unset($value['cnt_dbs']);
1991 unset($value['cnt_tbl']);
1992 }
1993 return $value;
1994 }, $container ),
1995 'apps' => array(),
1996 ),
1997 );
1998 $access = array(
1999 'select' => array(),
2000 'insert' => array(),
2001 'update' => array(),
2002 'delete' => array(),
2003 );
2004 $cls = WPDA_List_Columns_Cache::get_list_columns( $dbs, $tbl );
2005 $columns = $cls->get_table_columns();
2006 $columns_sorted = array();
2007 foreach ( $columns as $column ) {
2008 if ( isset( $column['column_name'] ) ) {
2009 $columns_sorted[$column['column_name']] = $column;
2010 }
2011 }
2012 $media = $this->get_media( $dbs, $tbl, $cls->get_table_columns() );
2013 $response['columns'] = $columns;
2014 $response['columns_sorted'] = $columns_sorted;
2015 $response['table_labels'] = $cls->get_table_header_labels();
2016 $response['form_labels'] = $cls->get_table_column_headers();
2017 $response['primary_key'] = $cls->get_table_primary_key();
2018 $response['access'] = $access;
2019 $response['settings'] = $this->get_table_settings( $tbl, $dbs );
2020 $response['media'] = $media['media'];
2021 $response['wp_media'] = $media['wp_media'];
2022 $table_settings = json_decode( (string) $container[0]['cnt_table'], true );
2023 if ( isset( $table_settings['table']['defaultWhere'] ) ) {
2024 $default_where = $table_settings['table']['defaultWhere'];
2025 } else {
2026 $default_where = '';
2027 }
2028 $response['table_info'] = $this->get_table_info( $dbs, $tbl, $default_where );
2029 return $this->WPDA_Rest_Response( '', $response );
2030 }
2031
2032 public function get_app_meta( $app_id ) {
2033 $app = WPDA_App_Model::get_by_id( $app_id );
2034 if ( !isset( $app[0]['app_type'] ) ) {
2035 return $this->bad_request();
2036 }
2037 if ( '5' === $app[0]['app_type'] || 5 === $app[0]['app_type'] ) {
2038 // App container
2039 $apps = WPDA_App_Apps_Model::select_all( $app_id, 0 );
2040 return $this->get_app_apps_meta( $app, $apps );
2041 } else {
2042 // Other container
2043 $container = WPDA_App_Container_Model::select( $app_id, 0 );
2044 if ( !isset( $container[0] ) ) {
2045 return $this->bad_request();
2046 }
2047 return $this->get_app_container_meta( $app_id, $container );
2048 }
2049 }
2050
2051 private function do_app_export_app( $app_id, $main_app_id ) {
2052 global $wpdb;
2053 $quotes = function ( $value ) {
2054 return str_replace( array(
2055 "'",
2056 '\\"',
2057 "\\\\t",
2058 "\\t",
2059 "\\\\n",
2060 "\\n",
2061 "\\r\\n",
2062 "\\r"
2063 ), array(
2064 "''",
2065 '\\\\"',
2066 "\\\\\\t",
2067 "\\\\t",
2068 "\\\\\\n",
2069 "\\\\n",
2070 "\\\\r\\\\n",
2071 "\\\\r"
2072 ), $value );
2073 };
2074 $app = WPDA_App_Model::get_by_id( $app_id );
2075 $app_settings = ( null === $app[0]['app_settings'] ? 'null' : "{$quotes( $app[0]['app_settings'] )}" );
2076 $app_theme = ( null === $app[0]['app_theme'] ? 'null' : "{$quotes( $app[0]['app_theme'] )}" );
2077 // phpcs:ignore PluginCheck.CodeAnalysis.Heredoc.NotAllowed
2078 $app_sql = <<<SQL
2079 # Import app
2080 insert into `{wp_prefix}wpda_app`
2081 \t(`app_name`
2082 \t,`app_title`
2083 \t,`app_type`
2084 \t,`app_settings`
2085 \t,`app_theme`
2086 \t,`app_add_to_menu`
2087 \t)
2088 values
2089 \t('{$quotes( $app[0]['app_name'] )}'
2090 \t,'{$quotes( $app[0]['app_title'] )}'
2091 \t,{$app[0]['app_type']}
2092 \t,'{$app_settings}'
2093 \t,'{$app_theme}'
2094 \t,{$app[0]['app_add_to_menu']}
2095 \t);
2096
2097 SET @APP_ID = LAST_INSERT_ID();
2098 insert into `wpda_transfer_apps_{$main_app_id}`
2099 values
2100 ({$app[0]['app_id']}
2101 ,(select LAST_INSERT_ID(`app_id`) from `{wp_prefix}wpda_app` order by 1 desc limit 1)
2102 );
2103
2104
2105 SQL;
2106 $containers = WPDA_App_Container_Model::select_all( $app_id );
2107 $containers_sql = '';
2108 foreach ( $containers as $container ) {
2109 $cnt_table = ( null === $container['cnt_table'] ? 'null' : "'{$quotes( $container['cnt_table'] )}'" );
2110 $cnt_form = ( null === $container['cnt_form'] ? 'null' : "'{$quotes( $container['cnt_form'] )}'" );
2111 $cnt_relation = ( null === $container['cnt_relation'] ? 'null' : "'{$quotes( $container['cnt_relation'] )}'" );
2112 $cnt_rform = ( null === $container['cnt_rform'] ? 'null' : "'{$quotes( $container['cnt_rform'] )}'" );
2113 $cnt_chart = ( null === $container['cnt_chart'] ? 'null' : "'{$quotes( $container['cnt_chart'] )}'" );
2114 $cnt_map = ( null === $container['cnt_map'] ? 'null' : "'{$quotes( $container['cnt_map'] )}'" );
2115 $cnt_query = ( null === $container['cnt_query'] ? 'null' : "'{$quotes( $container['cnt_query'] )}'" );
2116 // Replace default WordPress database with conversion string
2117 $cnt_dbs = ( $wpdb->dbname === $container['cnt_dbs'] ? '{wp_schema}' : "{$quotes( $container['cnt_dbs'] )}" );
2118 $cnt_table = str_replace( "\"dbs\":\"{$wpdb->dbname}\"", "\"dbs\":\"{wp_schema}\"", $cnt_table );
2119 $cnt_form = str_replace( "\"dbs\":\"{$wpdb->dbname}\"", "\"dbs\":\"{wp_schema}\"", $cnt_form );
2120 // phpcs:ignore PluginCheck.CodeAnalysis.Heredoc.NotAllowed
2121 $containers_sql .= <<<SQL
2122 # Import app container
2123 insert into `{wp_prefix}wpda_app_container`
2124 \t(`cnt_dbs`
2125 \t,`cnt_tbl`
2126 \t,`cnt_cls`
2127 \t,`cnt_title`
2128 \t,`app_id`
2129 \t,`cnt_seq_nr`
2130 \t,`cnt_table`
2131 \t,`cnt_form`
2132 \t,`cnt_relation`
2133 ,`cnt_rform`
2134 ,`cnt_chart`
2135 ,`cnt_map`
2136 ,`cnt_query`
2137 \t)
2138 values
2139 \t('{$cnt_dbs}'
2140 \t,'{$quotes( $container['cnt_tbl'] )}'
2141 \t,'{$quotes( $container['cnt_cls'] )}'
2142 \t,'{$quotes( $container['cnt_title'] )}'
2143 \t,@APP_ID
2144 \t,{$container['cnt_seq_nr']}
2145 \t,{$cnt_table}
2146 \t,{$cnt_form}
2147 \t,{$cnt_relation}
2148 \t,{$cnt_rform}
2149 \t,{$cnt_chart}
2150 \t,{$cnt_map}
2151 \t,{$cnt_query}
2152 \t);
2153
2154 insert into `wpda_transfer_containers_{$main_app_id}`
2155 values
2156 ({$container['cnt_id']}
2157 ,(select LAST_INSERT_ID(`cnt_id`) from `{wp_prefix}wpda_app_container` order by 1 desc limit 1)
2158 );
2159
2160
2161 SQL;
2162 }
2163 // Post update: update master container ids
2164 // phpcs:ignore PluginCheck.CodeAnalysis.Heredoc.NotAllowed
2165 $containers_sql .= <<<SQL
2166 # Update app master container IDs
2167 update `{wp_prefix}wpda_app_container` as a
2168 set a.`cnt_relation` =
2169 (
2170 select replace(
2171 a.`cnt_relation`,
2172 concat('"cnt_id_master":"', b.cnt_id_old, '"'),
2173 concat('"cnt_id_master":"', b.cnt_id_new, '"')
2174 )
2175 from `wpda_transfer_containers_{$main_app_id}` as b
2176 where a.`cnt_relation` like concat('%"cnt_id_master":"', b.cnt_id_old, '"%')
2177 )
2178 where a.`app_id` = @APP_ID
2179 and a.`cnt_relation` is not null;
2180
2181
2182 SQL;
2183 $apps = WPDA_App_Apps_Model::select_all( $app_id );
2184 $apps_sql = '';
2185 foreach ( $apps as $app ) {
2186 $apps_sql .= $this->do_app_export_app( $app['app_id_detail'], $main_app_id );
2187 }
2188 foreach ( $apps as $app ) {
2189 // phpcs:ignore PluginCheck.CodeAnalysis.Heredoc.NotAllowed
2190 $apps_sql .= <<<SQL
2191 # Import app relationships
2192 insert into `{wp_prefix}wpda_app_apps`
2193 \t(`app_id`
2194 \t,`app_id_detail`
2195 \t,`seq_nr`\t\t\t\t\t
2196 \t)
2197 values
2198 \t((select `app_id_new` from `wpda_transfer_apps_{$main_app_id}` where `app_id_old` = {$app['app_id']})
2199 \t,(select `app_id_new` from `wpda_transfer_apps_{$main_app_id}` where `app_id_old` = {$app['app_id_detail']})
2200 \t,{$app['seq_nr']}\t\t\t\t\t
2201 \t);
2202
2203
2204 SQL;
2205 }
2206 return $app_sql . $containers_sql . $apps_sql;
2207 }
2208
2209 private function do_app_export( $app_id ) {
2210 global $wpdb;
2211 $sql = '';
2212 // phpcs:ignore PluginCheck.CodeAnalysis.Heredoc.NotAllowed
2213 $begin_sql = <<<SQL
2214 /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
2215 /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
2216 /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
2217 /*!40101 SET NAMES {$wpdb->charset} */;
2218
2219 # Create temporary table
2220 CREATE TABLE `wpda_transfer_containers_{$app_id}`
2221 (cnt_id_old bigint(20) unsigned
2222 ,cnt_id_new bigint(20) unsigned
2223 );
2224
2225 CREATE TABLE `wpda_transfer_apps_{$app_id}`
2226 (app_id_old bigint(20) unsigned
2227 ,app_id_new bigint(20) unsigned
2228 );
2229
2230 SET @APP_ID = NULL;
2231
2232
2233 SQL;
2234 $sql .= $this->do_app_export_app( $app_id, $app_id );
2235 // phpcs:ignore PluginCheck.CodeAnalysis.Heredoc.NotAllowed
2236 $end_sql = <<<SQL
2237 # Drop temporary table
2238 DROP TABLE `wpda_transfer_containers_{$app_id}`;
2239 DROP TABLE `wpda_transfer_apps_{$app_id}`;
2240
2241 /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
2242 /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
2243 /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
2244
2245
2246 SQL;
2247 $data = array(
2248 'data' => $begin_sql . $sql . $end_sql,
2249 );
2250 return $this->WPDA_Rest_Response( __( 'App successfully exported', 'wp-data-access' ), $data );
2251 }
2252
2253 private function do_app_copy( $app_id ) {
2254 $copy = WPDA_App_Model::copy( $app_id );
2255 if ( false === $copy['app_id'] ) {
2256 return new \WP_Error('error', $copy['msg'], array(
2257 'status' => 403,
2258 ));
2259 } else {
2260 return $this->WPDA_Rest_Response( __( 'App successfully copied', 'wp-data-access' ) );
2261 }
2262 }
2263
2264 private function do_app_saveapp(
2265 $app_id,
2266 $app_name,
2267 $app_title,
2268 $app_type,
2269 $app_settings,
2270 $app_add_to_menu,
2271 $app_apps
2272 ) {
2273 $error_msg = WPDA_App_Model::update(
2274 $app_id,
2275 $app_name,
2276 $app_title,
2277 $app_type,
2278 $app_settings,
2279 $app_add_to_menu
2280 );
2281 if ( '' !== $error_msg ) {
2282 return new \WP_Error('error', $error_msg, array(
2283 'status' => 403,
2284 ));
2285 }
2286 WPDA_App_Apps_Model::update( $app_id, $app_apps );
2287 return $this->WPDA_Rest_Response( __( 'Changes successfully saved', 'wp-data-access' ) );
2288 }
2289
2290 private function do_app_save(
2291 $app_id,
2292 $app_name,
2293 $app_title,
2294 $app_type,
2295 $app_settings,
2296 $app_add_to_menu,
2297 $app_dbs,
2298 $app_tbl,
2299 $app_cls,
2300 $app_query
2301 ) {
2302 $error_msg = WPDA_App_Model::update(
2303 $app_id,
2304 $app_name,
2305 $app_title,
2306 $app_type,
2307 $app_settings,
2308 $app_add_to_menu
2309 );
2310 if ( '' !== $error_msg ) {
2311 return new \WP_Error('error', $error_msg, array(
2312 'status' => 403,
2313 ));
2314 }
2315 $error_msg = WPDA_App_Container_Model::update_master(
2316 $app_id,
2317 $app_dbs,
2318 $app_tbl,
2319 json_encode( $app_cls ),
2320 $app_query
2321 );
2322 if ( '' !== $error_msg ) {
2323 return new \WP_Error('error', $error_msg, array(
2324 'status' => 403,
2325 ));
2326 }
2327 return $this->WPDA_Rest_Response( __( 'Changes successfully saved', 'wp-data-access' ) );
2328 }
2329
2330 private function main_app_access( $app_id, &$msg = '', &$app = null ) {
2331 // Get app info
2332 $app = WPDA_App_Model::get_by_id( $app_id );
2333 if ( false === $app ) {
2334 // App not found
2335 $msg = __( 'Bad request', 'wp-data-access' );
2336 return false;
2337 }
2338 // Check access
2339 $app_settings_db = $app[0]['app_settings'];
2340 $app_settings = json_decode( (string) $app_settings_db, true );
2341 if ( !isset( $app_settings['rest_api']['authorization'], $app_settings['rest_api']['authorized_roles'], $app_settings['rest_api']['authorized_users'] ) || !is_array( $app_settings['rest_api']['authorized_roles'] ) || !is_array( $app_settings['rest_api']['authorized_users'] ) ) {
2342 // App contain no rest api settings
2343 $msg = __( 'Bad request', 'wp-data-access' );
2344 return false;
2345 }
2346 if ( !$this->current_user_can_access() && 'anonymous' !== $app_settings['rest_api']['authorization'] ) {
2347 // Check authorization
2348 // Check user role
2349 $user_roles = WPDA::get_current_user_roles();
2350 if ( !is_array( $user_roles ) || empty( array_intersect( $app_settings['rest_api']['authorized_roles'], $user_roles ) ) ) {
2351 // Check user login
2352 $user_login = WPDA::get_current_user_login();
2353 if ( !in_array( $user_login, $app_settings['rest_api']['authorized_users'] ) ) {
2354 $msg = __( 'Unauthorized', 'wp-data-access' );
2355 return false;
2356 }
2357 }
2358 }
2359 return true;
2360 }
2361
2362 public function check_app_access(
2363 $app_id,
2364 $cnt_id,
2365 $action,
2366 &$dbs,
2367 &$tbl,
2368 &$msg = '',
2369 &$settings = array()
2370 ) {
2371 if ( !$this->main_app_access( $app_id, $msg ) ) {
2372 return false;
2373 }
2374 // Get container
2375 $container = WPDA_App_Container_Model::get_container( $app_id, $cnt_id );
2376 if ( !is_array( $container ) || 0 === count( $container ) ) {
2377 // Container not found
2378 $msg = __( 'Bad request', 'wp-data-access' );
2379 return false;
2380 }
2381 if ( 'select' !== $action ) {
2382 $cnt_table = json_decode( (string) $container[0]['cnt_table'], true );
2383 if ( !isset( $cnt_table['table']['transactions'][$action] ) || false === $cnt_table['table']['transactions'][$action] ) {
2384 if ( !isset( $cnt_table['table']['bulkActions'][$action] ) || false === $cnt_table['table']['bulkActions'][$action] ) {
2385 $cnt_relation = json_decode( (string) $container[0]['cnt_relation'], true );
2386 if ( !(isset( $cnt_relation['cnt_id_master'] ) && $this->check_master_container_access( $app_id, $cnt_relation['cnt_id_master'], $action )) ) {
2387 $msg = __( 'Unauthorized', 'wp-data-access' );
2388 return false;
2389 }
2390 }
2391 }
2392 }
2393 // Return database name, table name and columns
2394 $dbs = $container[0]['cnt_dbs'];
2395 $tbl = $container[0]['cnt_tbl'];
2396 $settings = array(
2397 'columns' => json_decode( (string) $container[0]['cnt_cls'], true ),
2398 'table' => json_decode( (string) $container[0]['cnt_table'], true ),
2399 'form' => json_decode( (string) $container[0]['cnt_form'], true ),
2400 );
2401 return true;
2402 }
2403
2404 private function check_master_container_access( $app_id, $cnt_id, $action ) {
2405 $container = WPDA_App_Container_Model::get_container( $app_id, $cnt_id );
2406 if ( !is_array( $container ) || 0 === count( $container ) ) {
2407 // Container not found
2408 return false;
2409 }
2410 $cnt_table = json_decode( (string) $container[0]['cnt_table'], true );
2411 if ( !isset( $cnt_table['table']['transactions'][$action] ) || false === $cnt_table['table']['transactions'][$action] ) {
2412 $cnt_relation = json_decode( (string) $container[0]['cnt_relation'], true );
2413 if ( !(isset( $cnt_relation['cnt_id_master'] ) && $this->check_master_container_access( $app_id, $cnt_relation['cnt_id_master'], $action )) ) {
2414 return false;
2415 }
2416 }
2417 return true;
2418 }
2419
2420 private function process_params(
2421 $where,
2422 $search_custom,
2423 $search_params,
2424 $shortcode_params,
2425 $dynamic_params = array()
2426 ) {
2427 // Process $search_custom > URL parameters
2428 global $wpdb;
2429 foreach ( self::METHODS as $method ) {
2430 $offset = 0;
2431 $search = $method . '[';
2432 while ( ($pos_start = stripos( $where, $search, $offset )) !== false ) {
2433 if ( ($pos_end = stripos( $where, ']', $pos_start )) !== false ) {
2434 // Get filter
2435 $filter = substr( $where, $pos_start, $pos_end - $pos_start + 1 );
2436 // Get name
2437 $arg_name = substr( $where, $pos_start + strlen( $search ), $pos_end - $pos_start - strlen( $search ) );
2438 // Remove quotes from name
2439 if ( substr( $arg_name, 0, 1 ) === "'" && substr( $arg_name, -1 ) === "'" ) {
2440 $arg_name = substr( $arg_name, 1, -1 );
2441 }
2442 // Remove double quotes from name
2443 if ( substr( $arg_name, 0, 1 ) === '"' && substr( $arg_name, -1 ) === '"' ) {
2444 $arg_name = substr( $arg_name, 1, -1 );
2445 }
2446 // Handle GET args
2447 // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared
2448 if ( $method === self::METHODS[0] ) {
2449 if ( isset( $search_custom['get'][$arg_name] ) ) {
2450 $arg_value = sanitize_text_field( wp_unslash( $search_custom['get'][$arg_name] ) );
2451 $where = $wpdb->prepare( substr_replace(
2452 $where,
2453 '%s',
2454 $pos_start,
2455 $pos_end - $pos_start + 1
2456 ), $arg_value );
2457 } else {
2458 $where = str_replace( $filter, 'null', $where );
2459 }
2460 }
2461 // Handle POST args
2462 if ( $method === self::METHODS[1] ) {
2463 if ( isset( $search_custom['post'][$arg_name] ) ) {
2464 $arg_value = sanitize_text_field( wp_unslash( $search_custom['post'][$arg_name] ) );
2465 $where = $wpdb->prepare( substr_replace(
2466 $where,
2467 '%s',
2468 $pos_start,
2469 $pos_end - $pos_start + 1
2470 ), $arg_value );
2471 } else {
2472 $where = str_replace( $filter, 'null', $where );
2473 }
2474 }
2475 // Handle REQUEST args
2476 if ( $method === self::METHODS[2] ) {
2477 if ( isset( $search_custom['get'][$arg_name] ) ) {
2478 $arg_value = sanitize_text_field( wp_unslash( $search_custom['get'][$arg_name] ) );
2479 $where = $wpdb->prepare( substr_replace(
2480 $where,
2481 '%s',
2482 $pos_start,
2483 $pos_end - $pos_start + 1
2484 ), $arg_value );
2485 } elseif ( isset( $search_custom['post'][$arg_name] ) ) {
2486 $arg_value = sanitize_text_field( wp_unslash( $search_custom['post'][$arg_name] ) );
2487 $where = $wpdb->prepare( substr_replace(
2488 $where,
2489 '%s',
2490 $pos_start,
2491 $pos_end - $pos_start + 1
2492 ), $arg_value );
2493 } else {
2494 $where = str_replace( $filter, 'null', $where );
2495 }
2496 }
2497 // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared
2498 }
2499 $offset = $pos_start + 1;
2500 if ( $offset > strlen( $where ) ) {
2501 $offset = strlen( $where ) - 1;
2502 }
2503 }
2504 }
2505 // Process $search_params > shortcode parameters
2506 if ( is_array( $search_params ) && 1 === count( $search_params ) ) {
2507 $filter_field_name = $this->sanitize_db_identifier( array_keys( $search_params )[0] );
2508 $filter_field_value = sanitize_text_field( $search_params[$filter_field_name] );
2509 $filter_field_name_array = array_map( 'trim', explode( ',', $filter_field_name ) );
2510 // phpcs:ignore -- 8.1 proof
2511 $filter_field_value_array = array_map( 'trim', explode( ',', $filter_field_value ) );
2512 // phpcs:ignore -- 8.1 proof
2513 if ( count( $filter_field_name_array ) === count( $filter_field_value_array ) ) {
2514 // phpcs:ignore -- 8.1 proof
2515 // Add filter to where clause.
2516 // phpcs:disable Generic.CodeAnalysis.ForLoopWithTestFunctionCall, Squiz.PHP.DisallowSizeFunctionsInLoops, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnquotedComplexPlaceholder
2517 for ($i = 0; $i < count( $filter_field_name_array ); $i++) {
2518 $where .= (( '' === $where ? '' : ' and ' )) . $wpdb->prepare( ' `%1s` like %s ', array($filter_field_name_array[$i], $filter_field_value_array[$i]) );
2519 }
2520 // phpcs:enable Generic.CodeAnalysis.ForLoopWithTestFunctionCall, Squiz.PHP.DisallowSizeFunctionsInLoops, WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnquotedComplexPlaceholder
2521 }
2522 }
2523 // Substitute all shortcode parameters
2524 if ( is_array( $shortcode_params ) ) {
2525 foreach ( $shortcode_params as $column_name => $column_value ) {
2526 $occurences = substr_count( strtolower( $where ), strtolower( "shortcodeParam['{$column_name}']" ) );
2527 if ( 0 < $occurences ) {
2528 $column_values = array();
2529 for ($i = 0; $i < $occurences; $i++) {
2530 $column_values[] = sanitize_text_field( $column_value );
2531 }
2532 // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
2533 $where = $wpdb->prepare( str_ireplace( "shortcodeParam['{$column_name}']", '%s', $where ), $column_values );
2534 // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
2535 }
2536 }
2537 }
2538 // Substitute all unused shortcode parameter calls with null
2539 $offset = 0;
2540 $search = "shortcodeParam['";
2541 while ( ($pos_start = stripos( $where, $search, $offset )) !== false ) {
2542 if ( ($pos_end = stripos( $where, "']", $pos_start )) !== false ) {
2543 $shortcode_value = substr( $where, $pos_start, $pos_end - $pos_start + 2 );
2544 $where = str_ireplace( $shortcode_value, 'null', $where );
2545 }
2546 $offset = $pos_start + 4;
2547 if ( $offset > strlen( $where ) ) {
2548 $offset = strlen( $where ) - 1;
2549 }
2550 }
2551 // Substitute all dynamic parameters
2552 if ( is_array( $dynamic_params ) && 0 < count( $dynamic_params ) ) {
2553 foreach ( $dynamic_params as $column_name => $column_value ) {
2554 // phpcs:disable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
2555 $where = $wpdb->prepare( str_ireplace( "{:{$column_name}}", '%s', $where ), $column_value );
2556 // phpcs:enable WordPress.DB.PreparedSQL.NotPrepared, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
2557 }
2558 }
2559 return $where;
2560 }
2561
2562 }
2563