PluginProbe
WP Data Access – App Builder for Tables, Forms, Dashboards, Charts & Maps / 5.5.87
WP Data Access – App Builder for Tables, Forms, Dashboards, Charts & Maps v5.5.87
5.5.87 5.5.85 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 All 162 releases
wp-data-access / WPDataAccess / API / WPDA_Apps.php

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

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