PluginProbe
Visualizer – Tables & Charts Manager with Built-in AI Generator / 3.1.1
Visualizer – Tables & Charts Manager with Built-in AI Generator v3.1.1
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 / Params.php

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

364 lines 10.7 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_Params extends Visualizer_Source_Query {
29
30 /**
31 * The params that will form the query.
32 *
33 * @access protected
34 * @var string
35 */
36 protected $_params;
37
38 /**
39 * Constructor.
40 *
41 * @since 1.0.0
42 *
43 * @access public
44 * @param array $params The params that will form the query.
45 */
46 public function __construct( $params = null ) {
47 $this->_params = $params;
48 if ( ! empty( $params ) ) {
49 $this->build_query();
50 }
51 }
52
53 /**
54 * Rearrange columns so that a string column, if present, is always first in the select list as this will form the x axis.
55 */
56 private function rearrange_columns_for_x_axis( $columns, $select, $tables ) {
57 if ( ! $select ) {
58 return null;
59 }
60
61 $first = null;
62 $index = 0;
63 foreach ( $select as $column ) {
64 if ( ! is_null( $first ) ) {
65 break;
66 }
67 $table = is_array( $tables ) ? $tables[0] : $tables;
68 $col = $column;
69 if ( 0 !== strpos( $column, 'count(' ) ) {
70 if ( count( $tables ) > 1 ) {
71 $arr = explode( '.', $column );
72 $table = $arr[0];
73 $col = $arr[1];
74 }
75 foreach ( $columns[ $table ] as $table_cols ) {
76 if ( $table_cols['name'] === $column && 'n' !== $table_cols['type'] ) {
77 $first = $column;
78 break;
79 }
80 }
81 }
82 $index++;
83 }
84
85 if ( $first ) {
86 unset( $select[ --$index ] );
87 array_unshift( $select, $first );
88 }
89
90 return implode( ',', $select );
91 }
92
93 /**
94 * Build the final query.
95 *
96 * @access private
97 */
98 private function build_query() {
99 $args = $this->_params;
100
101 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Building query with params %s', print_r( $args, true ) ), 'debug', __FILE__, __LINE__ );
102
103 $table = $args['from'];
104 $tables = array( $table );
105 $mapping = self::get_db_table_mapping();
106 if ( array_key_exists( $table, $mapping ) ) {
107 $tables[] = $mapping[ $table ];
108 }
109
110 $cols = array();
111 foreach ( $tables as $table ) {
112 $cols[ $table ] = self::get_db_table_columns( $table, count( $tables ) > 1 );
113 }
114
115 if ( ! isset( $args['select'] ) ) {
116 return;
117 }
118
119 $query = '';
120 $select = 'SELECT ' . $this->rearrange_columns_for_x_axis( $cols, $args['select'], $tables );
121 $from = ' FROM ' . vsprintf( implode( ',', array_fill( 0, count( $tables ), '%s' ) ), $tables );
122 $group = '';
123 $order = '';
124 $limit = '';
125 $fk = '';
126 $where = array();
127
128 if ( isset( $args['group'] ) ) {
129 $group = ' GROUP BY ' . implode( ', ', $args['group'] );
130 }
131 if ( isset( $args['order'] ) ) {
132 $order = ' ORDER BY ' . implode( ', ', $args['order'] );
133 }
134 if ( ! empty( $args['limit'] ) ) {
135 $limit = ' LIMIT ' . $args['limit'];
136 }
137
138 $index = 0;
139 if ( ! empty( $args['where'] ) ) {
140 $scraps = array();
141 foreach ( $args['where'] as $column ) {
142 if ( empty( $column ) ) {
143 continue;
144 }
145 if ( strpos( $column, '.' ) !== false ) {
146 $table = strstr( $column, '.', true );
147 } else {
148 $table = $args['from'];
149 }
150 $scraps[] = array(
151 'table' => $table,
152 'col' => $column,
153 'index' => $index++,
154 );
155 }
156
157 if ( $scraps ) {
158 foreach ( $scraps as $scrap ) {
159 foreach ( $cols[ $scrap['table'] ] as $col ) {
160 if ( $scrap['col'] === $col['name'] ) {
161 $operator = $args[ $col['type'] . '-operator' ][ $scrap['index'] ];
162 $operand = $args[ $col['type'] ][ $scrap['index'] ];
163 $where[] = $scrap['col'] . " $operator '$operand'";
164 }
165 }
166 }
167 }
168 }
169
170 if ( count( $tables ) > 1 ) {
171 $fk = $this->get_foreign_key_constraint( $tables[0], $tables[1] );
172 if ( ! empty( $fk ) ) {
173 $where[] = $fk;
174 }
175 }
176
177 if ( empty( $where ) ) {
178 $where = '';
179 } else {
180 $where = ' WHERE ' . implode( ' AND ', $where );
181 }
182
183 $query = $select . $from . $where . $group . $order . $limit;
184 $this->_query = $query;
185
186 do_action( 'themeisle_log_event', Visualizer_Plugin::NAME, sprintf( 'Firing query: %s', $this->_query ), 'debug', __FILE__, __LINE__ );
187 }
188
189 /**
190 * Gets the relationship between tables in the database.
191 *
192 * @access public
193 * @return array
194 */
195 public static function get_db_table_mapping() {
196 global $wpdb;
197 $mapping = get_transient( 'visualizer_db_table_mapping' );
198 if ( $mapping ) {
199 return $mapping;
200 }
201 // no need to provide x=>y and then y=>x as we will flip the array shortly.
202 $mapping = array(
203 $wpdb->prefix . 'posts' => $wpdb->prefix . 'postmeta',
204 $wpdb->prefix . 'users' => $wpdb->prefix . 'usermeta',
205 $wpdb->prefix . 'terms' => $wpdb->prefix . 'termmeta',
206 $wpdb->prefix . 'comments' => $wpdb->prefix . 'commentmeta',
207 );
208 $mapping = apply_filters( 'visualizer_db_table_mapping', $mapping );
209 $mapping += array_flip( $mapping );
210 set_transient( 'visualizer_db_table_mapping', $mapping, HOUR_IN_SECONDS );
211 return $mapping;
212 }
213
214 /**
215 * Returns the foreign key relationship constraint between the tables.
216 *
217 * @param string $table1 Table 1.
218 * @param string $table2 Table 2.
219 * @access private
220 * @return string
221 */
222 private function get_foreign_key_constraint( $table1, $table2 ) {
223 global $wpdb;
224
225 $posts = array( $wpdb->prefix . 'posts', $wpdb->prefix . 'postmeta' );
226 $users = array( $wpdb->prefix . 'users', $wpdb->prefix . 'usermeta' );
227 $terms = array( $wpdb->prefix . 'terms', $wpdb->prefix . 'termmeta' );
228 $comments = array( $wpdb->prefix . 'comments', $wpdb->prefix . 'commentmeta' );
229
230 if ( in_array( $table1, $posts ) && in_array( $table2, $posts ) ) {
231 return $wpdb->prefix . 'posts.ID = ' . $wpdb->prefix . 'postmeta.post_id';
232 }
233 if ( in_array( $table1, $users ) && in_array( $table2, $users ) ) {
234 return $wpdb->prefix . 'users.ID = ' . $wpdb->prefix . 'usermeta.user_id';
235 }
236 if ( in_array( $table1, $terms ) && in_array( $table2, $terms ) ) {
237 return $wpdb->prefix . 'terms.term_id = ' . $wpdb->prefix . 'termmeta.term_id';
238 }
239 if ( in_array( $table1, $comments ) && in_array( $table2, $comments ) ) {
240 return $wpdb->prefix . 'comments.comment_id = ' . $wpdb->prefix . 'commentmeta.comment_id';
241 }
242
243 return apply_filters( 'visualizer_db_fk_constraint', '', $table1, $table2 );
244 }
245
246 /**
247 * Gets the column information for the table.
248 *
249 * @param string $table The table.
250 * @param bool $prefix_with_table Whether to prefix column name with the name of the table.
251 * @access private
252 * @return array
253 */
254 private static function get_db_table_columns( $table, $prefix_with_table = false ) {
255 global $wpdb;
256 $columns = get_transient( "visualizer_db_{$table}_columns" );
257 if ( $columns ) {
258 return $columns;
259 }
260 $columns = array();
261 // @codingStandardsIgnoreStart
262 $rows = $wpdb->get_results( "SHOW COLUMNS IN `$table`", ARRAY_N );
263 // @codingStandardsIgnoreEnd
264 if ( $rows ) {
265 // n => numeric, d => date-ish, s => string-ish.
266 foreach ( $rows as $row ) {
267 $col = ( $prefix_with_table ? "$table." : '' ) . $row[0];
268 $type = $row[1];
269 if ( strpos( $type, 'int' ) !== false || strpos( $type, 'float' ) !== false ) {
270 $type = 'n';
271 } elseif ( strpos( $type, 'date' ) !== false || strpos( $type, 'time' ) !== false ) {
272 $type = 'd';
273 } else {
274 $type = 's';
275 }
276 $columns[] = array( 'name' => $col, 'type' => $type );
277 }
278 }
279 $mapping = apply_filters( 'visualizer_db_table_columns', $columns, $table );
280 set_transient( "visualizer_db_{$table}_columns", $columns, DAY_IN_SECONDS );
281 return $columns;
282 }
283
284 /**
285 * Gets the dependent tables and then gets column information for all the tables.
286 *
287 * @param string $table The table.
288 * @access public
289 * @return array
290 */
291 public static function get_table_columns( $table ) {
292 $columns = array();
293 if ( ! $table ) {
294 return $columns;
295 }
296
297 $tables = array( $table );
298 $mapping = Visualizer_Source_Query_Params::get_db_table_mapping();
299 if ( array_key_exists( $table, $mapping ) ) {
300 $tables[] = $mapping[ $table ];
301 }
302 foreach ( $tables as $table ) {
303 $cols = self::get_db_table_columns( $table, count( $tables ) > 1 );
304 $columns = array_merge( $columns, $cols );
305 }
306 return $columns;
307 }
308
309 /**
310 * Gets the tables in the database;
311 *
312 * @access public
313 * @return array
314 */
315 public static function get_db_tables() {
316 global $wpdb;
317 $tables = get_transient( 'visualizer_db_tables' );
318 if ( $tables ) {
319 return $tables;
320 }
321
322 $prefix = apply_filters( 'visualizer_db_prefix', $wpdb->prefix );
323 $sql = $wpdb->get_col( 'SHOW TABLES', 0 );
324 foreach ( $sql as $table ) {
325 if ( empty( $prefix ) || 0 === strpos( $table, $prefix ) ) {
326 $tables[] = $table;
327 }
328 }
329 $tables = apply_filters( 'visualizer_db_tables', $tables );
330 set_transient( 'visualizer_db_tables', $tables, HOUR_IN_SECONDS );
331 return $tables;
332 }
333
334 /**
335 * Gets all tables and their columns.
336 *
337 * @access public
338 * @return array
339 */
340 public static function get_all_db_tables_column_mapping() {
341 $mapping = array();
342 $tables = self::get_db_tables();
343 foreach ( $tables as $table ) {
344 $cols = self::get_db_table_columns( $table, true );
345 $names = wp_list_pluck( $cols, 'name' );
346 $mapping[ $table ] = $names;
347 }
348 return $mapping;
349 }
350
351
352 /**
353 * Returns source name.
354 *
355 * @since 1.0.0
356 *
357 * @access public
358 * @return string The name of source.
359 */
360 public function getSourceName() {
361 return __CLASS__;
362 }
363 }
364