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

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

1,374 lines 53.7 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_Dictionary_Access;
8 use WPDataAccess\Data_Dictionary\WPDA_List_Columns_Cache;
9 use WPDataAccess\Plugin_Table_Models\WPDA_Table_Settings_Model;
10 use WPDataAccess\Utilities\WPDA_WP_Media;
11 use WPDataAccess\WPDA;
12 class WPDA_Table extends WPDA_API_Core {
13 const WPDA_SEARCH_MODES = array(
14 'contains',
15 'startsWith',
16 'endsWith',
17 'equals',
18 'notEquals',
19 'empty',
20 'notEmpty',
21 'between',
22 'betweenInclusive',
23 'greaterThan',
24 'greaterThanOrEqualTo',
25 'lessThan',
26 'lessThanOrEqualTo'
27 );
28
29 const RELATIONTABLEPREFIX = 'relationTableColumn___';
30
31 public function register_rest_routes() {
32 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'table/meta', array(
33 'methods' => array('POST'),
34 'callback' => array($this, 'table_meta'),
35 'permission_callback' => '__return_true',
36 'args' => array(
37 'dbs' => $this->get_param( 'dbs' ),
38 'tbl' => $this->get_param( 'tbl' ),
39 'waa' => array(
40 'required' => false,
41 'type' => 'boolean',
42 'description' => __( 'With admin actions (to support table exports)', 'wp-data-access' ),
43 ),
44 ),
45 ) );
46 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'table/select', array(
47 'methods' => array('GET', 'POST'),
48 'callback' => array($this, 'table_select'),
49 'permission_callback' => '__return_true',
50 'args' => array(
51 'dbs' => $this->get_param( 'dbs' ),
52 'tbl' => $this->get_param( 'tbl' ),
53 'col' => $this->get_param( 'cols' ),
54 'page_index' => $this->get_param( 'page_index' ),
55 'page_size' => $this->get_param( 'page_size' ),
56 'search' => $this->get_param( 'search' ),
57 'search_columns' => $this->get_param( 'search_columns' ),
58 'search_column_fns' => $this->get_param( 'search_column_fns' ),
59 'sorting' => $this->get_param( 'sorting' ),
60 'row_count' => $this->get_param( 'row_count' ),
61 'row_count_estimate' => $this->get_param( 'row_count_estimate' ),
62 'media' => $this->get_param( 'media' ),
63 'client_side' => $this->get_param( 'client_side' ),
64 ),
65 ) );
66 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'table/get', array(
67 'methods' => array('GET', 'POST'),
68 'callback' => array($this, 'table_get'),
69 'permission_callback' => '__return_true',
70 'args' => array(
71 'dbs' => $this->get_param( 'dbs' ),
72 'tbl' => $this->get_param( 'tbl' ),
73 'key' => $this->get_param( 'key' ),
74 'media' => $this->get_param( 'media' ),
75 ),
76 ) );
77 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'table/insert', array(
78 'methods' => array('GET', 'POST'),
79 'callback' => array($this, 'table_insert'),
80 'permission_callback' => '__return_true',
81 'args' => array(
82 'dbs' => $this->get_param( 'dbs' ),
83 'tbl' => $this->get_param( 'tbl' ),
84 'val' => $this->get_param( 'val' ),
85 ),
86 ) );
87 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'table/update', array(
88 'methods' => array('GET', 'POST'),
89 'callback' => array($this, 'table_update'),
90 'permission_callback' => '__return_true',
91 'args' => array(
92 'dbs' => $this->get_param( 'dbs' ),
93 'tbl' => $this->get_param( 'tbl' ),
94 'key' => $this->get_param( 'key' ),
95 'val' => $this->get_param( 'val' ),
96 ),
97 ) );
98 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'table/delete', array(
99 'methods' => array('GET', 'POST'),
100 'callback' => array($this, 'table_delete'),
101 'permission_callback' => '__return_true',
102 'args' => array(
103 'dbs' => $this->get_param( 'dbs' ),
104 'tbl' => $this->get_param( 'tbl' ),
105 'key' => $this->get_param( 'key' ),
106 ),
107 ) );
108 register_rest_route( WPDA_API::WPDA_NAMESPACE, 'table/lov', array(
109 'methods' => array('GET', 'POST'),
110 'callback' => array($this, 'table_lov'),
111 'permission_callback' => '__return_true',
112 'args' => array(
113 'dbs' => $this->get_param( 'dbs' ),
114 'tbl' => $this->get_param( 'tbl' ),
115 'col' => $this->get_param( 'col' ),
116 ),
117 ) );
118 }
119
120 /**
121 * Get table meta info.
122 *
123 * @param WP_REST_Request $request Rest API request.
124 * @return \WP_Error|\WP_REST_Response
125 */
126 public function table_meta( $request ) {
127 $dbs = $request->get_param( 'dbs' );
128 $tbl = $request->get_param( 'tbl' );
129 $waa = $request->get_param( 'waa' );
130 if ( $this->check_table_access(
131 $dbs,
132 $tbl,
133 $request,
134 'select',
135 $msg
136 ) ) {
137 return $this->WPDA_Rest_Response( '', $this->get_table_meta_data( $dbs, $tbl, $waa ) );
138 } else {
139 if ( 'rest_cookie_invalid_nonce' === $msg ) {
140 return $this->invalid_nonce();
141 } else {
142 return new \WP_Error('error', $msg, array(
143 'status' => 401,
144 ));
145 }
146 }
147 }
148
149 /**
150 * Database table query using the full primary key. Must return exactly one row.
151 *
152 * @param WP_REST_Request $request Rest API request.
153 * @return \WP_Error|\WP_REST_Response
154 */
155 public function table_get( $request ) {
156 $dbs = $request->get_param( 'dbs' );
157 $tbl = $request->get_param( 'tbl' );
158 $key = $request->get_param( 'key' );
159 $media = $request->get_param( 'media' );
160 if ( $this->check_table_access(
161 $dbs,
162 $tbl,
163 $request,
164 'select',
165 $msg
166 ) ) {
167 return $this->get(
168 $dbs,
169 $tbl,
170 $key,
171 $media
172 );
173 } else {
174 if ( 'rest_cookie_invalid_nonce' === $msg ) {
175 return $this->invalid_nonce();
176 } else {
177 return new \WP_Error('error', $msg, array(
178 'status' => 401,
179 ));
180 }
181 }
182 }
183
184 /**
185 * Insert one row.
186 *
187 * @param WP_REST_Request $request Rest API request.
188 * @return \WP_Error|\WP_REST_Response
189 */
190 public function table_insert( $request ) {
191 $dbs = $request->get_param( 'dbs' );
192 $tbl = $request->get_param( 'tbl' );
193 $val = $request->get_param( 'val' );
194 if ( $this->check_table_access(
195 $dbs,
196 $tbl,
197 $request,
198 'insert',
199 $msg
200 ) ) {
201 return $this->insert( $dbs, $tbl, $val );
202 } else {
203 if ( 'rest_cookie_invalid_nonce' === $msg ) {
204 return $this->invalid_nonce();
205 } else {
206 return new \WP_Error('error', $msg, array(
207 'status' => 401,
208 ));
209 }
210 }
211 }
212
213 /**
214 * Update uses primary key. Must return exactly one row.
215 *
216 * @param WP_REST_Request $request Rest API request.
217 * @return \WP_Error|\WP_REST_Response
218 */
219 public function table_update( $request ) {
220 $dbs = $request->get_param( 'dbs' );
221 $tbl = $request->get_param( 'tbl' );
222 $key = $request->get_param( 'key' );
223 $val = $request->get_param( 'val' );
224 if ( $this->check_table_access(
225 $dbs,
226 $tbl,
227 $request,
228 'update',
229 $msg
230 ) ) {
231 return $this->update(
232 $dbs,
233 $tbl,
234 $key,
235 $val
236 );
237 } else {
238 if ( 'rest_cookie_invalid_nonce' === $msg ) {
239 return $this->invalid_nonce();
240 } else {
241 return new \WP_Error('error', $msg, array(
242 'status' => 401,
243 ));
244 }
245 }
246 }
247
248 /**
249 * Delete uses primary key. Must return exactly one row.
250 *
251 * @param WP_REST_Request $request Rest API request.
252 * @return \WP_Error|\WP_REST_Response
253 */
254 public function table_delete( $request ) {
255 $dbs = $request->get_param( 'dbs' );
256 $tbl = $request->get_param( 'tbl' );
257 $key = $request->get_param( 'key' );
258 if ( $this->check_table_access(
259 $dbs,
260 $tbl,
261 $request,
262 'delete',
263 $msg
264 ) ) {
265 return $this->delete( $dbs, $tbl, $key );
266 } else {
267 if ( 'rest_cookie_invalid_nonce' === $msg ) {
268 return $this->invalid_nonce();
269 } else {
270 return new \WP_Error('error', $msg, array(
271 'status' => 401,
272 ));
273 }
274 }
275 }
276
277 /**
278 * Database table query to populate a list of values for a specific table/column.
279 *
280 * @param WP_REST_Request $request Rest API request.
281 * @return \WP_Error|\WP_REST_Response
282 */
283 public function table_lov( $request ) {
284 }
285
286 /**
287 * Database table query.
288 *
289 * Supports: searching, ordering and pagination.
290 *
291 * @param WP_REST_Request $request Rest API request.
292 * @return \WP_Error|\WP_REST_Response
293 */
294 public function table_select( $request ) {
295 $dbs = $request->get_param( 'dbs' );
296 $tbl = $request->get_param( 'tbl' );
297 $col = $request->get_param( 'col' );
298 $page_index = $request->get_param( 'page_index' );
299 $page_size = $request->get_param( 'page_size' );
300 $search = $request->get_param( 'search' );
301 $search_columns = $request->get_param( 'search_columns' );
302 $search_column_fns = $request->get_param( 'search_column_fns' );
303 $search_data_types = $request->get_param( 'search_data_types' );
304 $sorting = $request->get_param( 'sorting' );
305 $row_count = $request->get_param( 'row_count' );
306 $row_count_estimate = $request->get_param( 'row_count_estimate' );
307 $media = $request->get_param( 'media' );
308 $client_side = '1' === $request->get_param( 'client_side' );
309 if ( $this->check_table_access(
310 $dbs,
311 $tbl,
312 $request,
313 'select',
314 $msg
315 ) ) {
316 return $this->select(
317 $dbs,
318 $tbl,
319 $col,
320 $page_index,
321 $page_size,
322 $search,
323 $search_columns,
324 $search_column_fns,
325 $sorting,
326 $row_count,
327 $row_count_estimate,
328 $media,
329 '',
330 '',
331 array(),
332 array(),
333 array(),
334 $search_data_types,
335 $client_side
336 );
337 } else {
338 if ( 'rest_cookie_invalid_nonce' === $msg ) {
339 return $this->invalid_nonce();
340 } else {
341 return new \WP_Error('error', $msg, array(
342 'status' => 401,
343 ));
344 }
345 }
346 }
347
348 /**
349 * Perform query and return result as JSON response.
350 *
351 * @param string $dbs Schema name (database).
352 * @param string $tbl Table Name.
353 * @param array $column_name Column name.
354 * @param array $search Global search.
355 * @param array $search_columns Column filters.
356 * @param array $search_column_fns Column filter fns.
357 * @return \WP_Error|\WP_REST_Response
358 */
359 public function lov(
360 $dbs,
361 $tbl,
362 $column_name,
363 $cascade = false,
364 $default_where = '',
365 $search = '',
366 $column_names = array(),
367 $search_columns = array(),
368 $search_column_fns = array(),
369 $lookups = array(),
370 $md = array(),
371 $m2m_relationship = array(),
372 $search_data_types = array()
373 ) {
374 }
375
376 public function lookup(
377 $dbs,
378 $tbl,
379 $column_key,
380 $column_value,
381 $column_dynamic_values,
382 $default_where,
383 $cascade = false,
384 $cascade_table = '',
385 $cascade_column = '',
386 $cascade_where = '',
387 $search = '',
388 $column_names = array(),
389 $search_columns = array(),
390 $search_column_fns = array(),
391 $lookups = array(),
392 $md = array(),
393 $m2m_relationship = array(),
394 $search_data_types = array()
395 ) {
396 $wpdadb = WPDADB::get_db_connection( $dbs );
397 if ( null === $wpdadb ) {
398 // Error connecting.
399 return new \WP_Error('error', "Error connecting to database {$dbs}", array(
400 'status' => 420,
401 ));
402 } else {
403 // Connected, perform queries.
404 $suppress = $wpdadb->suppress_errors( true );
405 $subquery = '';
406 $where = '';
407 if ( '' !== trim( $default_where ) ) {
408 if ( 'where' !== strtolower( substr( trim( $default_where ), 0, 5 ) ) ) {
409 $where = "where {$default_where}";
410 } else {
411 $where = $default_where;
412 }
413 }
414 $dynamic_where = array();
415 if ( is_array( $column_dynamic_values ) && 0 < count( $column_dynamic_values ) ) {
416 foreach ( $column_dynamic_values as $key => $value ) {
417 $dynamic_where[] = $wpdadb->prepare( " `{$key}` = %s ", $value );
418 }
419 $where .= (( '' === $where ? ' where ' : ' and ' )) . ' (' . implode( ' and ', $dynamic_where ) . ') ';
420 }
421 if ( strpos( $column_value, ',' ) !== false ) {
422 $columns = explode( ',', $column_value );
423 $sql = $wpdadb->prepare( "\n\t\t\t\t\t\t\tselect distinct `%1s` as 'key'\n\t\t\t\t\t\t\t, `%1s`\n\t\t\t\t\t\t\tfrom `%1s`\n\t\t\t\t\t\t", array($column_key, implode( '`,`', $columns ), $tbl) );
424 } else {
425 $sql = $wpdadb->prepare( "\n\t\t\t\t\t\t\tselect distinct `%1s` as 'key'\n\t\t\t\t\t\t\t, `%1s` as 'value' \n\t\t\t\t\t\t\tfrom `%1s`\n\t\t\t\t\t\t", array($column_key, $column_value, $tbl) );
426 }
427 $sql .= " {$where} order by 2 ";
428 // $where already sanitized
429 $dataset = $wpdadb->get_results( $sql, 'OBJECT' );
430 $wpdadb->suppress_errors( $suppress );
431 // Send response.
432 if ( '' === $wpdadb->last_error ) {
433 // Prepare debug info.
434 if ( 'on' === WPDA::get_option( WPDA::OPTION_PLUGIN_DEBUG ) ) {
435 $debug = array(
436 'debug' => array(
437 'sql' => preg_replace( "/\\s+/", " ", $sql ),
438 'where' => $where ?? '',
439 ),
440 );
441 } else {
442 $debug = null;
443 }
444 // Add context node to response.
445 $context = array();
446 if ( isset( $debug['debug'] ) && 'on' === WPDA::get_option( WPDA::OPTION_PLUGIN_DEBUG ) ) {
447 $context['debug'] = $debug['debug'];
448 }
449 return $this->WPDA_Rest_Response( '', $dataset, $context );
450 } else {
451 return new \WP_Error('error', $wpdadb->last_error, array(
452 'status' => 420,
453 ));
454 }
455 }
456 }
457
458 /**
459 * Perform query and return result as JSON response.
460 *
461 * @param string $dbs Schema name (database).
462 * @param string $tbl Table Name.
463 * @param array $primary Primary (key|value pairs.
464 * @param array $media_columns Media columns.
465 * @param array $column_names Just a plain array containing the column names.
466 * @return \WP_Error|\WP_REST_Response
467 */
468 public function get(
469 $dbs,
470 $tbl,
471 $primary_key,
472 $media_columns = array(),
473 $column_names = array(),
474 $default_where = ''
475 ) {
476 $wpdadb = WPDADB::get_db_connection( $dbs );
477 if ( null === $wpdadb ) {
478 // Error connecting.
479 return new \WP_Error('error', "Error connecting to database {$dbs}", array(
480 'status' => 420,
481 ));
482 } else {
483 // Connected, perform queries.
484 $suppress = $wpdadb->suppress_errors( true );
485 $where = '';
486 foreach ( $primary_key as $primary_key_column => $primary_key_value ) {
487 $where = ( '' === $where ? ' where ' : $where . ' and ' );
488 $where .= $wpdadb->prepare( " `%1s` = %s ", array($primary_key_column, $primary_key_value) );
489 }
490 if ( '' !== $default_where ) {
491 if ( '' === $where ) {
492 $where = $default_where;
493 } else {
494 $where .= " and {$default_where} ";
495 }
496 }
497 // Get table column data types
498 $column_list = WPDA_List_Columns_Cache::get_list_columns( $dbs, $tbl );
499 $table_columns = $column_list->get_table_columns();
500 // Prepare selected column list
501 $columns_selected = array();
502 $search_data_types = array();
503 foreach ( $table_columns as $table_column ) {
504 $columns_selected[$table_column['column_name']] = true;
505 $search_data_types[$table_column['column_name']] = $table_column['data_type'];
506 }
507 $selected_columns = $this->get_selected_columns( $columns_selected, $search_data_types );
508 $sql = $wpdadb->prepare( "\n select {$selected_columns}\n from `%1s`\n {$where}\n ", array($tbl) );
509 $dataset = $wpdadb->get_results( $sql, 'ARRAY_A' );
510 // Prepare debug info.
511 if ( 'on' === WPDA::get_option( WPDA::OPTION_PLUGIN_DEBUG ) ) {
512 $debug = array(
513 'debug' => array(
514 'sql' => $sql,
515 'where' => $where,
516 ),
517 );
518 } else {
519 $debug = null;
520 }
521 $wpdadb->suppress_errors( $suppress );
522 // Send response.
523 $media = array();
524 if ( is_array( $media_columns ) && 0 < count( $media_columns ) ) {
525 foreach ( $media_columns as $media_column_name => $media_column_type ) {
526 if ( isset( $dataset[0][$media_column_name] ) ) {
527 if ( in_array( $media_column_type, [
528 'WP-Image',
529 'WP-Attachment',
530 'WP-Audio',
531 'WP-Video'
532 ] ) ) {
533 $media[$media_column_name] = WPDA_WP_Media::get_media_url( $dataset[0][$media_column_name] );
534 }
535 }
536 }
537 }
538 $context = array();
539 $context['media'] = $media;
540 if ( isset( $debug['debug'] ) && 'on' === WPDA::get_option( WPDA::OPTION_PLUGIN_DEBUG ) ) {
541 $context['debug'] = $debug['debug'];
542 }
543 if ( 0 === count( $dataset ) ) {
544 return $this->WPDA_Rest_Response( 'No data found', $dataset, array(
545 'debug' => $debug['debug'],
546 ) );
547 } else {
548 if ( 1 === count( $dataset ) ) {
549 return $this->WPDA_Rest_Response( '', $dataset, $context );
550 } else {
551 return $this->WPDA_Rest_Response( 'Query returned more than one row', $dataset, array(
552 'debug' => $debug['debug'],
553 ) );
554 }
555 }
556 }
557 }
558
559 public function insert( $dbs, $tbl, $column_values ) {
560 $wpdadb = WPDADB::get_db_connection( $dbs );
561 if ( null === $wpdadb ) {
562 // Error connecting.
563 return new \WP_Error('error', "Error connecting to database {$dbs}", array(
564 'status' => 420,
565 ));
566 } else {
567 // Get column default values
568 $column_list = WPDA_List_Columns_Cache::get_list_columns( $dbs, $tbl );
569 $table_columns = $column_list->get_table_columns();
570 foreach ( $table_columns as $table_column_type ) {
571 if ( isset( $column_values[$table_column_type['column_name']] ) && $column_values[$table_column_type['column_name']] === $table_column_type['column_default'] ) {
572 // Remove default values if send values equals column default to support defaults using functions
573 unset($column_values[$table_column_type['column_name']]);
574 }
575 }
576 // Sanitize column names and values.
577 $sanitized_column_values = self::sanitize_column_values( $dbs, $tbl, $column_values );
578 if ( false === $sanitized_column_values ) {
579 return new \WP_Error('error', "Invalid arguments", array(
580 'status' => 420,
581 ));
582 }
583 // Insert row.
584 $rows_inserted = $wpdadb->insert( $tbl, $sanitized_column_values );
585 // Send response.
586 if ( 1 === $rows_inserted ) {
587 return $this->WPDA_Rest_Response( __( 'Row successfully inserted', 'wp-data-access' ), null, array(
588 'insert_id' => $wpdadb->insert_id,
589 ) );
590 } else {
591 if ( '' !== $wpdadb->last_error ) {
592 return new \WP_Error('error', $wpdadb->last_error, array(
593 'status' => 420,
594 ));
595 } else {
596 return new \WP_Error('error', 'Insert failed', array(
597 'status' => 420,
598 ));
599 }
600 }
601 }
602 }
603
604 public function update(
605 $dbs,
606 $tbl,
607 $primary_key,
608 $column_values,
609 $column_names = array(),
610 $code_columns = array(),
611 $html_columns = array()
612 ) {
613 $wpdadb = WPDADB::get_db_connection( $dbs );
614 if ( null === $wpdadb ) {
615 // Error connecting.
616 return new \WP_Error('error', "Error connecting to database {$dbs}", array(
617 'status' => 420,
618 ));
619 } else {
620 // Sanitize column names and values.
621 $sanitized_column_values = self::sanitize_column_values(
622 $dbs,
623 $tbl,
624 $column_values,
625 $code_columns,
626 $html_columns
627 );
628 if ( false === $sanitized_column_values ) {
629 return new \WP_Error('error', "Invalid arguments", array(
630 'status' => 420,
631 ));
632 }
633 // Update row.
634 $rows_inserted = $wpdadb->update( $tbl, $sanitized_column_values, $primary_key );
635 // Send response.
636 if ( 0 === $rows_inserted ) {
637 return $this->WPDA_Rest_Response_Info( 'Nothing to update' );
638 } elseif ( 1 === $rows_inserted ) {
639 $context = null;
640 if ( 0 < count( $column_names ) ) {
641 // Return updated values
642 $updated_row = $this->get(
643 $dbs,
644 $tbl,
645 $primary_key,
646 $column_names
647 );
648 if ( isset( $updated_row->data['data'][0] ) ) {
649 $updated_values = $updated_row->data['data'][0];
650 $updated_context = array();
651 foreach ( $updated_values as $key => $value ) {
652 if ( !isset( $column_values[$key] ) ) {
653 $updated_context[$key] = $value;
654 }
655 }
656 if ( 0 < count( $updated_context ) ) {
657 $context = array(
658 'updated' => $updated_context,
659 );
660 }
661 }
662 }
663 return $this->WPDA_Rest_Response( __( 'Row successfully updated', 'wp-data-access' ), null, $context );
664 } else {
665 if ( '' !== $wpdadb->last_error ) {
666 return new \WP_Error('error', $wpdadb->last_error, array(
667 'status' => 420,
668 ));
669 } else {
670 return new \WP_Error('error', 'Update failed', array(
671 'status' => 420,
672 ));
673 }
674 }
675 }
676 }
677
678 public function delete( $dbs, $tbl, $primary_key ) {
679 $wpdadb = WPDADB::get_db_connection( $dbs );
680 if ( null === $wpdadb ) {
681 // Error connecting.
682 return new \WP_Error('error', "Error connecting to database {$dbs}", array(
683 'status' => 420,
684 ));
685 } else {
686 // Delete row.
687 $rows_deleted = $wpdadb->delete( $tbl, $primary_key );
688 // Send response.
689 if ( 0 === $rows_deleted ) {
690 return $this->WPDA_Rest_Response_Info( __( 'No data found', 'wp-data-access' ) );
691 } elseif ( 1 === $rows_deleted ) {
692 return $this->WPDA_Rest_Response( __( 'Row successfully deleted', 'wp-data-access' ) );
693 } else {
694 if ( '' !== $wpdadb->last_error ) {
695 return new \WP_Error('error', $wpdadb->last_error, array(
696 'status' => 420,
697 ));
698 } else {
699 return new \WP_Error('error', 'Delete failed', array(
700 'status' => 420,
701 ));
702 }
703 }
704 }
705 }
706
707 private function generate_lookup_condition(
708 $wpdadb,
709 $lookups,
710 $column_name,
711 $search_values,
712 $search_column_fns,
713 $filter_mode = null,
714 $filter_key = false
715 ) {
716 $lookup = $lookups[$column_name];
717 $lookup_table = $lookup['tbl'];
718 $lookup_key = $lookup['key'];
719 $lookup_columns = explode( ',', $lookup['value'] );
720 $lookup_where = array();
721 if ( $filter_key ) {
722 $filter_columns = array($lookup_key);
723 } else {
724 $filter_columns = $lookup_columns;
725 }
726 foreach ( $filter_columns as $lookup_column ) {
727 foreach ( $search_values as $search_value ) {
728 $lookup_where[] = $this->add_filter(
729 $wpdadb,
730 $lookup_column,
731 ( $filter_mode !== null ? $filter_mode : $search_column_fns[$column_name] ),
732 $search_value
733 );
734 }
735 }
736 if ( 0 < count( $lookup_where ) ) {
737 return $wpdadb->prepare( ' `%1s` in ( select `%1s` from `%1s` where (' . implode( ' or ', $lookup_where ) . ') ) ', array(
738 $column_name,
739 $lookup_key,
740 $lookup_table,
741 $lookup_columns[0],
742 "%{$search_values[0]}%"
743 ) );
744 } else {
745 return null;
746 }
747 }
748
749 public static function remove_where_from_sql( $sql ) {
750 if ( 'where' === substr( trim( $sql ), 0, 5 ) ) {
751 $pos = strpos( $sql, 'where' );
752 if ( false !== $pos ) {
753 $sql = substr_replace(
754 $sql,
755 '',
756 $pos,
757 5
758 );
759 }
760 }
761 return $sql;
762 }
763
764 private function get_md( $md, $wpdadb, $m2m_relationship ) {
765 }
766
767 private function get_global_filter(
768 $wpdadb,
769 $search,
770 $column_names,
771 $lookups,
772 $m2m_relationship
773 ) {
774 $where_global = array();
775 if ( null !== $search && "" !== $search ) {
776 foreach ( $column_names as $column_name => $queryable ) {
777 if ( $queryable ) {
778 if ( isset( $lookups[$column_name] ) ) {
779 // Perform look search.
780 $condition = $this->generate_lookup_condition(
781 $wpdadb,
782 $lookups,
783 $column_name,
784 array($search),
785 array(),
786 'contains'
787 );
788 if ( null !== $condition ) {
789 $where_global[] = $condition;
790 }
791 } else {
792 $where_global[] = $wpdadb->prepare( " `%1s` like '%s' ", array($this->convert_column_name( $m2m_relationship, $column_name ), '%' . esc_sql( $search ) . '%') );
793 }
794 }
795 }
796 }
797 return $where_global;
798 }
799
800 private function get_column_filters(
801 $wpdadb,
802 $search_columns,
803 $search_column_fns,
804 $lookups,
805 $m2m_relationship,
806 $search_data_types
807 ) {
808 }
809
810 private function get_where(
811 $wpdadb,
812 $default_where,
813 $md,
814 $m2m_relationship,
815 $search,
816 $column_names,
817 $lookups,
818 $search_columns,
819 $search_column_fns,
820 $search_data_types,
821 $geo_radius = array()
822 ) {
823 // Default where.
824 if ( '' !== trim( $default_where ) && 'where' !== strtolower( substr( trim( $default_where ), 0, 5 ) ) ) {
825 $where = "where {$default_where}";
826 } else {
827 $where = $default_where;
828 }
829 // Global filter.
830 $where_global = $this->get_global_filter(
831 $wpdadb,
832 $search,
833 $column_names,
834 $lookups,
835 $m2m_relationship
836 );
837 if ( 0 < count( $where_global ) ) {
838 $where .= (( '' === trim( $where ) ? ' where ' : ' and ' )) . $this->add_condition( $where_global, 'or' );
839 }
840 if ( is_array( $geo_radius ) && 0 < count( $geo_radius ) ) {
841 // Add geo radius to query
842 // Variable $geo_radius already sanitized in REST API
843 $unit = ( "km" == $geo_radius['unit'] ? 1000 : 1609.344 );
844 // km versus miles
845 if ( $geo_radius['col']['lat'] === $geo_radius['col']['lng'] ) {
846 // Location stored in GEOMETRY or POINT data type
847 $geocol = $geo_radius['col']['lat'];
848 $geo_where = " ( st_distance_sphere(point(st_y(`{$geocol}`), st_x(`{$geocol}`)), point({$geo_radius['loc']['lng']}, {$geo_radius['loc']['lat']})) / {$unit} ) < {$geo_radius['radius']} ";
849 } else {
850 // Latitude and longitude stored separately
851 $geo_where = " ( st_distance_sphere(point(`{$geo_radius['col']['lng']}`, `{$geo_radius['col']['lat']}`), point({$geo_radius['loc']['lng']}, {$geo_radius['loc']['lat']})) / {$unit} ) < {$geo_radius['radius']} ";
852 }
853 if ( '' === $where ) {
854 $where = " where {$geo_where} ";
855 } else {
856 $where .= " and {$geo_where} ";
857 }
858 }
859 return $where;
860 }
861
862 private function get_selected_columns( $column_names, $search_data_types ) {
863 // Check for geo columns
864 $geometryColumns = array();
865 if ( is_array( $search_data_types ) ) {
866 foreach ( $search_data_types as $column_name => $search_data_type ) {
867 if ( 'geometry' === strtolower( $search_data_type ) || 'point' === strtolower( $search_data_type ) ) {
868 $geometryColumns[] = $column_name;
869 }
870 }
871 }
872 return implode( ",", array_map( function ( $column_name ) use($geometryColumns) {
873 if ( in_array( $column_name, $geometryColumns ) ) {
874 return 'ST_AsText(`' . WPDA::remove_backticks( $column_name ) . '`) ' . " as `{$column_name}` ";
875 // Convert geo data to string
876 } else {
877 return '`' . WPDA::remove_backticks( $column_name ) . '`';
878 }
879 }, array_keys( $column_names ) ) );
880 }
881
882 /**
883 * Perform query and return result as JSON response.
884 *
885 * @param string $dbs Schema name (database).
886 * @param string $tbl Table Name.
887 * @param string $column_names Column Names.
888 * @param string $page_index Page number.
889 * @param string $page_size Rows per page.
890 * @param string $search Filter.
891 * @param string $search_columns Column search filters.
892 * @param string $search_column_fns Column search filter modes.
893 * @param string $Sorting Order by.
894 * @param integer $last_row_count Row count previous request.
895 * @param string $row_count_estimate Indicates if row count estimate should be used.
896 * @param string $media_columns Media columns.
897 * @param string $default_where Defaul where clause
898 * @param string $default_orderby Defaul order by clause
899 * @return \WP_Error|\WP_REST_Response
900 */
901 public function select(
902 $dbs,
903 $tbl,
904 $column_names,
905 $page_index,
906 $page_size,
907 $search,
908 $search_columns,
909 $search_column_fns,
910 $sorting,
911 $last_row_count,
912 $row_count_estimate,
913 $media_columns = array(),
914 $default_where = '',
915 $default_orderby = '',
916 $lookups = array(),
917 $md = array(),
918 $m2m_relationship = array(),
919 $search_data_types = array(),
920 $client_side = false,
921 $geo_radius = array()
922 ) {
923 $wpdadb = WPDADB::get_db_connection( $dbs );
924 if ( null === $wpdadb ) {
925 // Error connecting.
926 return new \WP_Error('error', "Error connecting to database {$dbs}", array(
927 'status' => 420,
928 ));
929 } else {
930 $suppress = $wpdadb->suppress_errors( true );
931 // Build where clause.
932 $where = $this->get_where(
933 $wpdadb,
934 $default_where,
935 $md,
936 $m2m_relationship,
937 $search,
938 $column_names,
939 $lookups,
940 $search_columns,
941 $search_column_fns,
942 $search_data_types,
943 $geo_radius
944 );
945 // Build order by.
946 $sqlorder = '';
947 if ( is_array( $sorting ) && 0 < count( $sorting ) ) {
948 foreach ( $sorting as $sort ) {
949 if ( '' === $sqlorder ) {
950 $sqlorder = 'order by ';
951 } else {
952 $sqlorder .= ',';
953 }
954 $sqlorder .= '`' . $this->convert_column_name( $m2m_relationship, $sort['id'] ) . '` ' . (( $sort['desc'] ? 'desc' : 'asc' ));
955 }
956 }
957 if ( '' === $sqlorder && '' !== trim( $default_orderby ) ) {
958 $sqlorder = $default_orderby;
959 }
960 // Add pagination.
961 if ( !is_numeric( $page_size ) ) {
962 $page_size = 10;
963 }
964 $offset = $page_index * $page_size;
965 // Calculate offset.
966 if ( !is_numeric( $offset ) ) {
967 $offset = 0;
968 }
969 // Prepare query.
970 $sql = "\n\t\t\t\t\tselect " . $this->get_selected_columns( $column_names, $search_data_types ) . "\n\t\t\t\t\tfrom `%1s`\n\t\t\t\t\t{$where}\n\t\t\t\t\t{$sqlorder}\n\t\t\t\t";
971 $sql_tables = array($tbl);
972 // Perpare query.
973 $sql = $wpdadb->prepare( ( true === $client_side ? $sql : $sql . (( 0 < $page_size ? " limit {$page_size} offset {$offset} " : '' )) ), $sql_tables );
974 // Prepare debug info.
975 if ( 'on' === WPDA::get_option( WPDA::OPTION_PLUGIN_DEBUG ) ) {
976 $debug = array(
977 'sql' => preg_replace( "/\\s+/", " ", $sql ),
978 'where' => $where,
979 'order by' => $sqlorder,
980 );
981 } else {
982 $debug = null;
983 }
984 // Perform query.
985 $dataset = $wpdadb->get_results( $sql, 'ARRAY_A' );
986 if ( $wpdadb->last_error ) {
987 // Handle SQL errors.
988 return new \WP_Error('error', $wpdadb->last_error, array(
989 'status' => 420,
990 'debug' => $debug,
991 ));
992 }
993 if ( is_numeric( $last_row_count ) and 0 <= $last_row_count ) {
994 // Prevents additional unnecessary queries.
995 $rowcount = $last_row_count;
996 } else {
997 if ( true === $client_side ) {
998 $rowcount = 0;
999 } else {
1000 $estimate = false;
1001 if ( '1' === $row_count_estimate && '' === $where ) {
1002 // Perform row count estimate
1003 $countrows = $wpdadb->get_results( $wpdadb->prepare( "\n\t\t\t\t\t\t\t\t\tselect table_rows as rowcount\n\t\t\t\t\t\t\t\t\t from information_schema.tables\n\t\t\t\t\t\t\t\t\twhere table_schema = %s\n\t\t\t\t\t\t\t\t\t and table_name = %s\n\t\t\t\t\t\t\t\t", [$wpdadb->dbname, $tbl] ), 'ARRAY_A' );
1004 if ( isset( $countrows[0]['rowcount'] ) && 0 != $countrows[0]['rowcount'] ) {
1005 $estimate = true;
1006 }
1007 }
1008 if ( !$estimate ) {
1009 if ( !$estimate ) {
1010 // (Re)Count rows.
1011 $countrows = $wpdadb->get_results( $wpdadb->prepare( "\n\t\t\t\t\t\t\t\t\t\tselect count(1) as rowcount\n\t\t\t\t\t\t\t\t\t\tfrom `%1s`\n\t\t\t\t\t\t\t\t\t\t{$where}\n\t\t\t\t\t\t\t\t\t", array($tbl) ), 'ARRAY_A' );
1012 }
1013 }
1014 if ( $wpdadb->last_error ) {
1015 // Handle SQL errors.
1016 return new \WP_Error('error', $wpdadb->last_error, array(
1017 'status' => 420,
1018 ));
1019 }
1020 if ( isset( $countrows[0]['rowcount'] ) ) {
1021 $rowcount = $countrows[0]['rowcount'];
1022 } else {
1023 $rowcount = 0;
1024 }
1025 }
1026 }
1027 // Add context node to response
1028 $context = array();
1029 if ( 'on' === WPDA::get_option( WPDA::OPTION_PLUGIN_DEBUG ) ) {
1030 $context['debug'] = $debug;
1031 }
1032 if ( is_array( $media_columns ) && 0 < count( $media_columns ) ) {
1033 // Handle WP media library
1034 $media = array();
1035 for ($i = 0; $i < count( $dataset ); $i++) {
1036 $media_row = array();
1037 foreach ( $media_columns as $media_column_name => $media_column_type ) {
1038 if ( isset( $dataset[$i][$media_column_name] ) ) {
1039 $media_row[$media_column_name] = WPDA_WP_Media::get_media_url( $dataset[$i][$media_column_name] );
1040 }
1041 }
1042 $media[] = $media_row;
1043 }
1044 // Add media to context node
1045 $context['media'] = $media;
1046 }
1047 $wpdadb->suppress_errors( $suppress );
1048 // Send response.
1049 $response = $this->WPDA_Rest_Response(
1050 '',
1051 $dataset,
1052 $context,
1053 array(
1054 'rowCount' => $rowcount,
1055 )
1056 );
1057 $response->header( 'X-WP-Total', $rowcount );
1058 // Total rows for this query.
1059 if ( 0 < $page_size ) {
1060 $pagecount = floor( $rowcount / $page_size );
1061 if ( $pagecount != $rowcount / $page_size ) {
1062 // phpcs:ignore WordPress.PHP.StrictComparisons
1063 $pagecount++;
1064 }
1065 } else {
1066 // Prevent division by zero
1067 $pagecount = 0;
1068 }
1069 $response->header( 'X-WP-TotalPages', $pagecount );
1070 // Total pages for this query.
1071 return $response;
1072 }
1073 }
1074
1075 private function convert_column_name( $m2m_relationship, $column_name ) {
1076 // Return plain column name.
1077 return $this->sanitize_db_identifier( $column_name );
1078 }
1079
1080 private function map_columns( $prefix, $column_names ) {
1081 return implode( ",", array_map( function ( $v ) use($prefix) {
1082 $c = $this->sanitize_db_identifier( $v );
1083 $r = ( 'd' === $prefix ? static::RELATIONTABLEPREFIX . $c : $c );
1084 return "`{$prefix}`.`{$c}` as \"{$r}\"";
1085 }, array_keys( $column_names ) ) );
1086 }
1087
1088 public function add_filter(
1089 $wpdadb,
1090 $search_column,
1091 $search_column_fns,
1092 $search_value,
1093 $m2m_relationship = array(),
1094 $search_data_types = array()
1095 ) {
1096 }
1097
1098 public static function add_condition( $where_lines, $operand = 'and' ) {
1099 if ( 0 < count( array_filter( $where_lines ) ) ) {
1100 // Apply all searches.
1101 return ' ( (' . implode( ") {$operand} (", array_filter( $where_lines ) ) . ') ) ';
1102 } else {
1103 return "";
1104 }
1105 }
1106
1107 /**
1108 * Get table meta data.
1109 *
1110 * @param string $dbs Database schema name.
1111 * @param string $tbl Database table name.
1112 * @param string $waa With admin actions.
1113 * @return array\object
1114 */
1115 public function get_table_meta_data( $dbs, $tbl, $waa ) {
1116 $sql_create_table = '';
1117 if ( WPDA::current_user_is_admin() ) {
1118 // Admin user has access to all resources
1119 $access = array(
1120 'select' => array('POST'),
1121 'insert' => array('POST'),
1122 'update' => array('POST'),
1123 'delete' => array('POST'),
1124 );
1125 // Get create table script
1126 $wpdadb = WPDADB::get_db_connection( $dbs );
1127 if ( null !== $wpdadb ) {
1128 $suppress_errors = $wpdadb->suppress_errors;
1129 $wpdadb->suppress_errors = true;
1130 // NO_TABLE_OPTIONS is deprecated in V8
1131 // $wpdadb->query( "SET sql_mode = 'NO_TABLE_OPTIONS'" );
1132 $sql = $wpdadb->get_results( $wpdadb->prepare( 'show create table `%1s`', array($tbl) ), 'ARRAY_N' );
1133 if ( isset( $sql[0][1] ) ) {
1134 $sql_create_table = $sql[0][1];
1135 }
1136 $wpdadb->suppress_errors = $suppress_errors;
1137 }
1138 } else {
1139 $access = $this->get_table_access( $dbs, $tbl );
1140 }
1141 $settings = new stdClass();
1142 if ( null !== $access ) {
1143 $columns = WPDA_List_Columns_Cache::get_list_columns( $dbs, $tbl );
1144 $settings_db = WPDA_Table_Settings_Model::query( $tbl, $dbs );
1145 if ( isset( $settings_db[0]['wpda_table_settings'] ) ) {
1146 $settings = json_decode( $settings_db[0]['wpda_table_settings'] );
1147 // Remove old settings from response.
1148 unset($settings->form_labels);
1149 unset($settings->list_labels);
1150 unset($settings->custom_settings);
1151 unset($settings->search_settings);
1152 }
1153 $settings->ui = WPDA_Settings::get_admin_settings( $dbs, $tbl );
1154 $rest_api = get_option( WPDA_API::WPDA_REST_API_TABLE_ACCESS );
1155 if ( isset( $rest_api[$dbs][$tbl] ) ) {
1156 $settings->rest_api = $rest_api[$dbs][$tbl];
1157 }
1158 $settings->env = $this->get_env();
1159 $wp_nonce_action_alter = "wpda-alter-{$tbl}";
1160 $wp_nonce_alter = wp_create_nonce( $wp_nonce_action_alter );
1161 $wp_nonce_refresh = null;
1162 $connect = null;
1163 global $wpdb;
1164 $settings->wp = [
1165 'roles' => $this->get_wp_roles(),
1166 'users' => $this->get_wp_users(),
1167 'home' => admin_url( 'admin.php' ),
1168 'homea' => admin_url( 'admin-ajax.php' ),
1169 'tables' => array_values( $wpdb->tables() ),
1170 'date_format' => get_option( 'date_format' ),
1171 'time_format' => get_option( 'time_format' ),
1172 'alter' => $wp_nonce_alter,
1173 'refresh' => $wp_nonce_refresh,
1174 'connect' => $connect,
1175 ];
1176 if ( true === $waa ) {
1177 $settings->wp['aonce'] = implode( '-', array(
1178 wp_create_nonce( 'wpda-export-' . json_encode( $tbl ) ),
1179 // Table export
1180 wp_create_nonce( 'wpda-rename-' . $tbl ),
1181 ) );
1182 }
1183 $media = $this->get_media( $dbs, $tbl, $columns->get_table_columns() );
1184 }
1185 return array(
1186 'columns' => $columns->get_table_columns(),
1187 'table_labels' => $columns->get_table_header_labels(),
1188 'form_labels' => $columns->get_table_column_headers(),
1189 'primary_key' => $columns->get_table_primary_key(),
1190 'access' => $access,
1191 'settings' => $settings,
1192 'media' => $media['media'],
1193 'wp_media' => $media['wp_media'],
1194 'table_info' => $this->get_table_info( $dbs, $tbl ),
1195 'create' => $sql_create_table,
1196 );
1197 }
1198
1199 private function get_table_access( $dbs, $tbl ) {
1200 if ( current_user_can( 'manage_options' ) ) {
1201 // Check administrator rights
1202 if ( is_admin() ) {
1203 $access = WPDA_Dictionary_Access::check_table_access_backend( $dbs, $tbl, $done );
1204 } else {
1205 $access = WPDA_Dictionary_Access::check_table_access_frontend( $dbs, $tbl, $done );
1206 }
1207 if ( $access ) {
1208 // Administrator access granted
1209 return array(
1210 'select' => array('POST'),
1211 'insert' => array('POST'),
1212 'update' => array('POST'),
1213 'delete' => array('POST'),
1214 );
1215 }
1216 }
1217 $tables = get_option( WPDA_API::WPDA_REST_API_TABLE_ACCESS );
1218 if ( false !== $tables && isset( $tables[$dbs][$tbl] ) && is_array( $tables[$dbs][$tbl] ) ) {
1219 $table = $tables[$dbs][$tbl];
1220 $table_access = new \stdClass();
1221 $table_access->select = $this->get_table_access_action( $table, 'select' );
1222 $table_access->insert = $this->get_table_access_action( $table, 'insert' );
1223 $table_access->update = $this->get_table_access_action( $table, 'update' );
1224 $table_access->delete = $this->get_table_access_action( $table, 'delete' );
1225 return $table_access;
1226 }
1227 return false;
1228 }
1229
1230 private function get_table_access_action( $table, $action ) {
1231 if ( isset( $table[$action]['authorization'], $table[$action]['methods'] ) && is_array( $table[$action]['methods'] ) && 0 < count( $table[$action]['methods'] ) ) {
1232 if ( 'anonymous' === $table[$action]['authorization'] ) {
1233 return $table[$action]['methods'];
1234 } else {
1235 // Check authorized users
1236 if ( isset( $table[$action]['authorized_users'] ) && is_array( $table[$action]['authorized_users'] ) && 0 < count( $table[$action]['authorized_users'] ) && in_array( (string) $this->get_user_login(), $table[$action]['authorized_users'] ) ) {
1237 return $table[$action]['methods'];
1238 }
1239 // Check authorized roles
1240 if ( isset( $table[$action]['authorized_roles'] ) && is_array( $table[$action]['authorized_roles'] ) && 0 < count( $table[$action]['authorized_roles'] ) && 0 < count( array_intersect( $this->get_user_roles(), $table[$action]['authorized_roles'] ) ) ) {
1241 return $table[$action]['methods'];
1242 }
1243 }
1244 }
1245 return array();
1246 }
1247
1248 /**
1249 * Check if access is grant for requested database/table.
1250 *
1251 * @param string $dbs Remote or local database connection string.
1252 * @param string $tbl Database table name.
1253 * @param onject $request Request object.
1254 * @param string $action Possible values: select, insert, update, delete.
1255 * @return bool
1256 */
1257 private function check_table_access(
1258 $dbs,
1259 $tbl,
1260 $request,
1261 $action,
1262 &$msg = ''
1263 ) {
1264 if ( WPDA::current_user_is_admin() ) {
1265 // Grant access to administrators always.
1266 return true;
1267 }
1268 $tables = get_option( WPDA_API::WPDA_REST_API_TABLE_ACCESS );
1269 if ( false === $tables ) {
1270 // No tables.
1271 $msg = __( 'Unauthorized', 'wp-data-access' );
1272 return false;
1273 }
1274 if ( !(isset( $tables[$dbs][$tbl][$action]['methods'] ) && is_array( $tables[$dbs][$tbl][$action]['methods'] )) ) {
1275 // No methods.
1276 $msg = __( 'Unauthorized', 'wp-data-access' );
1277 return false;
1278 } else {
1279 if ( !in_array( $request->get_method(), $tables[$dbs][$tbl][$action]['methods'] ) ) {
1280 //phpcs:ignore - 8.1 proof
1281 $msg = __( 'Unauthorized', 'wp-data-access' );
1282 return false;
1283 }
1284 }
1285 if ( !isset( $tables[$dbs][$tbl][$action]['authorization'] ) ) {
1286 // No authorization.
1287 $msg = __( 'Unauthorized', 'wp-data-access' );
1288 return false;
1289 } else {
1290 if ( 'anonymous' === $tables[$dbs][$tbl][$action]['authorization'] ) {
1291 // Access granted to all users.
1292 return true;
1293 }
1294 }
1295 global $wp_rest_auth_cookie;
1296 if ( true !== $wp_rest_auth_cookie ) {
1297 // No anonymous access.
1298 $msg = __( 'Unauthorized', 'wp-data-access' );
1299 return false;
1300 } else {
1301 if ( 'authorized' !== $tables[$dbs][$tbl][$action]['authorization'] ) {
1302 // Authorization check.
1303 $msg = __( 'Unauthorized', 'wp-data-access' );
1304 return false;
1305 }
1306 // Authorized access requires a valid nonce.
1307 if ( !wp_verify_nonce( $request->get_header( 'X-WP-Nonce' ), 'wp_rest' ) ) {
1308 $msg = 'rest_cookie_invalid_nonce';
1309 return false;
1310 }
1311 if ( !(isset( $tables[$dbs][$tbl][$action]['authorized_users'] ) && is_array( $tables[$dbs][$tbl][$action]['authorized_users'] )) ) {
1312 // No users.
1313 $msg = __( 'Unauthorized', 'wp-data-access' );
1314 return false;
1315 } else {
1316 $requesting_user_login = $this->get_user_login();
1317 if ( 0 < count( $tables[$dbs][$tbl][$action]['authorized_users'] ) && in_array( $requesting_user_login, $tables[$dbs][$tbl][$action]['authorized_users'] ) ) {
1318 return true;
1319 }
1320 }
1321 if ( !(isset( $tables[$dbs][$tbl][$action]['authorized_roles'] ) && is_array( $tables[$dbs][$tbl][$action]['authorized_roles'] )) ) {
1322 // No roles.
1323 $msg = __( 'Unauthorized', 'wp-data-access' );
1324 return false;
1325 } else {
1326 $requesting_user_roles = $this->get_user_roles();
1327 if ( false === $requesting_user_roles ) {
1328 $requesting_user_roles = array();
1329 }
1330 if ( 0 < count( $tables[$dbs][$tbl][$action]['authorized_roles'] ) && 0 < count( array_intersect( $requesting_user_roles, $tables[$dbs][$tbl][$action]['authorized_roles'] ) ) ) {
1331 return true;
1332 }
1333 }
1334 $msg = __( 'Unauthorized', 'wp-data-access' );
1335 return false;
1336 }
1337 }
1338
1339 private function sanitize_column_values(
1340 $dbs,
1341 $tbl,
1342 $column_values,
1343 $code_columns = array(),
1344 $html_columns = array()
1345 ) {
1346 $wpda_list_columns = WPDA_List_Columns_Cache::get_list_columns( $dbs, $tbl );
1347 $sanitized_column_values = [];
1348 foreach ( $column_values as $column_name => $column_value ) {
1349 $column_value = $column_values[$column_name];
1350 switch ( $wpda_list_columns->get_column_data_type( $column_name ) ) {
1351 case 'tinytext':
1352 case 'text':
1353 case 'mediumtext':
1354 case 'longtext':
1355 if ( null !== $column_value ) {
1356 if ( in_array( $column_name, $html_columns ) ) {
1357 $column_value = sanitize_textarea_field( $column_value );
1358 } else {
1359 $column_value = wp_kses_post( $column_value );
1360 }
1361 }
1362 break;
1363 default:
1364 if ( null !== $column_value ) {
1365 $column_value = sanitize_text_field( $column_value );
1366 }
1367 }
1368 $sanitized_column_values[$this->sanitize_db_identifier( $column_name )] = $column_value;
1369 }
1370 return $sanitized_column_values;
1371 }
1372
1373 }
1374