PluginProbe
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards / 5.5.84
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards v5.5.84
5.5.84 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 All 160 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.84, at WPDataAccess/API/WPDA_Apps.php

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