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 +1611 -117 5.5.35.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',
@@ -69,8 +142,9 @@
69 142 'callback' => array($this, 'app_details'),
70 143 'permission_callback' => '__return_true',
71 144 'args' => array(
72 145 'app_id' => $this->get_param( 'app_id' ),
146 + 'cnt_id' => $this->get_param( 'cnt_id' ),
73 147 ),
74 148 ) );
75 149 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/detailmeta', array(
76 150 'methods' => array('POST'),
@@ -76,12 +150,23 @@
76 150 'methods' => array('POST'),
77 151 'callback' => array($this, 'app_detail_meta'),
78 152 'permission_callback' => '__return_true',
79 153 'args' => array(
80 - 'app_id' => $this->get_param( 'app_id' ),
81 - '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' ),
82 157 ),
83 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 + ) );
84 169 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/relationship/create', array(
85 170 'methods' => array('POST'),
86 171 'callback' => array($this, 'app_relationship_create'),
87 172 'permission_callback' => '__return_true',
@@ -137,20 +222,29 @@
137 222 'app_name' => $this->get_param( 'app_name' ),
138 223 'app_title' => $this->get_param( 'app_title' ),
139 224 'app_type' => $this->get_param( 'app_type' ),
140 225 'app_settings' => $this->get_param( 'app_settings' ),
141 - 'app_add_to_menu' => array(
142 - 'required' => true,
143 - 'type' => 'integer',
144 - 'description' => __( 'Add app to dashboard menu', 'wp-data-access' ),
145 - 'sanitize_callback' => 'absint',
146 - 'validate_callback' => 'rest_validate_request_arg',
147 - ),
226 + 'app_add_to_menu' => $this->get_param( 'app_add_to_menu' ),
148 227 'app_dbs' => $this->get_param( 'dbs' ),
149 228 'app_tbl' => $this->get_param( 'tbl' ),
150 229 'app_cls' => $this->get_param( 'app_cls' ),
230 + 'app_query' => $this->get_param( 'app_query' ),
151 231 ),
152 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 + ) );
153 247 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/remove', array(
154 248 'methods' => array('POST'),
155 249 'callback' => array($this, 'app_remove'),
156 250 'permission_callback' => '__return_true',
@@ -174,9 +268,31 @@
174 268 ),
175 269 'settings' => array(
176 270 'required' => false,
177 271 'type' => 'string',
178 - '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' ),
179 295 'sanitize_callback' => 'sanitize_text_field',
180 296 'validate_callback' => 'rest_validate_request_arg',
181 297 ),
182 298 'theme' => array(
@@ -202,27 +318,43 @@
202 318 'search' => $this->get_param( 'search' ),
203 319 'search_columns' => $this->get_param( 'search_columns' ),
204 320 'search_column_fns' => $this->get_param( 'search_column_fns' ),
205 321 'search_column_lov' => $this->get_param( 'search_column_lov' ),
206 - '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(
207 334 'required' => false,
208 335 'type' => 'mixed',
209 - 'description' => __( 'Master detail join conditions', 'wp-data-access' ),
336 + 'description' => __( 'Geo radius segment', 'wp-data-access' ),
210 337 'sanitize_callback' => function ( $param ) {
211 - $columns = array();
212 - foreach ( rest_sanitize_object( $param ) as $column_name => $value ) {
213 - $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'] );
214 353 }
215 - return $columns;
354 + return $geo_radius;
216 355 },
217 - 'validate_callback' => function ( $param ) {
218 - return is_array( $param );
219 - },
220 356 ),
221 - 'sorting' => $this->get_param( 'sorting' ),
222 - 'row_count' => $this->get_param( 'row_count' ),
223 - 'row_count_estimate' => $this->get_param( 'row_count_estimate' ),
224 - 'media' => $this->get_param( 'media' ),
225 357 ),
226 358 ) );
227 359 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/get', array(
228 360 'methods' => array('POST'),
@@ -228,12 +360,13 @@
228 360 'methods' => array('POST'),
229 361 'callback' => array($this, 'app_get'),
230 362 'permission_callback' => '__return_true',
231 363 'args' => array(
232 - 'app_id' => $this->get_param( 'app_id' ),
233 - 'cnt_id' => $this->get_param( 'cnt_id' ),
234 - 'key' => $this->get_param( 'key' ),
235 - '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' ),
236 369 ),
237 370 ) );
238 371 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/insert', array(
239 372 'methods' => array('POST'),
@@ -239,11 +372,13 @@
239 372 'methods' => array('POST'),
240 373 'callback' => array($this, 'app_insert'),
241 374 'permission_callback' => '__return_true',
242 375 'args' => array(
243 - 'app_id' => $this->get_param( 'app_id' ),
244 - 'cnt_id' => $this->get_param( 'cnt_id' ),
245 - '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' ),
246 381 ),
247 382 ) );
248 383 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/update', array(
249 384 'methods' => array('POST'),
@@ -249,8 +384,21 @@
249 384 'methods' => array('POST'),
250 385 'callback' => array($this, 'app_update'),
251 386 'permission_callback' => '__return_true',
252 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(
253 401 'app_id' => $this->get_param( 'app_id' ),
254 402 'cnt_id' => $this->get_param( 'cnt_id' ),
255 403 'key' => $this->get_param( 'key' ),
256 404 'val' => $this->get_param( 'val' ),
@@ -273,12 +421,19 @@
273 421 'args' => array(
274 422 'app_id' => $this->get_param( 'app_id' ),
275 423 'cnt_id' => $this->get_param( 'cnt_id' ),
276 424 'col' => $this->get_param( 'col' ),
425 + 'cols' => $this->get_param( 'cols' ),
277 426 'search' => $this->get_param( 'search' ),
278 427 'search_columns' => $this->get_param( 'search_columns' ),
279 428 'search_column_fns' => $this->get_param( 'search_column_fns' ),
280 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' ),
281 436 ),
282 437 ) );
283 438 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/lookup', array(
284 439 'methods' => array('POST'),
@@ -284,21 +439,33 @@
284 439 'methods' => array('POST'),
285 440 'callback' => array($this, 'app_lookup'),
286 441 'permission_callback' => '__return_true',
287 442 'args' => array(
288 - 'app_id' => $this->get_param( 'app_id' ),
289 - 'cnt_id' => $this->get_param( 'cnt_id' ),
290 - 'target' => array(
443 + 'app_id' => $this->get_param( 'app_id' ),
444 + 'cnt_id' => $this->get_param( 'cnt_id' ),
445 + 'target' => array(
291 446 'required' => true,
292 447 'type' => 'string',
293 - 'description' => __( 'Target: table or form', 'wp-data-access' ),
448 + 'description' => __( 'Target: table or (r)form', 'wp-data-access' ),
294 449 'sanitize_callback' => 'sanitize_text_field',
295 450 'validate_callback' => 'rest_validate_request_arg',
296 451 ),
297 - 'col' => $this->get_param( 'col' ),
298 - 'colk' => $this->get_param( 'col' ),
299 - 'colv' => $this->get_param( 'col' ),
300 - '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' ),
301 468 ),
302 469 ) );
303 470 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'app/lookup/dbs', array(
304 471 'methods' => array('POST'),
@@ -329,10 +496,217 @@
329 496 'dbs' => $this->get_param( 'dbs' ),
330 497 'tbl' => $this->get_param( 'tbl' ),
331 498 ),
332 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 + ) );
333 638 }
334 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 +
335 709 private function get_app_columns( $columns ) {
336 710 if ( !is_array( $columns ) ) {
337 711 return false;
338 712 }
@@ -382,35 +756,122 @@
382 756 }
383 757 return $this->get_app_columns( $settings['columns'] );
384 758 }
385 759
386 - public function app_details( $request ) {
387 - if ( !$this->current_user_can_access() ) {
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 + }
388 766 return $this->unauthorized();
389 767 }
390 768 if ( !$this->current_user_token_valid( $request ) ) {
391 769 return $this->invalid_nonce();
392 770 }
393 - $app_id = $request->get_param( 'app_id' );
394 - return $this->WPDA_Rest_Response( '', WPDA_App_Container_Model::select( $app_id, 1 ) );
771 + return $this->do_app_export( $app_id );
395 772 }
396 773
397 - public function app_detail_meta( $request ) {
398 - if ( !$this->current_user_can_access() ) {
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 + }
399 780 return $this->unauthorized();
400 781 }
401 782 if ( !$this->current_user_token_valid( $request ) ) {
402 783 return $this->invalid_nonce();
403 784 }
785 + return $this->do_app_copy( $app_id );
786 + }
787 +
788 + public function app_details( $request ) {
404 789 $app_id = $request->get_param( 'app_id' );
405 790 $cnt_id = $request->get_param( 'cnt_id' );
406 - $container = WPDA_App_Container_Model::get_container( $cnt_id );
407 - if ( !isset( $container[0] ) ) {
408 - return $this->bad_request();
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 + }
409 809 }
410 - return $this->get_app_container_meta( $app_id, $container );
411 810 }
412 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 +
413 874 public function app_relationship_create( $request ) {
414 875 if ( !$this->current_user_can_access() ) {
415 876 return $this->unauthorized();
416 877 }
@@ -455,10 +916,8 @@
455 916 $app_dbs,
456 917 $app_tbl,
457 918 json_encode( $app_cls ),
458 919 $app_title,
459 - 1,
460 - null,
461 920 $app_relation
462 921 ) );
463 922 }
464 923
@@ -472,8 +931,29 @@
472 931 $cnt_id = $request->get_param( 'cnt_id' );
473 932 return $this->WPDA_Rest_Response( '', WPDA_App_Container_Model::delete_container( $cnt_id ) );
474 933 }
475 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 +
476 956 public function app_select( $request ) {
477 957 $app_id = $request->get_param( 'app_id' );
478 958 $cnt_id = $request->get_param( 'cnt_id' );
479 959 $col = $request->get_param( 'col' );
@@ -482,16 +962,30 @@
482 962 $search = $request->get_param( 'search' );
483 963 $search_columns = $request->get_param( 'search_columns' );
484 964 $search_column_fns = $request->get_param( 'search_column_fns' );
485 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' );
486 970 $md = $request->get_param( 'md' );
487 971 $sorting = $request->get_param( 'sorting' );
488 972 $row_count = $request->get_param( 'row_count' );
489 973 $row_count_estimate = $request->get_param( 'row_count_estimate' );
490 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();
491 979 $default_where = '';
492 980 $default_orderby = '';
493 981 $lookups = array();
982 + $m2m_relationship = array();
983 + if ( $client_side ) {
984 + // Delete search values on refresh
985 + $search = '';
986 + $search_columns = array();
987 + }
494 988 if ( $this->check_app_access(
495 989 $app_id,
496 990 $cnt_id,
497 991 'select',
@@ -499,23 +993,57 @@
499 993 $tbl,
500 994 $msg,
501 995 $settings
502 996 ) ) {
503 - $table_settings = $settings['table'] ?? array();
504 - // Get default where clause
505 - if ( isset( $table_settings['table']['defaultWhere'] ) ) {
506 - $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 + }
507 1027 }
508 - // Get default order by
509 - if ( isset( $table_settings['table']['defaultOrderBy'] ) ) {
510 - $default_orderby_db = $table_settings['table']['defaultOrderBy'];
511 - if ( is_array( $default_orderby_db ) ) {
512 - foreach ( $default_orderby_db as $orderby ) {
513 - if ( isset( $orderby['columnName'], $orderby['order'] ) && '' !== trim( $orderby['columnName'] ) ) {
514 - $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'];
515 1034 }
516 1035 }
517 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 + }
518 1046 }
519 1047 $table_api = new WPDA_Table();
520 1048 return $table_api->select(
521 1049 $dbs,
@@ -529,12 +1057,22 @@
529 1057 $sorting,
530 1058 $row_count,
531 1059 $row_count_estimate,
532 1060 $media,
533 - $default_where,
1061 + $this->process_params(
1062 + $default_where,
1063 + $search_custom,
1064 + $search_params,
1065 + $shortcode_params
1066 + ),
534 1067 $default_orderby,
535 1068 $lookups,
536 - $md
1069 + $md,
1070 + $m2m_relationship,
1071 + $search_data_types,
1072 + $client_side,
1073 + $geo_radius,
1074 + $docs
537 1075 );
538 1076 } else {
539 1077 if ( 'rest_cookie_invalid_nonce' === $msg ) {
540 1078 return $this->invalid_nonce();
@@ -545,17 +1083,32 @@
545 1083 }
546 1084 }
547 1085 }
548 1086
1087 + private function get_m2m_relationship( $relationship, $tbl, $cols ) {
1088 + return array();
1089 + }
1090 +
549 1091 private function get_lookup_lov( $column_lookup, $search_value, $search_type ) {
550 1092 return null;
551 1093 }
552 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 +
553 1104 public function app_get( $request ) {
554 1105 $app_id = $request->get_param( 'app_id' );
555 1106 $cnt_id = $request->get_param( 'cnt_id' );
556 1107 $key = $request->get_param( 'key' );
557 1108 $media = $request->get_param( 'media' );
1109 + $rel_tab = $request->get_param( 'rel_tab' );
1110 + $docs = array();
558 1111 if ( $this->check_app_access(
559 1112 $app_id,
560 1113 $cnt_id,
561 1114 'select',
@@ -575,9 +1128,10 @@
575 1128 $tbl,
576 1129 $key,
577 1130 $media,
578 1131 $column_names,
579 - $default_where
1132 + $default_where,
1133 + $docs
580 1134 );
581 1135 } else {
582 1136 if ( 'rest_cookie_invalid_nonce' === $msg ) {
583 1137 return $this->invalid_nonce();
@@ -592,8 +1146,10 @@
592 1146 public function app_insert( $request ) {
593 1147 $app_id = $request->get_param( 'app_id' );
594 1148 $cnt_id = $request->get_param( 'cnt_id' );
595 1149 $val = $request->get_param( 'val' );
1150 + $join_tab = $request->get_param( 'join_tab' );
1151 + $rel_tab = $request->get_param( 'rel_tab' );
596 1152 if ( $this->check_app_access(
597 1153 $app_id,
598 1154 $cnt_id,
599 1155 'insert',
@@ -618,8 +1174,10 @@
618 1174 $app_id = $request->get_param( 'app_id' );
619 1175 $cnt_id = $request->get_param( 'cnt_id' );
620 1176 $key = $request->get_param( 'key' );
621 1177 $val = $request->get_param( 'val' );
1178 + $join_tab = $request->get_param( 'join_tab' );
1179 + $rel_tab = $request->get_param( 'rel_tab' );
622 1180 if ( $this->check_app_access(
623 1181 $app_id,
624 1182 $cnt_id,
625 1183 'update',
@@ -624,16 +1182,33 @@
624 1182 $cnt_id,
625 1183 'update',
626 1184 $dbs,
627 1185 $tbl,
628 - $msg
1186 + $msg,
1187 + $settings
629 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 + }
630 1202 $table_api = new WPDA_Table();
631 1203 return $table_api->update(
632 1204 $dbs,
633 1205 $tbl,
634 1206 $key,
635 - $val
1207 + $val,
1208 + $column_names,
1209 + $code_columns,
1210 + $html_columns
636 1211 );
637 1212 } else {
638 1213 if ( 'rest_cookie_invalid_nonce' === $msg ) {
639 1214 return $this->invalid_nonce();
@@ -644,8 +1219,12 @@
644 1219 }
645 1220 }
646 1221 }
647 1222
1223 + public function app_update_inline( $request ) {
1224 + return $this->bad_request();
1225 + }
1226 +
648 1227 public function app_delete( $request ) {
649 1228 $app_id = $request->get_param( 'app_id' );
650 1229 $cnt_id = $request->get_param( 'cnt_id' );
651 1230 $key = $request->get_param( 'key' );
@@ -681,8 +1260,24 @@
681 1260 $col = $request->get_param( 'col' );
682 1261 $colk = $request->get_param( 'colk' );
683 1262 $colv = $request->get_param( 'colv' );
684 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();
685 1280 if ( $this->check_app_access(
686 1281 $app_id,
687 1282 $cnt_id,
688 1283 'select',
@@ -687,15 +1282,15 @@
687 1282 $cnt_id,
688 1283 'select',
689 1284 $dbs,
690 1285 $tbl,
691 - $msg
1286 + $msg,
1287 + $settings
692 1288 ) ) {
693 - $container = WPDA_App_Container_Model::get_container( $cnt_id );
1289 + $container = WPDA_App_Container_Model::get_container( $app_id, $cnt_id );
694 1290 if ( !isset( $container[0] ) ) {
695 1291 return $this->bad_request();
696 1292 }
697 - $default_where = '';
698 1293 $lookup = array();
699 1294 $lookup_dbs = "";
700 1295 $lookup_tbl = "";
701 1296 if ( 'form' === $target ) {
@@ -703,11 +1298,18 @@
703 1298 if ( isset( $container[0]['cnt_form'] ) ) {
704 1299 $lookup = json_decode( (string) $container[0]['cnt_form'], true );
705 1300 }
706 1301 } else {
707 - // Handle table lookup
708 - if ( isset( $container[0]['cnt_table'] ) ) {
709 - $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 + }
710 1312 }
711 1313 }
712 1314 if ( isset( $lookup['columns'] ) && is_array( $lookup['columns'] ) ) {
713 1315 foreach ( $lookup['columns'] as $column ) {
@@ -717,9 +1319,9 @@
717 1319 }
718 1320 $lookup_dbs = $column['lookup']['dbs'];
719 1321 $lookup_tbl = $column['lookup']['tbl'];
720 1322 if ( isset( $column['columnName'], $column['lookup']['defaultWhere'] ) ) {
721 - $default_where = $column['lookup']['defaultWhere'];
1323 + $default_where_lookup = $column['lookup']['defaultWhere'];
722 1324 }
723 1325 }
724 1326 }
725 1327 }
@@ -732,9 +1334,33 @@
732 1334 $lookup_tbl,
733 1335 $colk,
734 1336 $colv,
735 1337 $cold,
736 - $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
737 1363 );
738 1364 } else {
739 1365 if ( 'rest_cookie_invalid_nonce' === $msg ) {
740 1366 return $this->invalid_nonce();
@@ -746,8 +1372,12 @@
746 1372 }
747 1373 }
748 1374
749 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 + }
750 1380 $app_id = $request->get_param( 'app_id' );
751 1381 $cnt_id = $request->get_param( 'cnt_id' );
752 1382 if ( $this->check_app_access(
753 1383 $app_id,
@@ -770,8 +1400,12 @@
770 1400 }
771 1401 }
772 1402
773 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 + }
774 1408 $app_id = $request->get_param( 'app_id' );
775 1409 $cnt_id = $request->get_param( 'cnt_id' );
776 1410 $dbs = $request->get_param( 'dbs' );
777 1411 if ( $this->check_app_access(
@@ -795,8 +1429,12 @@
795 1429 }
796 1430 }
797 1431
798 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 + }
799 1437 $app_id = $request->get_param( 'app_id' );
800 1438 $cnt_id = $request->get_param( 'cnt_id' );
801 1439 $dbs = $request->get_param( 'dbs' );
802 1440 $tbl = $request->get_param( 'tbl' );
@@ -820,8 +1458,227 @@
820 1458 }
821 1459 }
822 1460 }
823 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 +
824 1681 public function app_meta( $request ) {
825 1682 $app_id = $request->get_param( 'app_id' );
826 1683 if ( !$this->main_app_access( $app_id, $msg ) ) {
827 1684 if ( 'rest_cookie_invalid_nonce' === $msg ) {
@@ -845,8 +1702,10 @@
845 1702 $app_id = $request->get_param( 'app_id' );
846 1703 $cnt_id = $request->get_param( 'cnt_id' );
847 1704 $target = $request->get_param( 'target' );
848 1705 $settings = $request->get_param( 'settings' );
1706 + $chart = $request->get_param( 'chart' );
1707 + $map = $request->get_param( 'map' );
849 1708 $theme = $request->get_param( 'theme' );
850 1709 return $this->do_app_settings(
851 1710 $app_id,
852 1711 $cnt_id,
@@ -851,8 +1710,10 @@
851 1710 $app_id,
852 1711 $cnt_id,
853 1712 $target,
854 1713 $settings,
1714 + $chart,
1715 + $map,
855 1716 $theme
856 1717 );
857 1718 }
858 1719
@@ -906,8 +1767,9 @@
906 1767 $app_dbs = $request->get_param( 'app_dbs' );
907 1768 $app_tbl = $request->get_param( 'app_tbl' );
908 1769 $app_cls = $request->get_param( 'app_cls' );
909 1770 $app_table = $request->get_param( 'app_table' );
1771 + $app_query = $request->get_param( 'app_query' );
910 1772 return $this->do_app_create(
911 1773 $app_name,
912 1774 $app_title,
913 1775 $app_type,
@@ -914,12 +1776,34 @@
914 1776 $app_settings,
915 1777 $app_dbs,
916 1778 $app_tbl,
917 1779 $app_cls,
918 - $app_table
1780 + $app_table,
1781 + $app_query
919 1782 );
920 1783 }
921 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 +
922 1806 public function app_remove( $request ) {
923 1807 if ( !$this->current_user_can_access() ) {
924 1808 return $this->unauthorized();
925 1809 }
@@ -947,8 +1831,9 @@
947 1831 // App container
948 1832 $app_dbs = $request->get_param( 'app_dbs' );
949 1833 $app_tbl = $request->get_param( 'app_tbl' );
950 1834 $app_cls = $request->get_param( 'app_cls' );
1835 + $app_query = $request->get_param( 'app_query' );
951 1836 return $this->do_app_save(
952 1837 $app_id,
953 1838 $app_name,
954 1839 $app_title,
@@ -956,20 +1841,48 @@
956 1841 $app_settings,
957 1842 $app_add_to_menu,
958 1843 $app_dbs,
959 1844 $app_tbl,
960 - $app_cls
1845 + $app_cls,
1846 + $app_query
961 1847 );
962 1848 }
963 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 +
964 1875 private function do_app_settings(
965 1876 $app_id,
966 1877 $cnt_id,
967 1878 $target,
968 1879 $settings,
1880 + $chart,
1881 + $map,
969 1882 $theme
970 1883 ) {
971 - 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 ) {
972 1885 return $this->bad_request();
973 1886 }
974 1887 if ( null === $settings || '' === $settings ) {
975 1888 // Perform reset
@@ -989,8 +1902,24 @@
989 1902 'status' => 403,
990 1903 ));
991 1904 }
992 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;
993 1922 case 'theme':
994 1923 $error_msg = WPDA_App_Model::update_theme( $app_id, null );
995 1924 if ( '' !== $error_msg ) {
996 1925 return new \WP_Error('error', $error_msg, array(
@@ -997,8 +1926,16 @@
997 1926 'status' => 403,
998 1927 ));
999 1928 }
1000 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;
1001 1938 default:
1002 1939 return $this->bad_request();
1003 1940 }
1004 1941 return $this->WPDA_Rest_Response( __( 'Reset was successful', 'wp-data-access' ) );
@@ -1010,16 +1947,71 @@
1010 1947 return new \WP_Error('error', $error_msg, array(
1011 1948 'status' => 403,
1012 1949 ));
1013 1950 }
1014 - } else {
1015 - // Update form settings
1016 - $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 );
1017 1953 if ( '' !== $error_msg ) {
1018 1954 return new \WP_Error('error', $error_msg, array(
1019 1955 'status' => 403,
1020 1956 ));
1021 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 + }
1022 2014 }
1023 2015 $error_msg = WPDA_App_Model::update_theme( $app_id, $theme );
1024 2016 if ( '' !== $error_msg ) {
1025 2017 return new \WP_Error('error', $error_msg, array(
@@ -1029,10 +2021,11 @@
1029 2021 return $this->WPDA_Rest_Response( __( 'Successfully saved settings', 'wp-data-access' ) );
1030 2022 }
1031 2023
1032 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 );
1033 2027 WPDA_App_Model::delete( $app_id );
1034 - WPDA_App_Container_Model::delete( $app_id );
1035 2028 return $this->WPDA_Rest_Response( __( 'Successfully deleted app', 'wp-data-access' ) );
1036 2029 }
1037 2030
1038 2031 private function do_app_create(
@@ -1042,9 +2035,10 @@
1042 2035 $app_settings,
1043 2036 $app_dbs,
1044 2037 $app_tbl,
1045 2038 $app_cls,
1046 - $app_table
2039 + $app_table,
2040 + $app_query
1047 2041 ) {
1048 2042 // Add app
1049 2043 $insert = WPDA_App_Model::create(
1050 2044 $app_name,
@@ -1061,9 +2055,11 @@
1061 2055 $app_tbl,
1062 2056 json_encode( $app_cls ),
1063 2057 $app_title,
1064 2058 0,
1065 - $app_table
2059 + $app_table,
2060 + null,
2061 + $app_query
1066 2062 );
1067 2063 if ( false !== $container['cnt_id'] ) {
1068 2064 // App and container successfully saved
1069 2065 return $this->WPDA_Rest_Response( __( 'Successfully saved changes', 'wp-data-access' ) );
@@ -1082,21 +2078,144 @@
1082 2078 ));
1083 2079 }
1084 2080 }
1085 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 +
1086 2115 private function get_app_init() {
1087 2116 return $this->WPDA_Rest_Response( '', array(
1088 2117 'roles' => $this->get_wp_roles(),
1089 2118 'users' => $this->get_wp_users(),
2119 + 'lang' => get_option( self::WPDA_APP_DEFAULT_LANG ),
1090 2120 ) );
1091 2121 }
1092 2122
1093 2123 private function get_app_list() {
1094 2124 $dataset = WPDA_App_Model::list();
1095 - return $this->WPDA_Rest_Response( '', $dataset );
2125 + $context = WPDA_App_Apps_Model::list();
2126 + return $this->WPDA_Rest_Response( '', $dataset, $context );
1096 2127 }
1097 2128
1098 - 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 ) {
1099 2218 $app = WPDA_App_Model::get_by_id( $app_id );
1100 2219 if ( false === $app ) {
1101 2220 return $this->bad_request();
1102 2221 }
@@ -1102,13 +2221,15 @@
1102 2221 }
1103 2222 if ( !isset( $container[0]['cnt_dbs'], $container[0]['cnt_tbl'], $container[0]['cnt_cls'] ) ) {
1104 2223 return $this->bad_request();
1105 2224 }
2225 + $dbs = $container[0]['cnt_dbs'];
2226 + $tbl = $container[0]['cnt_tbl'];
1106 2227 $response = array(
1107 2228 'app' => array(
1108 2229 'app' => $app,
1109 2230 'container' => array_map( function ( $value ) {
1110 - $show = current_user_can( 'manage_options' );
2231 + $show = WPDA::current_user_is_admin();
1111 2232 if ( !$show ) {
1112 2233 // Hide database and table name in responses for non admin users.
1113 2234 unset($value['cnt_dbs']);
1114 2235 unset($value['cnt_tbl']);
@@ -1114,13 +2235,11 @@
1114 2235 unset($value['cnt_tbl']);
1115 2236 }
1116 2237 return $value;
1117 2238 }, $container ),
2239 + 'apps' => array(),
1118 2240 ),
1119 2241 );
1120 - $dbs = $container[0]['cnt_dbs'];
1121 - $tbl = $container[0]['cnt_tbl'];
1122 - $cls = WPDA_List_Columns_Cache::get_list_columns( $dbs, $tbl );
1123 2242 $access = array(
1124 2243 'select' => array(),
1125 2244 'insert' => array(),
1126 2245 'update' => array(),
@@ -1125,26 +2244,24 @@
1125 2244 'insert' => array(),
1126 2245 'update' => array(),
1127 2246 'delete' => array(),
1128 2247 );
1129 - $settings = new stdClass();
1130 - $settings_db = WPDA_Table_Settings_Model::query( $tbl, $dbs );
1131 - if ( isset( $settings_db[0]['wpda_table_settings'] ) ) {
1132 - $settings = json_decode( (string) $settings_db[0]['wpda_table_settings'] );
1133 - // Remove old settings from response.
1134 - unset($settings->form_labels);
1135 - unset($settings->list_labels);
1136 - unset($settings->custom_settings);
1137 - 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 + }
1138 2255 }
1139 - $settings->env = $this->get_env();
1140 2256 $media = $this->get_media( $dbs, $tbl, $cls->get_table_columns() );
1141 - $response['columns'] = $cls->get_table_columns();
2257 + $response['columns'] = $columns;
2258 + $response['columns_sorted'] = $columns_sorted;
1142 2259 $response['table_labels'] = $cls->get_table_header_labels();
1143 2260 $response['form_labels'] = $cls->get_table_column_headers();
1144 2261 $response['primary_key'] = $cls->get_table_primary_key();
1145 2262 $response['access'] = $access;
1146 - $response['settings'] = $settings;
2263 + $response['settings'] = $this->get_table_settings( $tbl, $dbs );
1147 2264 $response['media'] = $media['media'];
1148 2265 $response['wp_media'] = $media['wp_media'];
1149 2266 $table_settings = json_decode( (string) $container[0]['cnt_table'], true );
1150 2267 if ( isset( $table_settings['table']['defaultWhere'] ) ) {
@@ -1155,16 +2272,280 @@
1155 2272 $response['table_info'] = $this->get_table_info( $dbs, $tbl, $default_where );
1156 2273 return $this->WPDA_Rest_Response( '', $response );
1157 2274 }
1158 2275
1159 - private function get_app_meta( $app_id ) {
1160 - $container = WPDA_App_Container_Model::select( $app_id, 0 );
1161 - 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'] ) ) {
1162 2279 return $this->bad_request();
1163 2280 }
1164 - 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 + }
1165 2293 }
1166 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 +
1167 2548 private function do_app_save(
1168 2549 $app_id,
1169 2550 $app_name,
1170 2551 $app_title,
@@ -1172,9 +2553,10 @@
1172 2553 $app_settings,
1173 2554 $app_add_to_menu,
1174 2555 $app_dbs,
1175 2556 $app_tbl,
1176 - $app_cls
2557 + $app_cls,
2558 + $app_query
1177 2559 ) {
1178 2560 $error_msg = WPDA_App_Model::update(
1179 2561 $app_id,
1180 2562 $app_name,
@@ -1192,9 +2574,9 @@
1192 2574 $app_id,
1193 2575 $app_dbs,
1194 2576 $app_tbl,
1195 2577 json_encode( $app_cls ),
1196 - 0
2578 + $app_query
1197 2579 );
1198 2580 if ( '' !== $error_msg ) {
1199 2581 return new \WP_Error('error', $error_msg, array(
1200 2582 'status' => 403,
@@ -1202,9 +2584,9 @@
1202 2584 }
1203 2585 return $this->WPDA_Rest_Response( __( 'Changes successfully saved', 'wp-data-access' ) );
1204 2586 }
1205 2587
1206 - private function main_app_access( $app_id, &$msg = '' ) {
2588 + private function main_app_access( $app_id, &$msg = '', &$app = null ) {
1207 2589 // Get app info
1208 2590 $app = WPDA_App_Model::get_by_id( $app_id );
1209 2591 if ( false === $app ) {
1210 2592 // App not found
@@ -1247,9 +2629,9 @@
1247 2629 if ( !$this->main_app_access( $app_id, $msg ) ) {
1248 2630 return false;
1249 2631 }
1250 2632 // Get container
1251 - $container = WPDA_App_Container_Model::get_container( $cnt_id );
2633 + $container = WPDA_App_Container_Model::get_container( $app_id, $cnt_id );
1252 2634 if ( !is_array( $container ) || 0 === count( $container ) ) {
1253 2635 // Container not found
1254 2636 $msg = __( 'Bad request', 'wp-data-access' );
1255 2637 return false;
@@ -1256,12 +2638,14 @@
1256 2638 }
1257 2639 if ( 'select' !== $action ) {
1258 2640 $cnt_table = json_decode( (string) $container[0]['cnt_table'], true );
1259 2641 if ( !isset( $cnt_table['table']['transactions'][$action] ) || false === $cnt_table['table']['transactions'][$action] ) {
1260 - $cnt_relation = json_decode( (string) $container[0]['cnt_relation'], true );
1261 - if ( !(isset( $cnt_relation['cnt_id_master'] ) && $this->check_master_container_access( $cnt_relation['cnt_id_master'], $action )) ) {
1262 - $msg = __( 'Unauthorized', 'wp-data-access' );
1263 - 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 + }
1264 2648 }
1265 2649 }
1266 2650 }
1267 2651 // Return database name, table name and columns
@@ -1274,10 +2658,10 @@
1274 2658 );
1275 2659 return true;
1276 2660 }
1277 2661
1278 - private function check_master_container_access( $cnt_id, $action ) {
1279 - $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 );
1280 2664 if ( !is_array( $container ) || 0 === count( $container ) ) {
1281 2665 // Container not found
1282 2666 return false;
1283 2667 }
@@ -1283,12 +2667,122 @@
1283 2667 }
1284 2668 $cnt_table = json_decode( (string) $container[0]['cnt_table'], true );
1285 2669 if ( !isset( $cnt_table['table']['transactions'][$action] ) || false === $cnt_table['table']['transactions'][$action] ) {
1286 2670 $cnt_relation = json_decode( (string) $container[0]['cnt_relation'], true );
1287 - 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 )) ) {
1288 2672 return false;
1289 2673 }
1290 2674 }
1291 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 );
1292 2786 }
1293 2787
1294 2788 }