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

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