PluginProbe
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards / 5.5.36
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards v5.5.36
5.5.85 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 All 161 releases
wp-data-access / WPDataAccess / Data_Tables / WPDA_Data_Tables.php

WPDA_Data_Tables.php in WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards 5.5.36, at WPDataAccess/Data_Tables/WPDA_Data_Tables.php

1,323 lines 62.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Suppress "error - 0 - No summary was found for this file" on phpdoc generation
5 *
6 * @package WPDataAccess\Data_Tables
7 */
8 namespace WPDataAccess\Data_Tables;
9
10 use stdClass;
11 use WPDataAccess\Connection\WPDADB;
12 use WPDataAccess\Data_Dictionary\WPDA_Dictionary_Exist;
13 use WPDataAccess\Data_Dictionary\WPDA_List_Columns_Cache;
14 use WPDataAccess\Macro\WPDA_Macro;
15 use WPDataAccess\Plugin_Table_Models\WPDA_Publisher_Model;
16 use WPDataAccess\Plugin_Table_Models\WPDA_Media_Model;
17 use WPDataAccess\Plugin_Table_Models\WPDA_Table_Settings_Model;
18 use WPDataAccess\List_Table\WPDA_List_Table;
19 use WPDataAccess\Premium\WPDAPRO_Data_Publisher\WPDAPRO_Data_Publisher_Manage_Styles;
20 use WPDataAccess\Premium\WPDAPRO_Geo_Location\WPDAPRO_Geo_Location_WS;
21 use WPDataAccess\Settings\WPDA_Settings_DataTables;
22 use WPDataAccess\Templates\WPDAPRO_Template_Data_Publisher_Color;
23 use WPDataAccess\Templates\WPDAPRO_Template_Data_Publisher_Space;
24 use WPDataAccess\Templates\WPDA_Template_Data_Publisher_Corner;
25 use WPDataAccess\WPDA;
26 /**
27 * Class WPDA_Data_Tables
28 *
29 * @author Peter Schulz
30 * @since 1.0.0
31 */
32 class WPDA_Data_Tables {
33 const METHODS = array('httpGet', 'httpPost', 'httpRequest');
34
35 protected static $pub_ids = array();
36
37 protected $pub_id_seq = '';
38
39 protected $wpda_list_columns = null;
40
41 protected $wpda_dictionary_checks = null;
42
43 protected $json = null;
44
45 protected $table_settings = null;
46
47 protected $hyperlink_positions = array();
48
49 protected $columns = array();
50
51 protected $column_labels = null;
52
53 protected $primary_index_sorted = array();
54
55 protected $buttons = '[]';
56
57 //CWG This is correct
58 protected $geomap = '';
59
60 protected $geo_search = '';
61
62 protected $geo_search_type = null;
63
64 protected $read_more_html = '';
65
66 protected $serverSide = false;
67
68 public static function enqueue_styles_and_script( $styling = 'default' ) {
69 wp_enqueue_script( 'jquery-ui-draggable' );
70 wp_enqueue_script( 'jquery-ui-resizable' );
71 // Plugin css
72 wp_enqueue_style( 'wpda_datatables_default' );
73 wp_enqueue_style( 'dashicons' );
74 // Needed to display icons for media attachments
75 // Plugin js
76 wp_enqueue_script( 'wpda_datatables' );
77 // Add jQuery DataTables library scripts
78 if ( is_admin() && WPDA::get_option( WPDA::OPTION_BE_LOAD_DATATABLES ) === 'on' || !is_admin() && WPDA::get_option( WPDA::OPTION_FE_LOAD_DATATABLES ) === 'on' ) {
79 wp_enqueue_script( 'jquery_datatables' );
80 }
81 if ( is_admin() && WPDA::get_option( WPDA::OPTION_BE_LOAD_DATATABLES_RESPONSE ) === 'on' || !is_admin() && WPDA::get_option( WPDA::OPTION_FE_LOAD_DATATABLES_RESPONSE ) === 'on' ) {
82 wp_enqueue_script( 'jquery_datatables_responsive' );
83 }
84 $style_added = false;
85 if ( !$style_added || 'default' === $styling ) {
86 // Add jQuery DataTables library styles
87 if ( is_admin() && WPDA::get_option( WPDA::OPTION_BE_LOAD_DATATABLES ) === 'on' || !is_admin() && WPDA::get_option( WPDA::OPTION_FE_LOAD_DATATABLES ) === 'on' ) {
88 wp_enqueue_style( 'jquery_datatables' );
89 }
90 if ( is_admin() && WPDA::get_option( WPDA::OPTION_BE_LOAD_DATATABLES_RESPONSE ) === 'on' || !is_admin() && WPDA::get_option( WPDA::OPTION_FE_LOAD_DATATABLES_RESPONSE ) === 'on' ) {
91 wp_enqueue_style( 'jquery_datatables_responsive' );
92 }
93 }
94 }
95
96 /**
97 * Generate jQuery DataTable code
98 *
99 * Table and column names provided are checked for existency and access to prevent hacking the DataTable code
100 * and SQL injection.
101 *
102 * @param int $pub_id Table ID.
103 * @param string $pub_name Table name.
104 * @param string $database Database name.
105 * @param string $table_name Database table name.
106 * @param string $column_names Comma separated list of column names.
107 * @param string $responsive Yes = responsive mode, No = No responsive mode.
108 * @param int $responsive_cols Number of columns to be displayed in responsive mode.
109 * @param string $responsive_type Modal, Collapsed or Expanded (only if $responsive = Yes).
110 * @param string $responsive_icon Yes = show icon, No = do not show icon (only if $responsive = Yes).
111 * @param string $sql_orderby SQL default order by
112 * @param string $filter_field_name Filter field name (CSV)
113 * @param string $filter_field_value Filter field value (CSV)
114 * @param string $nl2br Convert New Line characters to BR tags
115 *
116 * @return string response wpda_datatables_ajax_call
117 *
118 * @since 1.0.0
119 */
120 public function show(
121 $pub_id,
122 $pub_name,
123 $database,
124 $table_name,
125 $column_names,
126 $responsive,
127 $responsive_cols,
128 $responsive_type,
129 $responsive_icon,
130 $sql_orderby,
131 $filter_field_name = '',
132 $filter_field_value = '',
133 $nl2br = '',
134 $dashboard_styling = false,
135 $is_embedded = false
136 ) {
137 if ( '' === $pub_id && '' === $pub_name && '' === $table_name ) {
138 return '<p>' . __( 'ERROR: Missing argument [need at least pub_id, pub_name or table argument]', 'wp-data-access' ) . '</p>';
139 }
140 if ( '' !== $pub_id || '' !== $pub_name ) {
141 // Get data table information
142 if ( '' !== $pub_id ) {
143 $publication = WPDA_Publisher_Model::get_publication( $pub_id );
144 } else {
145 $publication = WPDA_Publisher_Model::get_publication_by_name( $pub_name );
146 }
147 if ( false === $publication ) {
148 // Querying tables in other schema's is not allowed!
149 return '<p>' . __( 'ERROR: Data table not found', 'wp-data-access' ) . '</p>';
150 }
151 $pub_id = $publication[0]['pub_id'];
152 $database = $publication[0]['pub_schema_name'];
153 $data_source = $publication[0]['pub_data_source'];
154 $table_name = $publication[0]['pub_table_name'];
155 $column_names = $publication[0]['pub_column_names'];
156 if ( null === $column_names || '' === trim( $column_names ) ) {
157 $column_names = '*';
158 }
159 $pub_query = $publication[0]['pub_query'];
160 $pub_cpt_query = $publication[0]['pub_cpt_query'];
161 $pub_cpt_format = $publication[0]['pub_cpt_format'];
162 $responsive = strtolower( (string) $publication[0]['pub_responsive'] );
163 $responsive_popup_title = $publication[0]['pub_responsive_popup_title'];
164 $responsive_cols = $publication[0]['pub_responsive_cols'];
165 $responsive_type = strtolower( (string) $publication[0]['pub_responsive_type'] );
166 $responsive_icon = strtolower( (string) $publication[0]['pub_responsive_icon'] );
167 $pub_flat_scrollx = strtolower( (string) $publication[0]['pub_flat_scrollx'] );
168 $pub_format = $publication[0]['pub_format'];
169 $sql_orderby = $publication[0]['pub_default_orderby'];
170 if ( null === $sql_orderby || 'null' === $sql_orderby ) {
171 $sql_orderby = '';
172 }
173 $pub_table_options_searching = $publication[0]['pub_table_options_searching'];
174 $pub_table_options_ordering = $publication[0]['pub_table_options_ordering'];
175 $pub_table_options_paging = $publication[0]['pub_table_options_paging'];
176 $pub_table_options_serverside = $publication[0]['pub_table_options_serverside'];
177 $pub_table_options_advanced = $publication[0]['pub_table_options_advanced'];
178 $pub_table_options_advanced = str_replace( array("\r", "\n", "\t"), '', (string) $pub_table_options_advanced );
179 $pub_responsive_modal_hyperlinks = $publication[0]['pub_responsive_modal_hyperlinks'];
180 $pub_sort_icons = $publication[0]['pub_sort_icons'];
181 $pub_styles = $publication[0]['pub_styles'];
182 $pub_extentions = $publication[0]['pub_extentions'];
183 if ( !isset( self::$pub_ids[$pub_id] ) ) {
184 self::$pub_ids[$pub_id] = 1;
185 $this->pub_id_seq = '';
186 } else {
187 self::$pub_ids[$pub_id]++;
188 $this->pub_id_seq = '_' . self::$pub_ids[$pub_id];
189 }
190 } else {
191 $pub_id = '0';
192 $data_source = 'Table';
193 $pub_query = null;
194 $pub_cpt_query = null;
195 $pub_cpt_format = '';
196 $responsive_popup_title = '';
197 $pub_format = '';
198 $pub_table_options_searching = 'on';
199 $pub_table_options_ordering = 'on';
200 $pub_table_options_paging = 'on';
201 $pub_table_options_serverside = 'on';
202 $pub_table_options_advanced = '';
203 $pub_responsive_modal_hyperlinks = '';
204 $pub_sort_icons = 'default';
205 $pub_styles = 'default';
206 $pub_extentions = '';
207 $pub_flat_scrollx = 'no';
208 $this->pub_id_seq = '';
209 }
210 // Activate scripts and styles
211 $styling = $this->set_style( $dashboard_styling, ( isset( $publication ) ? $publication : null ) );
212 self::enqueue_styles_and_script( $styling );
213 // Create JSON object from advanced settings
214 try {
215 $this->json = json_decode( (string) $pub_table_options_advanced );
216 if ( null === $this->json || is_array( $this->json ) ) {
217 $this->json = new stdClass();
218 }
219 } catch ( \Exception $e ) {
220 $this->json = new stdClass();
221 }
222 // Add extension support
223 $this->extension_wizard( $pub_extentions );
224 // Check for extra header column
225 $header2 = $this->add_extra_header();
226 // Check button usage
227 $use_buttons_extension = $this->use_buttons_extension();
228 switch ( $pub_sort_icons ) {
229 case 'none':
230 // Hide sort icons
231 wp_enqueue_style( 'wpda_datatables_hide_sort_icons' );
232 break;
233 default:
234 }
235 if ( 'on' !== $pub_table_options_searching || null === $pub_table_options_searching ) {
236 $pub_table_options_searching = 'false';
237 } else {
238 $pub_table_options_searching = 'true';
239 }
240 if ( 'on' !== $pub_table_options_ordering || null === $pub_table_options_ordering ) {
241 $pub_table_options_ordering = 'false';
242 } else {
243 $pub_table_options_ordering = 'true';
244 }
245 if ( 'on' !== $pub_table_options_paging || null === $pub_table_options_paging ) {
246 $pub_table_options_paging = 'false';
247 } else {
248 $pub_table_options_paging = 'true';
249 }
250 if ( !isset( $this->json->serverSide ) ) {
251 if ( 'on' !== $pub_table_options_serverside || null === $pub_table_options_serverside ) {
252 $this->json->serverSide = false;
253 }
254 }
255 if ( '' === $responsive_popup_title || null === $responsive_popup_title || 'Row details' === $responsive_popup_title ) {
256 $responsive_popup_title = __( 'Row details', 'wp-data-access' );
257 // Set title of modal window here to support i18n.
258 }
259 // WordPress database is default
260 if ( '' === $database ) {
261 global $wpdb;
262 $database = $wpdb->dbname;
263 }
264 if ( 'Query' === $data_source || 'CPT' === $data_source ) {
265 } else {
266 // Check if table exists to prevent SQL injection
267 $this->wpda_dictionary_checks = new WPDA_Dictionary_Exist($database, $table_name);
268 if ( !$this->wpda_dictionary_checks->table_exists( '0' === $pub_id, false ) ) {
269 // Table not found.
270 return '<p>' . __( 'ERROR: Invalid table name or not authorized', 'wp-data-access' ) . '</p>';
271 }
272 // Load table settings
273 $table_settings_db = WPDA_Table_Settings_Model::query( $table_name, $database );
274 if ( isset( $table_settings_db[0]['wpda_table_settings'] ) ) {
275 $this->table_settings = json_decode( (string) $table_settings_db[0]['wpda_table_settings'] );
276 }
277 // Get table settings > hyperlinks
278 $hyperlinks = array();
279 if ( isset( $this->table_settings->hyperlinks ) ) {
280 foreach ( $this->table_settings->hyperlinks as $hyperlink ) {
281 $hyperlink_label = ( isset( $hyperlink->hyperlink_label ) ? $hyperlink->hyperlink_label : '' );
282 $hyperlink_html = ( isset( $hyperlink->hyperlink_html ) ? $hyperlink->hyperlink_html : '' );
283 if ( $hyperlink_label !== '' && $hyperlink_html !== '' ) {
284 array_push( $hyperlinks, $hyperlink_label );
285 //phpcs:ignore - 8.1 proof
286 }
287 }
288 }
289 // Check for geolocation support
290 $geolocation = $this->get_geolocation_settings();
291 $row_count_estimate = WPDA::get_row_count_estimate( $database, $table_name, $this->table_settings );
292 $calc_estimate = $row_count_estimate['is_estimate'];
293 // Get table columns
294 $this->wpda_list_columns = WPDA_List_Columns_Cache::get_list_columns( $database, $table_name );
295 // Set columns to be queried
296 $this->columns = $this->get_columns( $column_names );
297 // Get column labels
298 $this->column_labels = $this->get_labels( $pub_format );
299 // Define dat table columns
300 $wpda_database_columns = $this->define_columns( $use_buttons_extension, $hyperlinks, $geolocation );
301 }
302 // Run filters to allow plugin users to add custom features
303 if ( has_filter( 'wpda_wpdataaccess_prepare' ) ) {
304 $wpda_wpdataaccess_prepare_filter = apply_filters(
305 'wpda_wpdataaccess_prepare',
306 '',
307 $database,
308 $table_name,
309 $pub_id,
310 $this->columns,
311 $this->table_settings
312 );
313 } else {
314 $wpda_wpdataaccess_prepare_filter = '';
315 }
316 // Get jQuery DataTables language
317 $language = $this->get_language();
318 // Create dynamic columns variable name (must be unique per data table to support multiple data tables on one page)
319 $columnsvar = 'wpdaDbColumns' . preg_replace( '/[^a-zA-Z0-9]/', '', $table_name ) . $pub_id;
320 // Add button extension
321 $this->add_buttons( $use_buttons_extension, $pub_id, $table_name );
322 // Add geolocation support
323 $this->add_geolocation(
324 $geolocation,
325 $pub_id,
326 $table_name,
327 $database
328 );
329 // Add read more button
330 $read_more = $this->add_read_more( $pub_id, $table_name, $pub_table_options_paging );
331 // Update extra header of necessary
332 $header2 = $this->update_extra_header( $header2, $pub_table_options_searching );
333 // Apply global styling
334 $dataTablesClass = $this->add_global_style( $styling, $pub_styles );
335 // Themes like DIVI use IDs to overwrite all defaults of others. This style reassures correct positioning
336 // of the responsive icon. This cannot be added to the plugin CSS files. It needs an ID to overwrite other
337 // ID styling.
338 $styling_default = "\n\t\t\t\t<style>\n\t\t\t\t\t#" . esc_attr( $table_name ) . "{$pub_id}.dataTable.wpda-datatable.dtr-inline.collapsed>tbody>tr>td.dtr-control,\n\t\t\t\t\t#" . esc_attr( $table_name ) . "{$pub_id}.dataTable.wpda-datatable.dtr-inline.collapsed>tbody>tr>th.dtr-control {\n \t\t\t\t\tpadding-left: 2.2em;\n\t\t\t\t\t}\n\t\t\t\t</style>";
339 // Add premium styling
340 $styling_template = $this->add_styling_template(
341 $pub_id,
342 $table_name,
343 $dashboard_styling,
344 ( isset( $publication ) ? $publication : null )
345 );
346 // Prepare values needed for ajax request
347 $database_value = $database;
348 $column_names_value = $column_names;
349 if ( '0' != $pub_id ) {
350 $database_value = '';
351 $column_names_value = '';
352 }
353 // Convert JSON to string
354 $json_value = $this->prepare_json( $responsive, $pub_flat_scrollx );
355 // Generate nonce
356 $wpnonce = $this->generate_nonce( $table_name, $column_names_value, $is_embedded );
357 $wpda_post_vars = [];
358 $http_get_args = [];
359 $http_post_args = [];
360 return $wpda_wpdataaccess_prepare_filter . $styling_default . $styling_template . "<div class='wpda_publication_container'><table id=\"" . esc_attr( $table_name ) . "{$pub_id}{$this->pub_id_seq}\" class=\"{$dataTablesClass}\" cellspacing=\"0\">" . '<thead>' . $this->show_header(
361 $responsive,
362 $responsive_cols,
363 $hyperlinks,
364 $header2,
365 $geolocation
366 ) . '</thead>' . '<tfoot>' . $this->show_header(
367 $responsive,
368 $responsive_cols,
369 $hyperlinks,
370 '',
371 $geolocation
372 ) . '</tfoot>' . '</table></div>' . $this->read_more_html . "<script type='text/javascript'>" . "var {$columnsvar}_advanced_options = " . $json_value . '; ' . "var {$columnsvar} = [" . $wpda_database_columns . '];' . "var {$columnsvar}_geosearch_options = " . json_encode( $this->geo_search_type ) . '; ' . "var {$table_name}_{$pub_id}_args = [" . json_encode( $wpda_post_vars, true ) . ']; ' . "var {$table_name}_{$pub_id}_gets = [" . json_encode( $http_get_args, true ) . ']; ' . "var {$table_name}_{$pub_id}_posts = [" . json_encode( $http_post_args, true ) . ']; ' . 'jQuery(function () {' . ' wpda_datatables_ajax_call(' . "\t\t{$columnsvar}," . ' "' . esc_attr( $database_value ) . '",' . ' "' . esc_attr( $table_name ) . '",' . ' "' . esc_attr( $column_names_value ) . '",' . ' "' . esc_attr( $responsive ) . '",' . ' "' . esc_attr( $responsive_popup_title ) . '",' . ' "' . esc_attr( $responsive_type ) . '",' . ' "' . esc_attr( $responsive_icon ) . '",' . ' "' . esc_attr( $language ) . '",' . ' "' . htmlentities( $sql_orderby ) . '",' . "\t\t{$pub_table_options_searching}," . "\t {$pub_table_options_ordering}," . "\t\t{$pub_table_options_paging}," . "\t\t{$columnsvar}_advanced_options," . "\t\t{$pub_id}," . ' "' . esc_attr( $pub_responsive_modal_hyperlinks ) . '",' . ' [' . implode( ',', $this->hyperlink_positions ) . '],' . ' "' . esc_attr( $filter_field_name ) . '",' . ' "' . esc_attr( $filter_field_value ) . '",' . ' "' . esc_attr( $nl2br ) . '",' . "\t\t{$this->buttons}," . "\t\t\"{$read_more}\"," . ' "' . (( $calc_estimate ? 'true' : 'false' )) . '",' . ' "' . trim( preg_replace( '/\\s+/', ' ', $this->geo_search ) ) . '",' . "\t\t{$columnsvar}_geosearch_options," . ' "' . $wpnonce . '",' . ' "' . $this->pub_id_seq . '"' . ' );' . '});' . '</script>' . $this->geomap;
373 }
374
375 protected function set_style( $dashboard_styling, $publication ) {
376 $styling = 'default';
377 return $styling;
378 }
379
380 protected function extension_wizard( $pub_extentions ) {
381 }
382
383 protected function add_extra_header() {
384 $header2 = '';
385 return $header2;
386 }
387
388 protected function use_buttons_extension() {
389 $use_buttons_extension = false;
390 return $use_buttons_extension;
391 }
392
393 protected function get_geolocation_settings() {
394 }
395
396 protected function get_columns( $column_names ) {
397 if ( '*' === $column_names ) {
398 // Get all column names from table.
399 $columns = array();
400 foreach ( $this->wpda_list_columns->get_table_columns() as $column ) {
401 $columns[] = $column['column_name'];
402 }
403 return $columns;
404 } else {
405 //phpcs:ignore - 8.1 proof
406 $columns = explode( ',', (string) $column_names );
407 // Create column ARRAY
408 // Check if columns exist to prevent sql injection
409 $i = 0;
410 foreach ( $columns as $column ) {
411 if ( 'wpda_hyperlink_' !== substr( $column, 0, 15 ) ) {
412 if ( !$this->wpda_dictionary_checks->column_exists( $column ) ) {
413 // Column not found
414 return __( 'ERROR: Column', 'wp-data-access' ) . ' ' . esc_attr( $column ) . ' ' . __( 'not found', 'wp-data-access' );
415 }
416 } else {
417 $this->hyperlink_positions[] = $i;
418 }
419 $i++;
420 }
421 return $columns;
422 }
423 }
424
425 protected function get_labels( $pub_format ) {
426 try {
427 $pub_format_json = json_decode( (string) $pub_format, true );
428 if ( isset( $pub_format_json['pub_format']['column_labels'] ) && is_array( $pub_format_json['pub_format']['column_labels'] ) ) {
429 return array_merge( $this->wpda_list_columns->get_table_column_headers(), $pub_format_json['pub_format']['column_labels'] );
430 } else {
431 return $this->wpda_list_columns->get_table_column_headers();
432 }
433 } catch ( \Exception $e ) {
434 return $this->wpda_list_columns->get_table_column_headers();
435 }
436 }
437
438 protected function define_columns( $use_buttons_extension, $hyperlinks, $geolocation ) {
439 $wpda_database_columns = '';
440 for ($i = 0; $i < count( $this->columns ); $i++) {
441 if ( 'wpda_hyperlink_' !== substr( $this->columns[$i], 0, 15 ) ) {
442 $column_label = ( isset( $this->column_labels[$this->columns[$i]] ) ? $this->column_labels[$this->columns[$i]] : $this->columns[$i] );
443 } else {
444 $column_label = $hyperlinks[substr( $this->columns[$i], strrpos( $this->columns[$i], '_' ) + 1 )];
445 }
446 $data_type = WPDA::get_type( $this->wpda_list_columns->get_column_data_type( $this->columns[$i] ) );
447 $data_type_class = "wpda_format_{$data_type}";
448 $wpda_database_columns_obj = (object) null;
449 $wpda_database_columns_obj->className = "{$this->columns[$i]} {$data_type_class}";
450 $wpda_database_columns_obj->name = $this->columns[$i];
451 $wpda_database_columns_obj->targets = $i;
452 $wpda_database_columns_obj->label = $column_label;
453 $wpda_database_columns_obj->searchBuilderType = WPDA::get_sb_type( $this->wpda_list_columns->get_column_data_type( $this->columns[$i] ) );
454 $wpda_database_columns .= json_encode( $wpda_database_columns_obj );
455 if ( $i < count( $this->columns ) - 1 ) {
456 //phpcs:ignore - 8.1 proof
457 $wpda_database_columns .= ',';
458 }
459 }
460 return $wpda_database_columns;
461 }
462
463 protected function get_language() {
464 // Check data table specific language
465 if ( isset( $this->json->wpda_language, WPDA_Settings_DataTables::FRONTEND_LANG[$this->json->wpda_language] ) ) {
466 return WPDA_Settings_DataTables::FRONTEND_LANG[$this->json->wpda_language];
467 }
468 // Get data table global language
469 $language = WPDA::get_option( WPDA::OPTION_DP_LANGUAGE );
470 $language_code = ( isset( WPDA_Settings_DataTables::FRONTEND_LANG[$language] ) ? WPDA_Settings_DataTables::FRONTEND_LANG[$language] : 'en-GB' );
471 return $language_code;
472 }
473
474 protected function add_buttons( $use_buttons_extension, $pub_id, $table_name ) {
475 }
476
477 private function get_button_caption() {
478 return ( isset( $this->json->wpda_button_caption ) && null !== $this->json->wpda_button_caption ? $this->json->wpda_button_caption : 'label' );
479 }
480
481 protected function add_export_button( $button_type, $icon, $hint ) {
482 }
483
484 protected function add_geolocation(
485 $geolocation,
486 $pub_id,
487 $table_name,
488 $database
489 ) {
490 $this->geo_search_type = (object) null;
491 }
492
493 protected function add_read_more( $pub_id, $table_name, $pub_table_options_paging ) {
494 if ( 'false' === $pub_table_options_paging && isset( $this->json->serverSide ) && ('true' === $this->json->serverSide || true === $this->json->serverSide) ) {
495 $this->read_more_html = '<div id="' . esc_attr( $table_name ) . "{$pub_id}_more_container\" class='wpda_more_container' >" . '<button id="' . esc_attr( $table_name ) . "{$pub_id}_more_button\" type='button' class='wpda_more_button dt-button'>SHOW MORE</button>" . '</div>';
496 }
497 return ( '' === $this->read_more_html ? 'false' : 'true' );
498 }
499
500 protected function update_extra_header( $header2, $pub_table_options_searching ) {
501 return $header2;
502 }
503
504 protected function add_global_style( $styling, $pub_styles ) {
505 $dataTablesClass = str_replace( array(',', 'default'), array(' ', 'display'), $pub_styles );
506 return $dataTablesClass;
507 }
508
509 protected function add_styling_template(
510 $pub_id,
511 $table_name,
512 $dashboard_styling,
513 $publication
514 ) {
515 $styling_template = '';
516 // Needed for jdt
517 $this->json->wpda_styling = $styling_template;
518 return $styling_template;
519 }
520
521 protected function prepare_json( $responsive, $pub_flat_scrollx ) {
522 if ( !isset( $this->json->dom ) ) {
523 $this->json->dom = 'lfrtip';
524 }
525 if ( 'no' === strtolower( $responsive ) && 'yes' === strtolower( $pub_flat_scrollx ) && !isset( $this->json->scrollX ) ) {
526 $this->json->scrollX = true;
527 }
528 // Convert JSON to string
529 return json_encode( $this->json );
530 }
531
532 protected function generate_nonce( $table_name, $column_names_value, $is_embedded ) {
533 // Generate nonce
534 $nonce_seed = 'wpda-publication-' . $table_name . '-' . $column_names_value;
535 if ( !$is_embedded ) {
536 // Normal WordPress nonce
537 return wp_create_nonce( $nonce_seed );
538 } else {
539 // Plugin string based nonce to secure embedding
540 return WPDA::wpda_create_sonce( $nonce_seed );
541 }
542 }
543
544 /**
545 * Show table header (footer as well)
546 *
547 * @param string $responsive Yes = responsive mode, No = Flat mode.
548 * @param int $responsive_cols Number of columns to be displayed in responsive mode.
549 * @param array $hyperlinks Hyperlinks defined in column settings.
550 * @param string $header2 Adds an extra header row if TRUE.
551 * @param mixed $geolocation
552 *
553 * @return HTML output
554 */
555 protected function show_header(
556 $responsive,
557 $responsive_cols,
558 $hyperlinks,
559 $header2,
560 $geolocation
561 ) {
562 $count = 0;
563 $html_output = '';
564 $html_search = '';
565 foreach ( $this->columns as $column ) {
566 $class = '';
567 if ( 'yes' === $responsive ) {
568 if ( is_numeric( $responsive_cols ) ) {
569 if ( (int) $responsive_cols > 0 ) {
570 if ( $count >= 0 && $count < $responsive_cols ) {
571 $class = 'all';
572 } else {
573 $class = 'none';
574 }
575 }
576 }
577 }
578 if ( 'wpda_hyperlink_' !== substr( $column, 0, 15 ) ) {
579 $column_label = ( isset( $this->column_labels[$column] ) ? $this->column_labels[$column] : $column );
580 } else {
581 $column_label = $hyperlinks[substr( $column, strrpos( $column, '_' ) + 1 )];
582 }
583 if ( 'header' === $header2 || 'both' === $header2 ) {
584 $html_search .= "<td class=\"{$class}\" data-column_name_search=\"{$column}\" data-column_name_label=\"{$column_label}\"></td>";
585 $html_output .= "<th class=\"{$class}\" data-column_name=\"{$column}\">{$column_label}</th>";
586 } else {
587 $html_output .= "<th class=\"{$class}\" data-column_name_search=\"{$column}\">{$column_label}</th>";
588 }
589 $count++;
590 }
591 if ( '' !== $html_search ) {
592 $html_search = "<tr>{$html_search}</tr>";
593 }
594 return "{$html_search}<tr>{$html_output}</tr>";
595 }
596
597 private function url_params( $where ) {
598 return $where;
599 }
600
601 /**
602 * Performs jQuery DataTable query
603 *
604 * Once a jQuery DataTable is build using {@see WPDA_Data_Tables::show()}, the DataTable is filled according
605 * to the search criteria and pagination settings on the Datable. The query is performed through this function.
606 * The query result is returned (echo) in JSON format. Table and column names are checked for existence and
607 * access to prevent hacking the DataTable code and SQL injection.
608 *
609 * @since 1.0.0
610 *
611 * @see WPDA_Data_Tables::show()
612 */
613 public function get_data() {
614 $where = '';
615 $_filter = array();
616 $has_sp = false;
617 $sp_columns = array();
618 $pub_id = ( isset( $_REQUEST['pubid'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['pubid'] ) ) : '' );
619 // input var okay.
620 $database = ( isset( $_REQUEST['wpdasrc'] ) ? str_replace( '`', '', sanitize_text_field( wp_unslash( $_REQUEST['wpdasrc'] ) ) ) : '' );
621 // input var okay.
622 $table_name = ( isset( $_REQUEST['wpdatabs'] ) ? str_replace( '`', '', sanitize_text_field( wp_unslash( $_REQUEST['wpdatabs'] ) ) ) : '' );
623 // input var okay.
624 $columns = ( isset( $_REQUEST['wpdacols'] ) ? str_replace( '`', '', sanitize_text_field( wp_unslash( $_REQUEST['wpdacols'] ) ) ) : '*' );
625 // input var okay.
626 $wpnonce = ( isset( $_REQUEST['wpnonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['wpnonce'] ) ) : '' );
627 // input var okay.
628 if ( '' === $pub_id && '' === $table_name ) {
629 // input var okay.
630 // Database and table name must be set!
631 $this->create_empty_response( 'Missing arguments' );
632 wp_die();
633 }
634 $this->serverSide = true;
635 // Set pagination values.
636 $offset = 0;
637 if ( isset( $_REQUEST['start'] ) ) {
638 $offset = sanitize_text_field( wp_unslash( $_REQUEST['start'] ) );
639 // input var okay.
640 }
641 $limit = -1;
642 // jQuery DataTables default.
643 if ( isset( $_REQUEST['length'] ) ) {
644 $limit = sanitize_text_field( wp_unslash( $_REQUEST['length'] ) );
645 // input var okay.
646 }
647 $publication_mode = 'normal';
648 if ( -1 == $limit && isset( $_REQUEST['more_start'] ) && isset( $_REQUEST['more_limit'] ) ) {
649 $publication_mode = 'more';
650 $offset = sanitize_text_field( wp_unslash( $_REQUEST['more_start'] ) );
651 // input var okay.
652 $limit = sanitize_text_field( wp_unslash( $_REQUEST['more_limit'] ) );
653 // input var okay.
654 }
655 if ( '' !== $pub_id && '0' != $pub_id ) {
656 // Get data
657 $publication = WPDA_Publisher_Model::get_publication( $pub_id );
658 if ( false === $publication ) {
659 // Data table not found
660 $this->create_empty_response( 'Invalid arguments' );
661 wp_die();
662 }
663 $kill_token = false;
664 $pub_table_options_advanced = $publication[0]['pub_table_options_advanced'];
665 $pub_table_options_advanced = str_replace( array("\r", "\n", "\t"), '', (string) $pub_table_options_advanced );
666 try {
667 $json = json_decode( (string) $pub_table_options_advanced );
668 $kill_token = isset( $json->killToken ) && (true === $json->killToken || 'true' === $json->killToken);
669 } catch ( \Exception $e ) {
670 $json = null;
671 }
672 $database = $publication[0]['pub_schema_name'];
673 $table_name = $publication[0]['pub_table_name'];
674 $columns = $publication[0]['pub_column_names'];
675 if ( null === $columns || '' === trim( $columns ) ) {
676 $columns = '*';
677 }
678 // Check token
679 $table_name_verify = ( 'Query' === $publication[0]['pub_data_source'] || 'CPT' === $publication[0]['pub_data_source'] ? "custom{$pub_id}" : $table_name );
680 if ( !$kill_token && !wp_verify_nonce( $wpnonce, 'wpda-publication-' . $table_name_verify . '-' ) && !WPDA::wpda_verify_sonce( $wpnonce, 'wpda-publication-' . $table_name_verify . '-' ) ) {
681 $this->create_empty_response( 'Token expired, please refresh page' );
682 wp_die();
683 }
684 // Get default where
685 if ( isset( $publication[0]['pub_default_where'] ) ) {
686 if ( null !== $publication[0]['pub_default_where'] && '' !== trim( $publication[0]['pub_default_where'] ) ) {
687 $where = $publication[0]['pub_default_where'];
688 }
689 }
690 // Get server side options.
691 if ( isset( $json->serverSide ) ) {
692 $this->serverSide = true === $json->serverSide || 'true' === $json->serverSide;
693 } else {
694 if ( 'on' !== $publication[0]['pub_table_options_serverside'] || null === $publication[0]['pub_table_options_serverside'] ) {
695 $this->serverSide = false;
696 }
697 }
698 } else {
699 // Check token = old shortcode usage
700 if ( !wp_verify_nonce( $wpnonce, 'wpda-publication-' . $table_name . '-' . $columns ) && !WPDA::wpda_verify_sonce( $wpnonce, 'wpda-publication-' . $table_name . '-' . $columns ) ) {
701 $this->create_empty_response( 'Token expired, please refresh page' );
702 wp_die();
703 }
704 // Do not allow to access other schemas
705 if ( strpos( $table_name, '.' ) ) {
706 $this->create_empty_response( 'Wrong argument' );
707 wp_die();
708 }
709 // Check access
710 $wpda_dictionary_checks = new WPDA_Dictionary_Exist($database, $table_name);
711 if ( !$wpda_dictionary_checks->table_exists( true, false ) ) {
712 $this->create_empty_response( 'Not authorized' );
713 wp_die();
714 }
715 // Init var to prevent undefined var messages.
716 $json = null;
717 }
718 if ( '' !== $where && 'where' !== strtolower( substr( trim( $where ), 0, 5 ) ) ) {
719 $where = "where {$where}";
720 }
721 if ( '' !== $where ) {
722 $_filter = array(
723 'filter_default' => $where,
724 );
725 }
726 $wpdadb = WPDADB::get_db_connection( $database );
727 if ( null === $wpdadb ) {
728 $this->create_empty_response( 'Invalid connection' );
729 wp_die();
730 // Remote database not available
731 }
732 // Add field filters from shortcode
733 $filter_field_name = str_replace( '`', '', sanitize_text_field( wp_unslash( $_REQUEST['filter_field_name'] ) ) );
734 // input var okay.
735 $filter_field_value = sanitize_text_field( wp_unslash( $_REQUEST['filter_field_value'] ) );
736 // input var okay.
737 if ( '' !== $filter_field_name && '' !== $filter_field_value ) {
738 $filter_field_name_array = array_map( 'trim', explode( ',', $filter_field_name ) );
739 //phpcs:ignore - 8.1 proof
740 $filter_field_value_array = array_map( 'trim', explode( ',', $filter_field_value ) );
741 //phpcs:ignore - 8.1 proof
742 if ( count( $filter_field_name_array ) === count( $filter_field_value_array ) ) {
743 //phpcs:ignore - 8.1 proof
744 // Add filter to where clause
745 for ($i = 0; $i < count( $filter_field_name_array ); $i++) {
746 //phpcs:ignore - 8.1 proof
747 if ( '' === $where ) {
748 $where = $wpdadb->prepare( " where `{$filter_field_name_array[$i]}` like %s ", array($filter_field_value_array[$i]) );
749 } else {
750 $where .= $wpdadb->prepare( " and `{$filter_field_name_array[$i]}` like %s ", array($filter_field_value_array[$i]) );
751 }
752 $_filter['filter_field_name'] = $filter_field_name;
753 $_filter['filter_field_value'] = $filter_field_value;
754 }
755 }
756 }
757 // Get all column names from table (must be comma separated string)
758 $this->wpda_list_columns = WPDA_List_Columns_Cache::get_list_columns( $database, $table_name );
759 $table_columns = $this->wpda_list_columns->get_table_columns();
760 // Save column:data_type pairs for fast access
761 $column_array_ordered = array();
762 foreach ( $table_columns as $column ) {
763 $column_array_ordered[$column['column_name']] = $column['data_type'];
764 }
765 // Load table settings
766 $table_settings_db = WPDA_Table_Settings_Model::query( $table_name, $database );
767 if ( isset( $table_settings_db[0]['wpda_table_settings'] ) ) {
768 $table_settings = json_decode( (string) $table_settings_db[0]['wpda_table_settings'] );
769 } else {
770 $table_settings = array();
771 }
772 if ( '*' === $columns ) {
773 // Get all column names from table (must be comma separated string).
774 $column_array = array();
775 foreach ( $table_columns as $column ) {
776 $column_array[] = $column['column_name'];
777 }
778 $columns = implode( ',', $column_array );
779 } else {
780 // Check if columns exist (prevent sql injection).
781 $wpda_dictionary_checks = new WPDA_Dictionary_Exist($database, $table_name);
782 $column_array = explode( ',', (string) $columns );
783 //phpcs:ignore - 8.1 proof
784 $has_dynamic_hyperlinks = false;
785 foreach ( $column_array as $column ) {
786 if ( 'wpda_hyperlink_' !== substr( $column, 0, 15 ) ) {
787 if ( !$wpda_dictionary_checks->column_exists( $column ) ) {
788 // Column not found.
789 $this->create_empty_response( 'Invalid column name' );
790 wp_die();
791 }
792 } else {
793 $has_dynamic_hyperlinks = true;
794 }
795 }
796 if ( $has_dynamic_hyperlinks ) {
797 // Check for columns needed for substitution and missing in the query
798 $hyperlink_substitution_columns = array();
799 if ( isset( $table_settings->hyperlinks ) ) {
800 foreach ( $table_settings->hyperlinks as $hyperlink ) {
801 if ( isset( $hyperlink->hyperlink_html ) ) {
802 foreach ( $table_columns as $column ) {
803 if ( stripos( $hyperlink->hyperlink_html, "\$\${$column['column_name']}\$\$" ) !== false ) {
804 $hyperlink_substitution_columns[$column['column_name']] = true;
805 }
806 }
807 }
808 }
809 }
810 foreach ( $hyperlink_substitution_columns as $hyperlink_substitution_column => $val ) {
811 if ( !in_array( $hyperlink_substitution_column, $column_array ) ) {
812 //phpcs:ignore - 8.1 proof
813 $columns .= ",{$hyperlink_substitution_column}";
814 }
815 }
816 }
817 }
818 // Save column name without backticks for later use
819 $column_array_clean = $column_array;
820 // Set order by.
821 $orderby = '';
822 if ( isset( $_REQUEST['order'] ) && is_array( $_REQUEST['order'] ) ) {
823 // input var okay.
824 $orderby_columns = array();
825 $orderby_args = array();
826 // Sanitize argument array and write result to temporary sanitizes array for processing:
827 foreach ( $_REQUEST['order'] as $order_column ) {
828 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
829 if ( isset( $order_column['column'] ) ) {
830 $orderby_args[] = array(
831 'column' => sanitize_sql_orderby( wp_unslash( $order_column['column'] ) ),
832 'dir' => ( isset( $order_column['dir'] ) && 'desc' === $order_column['dir'] ? 'desc' : 'asc' ),
833 );
834 }
835 }
836 foreach ( $orderby_args as $order_column ) {
837 // input var okay.
838 $column_index = $order_column['column'];
839 $column_name = str_replace( '`', '', $column_array[$column_index] );
840 $column_dir = $order_column['dir'];
841 $orderby_columns[] = "`{$column_name}` {$column_dir}";
842 }
843 $orderby = implode( ',', $orderby_columns );
844 }
845 // Add search criteria.
846 if ( isset( $_REQUEST['search']['value'] ) ) {
847 $search_value = sanitize_text_field( wp_unslash( $_REQUEST['search']['value'] ) );
848 // input var okay.
849 } else {
850 $search_value = '';
851 }
852 $where_columns = WPDA::construct_where_clause(
853 $database,
854 $table_name,
855 $this->wpda_list_columns->get_table_columns(),
856 $search_value
857 );
858 if ( '' !== $where_columns ) {
859 if ( '' === $where ) {
860 $where = " where {$where_columns} ";
861 } else {
862 $where .= " and {$where_columns} ";
863 }
864 }
865 if ( '' !== $where ) {
866 $where = WPDA::substitute_environment_vars( $where );
867 }
868 if ( '' !== $search_value ) {
869 $_filter['filter_dyn'] = $search_value;
870 }
871 foreach ( $_REQUEST as $key => $value ) {
872 if ( 'wpda_search_' === substr( $key, 0, 12 ) ) {
873 $_filter['filter_args'][$key] = $value;
874 }
875 }
876 $geo_radius_col = '';
877 // Execute query.
878 $column_array = explode( ',', (string) $columns );
879 //phpcs:ignore - 8.1 proof
880 $column_array_orig = $column_array;
881 $images_array = array();
882 $imagesurl_array = array();
883 $attachments_array = array();
884 $hyperlinks_array = array();
885 $hyperlinks_array_col = array();
886 $audio_array = array();
887 $video_array = array();
888 if ( isset( $publication[0]['pub_format'] ) && '' !== $publication[0]['pub_format'] && null !== $publication[0]['pub_format'] ) {
889 try {
890 $pub_format = json_decode( (string) $publication[0]['pub_format'], true );
891 } catch ( \Exception $e ) {
892 $pub_format = null;
893 }
894 $column_images = array();
895 $column_attachments = array();
896 if ( isset( $pub_format['pub_format']['column_images'] ) ) {
897 $column_images = $pub_format['pub_format']['column_images'];
898 }
899 if ( isset( $pub_format['pub_format']['column_attachments'] ) ) {
900 $column_attachments = $pub_format['pub_format']['column_attachments'];
901 }
902 $i = 0;
903 foreach ( $column_array as $col ) {
904 if ( isset( $column_images[$col] ) ) {
905 array_push( $images_array, $i );
906 //phpcs:ignore - 8.1 proof
907 }
908 $i++;
909 }
910 $i = 0;
911 foreach ( $column_array as $col ) {
912 if ( isset( $column_attachments[$col] ) ) {
913 array_push( $attachments_array, $i );
914 //phpcs:ignore - 8.1 proof
915 }
916 $i++;
917 }
918 } else {
919 $pub_format = null;
920 }
921 // Check media columns defined on plugin level and add to arrays
922 $i = 0;
923 foreach ( $column_array as $col ) {
924 if ( 'Image' === WPDA_Media_Model::get_column_media( $table_name, $col, $database ) ) {
925 if ( !isset( $images_array[$i] ) ) {
926 array_push( $images_array, $i );
927 //phpcs:ignore - 8.1 proof
928 }
929 } elseif ( 'ImageURL' === WPDA_Media_Model::get_column_media( $table_name, $col, $database ) ) {
930 array_push( $imagesurl_array, $i );
931 //phpcs:ignore - 8.1 proof
932 } elseif ( 'Attachment' === WPDA_Media_Model::get_column_media( $table_name, $col, $database ) ) {
933 if ( !isset( $attachments_array[$i] ) ) {
934 array_push( $attachments_array, $i );
935 //phpcs:ignore - 8.1 proof
936 }
937 } elseif ( 'Hyperlink' === WPDA_Media_Model::get_column_media( $table_name, $col, $database ) ) {
938 if ( !isset( $hyperlinks_array[$i] ) ) {
939 array_push( $hyperlinks_array, $i );
940 //phpcs:ignore - 8.1 proof
941 array_push( $hyperlinks_array_col, $col );
942 //phpcs:ignore - 8.1 proof
943 }
944 } elseif ( 'Audio' === WPDA_Media_Model::get_column_media( $table_name, $col, $database ) ) {
945 array_push( $audio_array, $i );
946 //phpcs:ignore - 8.1 proof
947 } elseif ( 'Video' === WPDA_Media_Model::get_column_media( $table_name, $col, $database ) ) {
948 array_push( $video_array, $i );
949 //phpcs:ignore - 8.1 proof
950 }
951 $i++;
952 }
953 // Change dynamic hyperlinks
954 $update = array();
955 $i = 0;
956 $hyperlinks_column_index = array();
957 foreach ( $column_array as $col ) {
958 if ( 'wpda_hyperlink_' === substr( $col, 0, 15 ) ) {
959 $update[$col] = "'x' as {$col}";
960 $hyperlinks_column_index[$i] = substr( $col, 15 );
961 } else {
962 $update[$col] = '`' . str_replace( '`', '', $col ) . '`';
963 }
964 $i++;
965 }
966 $column_array = $update;
967 $columns_backticks = implode( ',', $column_array ) . $geo_radius_col;
968 $query = "select {$columns_backticks} from `{$wpdadb->dbname}`.`{$table_name}` {$where}";
969 if ( '' !== $orderby ) {
970 $query .= " order by {$orderby} ";
971 }
972 if ( -1 != $limit ) {
973 $query .= " limit {$limit} offset {$offset}";
974 }
975 $hyperlinks = array();
976 if ( count( $hyperlinks_column_index ) ) {
977 //phpcs:ignore - 8.1 proof
978 if ( isset( $table_settings->hyperlinks ) ) {
979 foreach ( $table_settings->hyperlinks as $hyperlink ) {
980 $hyperlink_label = ( isset( $hyperlink->hyperlink_label ) ? $hyperlink->hyperlink_label : '' );
981 $hyperlink_target = ( isset( $hyperlink->hyperlink_target ) ? $hyperlink->hyperlink_target : false );
982 $hyperlink_html = ( isset( $hyperlink->hyperlink_html ) ? $hyperlink->hyperlink_html : '' );
983 if ( $hyperlink_label !== '' && $hyperlink_html !== '' ) {
984 //phpcs:ignore - 8.1 proof
985 array_push( $hyperlinks, array(
986 'hyperlink_label' => $hyperlink_label,
987 'hyperlink_target' => $hyperlink_target,
988 'hyperlink_html' => $hyperlink_html,
989 ) );
990 }
991 }
992 }
993 }
994 $nl2br = ( isset( $_REQUEST['nl2br'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['nl2br'] ) ) : '' );
995 // input var okay.
996 if ( 'on' === $nl2br || 'yes' === $nl2br || 'true' === $nl2br ) {
997 $nl2br = 'on';
998 } else {
999 if ( '' !== $pub_id ) {
1000 if ( isset( $publication[0]['pub_table_options_nl2br'] ) ) {
1001 $nl2br = $publication[0]['pub_table_options_nl2br'];
1002 }
1003 }
1004 }
1005 $wpdadb->suppress_errors( true );
1006 $rows = $wpdadb->get_results( $query, 'ARRAY_N' );
1007 // phpcs:ignore Standard.Category.SniffName.ErrorCode
1008 if ( '' !== $wpdadb->last_error ) {
1009 $this->create_empty_response( $wpdadb->last_error, $query );
1010 wp_die();
1011 }
1012 $rows_final = array();
1013 foreach ( $rows as $row ) {
1014 $row_orig = $row;
1015 if ( 'on' === $nl2br && null !== $nl2br ) {
1016 // Replace NL with BR tags
1017 for ($nl = 0; $nl < count( $row ); $nl++) {
1018 //phpcs:ignore - 8.1 proof
1019 $row[$nl] = nl2br( (string) $row[$nl] );
1020 }
1021 }
1022 foreach ( $hyperlinks_column_index as $key => $value ) {
1023 if ( isset( $hyperlinks[$value] ) ) {
1024 $hyperlink_html = ( isset( $hyperlinks[$value]['hyperlink_html'] ) ? $hyperlinks[$value]['hyperlink_html'] : '' );
1025 if ( '' !== $hyperlink_html ) {
1026 $i = 0;
1027 foreach ( $column_array as $column ) {
1028 $column_name = str_replace( '`', '', $column );
1029 $hyperlink_html = str_replace( "\$\${$column_name}\$\$", $row[$i], $hyperlink_html );
1030 $i++;
1031 }
1032 }
1033 $macro = new WPDA_Macro($hyperlink_html);
1034 $hyperlink_html = $macro->exe_macro();
1035 if ( '' !== $hyperlink_html ) {
1036 if ( false !== strpos( ltrim( $hyperlink_html ), '&lt;' ) ) {
1037 $row[$key] = html_entity_decode( $hyperlink_html );
1038 } else {
1039 $hyperlink_label = ( isset( $hyperlinks[$value]['hyperlink_label'] ) ? $hyperlinks[$value]['hyperlink_label'] : '' );
1040 $hyperlink_target = ( isset( $hyperlinks[$value]['hyperlink_target'] ) ? $hyperlinks[$value]['hyperlink_target'] : false );
1041 $target = ( true === $hyperlink_target ? "target='_blank'" : '' );
1042 $row[$key] = "<a href='" . str_replace( ' ', '+', $hyperlink_html ) . "' {$target}>{$hyperlink_label}</a>";
1043 }
1044 } else {
1045 $row[$key] = '';
1046 }
1047 } else {
1048 $row[$key] = 'ERROR';
1049 }
1050 }
1051 for ($i = 0; $i < count( $imagesurl_array ); $i++) {
1052 //phpcs:ignore - 8.1 proof
1053 $row[$imagesurl_array[$i]] = '<img src="' . $row[$imagesurl_array[$i]] . '" width="100%">';
1054 }
1055 for ($i = 0; $i < count( $images_array ); $i++) {
1056 //phpcs:ignore - 8.1 proof
1057 $image_ids = explode( ',', (string) $row[$images_array[$i]] );
1058 //phpcs:ignore - 8.1 proof
1059 $image_src = '';
1060 foreach ( $image_ids as $image_id ) {
1061 $url = wp_get_attachment_url( esc_attr( $image_id ) );
1062 if ( false !== $url ) {
1063 $image_src .= ( '' !== $image_src ? '<br/>' : '' );
1064 $image_src .= '<img src="' . $url . '" width="100%">';
1065 }
1066 }
1067 $row[$images_array[$i]] = $image_src;
1068 }
1069 for ($i = 0; $i < count( $attachments_array ); $i++) {
1070 //phpcs:ignore - 8.1 proof
1071 $media_ids = explode( ',', (string) $row[$attachments_array[$i]] );
1072 //phpcs:ignore - 8.1 proof
1073 $media_links = '';
1074 foreach ( $media_ids as $media_id ) {
1075 $url = wp_get_attachment_url( esc_attr( $media_id ) );
1076 if ( false !== $url ) {
1077 $mime_type = get_post_mime_type( $media_id );
1078 if ( false !== $mime_type ) {
1079 $title = get_the_title( esc_attr( $media_id ) );
1080 $media_links .= WPDA_List_Table::column_media_attachment( $url, $title, $mime_type );
1081 }
1082 }
1083 }
1084 $row[$attachments_array[$i]] = $media_links;
1085 }
1086 if ( isset( $hyperlinks_array ) ) {
1087 $hyperlink_definition = ( isset( $table_settings->table_settings->hyperlink_definition ) && 'text' === $table_settings->table_settings->hyperlink_definition ? 'text' : 'json' );
1088 for ($i = 0; $i < count( $hyperlinks_array ); $i++) {
1089 //phpcs:ignore - 8.1 proof
1090 if ( 'json' === $hyperlink_definition ) {
1091 $hyperlink = json_decode( (string) $row[$hyperlinks_array[$i]], true );
1092 if ( is_array( $hyperlink ) && isset( $hyperlink['label'] ) && isset( $hyperlink['url'] ) && isset( $hyperlink['target'] ) ) {
1093 if ( '' === $hyperlink['url'] ) {
1094 $row[$hyperlinks_array[$i]] = $hyperlink['label'];
1095 } else {
1096 $row[$hyperlinks_array[$i]] = "<a href='{$hyperlink['url']}' target='{$hyperlink['target']}'>{$hyperlink['label']}</a>";
1097 }
1098 } else {
1099 $row[$hyperlinks_array[$i]] = '';
1100 }
1101 } else {
1102 if ( null !== $row[$hyperlinks_array[$i]] && '' !== $row[$hyperlinks_array[$i]] ) {
1103 $hyperlink_label = $this->wpda_list_columns->get_column_label( $hyperlinks_array_col[$i] );
1104 $row[$hyperlinks_array[$i]] = "<a href='{$row[$hyperlinks_array[$i]]}' target='_blank'>{$hyperlink_label}</a>";
1105 } else {
1106 $row[$hyperlinks_array[$i]] = '';
1107 }
1108 }
1109 }
1110 }
1111 for ($i = 0; $i < count( $audio_array ); $i++) {
1112 //phpcs:ignore - 8.1 proof
1113 $media_ids = explode( ',', (string) $row[$audio_array[$i]] );
1114 //phpcs:ignore - 8.1 proof
1115 $media_links = '';
1116 foreach ( $media_ids as $media_id ) {
1117 if ( 'audio' === substr( get_post_mime_type( $media_id ), 0, 5 ) ) {
1118 $url = wp_get_attachment_url( esc_attr( $media_id ) );
1119 if ( false !== $url ) {
1120 $title = get_the_title( esc_attr( $media_id ) );
1121 if ( false !== $url ) {
1122 $media_links .= '<div class="wpda_tooltip" title="' . $title . '">' . do_shortcode( '[audio src="' . $url . '"]' ) . '</div>';
1123 }
1124 }
1125 }
1126 }
1127 $row[$audio_array[$i]] = $media_links;
1128 }
1129 for ($i = 0; $i < count( $video_array ); $i++) {
1130 //phpcs:ignore - 8.1 proof
1131 $media_ids = explode( ',', (string) $row[$video_array[$i]] );
1132 //phpcs:ignore - 8.1 proof
1133 $media_links = '';
1134 foreach ( $media_ids as $media_id ) {
1135 if ( 'video' === substr( get_post_mime_type( $media_id ), 0, 5 ) ) {
1136 $url = wp_get_attachment_url( esc_attr( $media_id ) );
1137 if ( false !== $url ) {
1138 if ( false !== $url ) {
1139 $media_links .= do_shortcode( '[video src="' . $url . '"]' );
1140 }
1141 }
1142 }
1143 }
1144 $row[$video_array[$i]] = $media_links;
1145 }
1146 // Format date and time columns
1147 for ($i = 0; $i < count( $row ); $i++) {
1148 //phpcs:ignore - 8.1 proof
1149 if ( '' !== $row[$i] && null !== $row[$i] ) {
1150 if ( isset( $column_array_clean[$i] ) ) {
1151 if ( isset( $column_array_ordered[$column_array_clean[$i]] ) ) {
1152 switch ( $column_array_ordered[$column_array_clean[$i]] ) {
1153 case 'date':
1154 $row[$i] = date_i18n( get_option( 'date_format' ), strtotime( $row[$i] ) );
1155 break;
1156 case 'time':
1157 $row[$i] = date_i18n( get_option( 'time_format' ), strtotime( $row[$i] ) );
1158 break;
1159 case 'datetime':
1160 case 'timestamp':
1161 $row[$i] = date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), strtotime( $row[$i] ) );
1162 }
1163 }
1164 }
1165 }
1166 }
1167 // Remove script tags if available
1168 for ($i = 0; $i < count( $row ); $i++) {
1169 //phpcs:ignore - 8.1 proof
1170 $row[$i] = str_replace( array('<script>', '</script>'), array('&lt;script&gt;', '&lt;/script&gt;'), (string) $row[$i] );
1171 }
1172 array_push( $rows_final, $row );
1173 //phpcs:ignore - 8.1 proof
1174 }
1175 if ( $this->serverSide ) {
1176 if ( isset( $_REQUEST['records_total'] ) && is_numeric( $_REQUEST['records_total'] ) && (!isset( $json->wpda_count_on_each_request ) || false === $json->wpda_count_on_each_request) ) {
1177 // Prevent row count on each request
1178 $rows_estimate = sanitize_text_field( wp_unslash( $_REQUEST['records_total'] ) );
1179 // input var okay.
1180 $do_real_count = false;
1181 } else {
1182 $row_count_estimate = WPDA::get_row_count_estimate( $database, $table_name, $table_settings );
1183 $rows_estimate = $row_count_estimate['row_count'];
1184 $do_real_count = $row_count_estimate['do_real_count'];
1185 }
1186 } else {
1187 $rows_estimate = count( $rows_final );
1188 //phpcs:ignore - 8.1 proof
1189 $do_real_count = false;
1190 }
1191 if ( 'more' === $publication_mode ) {
1192 // Use estimate row count
1193 $count_table = $rows_estimate;
1194 $count_table_filtered = $rows_estimate;
1195 } else {
1196 if ( !$do_real_count ) {
1197 // Use estimate row count
1198 $count_table = $rows_estimate;
1199 } else {
1200 // Count rows in table = real row count
1201 $query2 = "select count(*) from `{$wpdadb->dbname}`.`{$table_name}`";
1202 $count_rows = $wpdadb->get_results( $query2, 'ARRAY_N' );
1203 // phpcs:ignore Standard.Category.SniffName.ErrorCode
1204 $count_table = $count_rows[0][0];
1205 // Number of rows in table.
1206 }
1207 if ( isset( $_REQUEST['wpda_use_estimates_only'] ) && 'true' === $_REQUEST['wpda_use_estimates_only'] ) {
1208 // Prevent row count, only estimates required
1209 $count_table_filtered = $count_table;
1210 } else {
1211 if ( '' !== $where ) {
1212 if ( isset( $_REQUEST['records_filtered'] ) && is_numeric( $_REQUEST['records_filtered'] ) && (!isset( $json->wpda_count_on_each_request ) || false === $json->wpda_count_on_each_request) ) {
1213 $count_table_filtered = sanitize_text_field( wp_unslash( $_REQUEST['records_filtered'] ) );
1214 // input var okay.
1215 } else {
1216 // Count rows in selection (only necessary if a search criteria was entered).
1217 $query3 = "select count(*) from `{$wpdadb->dbname}`.`{$table_name}` {$where}";
1218 $count_rows_filtered = $wpdadb->get_results( $query3, 'ARRAY_N' );
1219 // phpcs:ignore Standard.Category.SniffName.ErrorCode
1220 $count_table_filtered = $count_rows_filtered[0][0];
1221 // Number of rows in table.
1222 }
1223 } else {
1224 // No search criteria entered: # filtered rows = # table rows.
1225 $count_table_filtered = $count_table;
1226 }
1227 }
1228 }
1229 // Convert query result to jQuery DataTables object.
1230 $obj = (object) null;
1231 $obj->draw = ( isset( $_REQUEST['draw'] ) ? intval( $_REQUEST['draw'] ) : 0 );
1232 $obj->recordsTotal = intval( $count_table );
1233 $obj->recordsFiltered = intval( $count_table_filtered );
1234 $obj->data = $rows_final;
1235 $obj->error = $wpdadb->last_error;
1236 if ( 'on' === WPDA::get_option( WPDA::OPTION_PLUGIN_DEBUG ) ) {
1237 $obj->debug = array(
1238 'columns' => $columns,
1239 'columns_backticks' => $columns_backticks,
1240 'query' => $query,
1241 'where' => $where,
1242 'orderby' => $orderby,
1243 'filter' => $_filter,
1244 'advanced_settings' => $json,
1245 'column_labels' => $this->wpda_list_columns->get_table_column_headers(),
1246 'labels' => array_flip( $this->get_labels( json_encode( $pub_format ) ) ),
1247 'serverSide' => $this->serverSide,
1248 );
1249 }
1250 // Send header
1251 if ( !WPDA::wpda_verify_sonce( $wpnonce, 'wpda-publication-' . $table_name . '-' ) ) {
1252 WPDA::sent_header( 'application/json' );
1253 } else {
1254 // Enable CORS for embedded publications
1255 WPDA::sent_header( 'application/json', '*' );
1256 }
1257 // Convert object to json. jQuery DataTables needs json format.
1258 echo json_encode( $obj );
1259 wp_die();
1260 }
1261
1262 private function get_data_custom_query(
1263 $publication,
1264 $json,
1265 $has_sp,
1266 $sp_columns,
1267 $sql_query,
1268 $is_cpt,
1269 $offset,
1270 $limit
1271 ) {
1272 }
1273
1274 private function get_orderby_from_request() {
1275 $orderby = '';
1276 // Init order by.
1277 if ( isset( $_REQUEST['order'] ) && is_array( $_REQUEST['order'] ) ) {
1278 // input var okay.
1279 foreach ( $_REQUEST['order'] as $order_column ) {
1280 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
1281 if ( isset( $order_column['column'], $order_column['dir'] ) && is_numeric( $order_column['column'] ) && ('asc' === $order_column['dir'] || 'desc' === $order_column['dir']) ) {
1282 $preprend = ( '' === $orderby ? ' order by ' : ',' );
1283 $orderby .= $preprend . (intval( $order_column['column'] ) + 1) . ' ' . $order_column['dir'];
1284 }
1285 }
1286 }
1287 return $orderby;
1288 }
1289
1290 private function sp(
1291 $wpdadb,
1292 $table_name,
1293 $columns,
1294 $panes,
1295 $where,
1296 $bt = '`'
1297 ) {
1298 $sp = array();
1299 return $sp;
1300 }
1301
1302 public function qb_group( $data ) {
1303 }
1304
1305 public function qb_criteria( $crit ) {
1306 }
1307
1308 private function qb( $labels ) {
1309 }
1310
1311 private function create_empty_response( $error = '', $debug = '' ) {
1312 $obj = (object) null;
1313 $obj->draw = 0;
1314 $obj->recordsTotal = 0;
1315 $obj->recordsFiltered = 0;
1316 $obj->data = array();
1317 $obj->error = $error;
1318 $obj->debug = $debug;
1319 echo json_encode( $obj );
1320 }
1321
1322 }
1323