PluginProbe
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards / 5.5.84
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards v5.5.84
5.5.84 5.5.83 5.5.82 5.5.81 5.5.80 5.5.79 5.5.77 5.5.76 5.5.75 5.5.73 5.5.72 5.5.22 5.5.23 5.5.29 5.5.3 5.5.31 5.5.32 5.5.34 5.5.35 5.5.36 5.5.37 5.5.4 5.5.40 5.5.41 5.5.42 All 160 releases
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.84, at WPDataAccess/Query_Builder/WPDA_Query_Builder.php

445 lines 17.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\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 private function wpdatmp_table(
37 $wpdadb,
38 $sql,
39 $data,
40 $table_name,
41 $var_name
42 ) {
43 // Create temporary table
44 $wpdadb->query( str_ireplace( array('CREATE TABLE', $table_name), array('CREATE TEMPORARY TABLE', $var_name), $sql['create_table'] ) );
45 $wpdadb_created = clone $wpdadb;
46 // Copy data to temporary table
47 foreach ( $data as $resultset ) {
48 $column_values = array();
49 foreach ( $resultset as $key => $val ) {
50 $column_values[$key] = $val;
51 }
52 $wpdadb->insert( $var_name, $column_values );
53 }
54 return $wpdadb_created;
55 }
56
57 private function wpdavar_table( $wpdadb, $query, $var_name ) {
58 $wpdadb->query( "set sql_quote_show_create = 'ON'" );
59 if ( null === $query['status'] ) {
60 return null;
61 }
62 $explain = $wpdadb->get_results( "explain {$query['status']->last_query}", 'ARRAY_A' );
63 if ( '' !== $wpdadb->last_error ) {
64 return null;
65 }
66 $table_name = $explain[0]['table'];
67 $create_table = $wpdadb->get_results( "show create table `{$table_name}`", 'ARRAY_N' );
68 if ( '' !== $wpdadb->last_error ) {
69 return null;
70 }
71 $sql = str_replace( "\n", '', $create_table[0][1] );
72 $pos = stripos( $sql, ') ENGINE=' );
73 $tbl = ( false === $pos ? $sql : substr( $sql, 0, $pos + 1 ) );
74 return array(
75 'table_name' => $table_name,
76 'create_table' => $tbl,
77 'data' => $query['status']->last_result,
78 );
79 }
80
81 public function check_query( $wpda_protect, $wpda_schemaname, $wpda_sqlquery ) {
82 $sql_parts = explode( ' ', trim( $wpda_sqlquery ) );
83 // phpcs:ignore -- 8.1 proof
84 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] )) ) {
85 return false;
86 }
87 if ( isset( $sql_parts[0] ) && isset( $sql_parts[1] ) && WPDA::is_wp_table( $sql_parts[1] ) && 'truncate' === strtolower( $sql_parts[0] ) ) {
88 return false;
89 }
90 if ( 'false' !== $wpda_protect && isset( $sql_parts[0] ) && in_array( strtolower( $sql_parts[0] ), self::EXPLAIN_COMMANDS ) ) {
91 $wpdadb = WPDADB::get_db_connection( $wpda_schemaname );
92 $suppress = $wpdadb->suppress_errors( true );
93 $explain = $wpdadb->get_results( "explain {$wpda_sqlquery}", 'ARRAY_A' );
94 $wpdadb->suppress_errors( $suppress );
95 foreach ( $explain as $check ) {
96 if ( in_array( strtolower( $check['select_type'] ), self::EXPLAIN_PROTECTED ) && WPDA::is_wp_table( $check['table'] ) ) {
97 return false;
98 }
99 }
100 }
101 return true;
102 }
103
104 public function get_query_list( $exclude = '', $user_id = null ) {
105 $wpda_query_builder_data = get_user_meta( ( null === $user_id ? WPDA::get_current_user_id() : $user_id ), self::QUERY_BUILDER_OPTIONS );
106 if ( is_array( $wpda_query_builder_data ) && count( $wpda_query_builder_data ) > 0 ) {
107 // phpcs:ignore -- 8.1 proof
108 $queries = $wpda_query_builder_data[0];
109 if ( null !== $exclude && '' !== $exclude ) {
110 $exclude_array = explode( ',', $exclude );
111 // phpcs:ignore -- 8.1 proof
112 foreach ( $exclude_array as $exclude_item ) {
113 unset($queries[$exclude_item]);
114 }
115 }
116 return $queries;
117 } else {
118 return array();
119 }
120 }
121
122 public function get_query_list_global( $exclude = '' ) {
123 $wpda_query_builder_data = get_option( self::QUERY_BUILDER_OPTIONS );
124 if ( is_array( $wpda_query_builder_data ) && count( $wpda_query_builder_data ) > 0 ) {
125 // phpcs:ignore -- 8.1 proof
126 $queries = $wpda_query_builder_data;
127 if ( null !== $exclude && '' !== $exclude ) {
128 $exclude_array = explode( ',', $exclude );
129 // phpcs:ignore -- 8.1 proof
130 foreach ( $exclude_array as $exclude_item ) {
131 unset($queries[$exclude_item]);
132 }
133 }
134 return $queries;
135 } else {
136 return array();
137 }
138 }
139
140 protected function update_query_list( $wpda_query_builder_data ) {
141 update_user_meta( WPDA::get_current_user_id(), self::QUERY_BUILDER_OPTIONS, $wpda_query_builder_data );
142 }
143
144 protected function update_query_list_global( $wpda_query_builder_data ) {
145 update_option( self::QUERY_BUILDER_OPTIONS, $wpda_query_builder_data );
146 }
147
148 public function get_query( $query_name, $user_id = null ) {
149 if ( null === $user_id ) {
150 $wpda_query_builder_data = $this->get_query_list();
151 } else {
152 $wpda_query_builder_data = $this->get_query_list( '', $user_id );
153 }
154 if ( is_array( $wpda_query_builder_data ) && isset( $wpda_query_builder_data[$query_name] ) ) {
155 return $wpda_query_builder_data[$query_name];
156 } else {
157 return array();
158 }
159 }
160
161 public function get_query_global( $query_name ) {
162 $wpda_query_builder_data = $this->get_query_list_global();
163 if ( is_array( $wpda_query_builder_data ) && isset( $wpda_query_builder_data[$query_name] ) ) {
164 return $wpda_query_builder_data[$query_name];
165 } else {
166 return array();
167 }
168 }
169
170 public function update_query_old(
171 $schema_name,
172 $query_name,
173 $query_sql,
174 $query_name_old,
175 $wpda_vqb = null,
176 $params = null
177 ) {
178 $wpda_query_builder_data = $this->get_query_list();
179 if ( '' !== $query_name_old && $query_name !== $query_name_old ) {
180 unset($wpda_query_builder_data[$query_name_old]);
181 }
182 $wpda_query_builder_data[$query_name] = array(
183 'schema_name' => $schema_name,
184 'query' => $query_sql,
185 'is_visual' => null !== $wpda_vqb,
186 'params' => $params,
187 );
188 $this->update_query_list( $wpda_query_builder_data );
189 }
190
191 public function update_query(
192 $schema_name,
193 $query_name,
194 $query_sql,
195 $query_name_old,
196 $is_visual,
197 $vqb,
198 $params
199 ) {
200 $wpda_query_builder_data = $this->get_query_list();
201 if ( '' !== $query_name_old && $query_name !== $query_name_old ) {
202 unset($wpda_query_builder_data[$query_name_old]);
203 }
204 $wpda_query_builder_data[$query_name] = array(
205 'schema_name' => $schema_name,
206 'query' => $query_sql,
207 'is_visual' => $is_visual,
208 'params' => $params,
209 );
210 if ( $vqb !== "" ) {
211 $wpda_query_builder_data[$query_name]['vqb'] = $vqb;
212 }
213 $this->update_query_list( $wpda_query_builder_data );
214 }
215
216 public function update_query_global(
217 $schema_name,
218 $query_name,
219 $query_sql,
220 $query_name_old,
221 $is_visual,
222 $vqb,
223 $params
224 ) {
225 $wpda_query_builder_data = $this->get_query_list_global();
226 if ( '' !== $query_name_old && $query_name !== $query_name_old ) {
227 unset($wpda_query_builder_data[$query_name_old]);
228 }
229 $wpda_query_builder_data[$query_name] = array(
230 'schema_name' => $schema_name,
231 'query' => $query_sql,
232 'is_visual' => $is_visual,
233 'params' => $params,
234 );
235 if ( $vqb !== "" ) {
236 $wpda_query_builder_data[$query_name]['vqb'] = $vqb;
237 }
238 $this->update_query_list_global( $wpda_query_builder_data );
239 }
240
241 public function delete_query( $query_name ) {
242 $wpda_query_builder_data = $this->get_query_list();
243 unset($wpda_query_builder_data[$query_name]);
244 $this->update_query_list( $wpda_query_builder_data );
245 $this->del_visual_query( $query_name );
246 }
247
248 public function delete_query_global( $query_name ) {
249 $wpda_query_builder_data = $this->get_query_list_global();
250 unset($wpda_query_builder_data[$query_name]);
251 $this->update_query_list_global( $wpda_query_builder_data );
252 $this->del_visual_query_global( $query_name );
253 }
254
255 public function get_visual_query( $query_name ) {
256 return get_user_meta( WPDA::get_current_user_id(), 'wpda_query_builder_' . $this->rewrite_query_name( $query_name ), true );
257 }
258
259 public function get_visual_query_global( $query_name ) {
260 return get_option( 'wpda_query_builder_' . $this->rewrite_query_name( $query_name ), true );
261 }
262
263 public function upd_visual_query( $query_name, $wpda_vqb ) {
264 update_user_meta( WPDA::get_current_user_id(), 'wpda_query_builder_' . $this->rewrite_query_name( $query_name ), $wpda_vqb );
265 }
266
267 public function upd_visual_query_global( $query_name, $wpda_vqb ) {
268 update_option( 'wpda_query_builder_' . $this->rewrite_query_name( $query_name ), $wpda_vqb );
269 }
270
271 protected function del_visual_query( $query_name ) {
272 delete_user_meta( WPDA::get_current_user_id(), 'wpda_query_builder_' . $this->rewrite_query_name( $query_name ) );
273 }
274
275 protected function del_visual_query_global( $query_name ) {
276 delete_option( 'wpda_query_builder_' . $this->rewrite_query_name( $query_name ) );
277 }
278
279 protected function rewrite_query_name( $query_name ) {
280 return str_replace( ' ', '_', $query_name );
281 }
282
283 private function substitute_sql_params( $wpdadb, $query, $params ) {
284 }
285
286 public function execute_query(
287 $dbs,
288 $query,
289 $limit,
290 $protect,
291 $params
292 ) {
293 $response = array(
294 'tabs' => array(),
295 'status' => null,
296 );
297 if ( $this->check_query( $protect, $dbs, $query ) ) {
298 // Execute query
299 $wpdadb = WPDADB::get_db_connection( $dbs );
300 if ( null !== $wpdadb ) {
301 $wpdadb->suppress_errors( true );
302 }
303 $sqllines = explode( "\n", $query );
304 // phpcs:ignore -- 8.1 proof
305 $sqlcmds = array();
306 $start_i = 0;
307 for ($i = 0; $i < count( $sqllines ); $i++) {
308 // phpcs:ignore -- 8.1 proof
309 if ( '/' === trim( $sqllines[$i] ) ) {
310 $sql = '';
311 for ($j = $start_i; $j < $i; $j++) {
312 if ( '' !== trim( $sqllines[$j] ) ) {
313 $sql .= "{$sqllines[$j]} ";
314 }
315 }
316 $sqlcmds[] = $sql;
317 $start_i = $i + 1;
318 }
319 }
320 if ( count( $sqlcmds ) > 0 ) {
321 // phpcs:ignore -- 8.1 proof
322 $tabs = array();
323 $vars = array();
324 $tmps = array();
325 // Process multiple SQL commands
326 for ($i = 0; $i < count( $sqlcmds ); $i++) {
327 // phpcs:ignore -- 8.1 proof
328 if ( '' !== $limit && 'select' === strtolower( substr( $sqlcmds[$i], 0, 6 ) ) ) {
329 $sqlcmds[$i] .= " limit {$limit} ";
330 }
331 $columns = WPDA::get_columns_from_query( $dbs, $sqlcmds[$i] );
332 // Need to reconnect when switching from local to remote and vice versa
333 $reconnected = false;
334 if ( 'use' === substr( strtolower( trim( $sqlcmds[$i] ) ), 0, 3 ) ) {
335 $use_cmd = explode( ' ', trim( $sqlcmds[$i] ) );
336 // phpcs:ignore -- 8.1 proof
337 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 )) ) {
338 $dbs = $use_cmd[1];
339 $wpdadb = WPDADB::get_db_connection( $dbs );
340 if ( null !== $wpdadb ) {
341 $wpdadb->suppress_errors( true );
342 }
343 $reconnected = true;
344 }
345 }
346 $exequery = true;
347 $var_name = null;
348 $wpdadb_saved = null;
349 switch ( strtolower( substr( trim( $sqlcmds[$i] ), 0, 7 ) ) ) {
350 case 'wpdavar':
351 $use_cmd = explode( ' ', trim( $sqlcmds[$i] ) );
352 // phpcs:ignore -- 8.1 proof
353 $var_name = ( isset( $use_cmd[1] ) ? $use_cmd[1] : null );
354 if ( $var_name !== null ) {
355 $vars[$var_name] = $tabs;
356 $tmps[$var_name] = $this->wpdavar_table( $wpdadb, $tabs[$i - 1], $var_name );
357 $exequery = false;
358 }
359 break;
360 case 'wpdatmp':
361 $use_cmd = explode( ' ', trim( $sqlcmds[$i] ) );
362 $var_name = ( isset( $use_cmd[1] ) ? $use_cmd[1] : null );
363 if ( $var_name !== null ) {
364 $wpdadb_saved = $this->wpdatmp_table(
365 $wpdadb,
366 $tmps[$var_name],
367 $tmps[$var_name]['data'],
368 $tmps[$var_name]['table_name'],
369 $var_name
370 );
371 $exequery = false;
372 }
373 $var_name = null;
374 // reset
375 break;
376 }
377 if ( !$reconnected && $exequery && null !== $wpdadb ) {
378 $wpdadb->query( $sqlcmds[$i] );
379 }
380 if ( null === $var_name ) {
381 $status = ( null !== $wpdadb_saved ? $wpdadb_saved : (( null !== $wpdadb ? clone $wpdadb : null )) );
382 $tabs[] = array(
383 'cmd' => $sqlcmds[$i],
384 'status' => $status,
385 'columns' => $columns,
386 );
387 } else {
388 $tabs[] = array(
389 'cmd' => $sqlcmds[$i],
390 'status' => ( isset( $vars[$var_name]['status'] ) ? $vars[$var_name]['status'] : null ),
391 'wpdavar' => ( isset( $tmps[$var_name] ) ? $tmps[$var_name] : null ),
392 'columns' => null,
393 );
394 }
395 if ( null === $wpdadb || '' !== $wpdadb->last_error ) {
396 break;
397 }
398 }
399 $response['tabs'] = $tabs;
400 } else {
401 $response['columns'] = WPDA::get_columns_from_query( $dbs, $query );
402 // Process single SQL command
403 if ( '' !== $limit && 'select' === strtolower( substr( $query, 0, 6 ) ) ) {
404 $query .= " limit {$limit} ";
405 }
406 if ( null !== $wpdadb ) {
407 $wpdadb->query( $query );
408 }
409 $response['cmd'] = $query;
410 $response['status'] = clone $wpdadb;
411 }
412 } else {
413 $response['status'] = '<strong>WP Data Access error:</strong> Query not allowed - WordPress tables are protected';
414 }
415 return $response;
416 }
417
418 public function add_query( $query_name, $query ) {
419 $wpda_query_builder_data = $this->get_query_list();
420 $wpda_query_builder_data[$query_name] = $query;
421 $this->update_query_list( $wpda_query_builder_data );
422 }
423
424 public function add_query_global( $query_name, $query ) {
425 $wpda_query_builder_data = $this->get_query_list_global();
426 $wpda_query_builder_data[$query_name] = $query;
427 $this->update_query_list_global( $wpda_query_builder_data );
428 }
429
430 public function get_hints( $dbs ) {
431 $tables = WPDA_Dictionary_Lists::get_tables( true, $dbs );
432 $hints = array();
433 foreach ( $tables as $table ) {
434 $columns = WPDA_Dictionary_Lists::get_table_columns( $table['table_name'], $dbs );
435 $hint_cols = array();
436 foreach ( $columns as $column ) {
437 $hint_cols[] = $column['column_name'];
438 }
439 $hints[$table['table_name']] = $hint_cols;
440 }
441 return $hints;
442 }
443
444 }
445