PluginProbe
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards / 5.5.80
WP Data Access – App Builder for Tables, Forms, Charts, Maps & Dashboards v5.5.80
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.80, at WPDataAccess/Data_Tables/WPDA_Data_Tables.php

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