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

WPDA_Query_Builder.php in WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards 5.5.43, at WPDataAccess/Query_Builder/WPDA_Query_Builder.php

929 lines 37.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace WPDataAccess\Query_Builder;
4
5 use WPDataAccess\Connection\WPDADB;
6 use WPDataAccess\Data_Dictionary\WPDA_Dictionary_Lists;
7 use WPDataAccess\WPDA;
8 class WPDA_Query_Builder {
9 const QUERY_BUILDER_OPTIONS = 'wpda_query_builder';
10
11 const QUERY_BUILDER_HINTS = 'wpda_sql_hints';
12
13 const EXPLAIN_COMMANDS = array(
14 'select',
15 'delete',
16 'insert',
17 'replace',
18 'update'
19 );
20
21 const EXPLAIN_PROTECTED = array(
22 'delete',
23 'insert',
24 'replace',
25 'update'
26 );
27
28 protected $databases = array();
29
30 protected $default_database = '';
31
32 protected $wpnonce = '';
33
34 protected $sql_hints = 'off';
35
36 public function show() {
37 $dbs = WPDA_Dictionary_Lists::get_db_schemas();
38 foreach ( $dbs as $db ) {
39 $this->databases[] = $db['schema_name'];
40 }
41 $this->default_database = WPDA::get_user_default_scheme();
42 $sql_hints = get_option( self::QUERY_BUILDER_HINTS );
43 if ( false !== $sql_hints ) {
44 $this->sql_hints = $sql_hints;
45 }
46 $this->wpnonce = wp_create_nonce( 'wpda-query-builder-' . WPDA::get_current_user_id() );
47 $this->html();
48 $this->css();
49 $this->js();
50 }
51
52 protected function html() {
53 $title = 'Query Builder';
54 ?>
55 <div class="wrap">
56 <span style="float:right">
57 <label style="font-weight:normal"><input type="checkbox" id="wpda_sql_hints" <?php
58 echo ( 'on' === $this->sql_hints ? 'checked' : '' );
59 ?>> Enable SQL hints</label>
60 </span>
61 <h1 class="wp-heading-inline">
62 <?php
63 echo esc_attr( $title );
64 ?>
65 </h1>
66 <div id="wpda_query_builder_open" style="display: none">
67 <fieldset class="wpda_fieldset" style="position:relative">
68 <legend>
69 Queries stored for user <?php
70 echo esc_attr( WPDA::get_current_user_login() );
71 ?>
72 </legend>
73 <label>
74 Select
75 </label>
76 <select id="wpda_query_builder_open_select"></select>
77 <a id="wpda_query_builder_open_open"
78 href="javascript:void(0)"
79 onclick="tabOpen()"
80 class="wpda_tooltip button button-primary"
81 title="Open query in new tab">
82 <i class="fas fa-folder-open wpda_icon_on_button"></i> Open selected</a>
83 <a id="wpda_query_builder_open_openall"
84 href="javascript:void(0)"
85 onclick="tabOpenAll()"
86 class="wpda_tooltip button button-secondary"
87 title="Open all stored queries in new tabs">
88 <i class="fas fa-folder-open wpda_icon_on_button"></i> Open all</a>
89 <a id="wpda_query_builder_open_delete"
90 href="javascript:void(0)"
91 onclick="deleteQuery()"
92 class="wpda_tooltip button button-secondary"
93 title="Delete query">
94 <i class="fas fa-trash wpda_icon_on_button"></i> Delete selected</a>
95 <a href="javascript:void(0)"
96 onclick="closeQuery()"
97 class="wpda_tooltip button button-secondary"
98 title="Close panel">
99 <i class="fas fa-times-circle wpda_icon_on_button"></i> Cancel</a>
100 </fieldset>
101 </div>
102 <div id="wpda_query_builder">
103 <nav class="nav-tab-wrapper">
104 </nav>
105 </div>
106 </div>
107 <?php
108 }
109
110 protected function css() {
111 // Overwrite default style
112 ?>
113 <style>
114 .ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr, .ui-corner-left, .ui-corner-tl {
115 border-radius: 0 !important;
116 }
117 .ui-widget.ui-widget-content {
118 border: none;
119 }
120 .wpda_query_builder_tabs .ui-widget-content {
121 background: none;
122 color: inherit;
123 }
124 /*.ui-widget-header {*/
125 /* font-weight: normal;*/
126 /* background: none;*/
127 /* border: none;*/
128 /* border-bottom: 1px solid #c3c4c7;*/
129 /*}*/
130 .ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor, .ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor, .ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
131 cursor: pointer;
132 }
133 .ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default, .ui-button, html .ui-button.ui-state-disabled:hover, html .ui-button.ui-state-disabled:active {
134 border: 1px solid #c3c4c7;
135 font-weight: bold;
136 color: #000 !important;
137 background: #dcdcde !important;
138 }
139 .ui-state-default:hover {
140 background: #f0f0f1 !important;
141 }
142 .ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active, a.ui-button:active, .ui-button:active, .ui-button.ui-state-active:hover {
143 border: 1px solid #c3c4c7;
144 border-bottom: none;
145 font-weight: bold;
146 color: #000 !important;
147 background: #f0f0f1 !important;
148 }
149 .ui-tabs-anchor {
150 color: #50575e !important;
151 }
152 .ui-tabs-anchor span.dashicons {
153 padding-left: 5px;
154 }
155 .ui-tabs .ui-tabs-panel {
156 padding: 0;
157 font-family: inherit;
158 font-size: inherit;
159 }
160 .ui-tabs .ui-tabs-nav li {
161 margin-left: 4px;
162 }
163 .ui-tabs .ui-tabs-nav .ui-tabs-anchor {
164 line-height: 20px;
165 }
166 </style>
167 <?php
168 }
169
170 protected function js() {
171 ?>
172 <script type="application/javascript">
173 var wpda_default_database = '<?php
174 echo esc_attr( $this->default_database );
175 ?>';
176 var wpda_databases = '';
177 <?php
178 global $wpdb;
179 $database_options = '';
180 foreach ( $this->databases as $database ) {
181 if ( $wpdb->dbname === $database ) {
182 $database_printed = "WordPress database ({$database})";
183 } else {
184 $database_printed = $database;
185 }
186 $database_options .= '<option value="' . $database . '">' . $database_printed . '</option>';
187 }
188 echo "wpda_databases = '{$database_options}';";
189 // phpcs:ignore WordPress.Security.EscapeOutput
190 ?>
191 var wpda_home_url = "<?php
192 echo admin_url( 'admin.php' );
193 // phpcs:ignore WordPress.Security.EscapeOutput
194 ?>";
195 var wpda_wpnonce = "<?php
196 echo esc_attr( $this->wpnonce );
197 ?>";
198 var wpda_loader_url = "<?php
199 echo plugins_url( '../../assets/images/loading.gif', __FILE__ );
200 // phpcs:ignore WordPress.Security.EscapeOutput
201 ?>";
202 var vqbInstalled = false;
203 <?php
204 ?>
205
206 function getColumns(schema, table, activeIndex, callback, rebuild = false) {
207 const url = location.pathname + '?action=wpda_get_table_widget_info';
208 const data = {
209 wpdaschema_name: schema,
210 table_name: table,
211 wpda_wpnonce: '<?php
212 echo esc_attr( wp_create_nonce( 'wpda-getdata-access-' . WPDA::get_current_user_login() ) );
213 ?>'
214 };
215 jQuery.post(
216 url,
217 data,
218 function (data) {
219 callback(schema, table, activeIndex, JSON.parse(data), rebuild);
220 }
221 );
222 }
223
224 jQuery(
225 function() {
226 tabNew();
227 jQuery('#wpda_query_builder nav').sortable();
228 jQuery('.wpda_tooltip').tooltip();
229 jQuery("#wpda_sql_hints").on('change', function() {
230 jQuery.ajax({
231 method: 'POST',
232 url: wpda_home_url + "?action=wpda_query_builder_set_db_hints",
233 data: {
234 wpda_wpnonce: wpda_wpnonce,
235 wpda_sqlhints: jQuery(this).is(":checked") ? 'on' : 'off'
236 }
237 }).done(
238 function (msg) {}
239 ).fail(
240 function (msg) {}
241 );
242
243 });
244 }
245 );
246 </script>
247 <?php
248 }
249
250 public function execute() {
251 $response = array(
252 'tabs' => array(),
253 'status' => null,
254 );
255 WPDA::sent_header( 'application/json' );
256 ob_start();
257 // Only for admins
258 if ( WPDA::current_user_is_admin() && isset(
259 $_POST['wpda_wpnonce'],
260 $_POST['wpda_schemaname'],
261 $_POST['wpda_sqlquery'],
262 $_POST['wpda_sqllimit'],
263 $_POST['wpda_protect']
264 ) ) {
265 $wpda_wpnonce = sanitize_text_field( wp_unslash( $_POST['wpda_wpnonce'] ) );
266 // input var okay.
267 $wpda_schemaname = sanitize_text_field( wp_unslash( $_POST['wpda_schemaname'] ) );
268 // input var okay.
269 $wpda_sqlquery = html_entity_decode( wp_unslash( $_POST['wpda_sqlquery'] ), ENT_QUOTES );
270 // input var okay.
271 $wpda_sqllimit = sanitize_text_field( wp_unslash( $_POST['wpda_sqllimit'] ) );
272 // input var okay.
273 $wpda_protect = sanitize_text_field( wp_unslash( $_POST['wpda_protect'] ) );
274 // input var okay.
275 // Check query
276 if ( $this->check_query( $wpda_protect, $wpda_schemaname, $wpda_sqlquery ) ) {
277 if ( wp_verify_nonce( $wpda_wpnonce, 'wpda-query-builder-' . WPDA::get_current_user_id() ) ) {
278 // Execute query
279 $wpdadb = WPDADB::get_db_connection( $wpda_schemaname );
280 if ( null !== $wpdadb ) {
281 $wpdadb->suppress_errors( true );
282 }
283 $sqllines = explode( "\n", $wpda_sqlquery );
284 //phpcs:ignore - 8.1 proof
285 $sqlcmds = array();
286 $start_i = 0;
287 for ($i = 0; $i < count( $sqllines ); $i++) {
288 //phpcs:ignore - 8.1 proof
289 if ( '/' === trim( $sqllines[$i] ) ) {
290 $sql = '';
291 for ($j = $start_i; $j < $i; $j++) {
292 if ( '' !== trim( $sqllines[$j] ) ) {
293 $sql .= "{$sqllines[$j]} ";
294 }
295 }
296 $sqlcmds[] = $sql;
297 $start_i = $i + 1;
298 }
299 }
300 if ( count( $sqlcmds ) > 0 ) {
301 //phpcs:ignore - 8.1 proof
302 $tabs = array();
303 $vars = array();
304 $tmps = array();
305 // Process multiple SQL commands
306 for ($i = 0; $i < count( $sqlcmds ); $i++) {
307 //phpcs:ignore - 8.1 proof
308 if ( '' !== $wpda_sqllimit && 'select' === strtolower( substr( $sqlcmds[$i], 0, 6 ) ) ) {
309 $sqlcmds[$i] .= " limit {$wpda_sqllimit} ";
310 }
311 $columns = WPDA::get_columns_from_query( $wpda_schemaname, $sqlcmds[$i] );
312 // Need to reconnect when switching from local to remote and vice versa
313 $reconnected = false;
314 if ( 'use' === substr( strtolower( trim( $sqlcmds[$i] ) ), 0, 3 ) ) {
315 $use_cmd = explode( ' ', trim( $sqlcmds[$i] ) );
316 //phpcs:ignore - 8.1 proof
317 if ( 2 === count( $use_cmd ) && (strtolower( trim( $use_cmd[1] ) ) !== strtolower( trim( $wpda_schemaname ) ) && 'rdb:' === substr( strtolower( trim( $use_cmd[1] ) ), 0, 4 ) || 'rdb:' === substr( strtolower( trim( $wpda_schemaname ) ), 0, 4 )) ) {
318 $wpda_schemaname = $use_cmd[1];
319 $wpdadb = WPDADB::get_db_connection( $wpda_schemaname );
320 if ( null !== $wpdadb ) {
321 $wpdadb->suppress_errors( true );
322 }
323 $reconnected = true;
324 }
325 }
326 $exequery = true;
327 $var_name = null;
328 $wpdadb_saved = null;
329 switch ( strtolower( substr( trim( $sqlcmds[$i] ), 0, 7 ) ) ) {
330 case 'wpdavar':
331 $use_cmd = explode( ' ', trim( $sqlcmds[$i] ) );
332 //phpcs:ignore - 8.1 proof
333 $var_name = ( isset( $use_cmd[1] ) ? $use_cmd[1] : null );
334 if ( $var_name !== null ) {
335 $vars[$var_name] = $tabs;
336 $tmps[$var_name] = $this->wpdavar_table( $wpdadb, $tabs[$i - 1], $var_name );
337 $exequery = false;
338 }
339 break;
340 case 'wpdatmp':
341 $use_cmd = explode( ' ', trim( $sqlcmds[$i] ) );
342 $var_name = ( isset( $use_cmd[1] ) ? $use_cmd[1] : null );
343 if ( $var_name !== null ) {
344 $wpdadb_saved = $this->wpdatmp_table(
345 $wpdadb,
346 $tmps[$var_name],
347 $tmps[$var_name]['data'],
348 $tmps[$var_name]['table_name'],
349 $var_name
350 );
351 $exequery = false;
352 }
353 $var_name = null;
354 // reset
355 break;
356 }
357 if ( !$reconnected && $exequery && null !== $wpdadb ) {
358 $wpdadb->query( $sqlcmds[$i] );
359 }
360 if ( null === $var_name ) {
361 $status = ( null !== $wpdadb_saved ? $wpdadb_saved : (( null !== $wpdadb ? clone $wpdadb : null )) );
362 $tabs[] = array(
363 'cmd' => $sqlcmds[$i],
364 'status' => $status,
365 'columns' => $columns,
366 );
367 } else {
368 $tabs[] = array(
369 'cmd' => $sqlcmds[$i],
370 'status' => ( isset( $vars[$var_name]['status'] ) ? $vars[$var_name]['status'] : null ),
371 'wpdavar' => ( isset( $tmps[$var_name] ) ? $tmps[$var_name] : null ),
372 'columns' => null,
373 );
374 }
375 if ( null === $wpdadb || '' !== $wpdadb->last_error ) {
376 break;
377 }
378 }
379 $response['tabs'] = $tabs;
380 } else {
381 $response['columns'] = WPDA::get_columns_from_query( $wpda_schemaname, $wpda_sqlquery );
382 // Process single SQL command
383 if ( '' !== $wpda_sqllimit && 'select' === strtolower( substr( $wpda_sqlquery, 0, 6 ) ) ) {
384 $wpda_sqlquery .= " limit {$wpda_sqllimit} ";
385 }
386 if ( null !== $wpdadb ) {
387 $wpdadb->query( $wpda_sqlquery );
388 }
389 $response['cmd'] = $wpda_sqlquery;
390 $response['status'] = $wpdadb;
391 }
392 } else {
393 $response['status'] = '<strong>WP Data Access error:</strong> Token expired, please refresh page';
394 }
395 } else {
396 $response['status'] = '<strong>WP Data Access error:</strong> Query not allowed - WordPress tables are protected';
397 }
398 } else {
399 $response['status'] = '<strong>WP Data Access error:</strong> Query execution failed';
400 }
401 ob_end_clean();
402 echo json_encode( $response );
403 }
404
405 public function wpdatmp_table(
406 $wpdadb,
407 $sql,
408 $data,
409 $table_name,
410 $var_name
411 ) {
412 // Create temporary table
413 $wpdadb->query( str_ireplace( array('CREATE TABLE', $table_name), array('CREATE TEMPORARY TABLE', $var_name), $sql['create_table'] ) );
414 $wpdadb_created = clone $wpdadb;
415 // Copy data to temporary table
416 foreach ( $data as $resultset ) {
417 $column_values = array();
418 foreach ( $resultset as $key => $val ) {
419 $column_values[$key] = $val;
420 }
421 $wpdadb->insert( $var_name, $column_values );
422 }
423 return $wpdadb_created;
424 }
425
426 public function wpdavar_table( $wpdadb, $query, $var_name ) {
427 $wpdadb->query( "set sql_quote_show_create = 'ON'" );
428 if ( null === $query['status'] ) {
429 return null;
430 }
431 $explain = $wpdadb->get_results( "explain {$query['status']->last_query}", 'ARRAY_A' );
432 if ( '' !== $wpdadb->last_error ) {
433 return null;
434 }
435 $table_name = $explain[0]['table'];
436 $create_table = $wpdadb->get_results( "show create table `{$table_name}`", 'ARRAY_N' );
437 if ( '' !== $wpdadb->last_error ) {
438 return null;
439 }
440 $sql = str_replace( "\n", '', $create_table[0][1] );
441 $pos = stripos( $sql, ') ENGINE=' );
442 $tbl = ( false === $pos ? $sql : substr( $sql, 0, $pos + 1 ) );
443 return array(
444 'table_name' => $table_name,
445 'create_table' => $tbl,
446 'data' => $query['status']->last_result,
447 );
448 }
449
450 public function check_query( $wpda_protect, $wpda_schemaname, $wpda_sqlquery ) {
451 $sql_parts = explode( ' ', trim( $wpda_sqlquery ) );
452 //phpcs:ignore - 8.1 proof
453 if ( isset( $sql_parts[0] ) && isset( $sql_parts[2] ) && WPDA::is_wp_table( $sql_parts[2] ) && ('drop' === strtolower( $sql_parts[0] ) || 'alter' === strtolower( $sql_parts[0] ) || 'rename' === strtolower( $sql_parts[0] ) || 'truncate' === strtolower( $sql_parts[0] )) ) {
454 return false;
455 }
456 if ( isset( $sql_parts[0] ) && isset( $sql_parts[1] ) && WPDA::is_wp_table( $sql_parts[1] ) && 'truncate' === strtolower( $sql_parts[0] ) ) {
457 return false;
458 }
459 if ( 'false' !== $wpda_protect && isset( $sql_parts[0] ) && in_array( strtolower( $sql_parts[0] ), self::EXPLAIN_COMMANDS ) ) {
460 $wpdadb = WPDADB::get_db_connection( $wpda_schemaname );
461 $suppress = $wpdadb->suppress_errors( true );
462 $explain = $wpdadb->get_results( "explain {$wpda_sqlquery}", 'ARRAY_A' );
463 $wpdadb->suppress_errors( $suppress );
464 foreach ( $explain as $check ) {
465 if ( in_array( strtolower( $check['select_type'] ), self::EXPLAIN_PROTECTED ) && WPDA::is_wp_table( $check['table'] ) ) {
466 return false;
467 }
468 }
469 }
470 return true;
471 }
472
473 public function save() {
474 $response = array(
475 'status' => null,
476 );
477 WPDA::sent_header( 'application/json' );
478 // Only for admins
479 if ( WPDA::current_user_is_admin() && isset(
480 $_POST['wpda_wpnonce'],
481 $_POST['wpda_schemaname'],
482 $_POST['wpda_sqlqueryname'],
483 $_POST['wpda_sqlqueryname_old'],
484 $_POST['wpda_sqlquery']
485 ) ) {
486 $wpda_wpnonce = sanitize_text_field( wp_unslash( $_POST['wpda_wpnonce'] ) );
487 // input var okay.
488 $wpda_schemaname = sanitize_text_field( wp_unslash( $_POST['wpda_schemaname'] ) );
489 // input var okay.
490 $wpda_sqlqueryname = sanitize_text_field( wp_unslash( $_POST['wpda_sqlqueryname'] ) );
491 // input var okay.
492 $wpda_sqlqueryname_old = sanitize_text_field( wp_unslash( $_POST['wpda_sqlqueryname_old'] ) );
493 // input var okay.
494 $wpda_sqlquery = sanitize_textarea_field( wp_unslash( $_POST['wpda_sqlquery'] ) );
495 // input var okay.
496 $wpda_vqb = null;
497 if ( wp_verify_nonce( $wpda_wpnonce, 'wpda-query-builder-' . WPDA::get_current_user_id() ) ) {
498 // Save query
499 if ( false === $this->update_query(
500 $wpda_schemaname,
501 $wpda_sqlqueryname,
502 $wpda_sqlquery,
503 $wpda_sqlqueryname_old,
504 $wpda_vqb
505 ) ) {
506 $response['status'] = 'Could not save query';
507 } else {
508 $response['status'] = 'Query saved';
509 }
510 } else {
511 $response['status'] = 'Token expired, please refresh page';
512 }
513 } else {
514 $response['status'] = 'Could not save query';
515 }
516 echo json_encode( $response );
517 }
518
519 public function open() {
520 $response = array(
521 'data' => array(),
522 'status' => null,
523 );
524 WPDA::sent_header( 'application/json' );
525 // Only for admins
526 if ( WPDA::current_user_is_admin() && isset( $_POST['wpda_wpnonce'], $_POST['wpda_exclude'] ) ) {
527 $wpda_wpnonce = sanitize_text_field( wp_unslash( $_POST['wpda_wpnonce'] ) );
528 // input var okay.
529 $wpda_exclude = sanitize_text_field( wp_unslash( $_POST['wpda_exclude'] ) );
530 // input var okay.
531 if ( wp_verify_nonce( $wpda_wpnonce, 'wpda-query-builder-' . WPDA::get_current_user_id() ) ) {
532 // Send list of available queries
533 $wpda_query_builder_data = $this->get_query_list( $wpda_exclude );
534 uksort( $wpda_query_builder_data, 'strnatcasecmp' );
535 //phpcs:ignore - 8.1 proof
536 $response['data'] = $wpda_query_builder_data;
537 } else {
538 $response['status'] = 'Token expired, please refresh page';
539 }
540 } else {
541 $response['status'] = 'Query list not available';
542 }
543 echo json_encode( $response );
544 }
545
546 public function delete() {
547 $response = array(
548 'status' => null,
549 );
550 WPDA::sent_header( 'application/json' );
551 // Only for admins
552 if ( WPDA::current_user_is_admin() && isset( $_POST['wpda_wpnonce'], $_POST['wpda_sqlqueryname'] ) ) {
553 $wpda_wpnonce = sanitize_text_field( wp_unslash( $_POST['wpda_wpnonce'] ) );
554 // input var okay.
555 $wpda_sqlqueryname = sanitize_text_field( wp_unslash( $_POST['wpda_sqlqueryname'] ) );
556 // input var okay.
557 if ( wp_verify_nonce( $wpda_wpnonce, 'wpda-query-builder-' . WPDA::get_current_user_id() ) ) {
558 // Save query
559 if ( false === $this->delete_query( $wpda_sqlqueryname ) ) {
560 $response['status'] = 'Could not delete query';
561 } else {
562 $response['status'] = 'Query deleted';
563 }
564 } else {
565 $response['status'] = 'Token expired, please refresh page';
566 }
567 } else {
568 $response['status'] = 'Could not save query';
569 }
570 echo json_encode( $response );
571 }
572
573 public function get_query_list( $exclude = '', $user_id = null ) {
574 $wpda_query_builder_data = get_user_meta( ( null === $user_id ? WPDA::get_current_user_id() : $user_id ), self::QUERY_BUILDER_OPTIONS );
575 if ( is_array( $wpda_query_builder_data ) && count( $wpda_query_builder_data ) > 0 ) {
576 //phpcs:ignore - 8.1 proof
577 $queries = $wpda_query_builder_data[0];
578 if ( null !== $exclude && '' !== $exclude ) {
579 $exclude_array = explode( ',', $exclude );
580 //phpcs:ignore - 8.1 proof
581 foreach ( $exclude_array as $exclude_item ) {
582 unset($queries[$exclude_item]);
583 }
584 }
585 return $queries;
586 } else {
587 return array();
588 }
589 }
590
591 public function get_query_list_global( $exclude = '' ) {
592 $wpda_query_builder_data = get_option( self::QUERY_BUILDER_OPTIONS );
593 if ( is_array( $wpda_query_builder_data ) && count( $wpda_query_builder_data ) > 0 ) {
594 //phpcs:ignore - 8.1 proof
595 $queries = $wpda_query_builder_data;
596 if ( null !== $exclude && '' !== $exclude ) {
597 $exclude_array = explode( ',', $exclude );
598 //phpcs:ignore - 8.1 proof
599 foreach ( $exclude_array as $exclude_item ) {
600 unset($queries[$exclude_item]);
601 }
602 }
603 return $queries;
604 } else {
605 return array();
606 }
607 }
608
609 protected function update_query_list( $wpda_query_builder_data ) {
610 update_user_meta( WPDA::get_current_user_id(), self::QUERY_BUILDER_OPTIONS, $wpda_query_builder_data );
611 }
612
613 protected function update_query_list_global( $wpda_query_builder_data ) {
614 update_option( self::QUERY_BUILDER_OPTIONS, $wpda_query_builder_data );
615 }
616
617 public function get_query( $query_name, $user_id = null ) {
618 if ( null === $user_id ) {
619 $wpda_query_builder_data = $this->get_query_list();
620 } else {
621 $wpda_query_builder_data = $this->get_query_list( '', $user_id );
622 }
623 if ( is_array( $wpda_query_builder_data ) && isset( $wpda_query_builder_data[$query_name] ) ) {
624 return $wpda_query_builder_data[$query_name];
625 } else {
626 return array();
627 }
628 }
629
630 public function get_query_global( $query_name ) {
631 $wpda_query_builder_data = $this->get_query_list_global();
632 if ( is_array( $wpda_query_builder_data ) && isset( $wpda_query_builder_data[$query_name] ) ) {
633 return $wpda_query_builder_data[$query_name];
634 } else {
635 return array();
636 }
637 }
638
639 public function update_query(
640 $schema_name,
641 $query_name,
642 $query_sql,
643 $query_name_old,
644 $wpda_vqb = null,
645 $params = null
646 ) {
647 $wpda_query_builder_data = $this->get_query_list();
648 if ( '' !== $query_name_old && $query_name !== $query_name_old ) {
649 unset($wpda_query_builder_data[$query_name_old]);
650 }
651 $wpda_query_builder_data[$query_name] = array(
652 'schema_name' => $schema_name,
653 'query' => $query_sql,
654 'is_visual' => null !== $wpda_vqb,
655 'params' => $params,
656 );
657 $this->update_query_list( $wpda_query_builder_data );
658 }
659
660 public function update_query_global(
661 $schema_name,
662 $query_name,
663 $query_sql,
664 $query_name_old,
665 $wpda_vqb = null,
666 $params = null
667 ) {
668 $wpda_query_builder_data = $this->get_query_list_global();
669 if ( '' !== $query_name_old && $query_name !== $query_name_old ) {
670 unset($wpda_query_builder_data[$query_name_old]);
671 }
672 $wpda_query_builder_data[$query_name] = array(
673 'schema_name' => $schema_name,
674 'query' => $query_sql,
675 'is_visual' => null !== $wpda_vqb,
676 'params' => $params,
677 );
678 $this->update_query_list_global( $wpda_query_builder_data );
679 // if ( wpda_freemius()->can_use_premium_code__premium_only() ) {
680 // $this->upd_visual_query( $query_name, $wpda_vqb );
681 // }
682 }
683
684 public function delete_query( $query_name ) {
685 $wpda_query_builder_data = $this->get_query_list();
686 unset($wpda_query_builder_data[$query_name]);
687 $this->update_query_list( $wpda_query_builder_data );
688 }
689
690 public function delete_query_global( $query_name ) {
691 $wpda_query_builder_data = $this->get_query_list_global();
692 unset($wpda_query_builder_data[$query_name]);
693 $this->update_query_list_global( $wpda_query_builder_data );
694 // if ( wpda_freemius()->can_use_premium_code__premium_only() ) {
695 // $this->del_visual_query( $query_name );
696 // }
697 }
698
699 public function get_visual_query( $query_name ) {
700 }
701
702 protected function upd_visual_query( $query_name, $wpda_vqb ) {
703 }
704
705 protected function del_visual_query( $query_name ) {
706 }
707
708 protected function rewrite_query_name( $query_name ) {
709 return str_replace( ' ', '_', $query_name );
710 }
711
712 public function get_db_hints() {
713 $response = array(
714 'status' => 'OK',
715 );
716 WPDA::sent_header( 'application/json' );
717 if ( WPDA::current_user_is_admin() && isset( $_REQUEST['wpda_wpnonce'], $_REQUEST['wpda_schemaname'] ) ) {
718 $wpda_wpnonce = sanitize_text_field( wp_unslash( $_REQUEST['wpda_wpnonce'] ) );
719 // input var okay.
720 $wpda_schemaname = sanitize_text_field( wp_unslash( $_REQUEST['wpda_schemaname'] ) );
721 // input var okay.
722 if ( wp_verify_nonce( $wpda_wpnonce, 'wpda-query-builder-' . WPDA::get_current_user_id() ) ) {
723 $tables = WPDA_Dictionary_Lists::get_tables( true, $wpda_schemaname );
724 $hints = array();
725 foreach ( $tables as $table ) {
726 $columns = WPDA_Dictionary_Lists::get_table_columns( $table['table_name'], $wpda_schemaname );
727 $hint_cols = array();
728 foreach ( $columns as $column ) {
729 $hint_cols[] = $column['column_name'];
730 }
731 $hints[$table['table_name']] = $hint_cols;
732 }
733 $response['tables'] = $hints;
734 } else {
735 $response['status'] = 'Token expired, please refresh page';
736 }
737 } else {
738 $response['status'] = 'Invalid arguments';
739 }
740 echo json_encode( $response );
741 }
742
743 public function set_db_hints() {
744 $response = array(
745 'status' => 'OK',
746 );
747 WPDA::sent_header( 'application/json' );
748 if ( WPDA::current_user_is_admin() && isset( $_REQUEST['wpda_wpnonce'], $_REQUEST['wpda_sqlhints'] ) ) {
749 $wpda_wpnonce = sanitize_text_field( wp_unslash( $_REQUEST['wpda_wpnonce'] ) );
750 // input var okay.
751 $wpda_sqlhints = sanitize_text_field( wp_unslash( $_REQUEST['wpda_sqlhints'] ) );
752 // input var okay.
753 if ( wp_verify_nonce( $wpda_wpnonce, 'wpda-query-builder-' . WPDA::get_current_user_id() ) ) {
754 update_option( self::QUERY_BUILDER_HINTS, $wpda_sqlhints );
755 }
756 }
757 $response['hint'] = $wpda_sqlhints;
758 echo json_encode( $response );
759 }
760
761 private function substitute_sql_params( $wpdadb, $query, $params ) {
762 }
763
764 public function execute_query(
765 $dbs,
766 $query,
767 $limit,
768 $protect,
769 $params
770 ) {
771 $response = array(
772 'tabs' => array(),
773 'status' => null,
774 );
775 if ( $this->check_query( $protect, $dbs, $query ) ) {
776 // Execute query
777 $wpdadb = WPDADB::get_db_connection( $dbs );
778 if ( null !== $wpdadb ) {
779 $wpdadb->suppress_errors( true );
780 }
781 $sqllines = explode( "\n", $query );
782 //phpcs:ignore - 8.1 proof
783 $sqlcmds = array();
784 $start_i = 0;
785 for ($i = 0; $i < count( $sqllines ); $i++) {
786 //phpcs:ignore - 8.1 proof
787 if ( '/' === trim( $sqllines[$i] ) ) {
788 $sql = '';
789 for ($j = $start_i; $j < $i; $j++) {
790 if ( '' !== trim( $sqllines[$j] ) ) {
791 $sql .= "{$sqllines[$j]} ";
792 }
793 }
794 $sqlcmds[] = $sql;
795 $start_i = $i + 1;
796 }
797 }
798 if ( count( $sqlcmds ) > 0 ) {
799 //phpcs:ignore - 8.1 proof
800 $tabs = array();
801 $vars = array();
802 $tmps = array();
803 // Process multiple SQL commands
804 for ($i = 0; $i < count( $sqlcmds ); $i++) {
805 //phpcs:ignore - 8.1 proof
806 if ( '' !== $limit && 'select' === strtolower( substr( $sqlcmds[$i], 0, 6 ) ) ) {
807 $sqlcmds[$i] .= " limit {$limit} ";
808 }
809 $columns = WPDA::get_columns_from_query( $dbs, $sqlcmds[$i] );
810 // Need to reconnect when switching from local to remote and vice versa
811 $reconnected = false;
812 if ( 'use' === substr( strtolower( trim( $sqlcmds[$i] ) ), 0, 3 ) ) {
813 $use_cmd = explode( ' ', trim( $sqlcmds[$i] ) );
814 //phpcs:ignore - 8.1 proof
815 if ( 2 === count( $use_cmd ) && (strtolower( trim( $use_cmd[1] ) ) !== strtolower( trim( $dbs ) ) && 'rdb:' === substr( strtolower( trim( $use_cmd[1] ) ), 0, 4 ) || 'rdb:' === substr( strtolower( trim( $dbs ) ), 0, 4 )) ) {
816 $dbs = $use_cmd[1];
817 $wpdadb = WPDADB::get_db_connection( $dbs );
818 if ( null !== $wpdadb ) {
819 $wpdadb->suppress_errors( true );
820 }
821 $reconnected = true;
822 }
823 }
824 $exequery = true;
825 $var_name = null;
826 $wpdadb_saved = null;
827 switch ( strtolower( substr( trim( $sqlcmds[$i] ), 0, 7 ) ) ) {
828 case 'wpdavar':
829 $use_cmd = explode( ' ', trim( $sqlcmds[$i] ) );
830 //phpcs:ignore - 8.1 proof
831 $var_name = ( isset( $use_cmd[1] ) ? $use_cmd[1] : null );
832 if ( $var_name !== null ) {
833 $vars[$var_name] = $tabs;
834 $tmps[$var_name] = $this->wpdavar_table( $wpdadb, $tabs[$i - 1], $var_name );
835 $exequery = false;
836 }
837 break;
838 case 'wpdatmp':
839 $use_cmd = explode( ' ', trim( $sqlcmds[$i] ) );
840 $var_name = ( isset( $use_cmd[1] ) ? $use_cmd[1] : null );
841 if ( $var_name !== null ) {
842 $wpdadb_saved = $this->wpdatmp_table(
843 $wpdadb,
844 $tmps[$var_name],
845 $tmps[$var_name]['data'],
846 $tmps[$var_name]['table_name'],
847 $var_name
848 );
849 $exequery = false;
850 }
851 $var_name = null;
852 // reset
853 break;
854 }
855 if ( !$reconnected && $exequery && null !== $wpdadb ) {
856 $wpdadb->query( $sqlcmds[$i] );
857 }
858 if ( null === $var_name ) {
859 $status = ( null !== $wpdadb_saved ? $wpdadb_saved : (( null !== $wpdadb ? clone $wpdadb : null )) );
860 $tabs[] = array(
861 'cmd' => $sqlcmds[$i],
862 'status' => $status,
863 'columns' => $columns,
864 );
865 } else {
866 $tabs[] = array(
867 'cmd' => $sqlcmds[$i],
868 'status' => ( isset( $vars[$var_name]['status'] ) ? $vars[$var_name]['status'] : null ),
869 'wpdavar' => ( isset( $tmps[$var_name] ) ? $tmps[$var_name] : null ),
870 'columns' => null,
871 );
872 }
873 if ( null === $wpdadb || '' !== $wpdadb->last_error ) {
874 break;
875 }
876 }
877 $response['tabs'] = $tabs;
878 } else {
879 $response['columns'] = WPDA::get_columns_from_query( $dbs, $query );
880 // Process single SQL command
881 if ( '' !== $limit && 'select' === strtolower( substr( $query, 0, 6 ) ) ) {
882 $query .= " limit {$limit} ";
883 }
884 if ( null !== $wpdadb ) {
885 $wpdadb->query( $query );
886 }
887 $response['cmd'] = $query;
888 $response['status'] = clone $wpdadb;
889 }
890 } else {
891 $response['status'] = '<strong>WP Data Access error:</strong> Query not allowed - WordPress tables are protected';
892 }
893 return $response;
894 }
895
896 public function add_query( $query_name, $query ) {
897 $wpda_query_builder_data = $this->get_query_list();
898 $wpda_query_builder_data[$query_name] = $query;
899 $this->update_query_list( $wpda_query_builder_data );
900 // if ( wpda_freemius()->can_use_premium_code__premium_only() ) {
901 // $this->del_visual_query( $query_name );
902 // }
903 }
904
905 public function add_query_global( $query_name, $query ) {
906 $wpda_query_builder_data = $this->get_query_list_global();
907 $wpda_query_builder_data[$query_name] = $query;
908 $this->update_query_list_global( $wpda_query_builder_data );
909 // if ( wpda_freemius()->can_use_premium_code__premium_only() ) {
910 // $this->del_visual_query( $query_name );
911 // }
912 }
913
914 public function get_hints( $dbs ) {
915 $tables = WPDA_Dictionary_Lists::get_tables( true, $dbs );
916 $hints = array();
917 foreach ( $tables as $table ) {
918 $columns = WPDA_Dictionary_Lists::get_table_columns( $table['table_name'], $dbs );
919 $hint_cols = array();
920 foreach ( $columns as $column ) {
921 $hint_cols[] = $column['column_name'];
922 }
923 $hints[$table['table_name']] = $hint_cols;
924 }
925 return $hints;
926 }
927
928 }
929