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
← All changes | WPDataAccess/API/WPDA_Apps.php +1570 -117 5.5.45.5.84 View file →
@@ -5,12 +5,42 @@
5 5 use stdClass;
6 6 use WPDataAccess\Connection\WPDADB;
7 7 use WPDataAccess\Data_Dictionary\WPDA_List_Columns_Cache;
8 8 use WPDataAccess\Plugin_Table_Models\WPDA_App_Container_Model;
9 +use WPDataAccess\Plugin_Table_Models\WPDA_App_Apps_Model;
9 10 use WPDataAccess\Plugin_Table_Models\WPDA_App_Model;
10 11 use WPDataAccess\Plugin_Table_Models\WPDA_Table_Settings_Model;
12 +use WPDataAccess\Utilities\WPDA_App_Localization;
11 13 use WPDataAccess\WPDA;
12 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 +
13 43 public function register_rest_routes() {
14 44 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/init', array(
15 45 'methods' => array('POST'),
16 46 'callback' => array($this, 'app_init'),
@@ -28,8 +58,22 @@
28 58 'args' => array(
29 59 'app_id' => $this->get_param( 'app_id' ),
30 60 ),
31 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 + ) );
32 76 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/table/meta', array(
33 77 'methods' => array('POST'),
34 78 'callback' => array($this, 'app_table_meta'),
35 79 'permission_callback' => '__return_true',
@@ -57,14 +101,43 @@
57 101 'app_cls' => $this->get_param( 'app_cls' ),
58 102 'app_table' => array(
59 103 'required' => true,
60 104 'type' => 'string',
61 - 'description' => __( 'Table settings', 'wp-data-access' ),
105 + 'description' => __( 'App table', 'wp-data-access' ),
62 106 'sanitize_callback' => 'sanitize_text_field',
63 107 'validate_callback' => 'rest_validate_request_arg',
64 108 ),
109 + 'app_query' => $this->get_param( 'app_query' ),
65 110 ),
66 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 + ) );
67 140 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/details', array(
68 141 'methods' => array('POST'),
69 142 'callback' => array($this, 'app_details'),
70 143 'permission_callback' => '__return_true',
@@ -77,12 +150,23 @@
77 150 'methods' => array('POST'),
78 151 'callback' => array($this, 'app_detail_meta'),
79 152 'permission_callback' => '__return_true',
80 153 'args' => array(
81 - 'app_id' => $this->get_param( 'app_id' ),
82 - 'cnt_id' => $this->get_param( 'cnt_id' ),
154 + 'app_id' => $this->get_param( 'app_id' ),
155 + 'cnt_id' => $this->get_param( 'cnt_id' ),
156 + 'rel_tab' => $this->get_param( 'rel_tab' ),
83 157 ),
84 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 + ) );
85 169 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/relationship/create', array(
86 170 'methods' => array('POST'),
87 171 'callback' => array($this, 'app_relationship_create'),
88 172 'permission_callback' => '__return_true',
@@ -138,20 +222,29 @@
138 222 'app_name' => $this->get_param( 'app_name' ),
139 223 'app_title' => $this->get_param( 'app_title' ),
140 224 'app_type' => $this->get_param( 'app_type' ),
141 225 'app_settings' => $this->get_param( 'app_settings' ),
142 - 'app_add_to_menu' => array(
143 - 'required' => true,
144 - 'type' => 'integer',
145 - 'description' => __( 'Add app to dashboard menu', 'wp-data-access' ),
146 - 'sanitize_callback' => 'absint',
147 - 'validate_callback' => 'rest_validate_request_arg',
148 - ),
226 + 'app_add_to_menu' => $this->get_param( 'app_add_to_menu' ),
149 227 'app_dbs' => $this->get_param( 'dbs' ),
150 228 'app_tbl' => $this->get_param( 'tbl' ),
151 229 'app_cls' => $this->get_param( 'app_cls' ),
230 + 'app_query' => $this->get_param( 'app_query' ),
152 231 ),
153 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 + ) );
154 247 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/remove', array(
155 248 'methods' => array('POST'),
156 249 'callback' => array($this, 'app_remove'),
157 250 'permission_callback' => '__return_true',
@@ -175,9 +268,31 @@
175 268 ),
176 269 'settings' => array(
177 270 'required' => false,
178 271 'type' => 'string',
179 - 'description' => __( 'Settings - JSON string', 'wp-data-access' ),
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' ),
180 295 'sanitize_callback' => 'sanitize_text_field',
181 296 'validate_callback' => 'rest_validate_request_arg',
182 297 ),
183 298 'theme' => array(
@@ -203,27 +318,43 @@
203 318 'search' => $this->get_param( 'search' ),
204 319 'search_columns' => $this->get_param( 'search_columns' ),
205 320 'search_column_fns' => $this->get_param( 'search_column_fns' ),
206 321 'search_column_lov' => $this->get_param( 'search_column_lov' ),
207 - 'md' => array(
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(
208 334 'required' => false,
209 335 'type' => 'mixed',
210 - 'description' => __( 'Master detail join conditions', 'wp-data-access' ),
336 + 'description' => __( 'Geo radius segment', 'wp-data-access' ),
211 337 'sanitize_callback' => function ( $param ) {
212 - $columns = array();
213 - foreach ( rest_sanitize_object( $param ) as $column_name => $value ) {
214 - $columns[$this->sanitize_db_identifier( $column_name )] = sanitize_text_field( wp_unslash( $value ) );
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'] );
215 353 }
216 - return $columns;
354 + return $geo_radius;
217 355 },
218 - 'validate_callback' => function ( $param ) {
219 - return is_array( $param );
220 - },
221 356 ),
222 - 'sorting' => $this->get_param( 'sorting' ),
223 - 'row_count' => $this->get_param( 'row_count' ),
224 - 'row_count_estimate' => $this->get_param( 'row_count_estimate' ),
225 - 'media' => $this->get_param( 'media' ),
226 357 ),
227 358 ) );
228 359 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/get', array(
229 360 'methods' => array('POST'),
@@ -229,12 +360,13 @@
229 360 'methods' => array('POST'),
230 361 'callback' => array($this, 'app_get'),
231 362 'permission_callback' => '__return_true',
232 363 'args' => array(
233 - 'app_id' => $this->get_param( 'app_id' ),
234 - 'cnt_id' => $this->get_param( 'cnt_id' ),
235 - 'key' => $this->get_param( 'key' ),
236 - 'media' => $this->get_param( 'media' ),
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' ),
237 369 ),
238 370 ) );
239 371 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/insert', array(
240 372 'methods' => array('POST'),
@@ -240,11 +372,13 @@
240 372 'methods' => array('POST'),
241 373 'callback' => array($this, 'app_insert'),
242 374 'permission_callback' => '__return_true',
243 375 'args' => array(
244 - 'app_id' => $this->get_param( 'app_id' ),
245 - 'cnt_id' => $this->get_param( 'cnt_id' ),
246 - 'val' => $this->get_param( 'val' ),
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' ),
247 381 ),
248 382 ) );
249 383 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/update', array(
250 384 'methods' => array('POST'),
@@ -250,8 +384,21 @@
250 384 'methods' => array('POST'),
251 385 'callback' => array($this, 'app_update'),
252 386 'permission_callback' => '__return_true',
253 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(
254 401 'app_id' => $this->get_param( 'app_id' ),
255 402 'cnt_id' => $this->get_param( 'cnt_id' ),
256 403 'key' => $this->get_param( 'key' ),
257 404 'val' => $this->get_param( 'val' ),
@@ -274,12 +421,19 @@
274 421 'args' => array(
275 422 'app_id' => $this->get_param( 'app_id' ),
276 423 'cnt_id' => $this->get_param( 'cnt_id' ),
277 424 'col' => $this->get_param( 'col' ),
425 + 'cols' => $this->get_param( 'cols' ),
278 426 'search' => $this->get_param( 'search' ),
279 427 'search_columns' => $this->get_param( 'search_columns' ),
280 428 'search_column_fns' => $this->get_param( 'search_column_fns' ),
281 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' ),
282 436 ),
283 437 ) );
284 438 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/lookup', array(
285 439 'methods' => array('POST'),
@@ -285,21 +439,33 @@
285 439 'methods' => array('POST'),
286 440 'callback' => array($this, 'app_lookup'),
287 441 'permission_callback' => '__return_true',
288 442 'args' => array(
289 - 'app_id' => $this->get_param( 'app_id' ),
290 - 'cnt_id' => $this->get_param( 'cnt_id' ),
291 - 'target' => array(
443 + 'app_id' => $this->get_param( 'app_id' ),
444 + 'cnt_id' => $this->get_param( 'cnt_id' ),
445 + 'target' => array(
292 446 'required' => true,
293 447 'type' => 'string',
294 - 'description' => __( 'Target: table or form', 'wp-data-access' ),
448 + 'description' => __( 'Target: table or (r)form', 'wp-data-access' ),
295 449 'sanitize_callback' => 'sanitize_text_field',
296 450 'validate_callback' => 'rest_validate_request_arg',
297 451 ),
298 - 'col' => $this->get_param( 'col' ),
299 - 'colk' => $this->get_param( 'col' ),
300 - 'colv' => $this->get_param( 'col' ),
301 - 'cold' => $this->get_param( 'key' ),
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' ),
302 468 ),
303 469 ) );
304 470 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/lookup/dbs', array(
305 471 'methods' => array('POST'),
@@ -330,10 +496,217 @@
330 496 'dbs' => $this->get_param( 'dbs' ),
331 497 'tbl' => $this->get_param( 'tbl' ),
332 498 ),
333 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 + ) );
334 638 }
335 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 +
336 709 private function get_app_columns( $columns ) {
337 710 if ( !is_array( $columns ) ) {
338 711 return false;
339 712 }
@@ -383,8 +756,36 @@
383 756 }
384 757 return $this->get_app_columns( $settings['columns'] );
385 758 }
386 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 +
387 788 public function app_details( $request ) {
388 789 $app_id = $request->get_param( 'app_id' );
389 790 $cnt_id = $request->get_param( 'cnt_id' );
390 791 if ( $this->check_app_access(
@@ -410,8 +811,9 @@
410 811
411 812 public function app_detail_meta( $request ) {
412 813 $app_id = $request->get_param( 'app_id' );
413 814 $cnt_id = $request->get_param( 'cnt_id' );
815 + $rel_tab = $request->get_param( 'rel_tab' );
414 816 if ( $this->check_app_access(
415 817 $app_id,
416 818 $cnt_id,
417 819 'select',
@@ -419,13 +821,13 @@
419 821 $tbl,
420 822 $msg,
421 823 $settings
422 824 ) ) {
423 - $container = WPDA_App_Container_Model::get_container( $cnt_id );
825 + $container = WPDA_App_Container_Model::get_container( $app_id, $cnt_id );
424 826 if ( !isset( $container[0] ) ) {
425 827 return $this->bad_request();
426 828 }
427 - return $this->get_app_container_meta( $app_id, $container );
829 + return $this->get_app_container_meta( $app_id, $container, $rel_tab );
428 830 } else {
429 831 if ( 'rest_cookie_invalid_nonce' === $msg ) {
430 832 return $this->invalid_nonce();
431 833 } else {
@@ -435,8 +837,41 @@
435 837 }
436 838 }
437 839 }
438 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 +
439 874 public function app_relationship_create( $request ) {
440 875 if ( !$this->current_user_can_access() ) {
441 876 return $this->unauthorized();
442 877 }
@@ -481,10 +916,8 @@
481 916 $app_dbs,
482 917 $app_tbl,
483 918 json_encode( $app_cls ),
484 919 $app_title,
485 - 1,
486 - null,
487 920 $app_relation
488 921 ) );
489 922 }
490 923
@@ -498,8 +931,29 @@
498 931 $cnt_id = $request->get_param( 'cnt_id' );
499 932 return $this->WPDA_Rest_Response( '', WPDA_App_Container_Model::delete_container( $cnt_id ) );
500 933 }
501 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 +
502 956 public function app_select( $request ) {
503 957 $app_id = $request->get_param( 'app_id' );
504 958 $cnt_id = $request->get_param( 'cnt_id' );
505 959 $col = $request->get_param( 'col' );
@@ -508,16 +962,30 @@
508 962 $search = $request->get_param( 'search' );
509 963 $search_columns = $request->get_param( 'search_columns' );
510 964 $search_column_fns = $request->get_param( 'search_column_fns' );
511 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' );
512 970 $md = $request->get_param( 'md' );
513 971 $sorting = $request->get_param( 'sorting' );
514 972 $row_count = $request->get_param( 'row_count' );
515 973 $row_count_estimate = $request->get_param( 'row_count_estimate' );
516 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();
517 979 $default_where = '';
518 980 $default_orderby = '';
519 981 $lookups = array();
982 + $m2m_relationship = array();
983 + if ( $client_side ) {
984 + // Delete search values on refresh
985 + $search = '';
986 + $search_columns = array();
987 + }
520 988 if ( $this->check_app_access(
521 989 $app_id,
522 990 $cnt_id,
523 991 'select',
@@ -525,23 +993,57 @@
525 993 $tbl,
526 994 $msg,
527 995 $settings
528 996 ) ) {
529 - $table_settings = $settings['table'] ?? array();
530 - // Get default where clause
531 - if ( isset( $table_settings['table']['defaultWhere'] ) ) {
532 - $default_where = $table_settings['table']['defaultWhere'];
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 + }
533 1027 }
534 - // Get default order by
535 - if ( isset( $table_settings['table']['defaultOrderBy'] ) ) {
536 - $default_orderby_db = $table_settings['table']['defaultOrderBy'];
537 - if ( is_array( $default_orderby_db ) ) {
538 - foreach ( $default_orderby_db as $orderby ) {
539 - if ( isset( $orderby['columnName'], $orderby['order'] ) && '' !== trim( $orderby['columnName'] ) ) {
540 - $default_orderby .= (( '' === $default_orderby ? 'order by ' : ',' )) . '`' . WPDA::remove_backticks( $orderby['columnName'] ) . '` ' . (( 'desc' === $orderby['order'] ? 'desc' : 'asc' ));
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'];
541 1034 }
542 1035 }
543 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 + }
544 1046 }
545 1047 $table_api = new WPDA_Table();
546 1048 return $table_api->select(
547 1049 $dbs,
@@ -555,12 +1057,22 @@
555 1057 $sorting,
556 1058 $row_count,
557 1059 $row_count_estimate,
558 1060 $media,
559 - $default_where,
1061 + $this->process_params(
1062 + $default_where,
1063 + $search_custom,
1064 + $search_params,
1065 + $shortcode_params
1066 + ),
560 1067 $default_orderby,
561 1068 $lookups,
562 - $md
1069 + $md,
1070 + $m2m_relationship,
1071 + $search_data_types,
1072 + $client_side,
1073 + $geo_radius,
1074 + $docs
563 1075 );
564 1076 } else {
565 1077 if ( 'rest_cookie_invalid_nonce' === $msg ) {
566 1078 return $this->invalid_nonce();
@@ -571,17 +1083,32 @@
571 1083 }
572 1084 }
573 1085 }
574 1086
1087 + private function get_m2m_relationship( $relationship, $tbl, $cols ) {
1088 + return array();
1089 + }
1090 +
575 1091 private function get_lookup_lov( $column_lookup, $search_value, $search_type ) {
576 1092 return null;
577 1093 }
578 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 +
579 1104 public function app_get( $request ) {
580 1105 $app_id = $request->get_param( 'app_id' );
581 1106 $cnt_id = $request->get_param( 'cnt_id' );
582 1107 $key = $request->get_param( 'key' );
583 1108 $media = $request->get_param( 'media' );
1109 + $rel_tab = $request->get_param( 'rel_tab' );
1110 + $docs = array();
584 1111 if ( $this->check_app_access(
585 1112 $app_id,
586 1113 $cnt_id,
587 1114 'select',
@@ -601,9 +1128,10 @@
601 1128 $tbl,
602 1129 $key,
603 1130 $media,
604 1131 $column_names,
605 - $default_where
1132 + $default_where,
1133 + $docs
606 1134 );
607 1135 } else {
608 1136 if ( 'rest_cookie_invalid_nonce' === $msg ) {
609 1137 return $this->invalid_nonce();
@@ -618,8 +1146,10 @@
618 1146 public function app_insert( $request ) {
619 1147 $app_id = $request->get_param( 'app_id' );
620 1148 $cnt_id = $request->get_param( 'cnt_id' );
621 1149 $val = $request->get_param( 'val' );
1150 + $join_tab = $request->get_param( 'join_tab' );
1151 + $rel_tab = $request->get_param( 'rel_tab' );
622 1152 if ( $this->check_app_access(
623 1153 $app_id,
624 1154 $cnt_id,
625 1155 'insert',
@@ -644,8 +1174,10 @@
644 1174 $app_id = $request->get_param( 'app_id' );
645 1175 $cnt_id = $request->get_param( 'cnt_id' );
646 1176 $key = $request->get_param( 'key' );
647 1177 $val = $request->get_param( 'val' );
1178 + $join_tab = $request->get_param( 'join_tab' );
1179 + $rel_tab = $request->get_param( 'rel_tab' );
648 1180 if ( $this->check_app_access(
649 1181 $app_id,
650 1182 $cnt_id,
651 1183 'update',
@@ -657,8 +1189,17 @@
657 1189 $column_names = $this->get_app_form_columns( $settings );
658 1190 if ( false === $column_names ) {
659 1191 $column_names = array();
660 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 + }
661 1202 $table_api = new WPDA_Table();
662 1203 return $table_api->update(
663 1204 $dbs,
664 1205 $tbl,
@@ -663,9 +1204,11 @@
663 1204 $dbs,
664 1205 $tbl,
665 1206 $key,
666 1207 $val,
667 - $column_names
1208 + $column_names,
1209 + $code_columns,
1210 + $html_columns
668 1211 );
669 1212 } else {
670 1213 if ( 'rest_cookie_invalid_nonce' === $msg ) {
671 1214 return $this->invalid_nonce();
@@ -676,8 +1219,12 @@
676 1219 }
677 1220 }
678 1221 }
679 1222
1223 + public function app_update_inline( $request ) {
1224 + return $this->bad_request();
1225 + }
1226 +
680 1227 public function app_delete( $request ) {
681 1228 $app_id = $request->get_param( 'app_id' );
682 1229 $cnt_id = $request->get_param( 'cnt_id' );
683 1230 $key = $request->get_param( 'key' );
@@ -713,8 +1260,24 @@
713 1260 $col = $request->get_param( 'col' );
714 1261 $colk = $request->get_param( 'colk' );
715 1262 $colv = $request->get_param( 'colv' );
716 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();
717 1280 if ( $this->check_app_access(
718 1281 $app_id,
719 1282 $cnt_id,
720 1283 'select',
@@ -719,15 +1282,15 @@
719 1282 $cnt_id,
720 1283 'select',
721 1284 $dbs,
722 1285 $tbl,
723 - $msg
1286 + $msg,
1287 + $settings
724 1288 ) ) {
725 - $container = WPDA_App_Container_Model::get_container( $cnt_id );
1289 + $container = WPDA_App_Container_Model::get_container( $app_id, $cnt_id );
726 1290 if ( !isset( $container[0] ) ) {
727 1291 return $this->bad_request();
728 1292 }
729 - $default_where = '';
730 1293 $lookup = array();
731 1294 $lookup_dbs = "";
732 1295 $lookup_tbl = "";
733 1296 if ( 'form' === $target ) {
@@ -735,11 +1298,18 @@
735 1298 if ( isset( $container[0]['cnt_form'] ) ) {
736 1299 $lookup = json_decode( (string) $container[0]['cnt_form'], true );
737 1300 }
738 1301 } else {
739 - // Handle table lookup
740 - if ( isset( $container[0]['cnt_table'] ) ) {
741 - $lookup = json_decode( (string) $container[0]['cnt_table'], true );
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 + }
742 1312 }
743 1313 }
744 1314 if ( isset( $lookup['columns'] ) && is_array( $lookup['columns'] ) ) {
745 1315 foreach ( $lookup['columns'] as $column ) {
@@ -749,9 +1319,9 @@
749 1319 }
750 1320 $lookup_dbs = $column['lookup']['dbs'];
751 1321 $lookup_tbl = $column['lookup']['tbl'];
752 1322 if ( isset( $column['columnName'], $column['lookup']['defaultWhere'] ) ) {
753 - $default_where = $column['lookup']['defaultWhere'];
1323 + $default_where_lookup = $column['lookup']['defaultWhere'];
754 1324 }
755 1325 }
756 1326 }
757 1327 }
@@ -764,9 +1334,33 @@
764 1334 $lookup_tbl,
765 1335 $colk,
766 1336 $colv,
767 1337 $cold,
768 - $default_where
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
769 1363 );
770 1364 } else {
771 1365 if ( 'rest_cookie_invalid_nonce' === $msg ) {
772 1366 return $this->invalid_nonce();
@@ -778,8 +1372,12 @@
778 1372 }
779 1373 }
780 1374
781 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 + }
782 1380 $app_id = $request->get_param( 'app_id' );
783 1381 $cnt_id = $request->get_param( 'cnt_id' );
784 1382 if ( $this->check_app_access(
785 1383 $app_id,
@@ -802,8 +1400,12 @@
802 1400 }
803 1401 }
804 1402
805 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 + }
806 1408 $app_id = $request->get_param( 'app_id' );
807 1409 $cnt_id = $request->get_param( 'cnt_id' );
808 1410 $dbs = $request->get_param( 'dbs' );
809 1411 if ( $this->check_app_access(
@@ -827,8 +1429,12 @@
827 1429 }
828 1430 }
829 1431
830 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 + }
831 1437 $app_id = $request->get_param( 'app_id' );
832 1438 $cnt_id = $request->get_param( 'cnt_id' );
833 1439 $dbs = $request->get_param( 'dbs' );
834 1440 $tbl = $request->get_param( 'tbl' );
@@ -852,8 +1458,227 @@
852 1458 }
853 1459 }
854 1460 }
855 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 +
856 1681 public function app_meta( $request ) {
857 1682 $app_id = $request->get_param( 'app_id' );
858 1683 if ( !$this->main_app_access( $app_id, $msg ) ) {
859 1684 if ( 'rest_cookie_invalid_nonce' === $msg ) {
@@ -877,8 +1702,10 @@
877 1702 $app_id = $request->get_param( 'app_id' );
878 1703 $cnt_id = $request->get_param( 'cnt_id' );
879 1704 $target = $request->get_param( 'target' );
880 1705 $settings = $request->get_param( 'settings' );
1706 + $chart = $request->get_param( 'chart' );
1707 + $map = $request->get_param( 'map' );
881 1708 $theme = $request->get_param( 'theme' );
882 1709 return $this->do_app_settings(
883 1710 $app_id,
884 1711 $cnt_id,
@@ -883,8 +1710,10 @@
883 1710 $app_id,
884 1711 $cnt_id,
885 1712 $target,
886 1713 $settings,
1714 + $chart,
1715 + $map,
887 1716 $theme
888 1717 );
889 1718 }
890 1719
@@ -938,8 +1767,9 @@
938 1767 $app_dbs = $request->get_param( 'app_dbs' );
939 1768 $app_tbl = $request->get_param( 'app_tbl' );
940 1769 $app_cls = $request->get_param( 'app_cls' );
941 1770 $app_table = $request->get_param( 'app_table' );
1771 + $app_query = $request->get_param( 'app_query' );
942 1772 return $this->do_app_create(
943 1773 $app_name,
944 1774 $app_title,
945 1775 $app_type,
@@ -946,12 +1776,34 @@
946 1776 $app_settings,
947 1777 $app_dbs,
948 1778 $app_tbl,
949 1779 $app_cls,
950 - $app_table
1780 + $app_table,
1781 + $app_query
951 1782 );
952 1783 }
953 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 +
954 1806 public function app_remove( $request ) {
955 1807 if ( !$this->current_user_can_access() ) {
956 1808 return $this->unauthorized();
957 1809 }
@@ -979,8 +1831,9 @@
979 1831 // App container
980 1832 $app_dbs = $request->get_param( 'app_dbs' );
981 1833 $app_tbl = $request->get_param( 'app_tbl' );
982 1834 $app_cls = $request->get_param( 'app_cls' );
1835 + $app_query = $request->get_param( 'app_query' );
983 1836 return $this->do_app_save(
984 1837 $app_id,
985 1838 $app_name,
986 1839 $app_title,
@@ -988,20 +1841,48 @@
988 1841 $app_settings,
989 1842 $app_add_to_menu,
990 1843 $app_dbs,
991 1844 $app_tbl,
992 - $app_cls
1845 + $app_cls,
1846 + $app_query
993 1847 );
994 1848 }
995 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 +
996 1875 private function do_app_settings(
997 1876 $app_id,
998 1877 $cnt_id,
999 1878 $target,
1000 1879 $settings,
1880 + $chart,
1881 + $map,
1001 1882 $theme
1002 1883 ) {
1003 - if ( 1 > $app_id || 1 > $cnt_id || 'table' !== $target && 'form' !== $target && 'theme' !== $target ) {
1884 + if ( 1 > $app_id || 1 > $cnt_id || 'table' !== $target && 'form' !== $target && 'rform' !== $target && 'theme' !== $target && 'chart' !== $target && 'map' !== $target && 'dashboard' !== $target ) {
1004 1885 return $this->bad_request();
1005 1886 }
1006 1887 if ( null === $settings || '' === $settings ) {
1007 1888 // Perform reset
@@ -1021,8 +1902,24 @@
1021 1902 'status' => 403,
1022 1903 ));
1023 1904 }
1024 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;
1025 1922 case 'theme':
1026 1923 $error_msg = WPDA_App_Model::update_theme( $app_id, null );
1027 1924 if ( '' !== $error_msg ) {
1028 1925 return new \WP_Error('error', $error_msg, array(
@@ -1029,8 +1926,16 @@
1029 1926 'status' => 403,
1030 1927 ));
1031 1928 }
1032 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;
1033 1938 default:
1034 1939 return $this->bad_request();
1035 1940 }
1036 1941 return $this->WPDA_Rest_Response( __( 'Reset was successful', 'wp-data-access' ) );
@@ -1042,16 +1947,71 @@
1042 1947 return new \WP_Error('error', $error_msg, array(
1043 1948 'status' => 403,
1044 1949 ));
1045 1950 }
1046 - } else {
1047 - // Update form settings
1048 - $error_msg = WPDA_App_Container_Model::update_form_settings( $cnt_id, $settings );
1951 + // Update chart settings
1952 + $error_msg = WPDA_App_Container_Model::update_chart_settings( $cnt_id, $chart );
1049 1953 if ( '' !== $error_msg ) {
1050 1954 return new \WP_Error('error', $error_msg, array(
1051 1955 'status' => 403,
1052 1956 ));
1053 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 + }
1054 2014 }
1055 2015 $error_msg = WPDA_App_Model::update_theme( $app_id, $theme );
1056 2016 if ( '' !== $error_msg ) {
1057 2017 return new \WP_Error('error', $error_msg, array(
@@ -1061,10 +2021,11 @@
1061 2021 return $this->WPDA_Rest_Response( __( 'Successfully saved settings', 'wp-data-access' ) );
1062 2022 }
1063 2023
1064 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 );
1065 2027 WPDA_App_Model::delete( $app_id );
1066 - WPDA_App_Container_Model::delete( $app_id );
1067 2028 return $this->WPDA_Rest_Response( __( 'Successfully deleted app', 'wp-data-access' ) );
1068 2029 }
1069 2030
1070 2031 private function do_app_create(
@@ -1074,9 +2035,10 @@
1074 2035 $app_settings,
1075 2036 $app_dbs,
1076 2037 $app_tbl,
1077 2038 $app_cls,
1078 - $app_table
2039 + $app_table,
2040 + $app_query
1079 2041 ) {
1080 2042 // Add app
1081 2043 $insert = WPDA_App_Model::create(
1082 2044 $app_name,
@@ -1093,9 +2055,11 @@
1093 2055 $app_tbl,
1094 2056 json_encode( $app_cls ),
1095 2057 $app_title,
1096 2058 0,
1097 - $app_table
2059 + $app_table,
2060 + null,
2061 + $app_query
1098 2062 );
1099 2063 if ( false !== $container['cnt_id'] ) {
1100 2064 // App and container successfully saved
1101 2065 return $this->WPDA_Rest_Response( __( 'Successfully saved changes', 'wp-data-access' ) );
@@ -1114,21 +2078,144 @@
1114 2078 ));
1115 2079 }
1116 2080 }
1117 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 +
1118 2115 private function get_app_init() {
1119 2116 return $this->WPDA_Rest_Response( '', array(
1120 2117 'roles' => $this->get_wp_roles(),
1121 2118 'users' => $this->get_wp_users(),
2119 + 'lang' => get_option( self::WPDA_APP_DEFAULT_LANG ),
1122 2120 ) );
1123 2121 }
1124 2122
1125 2123 private function get_app_list() {
1126 2124 $dataset = WPDA_App_Model::list();
1127 - return $this->WPDA_Rest_Response( '', $dataset );
2125 + $context = WPDA_App_Apps_Model::list();
2126 + return $this->WPDA_Rest_Response( '', $dataset, $context );
1128 2127 }
1129 2128
1130 - private function get_app_container_meta( $app_id, $container ) {
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 ) {
1131 2218 $app = WPDA_App_Model::get_by_id( $app_id );
1132 2219 if ( false === $app ) {
1133 2220 return $this->bad_request();
1134 2221 }
@@ -1134,13 +2221,15 @@
1134 2221 }
1135 2222 if ( !isset( $container[0]['cnt_dbs'], $container[0]['cnt_tbl'], $container[0]['cnt_cls'] ) ) {
1136 2223 return $this->bad_request();
1137 2224 }
2225 + $dbs = $container[0]['cnt_dbs'];
2226 + $tbl = $container[0]['cnt_tbl'];
1138 2227 $response = array(
1139 2228 'app' => array(
1140 2229 'app' => $app,
1141 2230 'container' => array_map( function ( $value ) {
1142 - $show = current_user_can( 'manage_options' );
2231 + $show = WPDA::current_user_is_admin();
1143 2232 if ( !$show ) {
1144 2233 // Hide database and table name in responses for non admin users.
1145 2234 unset($value['cnt_dbs']);
1146 2235 unset($value['cnt_tbl']);
@@ -1146,13 +2235,11 @@
1146 2235 unset($value['cnt_tbl']);
1147 2236 }
1148 2237 return $value;
1149 2238 }, $container ),
2239 + 'apps' => array(),
1150 2240 ),
1151 2241 );
1152 - $dbs = $container[0]['cnt_dbs'];
1153 - $tbl = $container[0]['cnt_tbl'];
1154 - $cls = WPDA_List_Columns_Cache::get_list_columns( $dbs, $tbl );
1155 2242 $access = array(
1156 2243 'select' => array(),
1157 2244 'insert' => array(),
1158 2245 'update' => array(),
@@ -1157,35 +2244,24 @@
1157 2244 'insert' => array(),
1158 2245 'update' => array(),
1159 2246 'delete' => array(),
1160 2247 );
1161 - $settings = new stdClass();
1162 - $settings_db = WPDA_Table_Settings_Model::query( $tbl, $dbs );
1163 - if ( isset( $settings_db[0]['wpda_table_settings'] ) ) {
1164 - $settings = json_decode( (string) $settings_db[0]['wpda_table_settings'] );
1165 - // Remove old settings from response.
1166 - unset($settings->form_labels);
1167 - unset($settings->list_labels);
1168 - unset($settings->custom_settings);
1169 - unset($settings->search_settings);
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 + }
1170 2255 }
1171 - $settings->env = $this->get_env();
1172 - global $wpdb;
1173 - $settings->wp = [
1174 - 'roles' => $this->get_wp_roles(),
1175 - 'users' => $this->get_wp_users(),
1176 - 'home' => admin_url( 'admin.php' ),
1177 - 'tables' => array_values( $wpdb->tables() ),
1178 - 'date_format' => get_option( 'date_format' ),
1179 - 'time_format' => get_option( 'time_format' ),
1180 - ];
1181 2256 $media = $this->get_media( $dbs, $tbl, $cls->get_table_columns() );
1182 - $response['columns'] = $cls->get_table_columns();
2257 + $response['columns'] = $columns;
2258 + $response['columns_sorted'] = $columns_sorted;
1183 2259 $response['table_labels'] = $cls->get_table_header_labels();
1184 2260 $response['form_labels'] = $cls->get_table_column_headers();
1185 2261 $response['primary_key'] = $cls->get_table_primary_key();
1186 2262 $response['access'] = $access;
1187 - $response['settings'] = $settings;
2263 + $response['settings'] = $this->get_table_settings( $tbl, $dbs );
1188 2264 $response['media'] = $media['media'];
1189 2265 $response['wp_media'] = $media['wp_media'];
1190 2266 $table_settings = json_decode( (string) $container[0]['cnt_table'], true );
1191 2267 if ( isset( $table_settings['table']['defaultWhere'] ) ) {
@@ -1196,16 +2272,280 @@
1196 2272 $response['table_info'] = $this->get_table_info( $dbs, $tbl, $default_where );
1197 2273 return $this->WPDA_Rest_Response( '', $response );
1198 2274 }
1199 2275
1200 - private function get_app_meta( $app_id ) {
1201 - $container = WPDA_App_Container_Model::select( $app_id, 0 );
1202 - if ( !isset( $container[0] ) ) {
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'] ) ) {
1203 2279 return $this->bad_request();
1204 2280 }
1205 - return $this->get_app_container_meta( $app_id, $container );
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 + }
1206 2293 }
1207 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 +
1208 2548 private function do_app_save(
1209 2549 $app_id,
1210 2550 $app_name,
1211 2551 $app_title,
@@ -1213,9 +2553,10 @@
1213 2553 $app_settings,
1214 2554 $app_add_to_menu,
1215 2555 $app_dbs,
1216 2556 $app_tbl,
1217 - $app_cls
2557 + $app_cls,
2558 + $app_query
1218 2559 ) {
1219 2560 $error_msg = WPDA_App_Model::update(
1220 2561 $app_id,
1221 2562 $app_name,
@@ -1233,9 +2574,9 @@
1233 2574 $app_id,
1234 2575 $app_dbs,
1235 2576 $app_tbl,
1236 2577 json_encode( $app_cls ),
1237 - 0
2578 + $app_query
1238 2579 );
1239 2580 if ( '' !== $error_msg ) {
1240 2581 return new \WP_Error('error', $error_msg, array(
1241 2582 'status' => 403,
@@ -1243,9 +2584,9 @@
1243 2584 }
1244 2585 return $this->WPDA_Rest_Response( __( 'Changes successfully saved', 'wp-data-access' ) );
1245 2586 }
1246 2587
1247 - private function main_app_access( $app_id, &$msg = '' ) {
2588 + private function main_app_access( $app_id, &$msg = '', &$app = null ) {
1248 2589 // Get app info
1249 2590 $app = WPDA_App_Model::get_by_id( $app_id );
1250 2591 if ( false === $app ) {
1251 2592 // App not found
@@ -1288,9 +2629,9 @@
1288 2629 if ( !$this->main_app_access( $app_id, $msg ) ) {
1289 2630 return false;
1290 2631 }
1291 2632 // Get container
1292 - $container = WPDA_App_Container_Model::get_container( $cnt_id );
2633 + $container = WPDA_App_Container_Model::get_container( $app_id, $cnt_id );
1293 2634 if ( !is_array( $container ) || 0 === count( $container ) ) {
1294 2635 // Container not found
1295 2636 $msg = __( 'Bad request', 'wp-data-access' );
1296 2637 return false;
@@ -1297,12 +2638,14 @@
1297 2638 }
1298 2639 if ( 'select' !== $action ) {
1299 2640 $cnt_table = json_decode( (string) $container[0]['cnt_table'], true );
1300 2641 if ( !isset( $cnt_table['table']['transactions'][$action] ) || false === $cnt_table['table']['transactions'][$action] ) {
1301 - $cnt_relation = json_decode( (string) $container[0]['cnt_relation'], true );
1302 - if ( !(isset( $cnt_relation['cnt_id_master'] ) && $this->check_master_container_access( $cnt_relation['cnt_id_master'], $action )) ) {
1303 - $msg = __( 'Unauthorized', 'wp-data-access' );
1304 - return false;
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 + }
1305 2648 }
1306 2649 }
1307 2650 }
1308 2651 // Return database name, table name and columns
@@ -1315,10 +2658,10 @@
1315 2658 );
1316 2659 return true;
1317 2660 }
1318 2661
1319 - private function check_master_container_access( $cnt_id, $action ) {
1320 - $container = WPDA_App_Container_Model::get_container( $cnt_id );
2662 + private function check_master_container_access( $app_id, $cnt_id, $action ) {
2663 + $container = WPDA_App_Container_Model::get_container( $app_id, $cnt_id );
1321 2664 if ( !is_array( $container ) || 0 === count( $container ) ) {
1322 2665 // Container not found
1323 2666 return false;
1324 2667 }
@@ -1324,12 +2667,122 @@
1324 2667 }
1325 2668 $cnt_table = json_decode( (string) $container[0]['cnt_table'], true );
1326 2669 if ( !isset( $cnt_table['table']['transactions'][$action] ) || false === $cnt_table['table']['transactions'][$action] ) {
1327 2670 $cnt_relation = json_decode( (string) $container[0]['cnt_relation'], true );
1328 - if ( !(isset( $cnt_relation['cnt_id_master'] ) && $this->check_master_container_access( $cnt_relation['cnt_id_master'], $action )) ) {
2671 + if ( !(isset( $cnt_relation['cnt_id_master'] ) && $this->check_master_container_access( $app_id, $cnt_relation['cnt_id_master'], $action )) ) {
1329 2672 return false;
1330 2673 }
1331 2674 }
1332 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 );
1333 2786 }
1334 2787
1335 2788 }