PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.10.13
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.10.13
4.0.7 4.0.6 4.0.5 4.0.4 4.0.3 3.0.5 3.0.6 3.0.7 3.0.8 3.0.9 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.10.1 3.10.10 3.10.11 3.10.12 3.10.13 3.10.14 3.10.15 3.10.2 3.10.3 3.10.4 All 148 releases
visualizer / classes / Visualizer / Source / Query.php

Query.php in Visualizer – Tables & Charts Manager with Built-in AI Generator 3.10.13, at classes/Visualizer/Source/Query.php

281 lines 7.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 // +----------------------------------------------------------------------+
4 // | Copyright 2013 Madpixels (email : visualizer@madpixels.net) |
5 // +----------------------------------------------------------------------+
6 // | This program is free software; you can redistribute it and/or modify |
7 // | it under the terms of the GNU General Public License, version 2, as |
8 // | published by the Free Software Foundation. |
9 // | |
10 // | This program is distributed in the hope that it will be useful, |
11 // | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 // | GNU General Public License for more details. |
14 // | |
15 // | You should have received a copy of the GNU General Public License |
16 // | along with this program; if not, write to the Free Software |
17 // | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, |
18 // | MA 02110-1301 USA |
19 // +----------------------------------------------------------------------+
20 // | Author: Eugene Manuilov <eugene@manuilov.org> |
21 // +----------------------------------------------------------------------+
22 /**
23 * Source manager for query builder.
24 *
25 * @category Visualizer
26 * @package Source
27 */
28 class Visualizer_Source_Query extends Visualizer_Source {
29
30 /**
31 * The query.
32 *
33 * @access protected
34 * @var string
35 */
36 protected $_query;
37
38 /**
39 * The chart id.
40 *
41 * @access protected
42 * @var int
43 */
44 protected $_chart_id;
45
46 /**
47 * Any additional parameters (e.g. for connecting to a remote db).
48 *
49 * @access protected
50 * @var array
51 */
52 protected $_params;
53
54 /**
55 * Constructor.
56 *
57 * @access public
58 * @param string $query The query.
59 * @param int $chart_id The chart id.
60 * @param array $params Any additional parameters (e.g. for connecting to a remote db).
61 */
62 public function __construct( $query = null, $chart_id = null, $params = null ) {
63 $this->_query = $query;
64 $this->_chart_id = $chart_id;
65 $this->_params = $params;
66 }
67
68 /**
69 * Fetches information from source, parses it and builds series and data arrays.
70 *
71 * @param bool $as_html Should the result be fetched as an HTML table or as an object.
72 * @param bool $results_as_numeric_array Should the result be fetched as ARRAY_N instead of ARRAY_A.
73 * @param bool $raw_results Should the result be returned without processing.
74 * @access public
75 * @return boolean TRUE on success, otherwise FALSE.
76 */
77 public function fetch( $as_html = false, $results_as_numeric_array = false, $raw_results = false ) {
78 if ( empty( $this->_query ) ) {
79 return false;
80 }
81
82 // only select queries allowed.
83 if ( ! preg_match( '/\s*(\bselect\b)\s/i', $this->_query ) ) {
84 $this->_error = __( 'Only SELECT queries are allowed', 'visualizer' );
85 return false;
86 }
87
88 // if previous check passed, check for disallowed query parts to prevent subqueries and other harmful queries.
89 $disallow_query_parts = array(
90 'INSERT',
91 'UPDATE',
92 'DELETE',
93 'RENAME',
94 'DROP',
95 'CREATE',
96 'TRUNCATE',
97 'ALTER',
98 'COMMIT',
99 'ROLLBACK',
100 'MERGE',
101 'CALL',
102 'EXPLAIN',
103 'LOCK',
104 'GRANT',
105 'REVOKE',
106 'SAVEPOINT',
107 'TRANSACTION',
108 'SET',
109 );
110 $disallow_regex = implode(
111 '|',
112 array_map(
113 function ( $value ) {
114 return '\b' . $value . '\b';
115 }, $disallow_query_parts
116 )
117 );
118
119 if ( preg_match( '/(' . $disallow_regex . ')/i', $this->_query) !== 0 ) {
120 $this->_error = __( 'Only SELECT queries are allowed', 'visualizer' );
121 return false;
122 }
123
124 // impose a limit if no limit clause is provided.
125 if ( strpos( strtolower( $this->_query ), ' limit ' ) === false ) {
126 $this->_query .= ' LIMIT ' . apply_filters( 'visualizer_sql_query_limit', 1000, $this->_chart_id );
127 }
128
129 $this->_query = apply_filters( 'visualizer_db_query', $this->_query, $this->_chart_id, $this->_params );
130
131 $results = array();
132 $headers = array();
133
134 // short circuit results for remote dbs.
135 if ( false !== ( $remote_results = apply_filters( 'visualizer_db_query_execute', false, $this->_query, $as_html, $results_as_numeric_array, $raw_results, $this->_chart_id, $this->_params ) ) ) {
136 $error = $remote_results['error'];
137 if ( empty( $error ) ) {
138 $results = $remote_results['results'];
139 $headers = $remote_results['headers'];
140 }
141
142 $this->_error = $error;
143
144 if ( $raw_results ) {
145 return $results;
146 }
147 }
148
149 if ( ! ( $results && $headers ) ) {
150 global $wpdb;
151 $wpdb->hide_errors();
152 // @codingStandardsIgnoreStart
153 $rows = $wpdb->get_results( $this->_query, $results_as_numeric_array ? ARRAY_N : ARRAY_A );
154 // @codingStandardsIgnoreEnd
155 $wpdb->show_errors();
156
157 if ( $raw_results ) {
158 return $rows;
159 }
160
161 if ( $rows ) {
162 $results = array();
163 $headers = array();
164 if ( $rows ) {
165 $row_num = 0;
166 foreach ( $rows as $row ) {
167 $result = array();
168 $col_num = 0;
169 foreach ( $row as $k => $v ) {
170 $result[] = $v;
171 if ( 0 === $row_num ) {
172 $headers[] = array( 'type' => $this->get_col_type( $col_num++ ), 'label' => $k );
173 }
174 }
175 $results[] = $result;
176 $row_num++;
177 }
178 }
179
180 $this->_error = $wpdb->last_error;
181 }
182 }
183 // Query log.
184 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Firing query %s to get results %s with error %s', $this->_query, print_r( $rows, true ), print_r( $wpdb->last_error, true ) ), 'debug', __FILE__, __LINE__ );
185
186 if ( $as_html ) {
187 $results = $this->html( $headers, $results );
188 } else {
189 $results = $this->object( $headers, $results );
190 }
191
192 return apply_filters( 'visualizer_db_query_results', $results, $headers, $as_html, $results_as_numeric_array, $raw_results, $this->_query, $this->_chart_id, $this->_params );
193 }
194
195 /**
196 * Get the data type of the column.
197 *
198 * @param int $col_num The column index in the fetched result set.
199 * @access private
200 * @return int
201 */
202 private function get_col_type( $col_num ) {
203 global $wpdb;
204 switch ( $wpdb->get_col_info( 'type', $col_num ) ) {
205 case 0:
206 case 5:
207 case 4:
208 case 9:
209 case 3:
210 case 2:
211 case 246:
212 case 8:
213 // numeric.
214 return 'number';
215 case 10:
216 case 12:
217 case 14:
218 // date.
219 return 'date';
220 }
221 return 'string';
222 }
223
224 /**
225 * Returns the HTML output.
226 *
227 * @param array $headers The headers of the result set.
228 * @param array $results The data of the result set.
229 * @access private
230 * @return string
231 */
232 private function html( $headers, $results ) {
233 return Visualizer_Render_Layout::show( 'db-wizard-results', $headers, $results );
234 }
235
236 /**
237 * Sets the series and data.
238 *
239 * @param array $headers The headers of the result set.
240 * @param array $results The data of the result set.
241 * @access private
242 * @return bool
243 */
244 private function object( $headers, $results ) {
245 $series = array();
246 foreach ( $headers as $header ) {
247 $series[] = $header;
248 }
249 $this->_series = $series;
250
251 $data = array();
252 foreach ( $results as $row ) {
253 $data[] = $this->_normalizeData( $row );
254 }
255 $this->_data = $data;
256 return $this->_data;
257 }
258
259 /**
260 * Returns the final query.
261 *
262 * @access public
263 * @return string
264 */
265 public function get_query() {
266 return $this->_query;
267 }
268
269 /**
270 * Returns source name.
271 *
272 * @since 1.0.0
273 *
274 * @access public
275 * @return string The name of source.
276 */
277 public function getSourceName() {
278 return __CLASS__;
279 }
280 }
281