wpDataTables Lite - Version 2.1.42

Version Description

  • Feature: Caching tables data for non-server-side tables (Excel, CSV, XML, JSON, and PHP array).
  • Feature: Auto update table cache for non-server-side tables (Excel, CSV, XML, JSON, and PHP array). Other small bug fixes and stability improvements.
Download this release

Release Info

Developer wpDataTables
Plugin Icon 128x128 wpDataTables Lite
Version 2.1.42
Comparing to
See all releases

Code changes from version 2.1.41 to 2.1.42

assets/js/wpdatatables/admin/plugin-settings/main.js CHANGED
@@ -25,6 +25,7 @@
25
  wpdatatable_plugin_config.setDateFormat( $(this).val() );
26
  });
27
 
 
28
  /**
29
  * Number of tables on admin page - "Tables per admin page"
30
  */
@@ -208,6 +209,13 @@
208
  wpdatatable_plugin_config.setCustomCss( $(this).val() );
209
  });
210
 
 
 
 
 
 
 
 
211
  /**
212
  * Toggle minified JS - "Use minified wpDataTables Javascript"
213
  */
@@ -233,7 +241,7 @@
233
  wpdatatable_plugin_config.setDecimalPlaces ( wdt_current_config.wdtDecimalPlaces );
234
  wpdatatable_plugin_config.setTabletWidth(wdt_current_config.wdtTabletWidth);
235
  wpdatatable_plugin_config.setMobileWidth(wdt_current_config.wdtMobileWidth);
236
-
237
 
238
  wpdatatable_plugin_config.setPurchaseCode ( wdt_current_config.wdtPurchaseCode );
239
  wpdatatable_plugin_config.setGettingStartedPageStatus(wdt_current_config.wdtGettingStartedPageStatus== 1 ? 1 : 0);
@@ -304,6 +312,14 @@
304
  savePluginSettings();
305
  });
306
 
 
 
 
 
 
 
 
 
307
  /**
308
  * Add ace editor on Global custom CSS
309
  */
@@ -343,5 +359,35 @@
343
  }
344
  })
345
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
346
  });
347
  })(jQuery);
25
  wpdatatable_plugin_config.setDateFormat( $(this).val() );
26
  });
27
 
28
+
29
  /**
30
  * Number of tables on admin page - "Tables per admin page"
31
  */
209
  wpdatatable_plugin_config.setCustomCss( $(this).val() );
210
  });
211
 
212
+ /**
213
+ * Turn on auto update option - "Auto update cache option"
214
+ */
215
+ $('#wdt-auto-update-option').change(function (e) {
216
+ wpdatatable_plugin_config.setAutoUpdateOption($(this).is(':checked') ? 1 : 0);
217
+ });
218
+
219
  /**
220
  * Toggle minified JS - "Use minified wpDataTables Javascript"
221
  */
241
  wpdatatable_plugin_config.setDecimalPlaces ( wdt_current_config.wdtDecimalPlaces );
242
  wpdatatable_plugin_config.setTabletWidth(wdt_current_config.wdtTabletWidth);
243
  wpdatatable_plugin_config.setMobileWidth(wdt_current_config.wdtMobileWidth);
244
+ wpdatatable_plugin_config.setAutoUpdateOption(wdt_current_config.wdtAutoUpdateOption == 1 ? 1 : 0);
245
 
246
  wpdatatable_plugin_config.setPurchaseCode ( wdt_current_config.wdtPurchaseCode );
247
  wpdatatable_plugin_config.setGettingStartedPageStatus(wdt_current_config.wdtGettingStartedPageStatus== 1 ? 1 : 0);
312
  savePluginSettings();
313
  });
314
 
315
+ /**
316
+ * Delete Google settings
317
+ */
318
+ $(document).on('click', '#wdt-delete-log-errors-cache', function (e) {
319
+ $('.wdt-preload-layer').animateFadeIn();
320
+ deleteLogErrorsCache();
321
+ });
322
+
323
  /**
324
  * Add ace editor on Global custom CSS
325
  */
359
  }
360
  })
361
  }
362
+
363
+ function deleteLogErrorsCache() {
364
+ $.ajax({
365
+ url: ajaxurl,
366
+ method: 'POST',
367
+ data: {
368
+ action: 'wpdatatables_delete_log_errors_cache',
369
+ wdtNonce: $('#wdtNonce').val()
370
+ },
371
+ success: function (result) {
372
+ if (result != '') {
373
+ $('#wdt-error-modal .modal-body').html(result);
374
+ $('#wdt-error-modal').modal('show');
375
+ $('.wdt-preload-layer').animateFadeOut();
376
+ } else {
377
+ $('.wdt-preload-layer').animateFadeOut();
378
+ wdtNotify(
379
+ wpdatatables_edit_strings.success,
380
+ 'Deleted errors log from cache table!',
381
+ 'success'
382
+ );
383
+ }
384
+ },
385
+ error: function (){
386
+ $('#wdt-error-modal .modal-body').html('There was an error while trying to delete errors log in cache table!');
387
+ $('#wdt-error-modal').modal('show');
388
+ $('.wdt-preload-layer').animateFadeOut();
389
+ }
390
+ });
391
+ }
392
  });
393
  })(jQuery);
assets/js/wpdatatables/admin/plugin-settings/plugin_config_object.js CHANGED
@@ -84,6 +84,19 @@ var wpdatatable_plugin_config = {
84
  jQuery('#wdt-date-format').selectpicker( 'val', dateFormat );
85
  }
86
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
87
 
88
  setTablesAdmin: function ( tablesAdmin ) {
89
  if( wdt_current_config.wdtTablesPerPage != tablesAdmin ){
84
  jQuery('#wdt-date-format').selectpicker( 'val', dateFormat );
85
  }
86
  },
87
+ setAutoUpdateOption: function ( option ) {
88
+ if( wdt_current_config.wdtAutoUpdateOption != option ){
89
+ wdt_current_config.wdtAutoUpdateOption = option;
90
+ }
91
+ if (option){
92
+ jQuery('.auto-update-cache-instructions').removeClass('hidden');
93
+ } else {
94
+ jQuery('.auto-update-cache-instructions').addClass('hidden');
95
+ }
96
+ if( jQuery('#wdt-auto-update-option').val() != option ){
97
+ jQuery('#wdt-auto-update-option').prop( 'checked', option );
98
+ }
99
+ },
100
 
101
  setTablesAdmin: function ( tablesAdmin ) {
102
  if( wdt_current_config.wdtTablesPerPage != tablesAdmin ){
assets/js/wpdatatables/admin/table-settings/main.js CHANGED
@@ -234,6 +234,20 @@
234
  wpdatatable_config.setGlobalSearch( $(this).is(':checked') ? 1 : 0 );
235
  });
236
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
237
  /**
238
  * Toggle Filters in form
239
  */
234
  wpdatatable_config.setGlobalSearch( $(this).is(':checked') ? 1 : 0 );
235
  });
236
 
237
+ /**
238
+ * Toggle cache source data
239
+ */
240
+ $('#wpdt-cache-source-data').change(function (e) {
241
+ wpdatatable_config.setCacheSourceData($(this).is(':checked') ? 1 : 0);
242
+ });
243
+
244
+ /**
245
+ * Toggle auto update cache
246
+ */
247
+ $('#wpdt-auto-update-cache').change(function (e) {
248
+ wpdatatable_config.setAutoUpdateCache($(this).is(':checked') ? 1 : 0);
249
+ });
250
+
251
  /**
252
  * Toggle Filters in form
253
  */
assets/js/wpdatatables/admin/table-settings/table_config_object.js CHANGED
@@ -38,6 +38,8 @@ var wpdatatable_config = {
38
  verticalScrollHeight: 600,
39
  filtering: 1,
40
  global_search: 1,
 
 
41
  editable: 0,
42
  popover_tools: 0,
43
  mysql_table_name: '',
@@ -536,6 +538,37 @@ var wpdatatable_config = {
536
  wpdatatable_config.sorting = sorting;
537
  jQuery('#wdt-global-sorting').prop('checked', sorting);
538
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
  /**
540
  * Enable or disable Global Search block
541
  * @param globalSearch 1 or 0
@@ -884,7 +917,8 @@ var wpdatatable_config = {
884
  wpdatatable_config.addColumn(new WDTColumn(tableJSON.columns[i]));
885
  }
886
  wpdatatable_config.fillColumnsBlock();
887
-
 
888
 
889
  wpdatatable_config.setLimitLayout(parseInt(tableJSON.fixed_layout));
890
  wpdatatable_config.setGlobalSearch(parseInt(tableJSON.global_search));
38
  verticalScrollHeight: 600,
39
  filtering: 1,
40
  global_search: 1,
41
+ cache_source_data: 0,
42
+ auto_update_cache: 0,
43
  editable: 0,
44
  popover_tools: 0,
45
  mysql_table_name: '',
538
  wpdatatable_config.sorting = sorting;
539
  jQuery('#wdt-global-sorting').prop('checked', sorting);
540
  },
541
+ /**
542
+ * Enable or disable cache source data
543
+ * @param cacheSourceData 1 or 0
544
+ */
545
+ setCacheSourceData: function( cacheSourceData ){
546
+ wpdatatable_config.cache_source_data = cacheSourceData;
547
+ let allowedTableTypes = ['csv', 'xls', 'xml', 'json','serialized'];
548
+ if (allowedTableTypes.includes(wpdatatable_config.table_type)){
549
+ jQuery('.wdt-table-settings .cache-settings-block').removeClass('hidden');
550
+ jQuery('.wdt-table-settings .auto-update-cache-block').removeClass('hidden');
551
+ } else {
552
+ jQuery('.wdt-table-settings .cache-settings-block').addClass('hidden');
553
+ jQuery('.wdt-table-settings .auto-update-cache-block').addClass('hidden');
554
+ }
555
+ if (cacheSourceData == 0){
556
+ wpdatatable_config.auto_update_cache = 0
557
+ jQuery('#wpdt-auto-update-cache').prop( 'checked', 0 );
558
+ jQuery('.wdt-table-settings .auto-update-cache-block').addClass('hidden');
559
+ } else {
560
+ jQuery('.wdt-table-settings .auto-update-cache-block').removeClass('hidden');
561
+ }
562
+ jQuery('#wpdt-cache-source-data').prop( 'checked', cacheSourceData );
563
+ },
564
+ /**
565
+ * Enable or disable auto update data in cache
566
+ * @param autoUpdateCache 1 or 0
567
+ */
568
+ setAutoUpdateCache: function( autoUpdateCache ){
569
+ wpdatatable_config.auto_update_cache = autoUpdateCache;
570
+ jQuery('#wpdt-auto-update-cache').prop( 'checked', autoUpdateCache );
571
+ },
572
  /**
573
  * Enable or disable Global Search block
574
  * @param globalSearch 1 or 0
917
  wpdatatable_config.addColumn(new WDTColumn(tableJSON.columns[i]));
918
  }
919
  wpdatatable_config.fillColumnsBlock();
920
+ wpdatatable_config.setCacheSourceData( parseInt( tableJSON.cache_source_data ) );
921
+ wpdatatable_config.setAutoUpdateCache( parseInt( tableJSON.auto_update_cache ) );
922
 
923
  wpdatatable_config.setLimitLayout(parseInt(tableJSON.fixed_layout));
924
  wpdatatable_config.setGlobalSearch(parseInt(tableJSON.global_search));
config/config.inc.php CHANGED
@@ -9,7 +9,7 @@ defined('ABSPATH') or die("Cannot access pages directly.");
9
 
10
  // Current version
11
 
12
- define('WDT_CURRENT_VERSION', '2.1.41');
13
 
14
  // Number of active plugin installs for wpDataTables
15
  define('WDT_NUMBER_OF_ACTIVE_INSTALLS', '66,000+');
9
 
10
  // Current version
11
 
12
+ define('WDT_CURRENT_VERSION', '2.1.42');
13
 
14
  // Number of active plugin installs for wpDataTables
15
  define('WDT_NUMBER_OF_ACTIVE_INSTALLS', '66,000+');
controllers/wdt_admin_ajax_actions.php CHANGED
@@ -113,6 +113,8 @@ function wdtDuplicateTable() {
113
  'filtering' => $tableData->filtering,
114
  'filtering_form' => $tableData->filtering_form,
115
  'sorting' => $tableData->sorting,
 
 
116
  'tools' => $tableData->tools,
117
  'server_side' => $tableData->server_side,
118
  'editable' => $tableData->editable,
@@ -407,7 +409,29 @@ function wdtGetColumnsDataByTableId() {
407
 
408
  add_action('wp_ajax_wpdatatables_get_columns_data_by_table_id', 'wdtGetColumnsDataByTableId');
409
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
410
 
 
411
 
412
  /**
413
  * List all tables in JSON
113
  'filtering' => $tableData->filtering,
114
  'filtering_form' => $tableData->filtering_form,
115
  'sorting' => $tableData->sorting,
116
+ 'cache_source_data' => $tableData->cache_source_data,
117
+ 'auto_update_cache' => $tableData->auto_update_cache,
118
  'tools' => $tableData->tools,
119
  'server_side' => $tableData->server_side,
120
  'editable' => $tableData->editable,
409
 
410
  add_action('wp_ajax_wpdatatables_get_columns_data_by_table_id', 'wdtGetColumnsDataByTableId');
411
 
412
+ /**
413
+ * Delete log_errors in cache table
414
+ */
415
+ function wdtDeleteLogErrorsCache()
416
+ {
417
+ global $wpdb;
418
+
419
+ if (!current_user_can('manage_options') || !wp_verify_nonce($_POST['wdtNonce'], 'wdtSettingsNonce')) {
420
+ exit();
421
+ }
422
+ $result = '';
423
+
424
+ $wpdb->query("UPDATE " . $wpdb->prefix . "wpdatatables_cache SET log_errors = ''");
425
+
426
+ if ($wpdb->last_error != '') {
427
+ $result = 'Database error: ' . $wpdb->last_error;
428
+ }
429
+
430
+ echo $result;
431
+ exit();
432
+ }
433
 
434
+ add_action('wp_ajax_wpdatatables_delete_log_errors_cache', 'wdtDeleteLogErrorsCache');
435
 
436
  /**
437
  * List all tables in JSON
controllers/wdt_functions.php CHANGED
@@ -41,6 +41,8 @@ function wdtActivationCreateTables() {
41
  fixed_columns tinyint(1) NOT NULL default '-1',
42
  fixed_layout tinyint(1) NOT NULL default '0',
43
  responsive tinyint(1) NOT NULL default '0',
 
 
44
  scrollable tinyint(1) NOT NULL default '0',
45
  word_wrap tinyint(1) NOT NULL default '0',
46
  hide_before_load tinyint(1) NOT NULL default '0',
@@ -100,11 +102,24 @@ function wdtActivationCreateTables() {
100
  data TEXT NOT NULL default '',
101
  UNIQUE KEY id (id)
102
  ) DEFAULT CHARSET=utf8 COLLATE utf8_general_ci";
 
 
 
 
 
 
 
 
 
 
 
 
103
  require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
104
  dbDelta($tablesSql);
105
  dbDelta($columnsSql);
106
  dbDelta($chartsSql);
107
  dbDelta($rowsSql);
 
108
  if (!get_option('wdtUseSeparateCon')) {
109
  update_option('wdtUseSeparateCon', false);
110
  }
@@ -165,6 +180,12 @@ function wdtActivationCreateTables() {
165
  if (!get_option('wdtDateFormat')) {
166
  update_option('wdtDateFormat', 'd/m/Y');
167
  }
 
 
 
 
 
 
168
  if (get_option('wdtParseShortcodes') === false) {
169
  update_option('wdtParseShortcodes', false);
170
  }
@@ -371,6 +392,8 @@ function wdtUninstallDelete() {
371
  delete_option('wdtCSVDelimiter');
372
  delete_option('wdtSortingOrderBrowseTables');
373
  delete_option('wdtDateFormat');
 
 
374
  delete_option('wdtCustomJs');
375
  delete_option('wdtCustomCss');
376
  delete_option('wdtBaseSkin');
@@ -391,6 +414,7 @@ function wdtUninstallDelete() {
391
  $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}wpdatatables_columns");
392
  $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}wpdatacharts");
393
  $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}wpdatatables_rows");
 
394
  }
395
  }
396
 
41
  fixed_columns tinyint(1) NOT NULL default '-1',
42
  fixed_layout tinyint(1) NOT NULL default '0',
43
  responsive tinyint(1) NOT NULL default '0',
44
+ cache_source_data tinyint(1) NOT NULL default '0',
45
+ auto_update_cache tinyint(1) NOT NULL default '0',
46
  scrollable tinyint(1) NOT NULL default '0',
47
  word_wrap tinyint(1) NOT NULL default '0',
48
  hide_before_load tinyint(1) NOT NULL default '0',
102
  data TEXT NOT NULL default '',
103
  UNIQUE KEY id (id)
104
  ) DEFAULT CHARSET=utf8 COLLATE utf8_general_ci";
105
+ $cacheTableName = $wpdb->prefix . 'wpdatatables_cache';
106
+ $cacheSql = "CREATE TABLE {$cacheTableName} (
107
+ id bigint(20) NOT NULL AUTO_INCREMENT,
108
+ table_id bigint(20) NOT NULL,
109
+ table_type varchar(55) NOT NULL default '',
110
+ table_content text NOT NULL default '',
111
+ auto_update tinyint(1) NOT NULL default 0,
112
+ updated_time TIMESTAMP NOT NULL default CURRENT_TIMESTAMP,
113
+ data LONGTEXT NOT NULL default '',
114
+ log_errors text NOT NULL default '',
115
+ UNIQUE KEY id (id)
116
+ ) DEFAULT CHARSET=utf8 COLLATE utf8_general_ci";
117
  require_once(ABSPATH . 'wp-admin/includes/upgrade.php');
118
  dbDelta($tablesSql);
119
  dbDelta($columnsSql);
120
  dbDelta($chartsSql);
121
  dbDelta($rowsSql);
122
+ dbDelta($cacheSql);
123
  if (!get_option('wdtUseSeparateCon')) {
124
  update_option('wdtUseSeparateCon', false);
125
  }
180
  if (!get_option('wdtDateFormat')) {
181
  update_option('wdtDateFormat', 'd/m/Y');
182
  }
183
+ if (get_option('wdtAutoUpdateOption') === false) {
184
+ update_option('wdtAutoUpdateOption', 0);
185
+ }
186
+ if (!get_option('wdtAutoUpdateHash')) {
187
+ update_option('wdtAutoUpdateHash', bin2hex(openssl_random_pseudo_bytes(22)));
188
+ }
189
  if (get_option('wdtParseShortcodes') === false) {
190
  update_option('wdtParseShortcodes', false);
191
  }
392
  delete_option('wdtCSVDelimiter');
393
  delete_option('wdtSortingOrderBrowseTables');
394
  delete_option('wdtDateFormat');
395
+ delete_option('wdtAutoUpdateOption');
396
+ delete_option('wdtAutoUpdateHash');
397
  delete_option('wdtCustomJs');
398
  delete_option('wdtCustomCss');
399
  delete_option('wdtBaseSkin');
414
  $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}wpdatatables_columns");
415
  $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}wpdatacharts");
416
  $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}wpdatatables_rows");
417
+ $wpdb->query("DROP TABLE IF EXISTS {$wpdb->prefix}wpdatatables_cache");
418
  }
419
  }
420
 
readme.txt CHANGED
@@ -2,11 +2,11 @@
2
  Contributors: wpDataTables
3
  Author URI: https://tms-outsource.com
4
  Plugin URI: https://wpdatatables.com/
5
- Tags: table, table builder, data tables, tables, charts, datatables, csv, excel, json, simple table, tables from csv, tables from excel, dynamic tables, merge cells, pricing tables, responsive tables, responsive charts, grouping data, pricing table, row grouping, chart, pie charts, mysql tables, table plugin, wp table, wordpress table plugin, wordpress tables, editing charts, google charts, chartjs, xml, php array, line chart, donut, bar chart, histogram, area chart, bubble chart, gauge chart, scatter chart, candlestick, waterfall, polar, radar
6
  Requires at least: 4.0
7
  Tested up to: 6.0.2
8
  Requires PHP: 5.6
9
- Stable tag: 2.1.41
10
  License: GPLv2 or later
11
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
12
 
@@ -64,6 +64,15 @@ XML - *(Extensible Markup Language)* is a universal standard for presenting data
64
  JSON *(JavaScript Object Notation)* is a popular interlingual data exchange format. Many server applications provide public data in JSON format. JSON is based on the syntax of Javascript objects. Since most web applications use client-side JavaScript, JSON has become the 'de facto' standard for packing data on the web and wpDataTables also supports the JSON format as an input data source.
65
  Learn [How to create WordPress tables from JSON](https://wpdatatables.com/documentation/creating-wpdatatables/creating-wpdatatables-from-json-input/) in our documentation.
66
 
 
 
 
 
 
 
 
 
 
67
  == Develop dynamic WordPress table from Serialized PHP array ==
68
 
69
  For developer users, or users who are at least somewhat familiar with PHP language, that previous input data sources (Excel, CSV, XML of JSON) are not flexible enough for dynamic data presentation. We didn't want to limit your freedom in wpDataTables, so we implemented serialized PHP arrays as one of data sources, so you are able to create dynamic datatables. You can prepare data from some private or public API, or use WP Query to get data from your posts, get data by depending on some variables in the URL, or use some other complex logic. Learn how you can prepare a PHP file and [How to create WordPress tables based on serialized PHP arrays](https://wpdatatables.com/documentation/creating-wpdatatables/creating-wpdatatables-from-serialized-php-array/) in our docs.
@@ -352,6 +361,11 @@ This can be changed from the “Number format” drop-down menu in the wpDataTab
352
 
353
  == Changelog ==
354
 
 
 
 
 
 
355
  = 2.1.41 =
356
  * CSS update.
357
  Other small bug fixes and stability improvements.
2
  Contributors: wpDataTables
3
  Author URI: https://tms-outsource.com
4
  Plugin URI: https://wpdatatables.com/
5
+ Tags: table, table builder, data tables, tables, charts, datatables, csv, excel, json, simple table, tables from csv, tables from excel, dynamic tables, merge cells, cache, cache tables, caching, auto update, auto update tables, pricing tables, responsive tables, responsive charts, grouping data, pricing table, row grouping, chart, pie charts, mysql tables, table plugin, wp table, wordpress table plugin, wordpress tables, editing charts, google charts, chartjs, xml, php array, line chart, donut, bar chart, histogram, area chart, bubble chart, gauge chart, scatter chart, candlestick, waterfall, polar, radar
6
  Requires at least: 4.0
7
  Tested up to: 6.0.2
8
  Requires PHP: 5.6
9
+ Stable tag: 2.1.42
10
  License: GPLv2 or later
11
  License URI: http://www.gnu.org/licenses/gpl-2.0.html
12
 
64
  JSON *(JavaScript Object Notation)* is a popular interlingual data exchange format. Many server applications provide public data in JSON format. JSON is based on the syntax of Javascript objects. Since most web applications use client-side JavaScript, JSON has become the 'de facto' standard for packing data on the web and wpDataTables also supports the JSON format as an input data source.
65
  Learn [How to create WordPress tables from JSON](https://wpdatatables.com/documentation/creating-wpdatatables/creating-wpdatatables-from-json-input/) in our documentation.
66
 
67
+ == NEW! Cache tables data ==
68
+
69
+ We are introducing a new feature that will dramatically increase the loading performance of your tables created from existing data sources like CSV, Excel, XML, JSON, and PHP array. As you know, in this case, you will upload the file and initialize the table, whereupon it will be read every time the page loads. Before this version of wpDataTables, if the source file was larger than 3.000 – 5.000 rows, the page load and generation time was slow. But not anymore!
70
+ More details in our docs about [Caching tables in Wordpress](https://wpdatatables.com/documentation/table-features/caching-data-and-auto-update-cache-in-wordpress-tables/).
71
+
72
+ == NEW! Auto update table cache from source file ==
73
+
74
+ This new option is related with previous option caching tables. If you are updating your source file frequently, and want to keep the data in the table updated after a custom interval, the new feature Auto update cache from the source file will be perfect for you. It will update table cached data based on the source file following the time interval that you will set in the cron job. You can read more in our docs about [Auto update cache from source and cron job instructions](https://wpdatatables.com/documentation/table-features/caching-data-and-auto-update-cache-in-wordpress-tables/#auto-update-cache).
75
+
76
  == Develop dynamic WordPress table from Serialized PHP array ==
77
 
78
  For developer users, or users who are at least somewhat familiar with PHP language, that previous input data sources (Excel, CSV, XML of JSON) are not flexible enough for dynamic data presentation. We didn't want to limit your freedom in wpDataTables, so we implemented serialized PHP arrays as one of data sources, so you are able to create dynamic datatables. You can prepare data from some private or public API, or use WP Query to get data from your posts, get data by depending on some variables in the URL, or use some other complex logic. Learn how you can prepare a PHP file and [How to create WordPress tables based on serialized PHP arrays](https://wpdatatables.com/documentation/creating-wpdatatables/creating-wpdatatables-from-serialized-php-array/) in our docs.
361
 
362
  == Changelog ==
363
 
364
+ = 2.1.42 =
365
+ * Feature: [Caching tables data](https://wpdatatables.com/documentation/table-features/caching-data-and-auto-update-cache-in-wordpress-tables/) for non-server-side tables (Excel, CSV, XML, JSON, and PHP array).
366
+ * Feature: [Auto update table cache](https://wpdatatables.com/documentation/table-features/caching-data-and-auto-update-cache-in-wordpress-tables/) for non-server-side tables (Excel, CSV, XML, JSON, and PHP array).
367
+ Other small bug fixes and stability improvements.
368
+
369
  = 2.1.41 =
370
  * CSS update.
371
  Other small bug fixes and stability improvements.
source/class.wdtconfigcontroller.php CHANGED
@@ -270,7 +270,8 @@ class WDTConfigController {
270
  'scrollable' => $table->scrollable,
271
  'auto_refresh' => $table->auto_refresh,
272
  'editor_roles' => $table->editor_roles,
273
-
 
274
 
275
 
276
  'userid_column_id' => (int)$table->userid_column_id,
@@ -352,6 +353,8 @@ class WDTConfigController {
352
  $table->auto_refresh = (int)$table->auto_refresh;
353
  $table->info_block = (int)$table->info_block;
354
  $table->responsiveAction = sanitize_text_field($table->responsiveAction);
 
 
355
  $table->pagination = (int)$table->pagination;
356
  $table->paginationAlign = sanitize_text_field($table->paginationAlign);
357
  $table->paginationLayout = sanitize_text_field($table->paginationLayout);
@@ -1044,6 +1047,8 @@ class WDTConfigController {
1044
  $table->paginationAlign = 'right';
1045
  $table->paginationLayout = 'full_numbers';
1046
  $table->simpleResponsive = 0;
 
 
1047
  $table->simpleHeader = 0;
1048
  $table->stripeTable = 0;
1049
  $table->cellPadding = 10;
270
  'scrollable' => $table->scrollable,
271
  'auto_refresh' => $table->auto_refresh,
272
  'editor_roles' => $table->editor_roles,
273
+ 'cache_source_data' => $table->cache_source_data,
274
+ 'auto_update_cache' => $table->auto_update_cache,
275
 
276
 
277
  'userid_column_id' => (int)$table->userid_column_id,
353
  $table->auto_refresh = (int)$table->auto_refresh;
354
  $table->info_block = (int)$table->info_block;
355
  $table->responsiveAction = sanitize_text_field($table->responsiveAction);
356
+ $table->cache_source_data = (int)$table->cache_source_data;
357
+ $table->auto_update_cache = (int)$table->auto_update_cache;
358
  $table->pagination = (int)$table->pagination;
359
  $table->paginationAlign = sanitize_text_field($table->paginationAlign);
360
  $table->paginationLayout = sanitize_text_field($table->paginationLayout);
1047
  $table->paginationAlign = 'right';
1048
  $table->paginationLayout = 'full_numbers';
1049
  $table->simpleResponsive = 0;
1050
+ $table->cache_source_data = 0;
1051
+ $table->auto_update_cache = 0;
1052
  $table->simpleHeader = 0;
1053
  $table->stripeTable = 0;
1054
  $table->cellPadding = 10;
source/class.wdtsettingscontroller.php CHANGED
@@ -33,6 +33,26 @@ class WDTSettingsController {
33
 
34
  public static function saveSettings( $settings ){
35
  $settings = self::sanitizeSettings( stripslashes_deep( $settings ) );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
36
 
37
  foreach($settings as $key=>$value) {
38
  update_option($key, $value);
@@ -81,6 +101,7 @@ class WDTSettingsController {
81
  'wdtMinFunctionsLabel' => get_option('wdtMinFunctionsLabel'),
82
  'wdtMaxFunctionsLabel' => get_option('wdtMaxFunctionsLabel'),
83
  'wdtFontColorSettings' => get_option('wdtFontColorSettings') ? get_option('wdtFontColorSettings') : new stdClass(),
 
84
  );
85
  }
86
 
33
 
34
  public static function saveSettings( $settings ){
35
  $settings = self::sanitizeSettings( stripslashes_deep( $settings ) );
36
+ $autoUpdateOption = (int)$settings['wdtAutoUpdateOption'];
37
+
38
+ if (!$autoUpdateOption){
39
+ global $wpdb;
40
+ $wpdb->query(
41
+ $wpdb->prepare(
42
+ "UPDATE " . $wpdb->prefix . "wpdatatables_cache
43
+ SET auto_update = %d",
44
+ $autoUpdateOption
45
+ )
46
+ );
47
+ $wpdb->query(
48
+ $wpdb->prepare(
49
+ "UPDATE " . $wpdb->prefix . "wpdatatables
50
+ SET auto_update_cache = %d",
51
+ $autoUpdateOption
52
+ )
53
+ );
54
+
55
+ }
56
 
57
  foreach($settings as $key=>$value) {
58
  update_option($key, $value);
101
  'wdtMinFunctionsLabel' => get_option('wdtMinFunctionsLabel'),
102
  'wdtMaxFunctionsLabel' => get_option('wdtMaxFunctionsLabel'),
103
  'wdtFontColorSettings' => get_option('wdtFontColorSettings') ? get_option('wdtFontColorSettings') : new stdClass(),
104
+ 'wdtAutoUpdateOption' => get_option('wdtAutoUpdateOption'),
105
  );
106
  }
107
 
source/class.wpdatatable.php CHANGED
@@ -38,6 +38,8 @@ class WPDataTable
38
  private $_firstOnPage = false;
39
  private $_groupingEnabled = false;
40
  private $_wdtColumnGroupIndex = 0;
 
 
41
  private $_showAdvancedFilter = false;
42
  private $_wdtTableSort = true;
43
  private $_serverProcessing = false;
@@ -966,6 +968,22 @@ class WPDataTable
966
  $this->_responsiveAction = $responsiveAction;
967
  }
968
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
969
 
970
  public function enableGrouping()
971
  {
@@ -1547,101 +1565,251 @@ class WPDataTable
1547
  return array_values($row);
1548
  }
1549
 
1550
-
1551
- public function jsonBasedConstruct($json, $wdtParameters = array())
1552
- {
1553
- $json = WDTTools::curlGetData($json);
1554
- $json = apply_filters('wpdatatables_filter_json', $json, $this->getWpId());
1555
- return $this->arrayBasedConstruct(json_decode($json, true), $wdtParameters);
1556
- }
1557
-
1558
- public function XMLBasedConstruct($xml, $wdtParameters = array())
1559
- {
1560
- if (!$xml) {
1561
- throw new WDTException('File you provided cannot be found.');
1562
- }
1563
- if (strpos($xml, '.xml') === false) {
1564
- throw new WDTException('Non-XML file provided!');
1565
- }
1566
- $XMLObject = simplexml_load_file($xml);
1567
- $XMLObject = apply_filters('wpdatatables_filter_simplexml', $XMLObject, $this->getWpId());
1568
- $XMLArray = WDTTools::convertXMLtoArr($XMLObject);
1569
- foreach ($XMLArray as &$xml_el) {
1570
- if (is_array($xml_el) && array_key_exists('attributes', $xml_el)) {
1571
- $xml_el = $xml_el['attributes'];
1572
- }
1573
- }
1574
- return $this->arrayBasedConstruct($XMLArray, $wdtParameters);
1575
- }
1576
-
1577
- public function excelBasedConstruct($xls_url, $wdtParameters = array())
1578
- {
1579
- ini_set('memory_limit', '2048M');
1580
- if (!$xls_url) {
1581
- throw new WDTException('Excel file not found!');
1582
- }
1583
- if (!file_exists($xls_url)) {
1584
- throw new WDTException('Provided file ' . stripcslashes($xls_url) . ' does not exist!');
1585
- }
1586
-
1587
- $format = 'xls';
1588
- if (strpos(strtolower($xls_url), '.xlsx')) {
1589
- $objReader = new Xlsx();
1590
- } elseif (strpos(strtolower($xls_url), '.xls')) {
1591
- $objReader = new Xls();
1592
- } elseif (strpos(strtolower($xls_url), '.ods')) {
1593
- $format = 'ods';
1594
- $objReader = new Ods();
1595
- } elseif (strpos(strtolower($xls_url), '.csv')) {
1596
- $format = 'csv';
1597
- $objReader = new Csv();
1598
- $csvDelimiter = stripcslashes(get_option('wdtCSVDelimiter')) ? stripcslashes(get_option('wdtCSVDelimiter')) : WDTTools::detectCSVDelimiter($xls_url);
1599
- $objReader->setDelimiter($csvDelimiter);
1600
- } else {
1601
- throw new WDTException('File format not supported!');
1602
- }
1603
-
1604
- $objPHPExcel = $objReader->load($xls_url);
1605
- $objWorksheet = $objPHPExcel->getActiveSheet();
1606
- $highestRow = $objWorksheet->getHighestRow();
1607
- $highestColumn = $objWorksheet->getHighestDataColumn();
1608
-
1609
- $headingsArray = $objWorksheet->rangeToArray('A1:' . $highestColumn . '1', null, true, true, true);
1610
- $headingsArray = array_map('trim', $headingsArray[1]);
1611
-
1612
- $r = -1;
1613
- $namedDataArray = array();
1614
- $dataRows = $objWorksheet->rangeToArray('A2:' . $highestColumn . $highestRow, null, true, true, true);
1615
- for ($row = 2; $row <= $highestRow; ++$row) {
1616
- if (max($dataRows[$row]) !== null) {
1617
- ++$r;
1618
- foreach ($headingsArray as $dataColumnIndex => $dataColumnHeading) {
1619
- $dataColumnHeading = trim(preg_replace('/\s\s+/', ' ', str_replace("\n", " ", $dataColumnHeading)));
1620
- $namedDataArray[$r][$dataColumnHeading] = $dataRows[$row][$dataColumnIndex];
1621
- $currentDateFormat = isset($wdtParameters['dateInputFormat'][$dataColumnHeading]) ? $wdtParameters['dateInputFormat'][$dataColumnHeading] : null;
1622
- if (!empty($wdtParameters['data_types'][$dataColumnHeading]) && in_array($wdtParameters['data_types'][$dataColumnHeading], array('date', 'datetime', 'time'))) {
1623
- if ($format === 'xls') {
1624
- $cell = $objPHPExcel->getActiveSheet()->getCell($dataColumnIndex . '' . $row);
1625
- if (Date::isDateTime($cell) && $cell->getValue() !== null) {
1626
- $namedDataArray[$r][$dataColumnHeading] = Date::excelToTimestamp($cell->getValue());
1627
- } else {
1628
- $namedDataArray[$r][$dataColumnHeading] = WDTTools::wdtConvertStringToUnixTimestamp($dataRows[$row][$dataColumnIndex], $currentDateFormat);
1629
- }
1630
- } elseif ($format === 'csv') {
1631
- $namedDataArray[$r][$dataColumnHeading] = WDTTools::wdtConvertStringToUnixTimestamp($dataRows[$row][$dataColumnIndex], $currentDateFormat);
1632
- }
1633
- }
1634
- }
1635
- }
1636
- }
1637
-
1638
- // Let arrayBasedConstruct know that dates have been converted to timestamps
1639
- $wdtParameters['dates_detected'] = true;
1640
-
1641
- $namedDataArray = apply_filters('wpdatatables_filter_excel_array', $namedDataArray, $this->getWpId(), $xls_url);
1642
-
1643
- return $this->arrayBasedConstruct($namedDataArray, $wdtParameters);
1644
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1645
 
1646
  /**
1647
  * Helper method that renders the modal
@@ -1905,7 +2073,10 @@ class WPDataTable
1905
  *
1906
  * @param $tableData
1907
  * @param $columnData
 
 
1908
  */
 
1909
  public function fillFromData($tableData, $columnData)
1910
  {
1911
  if (empty($tableData->table_type)) {
@@ -1995,6 +2166,8 @@ class WPDataTable
1995
  } else {
1996
  $this->disablePagination();
1997
  }
 
 
1998
 
1999
  switch ($tableData->table_type) {
2000
 
@@ -2018,28 +2191,18 @@ class WPDataTable
2018
  );
2019
  break;
2020
  case 'serialized':
2021
- $url = apply_filters('wpdatatables_filter_url_php_array', $tableData->content, $this->getWpId());
2022
- $serialized_content = apply_filters('wpdatatables_filter_serialized', WDTTools::curlGetData($url), $this->getWpId());
2023
- $array = unserialize($serialized_content);
2024
- $this->arrayBasedConstruct(
2025
- $array,
2026
- $params
2027
- );
2028
  break;
2029
-
2030
-
2031
  default:
2032
  // Solution for addons
2033
- if (has_action('wpdatatables_generate_' . $tableData->table_type)) {
2034
- do_action(
2035
- 'wpdatatables_generate_' . $tableData->table_type,
2036
- $this,
2037
- $tableData->content,
2038
- $params
2039
- );
2040
- } else {
2041
- throw new WDTException(__('You are trying to load a table of an unknown type. Probably you did not activate the addon which is required to use this table type.', 'wpdatatables'));
2042
- }
2043
  break;
2044
  }
2045
  if (!empty($tableData->content)) {
@@ -2639,6 +2802,8 @@ class WPDataTable
2639
 
2640
  $wpdb->delete("{$wpdb->prefix}wpdatatables", array('id' => (int)$tableId));
2641
  $wpdb->delete("{$wpdb->prefix}wpdatatables_columns", array('table_id' => (int)$tableId));
 
 
2642
  $wpdb->delete("{$wpdb->prefix}wpdatacharts", array('wpdatatable_id' => (int)$tableId));
2643
 
2644
  return true;
38
  private $_firstOnPage = false;
39
  private $_groupingEnabled = false;
40
  private $_wdtColumnGroupIndex = 0;
41
+ private $_cache_source_data = false;
42
+ private $_auto_update_cache = false;
43
  private $_showAdvancedFilter = false;
44
  private $_wdtTableSort = true;
45
  private $_serverProcessing = false;
968
  $this->_responsiveAction = $responsiveAction;
969
  }
970
 
971
+ public function setCacheSourceData($cacheSourceData) {
972
+ $this->_cache_source_data = (bool)$cacheSourceData;
973
+ }
974
+
975
+ public function getCacheSourceData() {
976
+ return $this->_cache_source_data;
977
+ }
978
+
979
+ public function setAutoUpdateCache($autoUpdateCache) {
980
+ $this->_auto_update_cache = (bool)$autoUpdateCache;
981
+ }
982
+
983
+ public function getAutoUpdateCache() {
984
+ return $this->_auto_update_cache;
985
+ }
986
+
987
 
988
  public function enableGrouping()
989
  {
1565
  return array_values($row);
1566
  }
1567
 
1568
+ public function customBasedConstruct($tableData, $wdtParameters = array()) {
1569
+ if (has_action('wpdatatables_generate_' . $tableData->table_type)) {
1570
+ do_action(
1571
+ 'wpdatatables_generate_' . $tableData->table_type,
1572
+ $this,
1573
+ $tableData->content,
1574
+ $wdtParameters
1575
+ );
1576
+ } else {
1577
+ throw new WDTException(__('You are trying to load a table of an unknown type. Probably you did not activate the addon which is required to use this table type.', 'wpdatatables'));
1578
+ }
1579
+ }
1580
+
1581
+
1582
+ /**
1583
+ * @throws Exception
1584
+ */
1585
+ public function jsonBasedConstruct($json, $wdtParameters = array()) {
1586
+ $cache = WPDataTableCache::maybeCache($this->getCacheSourceData(), (int)$this->getWpId());
1587
+ if (!$cache){
1588
+ $jsonArray = self::sourceRenderData($this, 'json', $json);
1589
+ } else {
1590
+ $jsonArray = $cache;
1591
+ }
1592
+
1593
+ $jsonArray = apply_filters('wpdatatables_filter_json_array', $jsonArray, $this->getWpId(), $json);
1594
+
1595
+ return $this->arrayBasedConstruct($jsonArray, $wdtParameters);
1596
+ }
1597
+
1598
+ /**
1599
+ * @throws Exception
1600
+ */
1601
+ public function serializedPHPBasedConstruct($url, $wdtParameters = array()) {
1602
+ $cache = WPDataTableCache::maybeCache($this->getCacheSourceData(), (int)$this->getWpId());
1603
+ if (!$cache){
1604
+ $PHPArray = self::sourceRenderData($this, 'serialized', $url);
1605
+ } else {
1606
+ $PHPArray = $cache;
1607
+ }
1608
+
1609
+ $PHPArray = apply_filters('wpdatatables_filter_php_array', $PHPArray, $this->getWpId(), $url);
1610
+
1611
+ return $this->arrayBasedConstruct($PHPArray, $wdtParameters);
1612
+ }
1613
+
1614
+ /**
1615
+ * @throws WDTException
1616
+ */
1617
+ public function XMLBasedConstruct($xml, $wdtParameters = array()) {
1618
+ $cache = WPDataTableCache::maybeCache($this->getCacheSourceData(), (int)$this->getWpId());
1619
+ if (!$cache){
1620
+ if (!$xml) {
1621
+ throw new WDTException('File you provided cannot be found.');
1622
+ }
1623
+ $XMLArray = self::sourceRenderData($this, 'xml', $xml);
1624
+ } else {
1625
+ $XMLArray = $cache;
1626
+ }
1627
+
1628
+ $XMLArray = apply_filters('wpdatatables_filter_xml_array', $XMLArray, $this->getWpId(), $xml);
1629
+
1630
+ return $this->arrayBasedConstruct($XMLArray, $wdtParameters);
1631
+ }
1632
+
1633
+ /**
1634
+ * @throws WDTException
1635
+ * @throws \PhpOffice\PhpSpreadsheet\Exception
1636
+ * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
1637
+ * @throws Exception
1638
+ */
1639
+ public function excelBasedConstruct($xls_url, $wdtParameters = array()) {
1640
+ $cache = WPDataTableCache::maybeCache($this->getCacheSourceData(), (int)$this->getWpId());
1641
+ if (!$cache){
1642
+ ini_set('memory_limit', '2048M');
1643
+ if (!$xls_url) {
1644
+ throw new WDTException(esc_html__('Excel file not found!','wpdatatables'));
1645
+ }
1646
+ if (!file_exists($xls_url)) {
1647
+ throw new WDTException('Provided file ' . stripcslashes($xls_url) . ' does not exist!');
1648
+ }
1649
+
1650
+ $format = substr(strrchr($xls_url, "."), 1);
1651
+ $objReader = self::createObjectReader($xls_url);
1652
+ $xls_url = apply_filters( 'wpdatatables_filter_excel_based_data_url', $xls_url, $this->getWpId() );
1653
+ $objPHPExcel = $objReader->load($xls_url);
1654
+ $objWorksheet = $objPHPExcel->getActiveSheet();
1655
+ $highestRow = $objWorksheet->getHighestRow();
1656
+ $highestColumn = $objWorksheet->getHighestDataColumn();
1657
+
1658
+ $headingsArray = $objWorksheet->rangeToArray('A1:' . $highestColumn . '1', null, true, true, true);
1659
+ $headingsArray = array_map('trim', $headingsArray[1]);
1660
+
1661
+ $r = -1;
1662
+ $namedDataArray = array();
1663
+
1664
+ $dataRows = $objWorksheet->rangeToArray('A2:' . $highestColumn . $highestRow, null, true, true, true);
1665
+ for ($row = 2; $row <= $highestRow; ++$row) {
1666
+ if (max($dataRows[$row]) !== null) {
1667
+ ++$r;
1668
+ foreach ($headingsArray as $dataColumnIndex => $dataColumnHeading) {
1669
+ $dataColumnHeading = trim(preg_replace('/\s\s+/', ' ', str_replace("\n", " ", $dataColumnHeading)));
1670
+ $namedDataArray[$r][$dataColumnHeading] = trim($dataRows[$row][$dataColumnIndex]);
1671
+ $currentDateFormat = isset($wdtParameters['dateInputFormat'][$dataColumnHeading]) ? $wdtParameters['dateInputFormat'][$dataColumnHeading] : null;
1672
+ if (!empty($wdtParameters['data_types'][$dataColumnHeading]) && in_array($wdtParameters['data_types'][$dataColumnHeading], array('date', 'datetime', 'time'))) {
1673
+ if ($format === 'xls' || $format === 'ods') {
1674
+ $cell = $objPHPExcel->getActiveSheet()->getCell($dataColumnIndex . '' . $row);
1675
+ if (Date::isDateTime($cell) && $cell->getValue() !== null) {
1676
+ $namedDataArray[$r][$dataColumnHeading] = Date::excelToTimestamp($cell->getValue());
1677
+ } else {
1678
+ $namedDataArray[$r][$dataColumnHeading] = WDTTools::wdtConvertStringToUnixTimestamp($dataRows[$row][$dataColumnIndex], $currentDateFormat);
1679
+ }
1680
+ } elseif ($format === 'csv') {
1681
+ $namedDataArray[$r][$dataColumnHeading] = WDTTools::wdtConvertStringToUnixTimestamp($dataRows[$row][$dataColumnIndex], $currentDateFormat);
1682
+ }
1683
+ }
1684
+ }
1685
+ }
1686
+ }
1687
+ if (empty($namedDataArray)) {
1688
+ throw new WDTException(esc_html__('There is no data in your source file. Please check your source file and try again.','wpdatatables'));
1689
+ }
1690
+
1691
+ WPDataTableCache::maybeSaveData(
1692
+ (int)$this->getWpId(),
1693
+ $format,
1694
+ $xls_url,
1695
+ $this->getAutoUpdateCache(),
1696
+ $namedDataArray,
1697
+ $this->getCacheSourceData()
1698
+ );
1699
+
1700
+ } else {
1701
+ $namedDataArray = $cache;
1702
+ }
1703
+
1704
+ // Let arrayBasedConstruct know that dates have been converted to timestamps
1705
+ $wdtParameters['dates_detected'] = true;
1706
+
1707
+ $namedDataArray = apply_filters('wpdatatables_filter_excel_array', $namedDataArray, $this->getWpId(), $xls_url);
1708
+
1709
+ return $this->arrayBasedConstruct($namedDataArray, $wdtParameters);
1710
+ }
1711
+
1712
+ /**
1713
+ * Helper method to get data from source URL
1714
+ * @param $sourceObj
1715
+ * @param $sourceType
1716
+ * @param $source
1717
+ * @return array|mixed|string|void|null
1718
+ * @throws WDTException
1719
+ * @throws Exception
1720
+ */
1721
+ public static function sourceRenderData($sourceObj, $sourceType, $source) {
1722
+ $wpId = $sourceObj->getWpId();
1723
+ $sourceArray = array();
1724
+ if ($sourceType == 'json') {
1725
+ $sourceArray = self::jsonRenderData($source, $wpId);
1726
+ }
1727
+
1728
+ if ($sourceType == 'serialized') {
1729
+ $sourceArray = self::serializedPhpRenderData($source, $wpId);
1730
+ }
1731
+
1732
+ if ($sourceType == 'xml') {
1733
+ $sourceArray = self::xmlRenderData($source, $wpId);
1734
+ }
1735
+
1736
+ WPDataTableCache::maybeSaveData(
1737
+ (int)$wpId,
1738
+ $sourceType,
1739
+ $source,
1740
+ $sourceObj->getAutoUpdateCache(),
1741
+ $sourceArray,
1742
+ $sourceObj->getCacheSourceData()
1743
+ );
1744
+
1745
+ return $sourceArray;
1746
+ }
1747
+
1748
+ /**
1749
+ * Helper method to get data from source URL
1750
+ * @param $json
1751
+ * @param $id
1752
+ * @return mixed|null
1753
+ * @throws Exception
1754
+ */
1755
+ public static function jsonRenderData($json, $id) {
1756
+ $json = WDTTools::curlGetData($json);
1757
+ $json = apply_filters('wpdatatables_filter_json', $json, $id);
1758
+ return json_decode($json, true);
1759
+ }
1760
+
1761
+ /**
1762
+ * Helper method to get data from source URL
1763
+ * @param $url
1764
+ * @param $id
1765
+ * @return mixed
1766
+ */
1767
+ public static function serializedPhpRenderData($url, $id) {
1768
+ $url = apply_filters('wpdatatables_filter_url_php_array', $url, $id);
1769
+ $serialized_content = apply_filters('wpdatatables_filter_serialized', WDTTools::curlGetData($url), $id);
1770
+ return unserialize($serialized_content);
1771
+ }
1772
+
1773
+ /**
1774
+ * Helper method to get data from source URL
1775
+ * @param $xml
1776
+ * @return array|string
1777
+ */
1778
+ public static function xmlRenderData( $xml, $id) {
1779
+ $XMLObject = simplexml_load_file($xml);
1780
+ $XMLObject = apply_filters('wpdatatables_filter_simplexml', $XMLObject, $id);
1781
+ $XMLArray = WDTTools::convertXMLtoArr($XMLObject);
1782
+ foreach ($XMLArray as &$xml_el) {
1783
+ if (is_array($xml_el) && array_key_exists('attributes', $xml_el)) {
1784
+ $xml_el = $xml_el['attributes'];
1785
+ }
1786
+ }
1787
+ return $XMLArray;
1788
+ }
1789
+
1790
+ /**
1791
+ * Creates a reader depending on the file extension
1792
+ * @param $file
1793
+ * @return Csv|Ods|Xls|Xlsx
1794
+ * @throws WDTException
1795
+ */
1796
+ public static function createObjectReader($file) {
1797
+ if (strpos(strtolower($file), '.xlsx')) {
1798
+ $objReader = new Xlsx();
1799
+ } elseif (strpos(strtolower($file), '.xls')) {
1800
+ $objReader = new Xls();
1801
+ } elseif (strpos(strtolower($file), '.ods')) {
1802
+ $objReader = new Ods();
1803
+ } elseif (strpos(strtolower($file), '.csv')) {
1804
+ $objReader = new Csv();
1805
+ $csvDelimiter = stripcslashes(get_option('wdtCSVDelimiter')) ? stripcslashes(get_option('wdtCSVDelimiter')) : WDTTools::detectCSVDelimiter($file);
1806
+ $objReader->setDelimiter($csvDelimiter);
1807
+ } else {
1808
+ throw new WDTException('File format not supported!');
1809
+ }
1810
+
1811
+ return $objReader;
1812
+ }
1813
 
1814
  /**
1815
  * Helper method that renders the modal
2073
  *
2074
  * @param $tableData
2075
  * @param $columnData
2076
+ * @throws WDTException
2077
+ * @throws Exception
2078
  */
2079
+
2080
  public function fillFromData($tableData, $columnData)
2081
  {
2082
  if (empty($tableData->table_type)) {
2166
  } else {
2167
  $this->disablePagination();
2168
  }
2169
+ $this->setCacheSourceData(!empty($tableData->cache_source_data));
2170
+ $this->setAutoUpdateCache(!empty($tableData->auto_update_cache));
2171
 
2172
  switch ($tableData->table_type) {
2173
 
2191
  );
2192
  break;
2193
  case 'serialized':
2194
+ $this->serializedPHPBasedConstruct(
2195
+ $tableData->content,
2196
+ $params
2197
+ );
 
 
 
2198
  break;
 
 
2199
  default:
2200
  // Solution for addons
2201
+ $this->customBasedConstruct(
2202
+ $tableData->content,
2203
+ $params
2204
+ );
2205
+
 
 
 
 
 
2206
  break;
2207
  }
2208
  if (!empty($tableData->content)) {
2802
 
2803
  $wpdb->delete("{$wpdb->prefix}wpdatatables", array('id' => (int)$tableId));
2804
  $wpdb->delete("{$wpdb->prefix}wpdatatables_columns", array('table_id' => (int)$tableId));
2805
+ $wpdb->delete("{$wpdb->prefix}wpdatatables_rows", array('table_id' => (int)$tableId));
2806
+ $wpdb->delete("{$wpdb->prefix}wpdatatables_cache", array('table_id' => (int)$tableId));
2807
  $wpdb->delete("{$wpdb->prefix}wpdatacharts", array('wpdatatable_id' => (int)$tableId));
2808
 
2809
  return true;
source/class.wpdatatablecache.php ADDED
@@ -0,0 +1,405 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+
3
+ use PhpOffice\PhpSpreadsheet\Shared\Date;
4
+
5
+ defined('ABSPATH') or die('Access denied.');
6
+
7
+ class WPDataTableCache
8
+ {
9
+
10
+ public static function maybeCache($createCache, $tableID)
11
+ {
12
+ if ($tableID) {
13
+
14
+ if (!$createCache) {
15
+ self::delete($tableID);
16
+ return false;
17
+ }
18
+
19
+ $cache = self::isCacheDataExist($tableID);
20
+
21
+ if (!$cache) {
22
+ return false;
23
+ }
24
+
25
+ if (isset($_POST['action']) && $_POST['action'] === 'wpdatatables_save_table_config') {
26
+ self::delete($tableID);
27
+ return false;
28
+ }
29
+
30
+ if (!isset($cache->data))
31
+ return false;
32
+
33
+ return json_decode($cache->data, true);
34
+ }
35
+
36
+ return false;
37
+ }
38
+
39
+ private static function updateData($tableID, $sourceData)
40
+ {
41
+ global $wpdb;
42
+ if ($tableID) {
43
+ $sourceData = self::filterUserData($sourceData, $tableID);
44
+ $wpdb->update(
45
+ $wpdb->prefix . "wpdatatables_cache",
46
+ array(
47
+ 'data' => json_encode($sourceData),
48
+ 'updated_time' => current_time('mysql'),
49
+ ),
50
+ array('table_id' => $tableID)
51
+ );
52
+ if ($wpdb->last_error !== '') {
53
+ self::_logErrors(
54
+ 'Update cache error:',
55
+ $wpdb->last_error,
56
+ 1,
57
+ $tableID
58
+ );
59
+ }
60
+ } else {
61
+ self::_logErrors(
62
+ 'Update cache error:',
63
+ 'Table ID is not set for auto update data.',
64
+ 1,
65
+ $tableID
66
+ );
67
+ }
68
+ }
69
+ private static function filterUserData ($sourceData, $tableID){
70
+ $filterSourceData= apply_filters('wpdatatables_filter_source_data_on_auto_update_cache', true, $tableID);
71
+ if (!current_user_can('unfiltered_html') && $filterSourceData) {
72
+ $tempSourceData = $sourceData;
73
+ $sourceData = [];
74
+ foreach ($tempSourceData as $index => $tempData) {
75
+ foreach ($tempData as $key => $data) {
76
+ $sourceData[$index][wp_kses_post($key)] = wp_kses_post($data);
77
+ }
78
+ }
79
+ return $sourceData;
80
+ }
81
+ return $sourceData;
82
+ }
83
+
84
+ public static function maybeSaveData($tableID, $tableType, $tableContent, $autoUpdate, $sourceData, $isCache)
85
+ {
86
+ global $wpdb;
87
+ if ($tableID && $isCache) {
88
+ if (!empty($sourceData)) {
89
+ $sourceData = self::filterUserData($sourceData, $tableID);
90
+ $wpdb->insert(
91
+ $wpdb->prefix . "wpdatatables_cache",
92
+ array(
93
+ 'table_id' => $tableID,
94
+ 'table_type' => $tableType,
95
+ 'table_content' => $tableContent,
96
+ 'auto_update' => $autoUpdate,
97
+ 'data' => json_encode($sourceData)
98
+ )
99
+ );
100
+ if ($wpdb->last_error !== '')
101
+ self::_logErrors('Save cache error:', $wpdb->last_error, 0, $tableID);
102
+
103
+ }
104
+ }
105
+ }
106
+
107
+ private static function delete($tableID)
108
+ {
109
+ if ($tableID) {
110
+ global $wpdb;
111
+ $wpdb->delete(
112
+ $wpdb->prefix . "wpdatatables_cache",
113
+ array(
114
+ 'table_id' => $tableID
115
+ ),
116
+ array(
117
+ '%d'
118
+ )
119
+ );
120
+ if ($wpdb->last_error !== '')
121
+ self::_logErrors('Delete cache error:', $wpdb->last_error, 0, $tableID);
122
+ }
123
+ }
124
+
125
+ private static function isCacheDataExist($tableID)
126
+ {
127
+ global $wpdb;
128
+ $cacheQuery = $wpdb->prepare(
129
+ "SELECT data
130
+ FROM " . $wpdb->prefix . "wpdatatables_cache
131
+ WHERE table_id = %d",
132
+ $tableID
133
+ );
134
+
135
+ $cache = $wpdb->get_row($cacheQuery);
136
+
137
+ if ($wpdb->last_error !== '') {
138
+ self::_logErrors('Get cache data error:', $wpdb->last_error, 0, $tableID);
139
+ return false;
140
+ }
141
+
142
+ if ($cache === null) {
143
+ return false;
144
+ }
145
+
146
+ return $cache;
147
+ }
148
+
149
+ private static function getTablesWithCacheForAutoUpdate()
150
+ {
151
+ global $wpdb;
152
+ $tablesForAutoUpdateQuery = "SELECT table_id, table_type, table_content, updated_time, data
153
+ FROM " . $wpdb->prefix . "wpdatatables_cache
154
+ WHERE auto_update = 1
155
+ ORDER BY id";
156
+
157
+ $tablesForAutoUpdate = $wpdb->get_results($tablesForAutoUpdateQuery, ARRAY_A);
158
+
159
+ if ($wpdb->last_error !== '') {
160
+ self::_logErrors('Error get tables with cache:', $wpdb->last_error, 0, 0);
161
+ return false;
162
+ }
163
+
164
+ if ($tablesForAutoUpdate === null) {
165
+ return false;
166
+ }
167
+
168
+ return $tablesForAutoUpdate;
169
+ }
170
+
171
+ public static function addAutoUpdateHooks()
172
+ {
173
+ add_action('wp_ajax_wdtable_update_cache', array(__CLASS__, 'maybeAutoUpdate'));
174
+ add_action('wp_ajax_nopriv_wdtable_update_cache', array(__CLASS__, 'maybeAutoUpdate'));
175
+ }
176
+
177
+ private static function _logErrors($title, $log, $autoUpdate, $tableID)
178
+ {
179
+ global $wpdb;
180
+ $logMessage = 'wpDataTables - ';
181
+
182
+ if ($title) {
183
+ $logMessage = $logMessage . $title;
184
+ }
185
+ $logMessage = $logMessage . ' ' . $log;
186
+
187
+ if ($tableID) {
188
+ $logMessage = $logMessage . ' Table ID=' . $tableID;
189
+ if ($autoUpdate) {
190
+ $logError = current_time('mysql') . ' - ' . $title . ' ' . $log . '<br>';
191
+ $wpdb->query(
192
+ $wpdb->prepare(
193
+ "UPDATE " . $wpdb->prefix . "wpdatatables_cache
194
+ SET log_errors = CONCAT(log_errors, %s) WHERE table_id = %d",
195
+ $logError,
196
+ $tableID
197
+ )
198
+ );
199
+ }
200
+ }
201
+
202
+ error_log($logMessage);
203
+ }
204
+
205
+ public static function maybeAutoUpdate()
206
+ {
207
+ $autoUpdateHash = get_option('wdtAutoUpdateHash');
208
+
209
+ if ($autoUpdateHash !== $_GET['wdtable_cache_verify']) return;
210
+
211
+ $cacheTables = self::getTablesWithCacheForAutoUpdate();
212
+
213
+ if (!$cacheTables) {
214
+ return;
215
+ }
216
+
217
+ foreach ($cacheTables as $cacheTable) {
218
+
219
+ $result = self::_renderDataFromSource(
220
+ $cacheTable['table_id'],
221
+ $cacheTable['table_type'],
222
+ $cacheTable['table_content']
223
+ );
224
+
225
+ if (isset($result['status']) && $result['status'] === 'success') {
226
+ if (!isset($result['data'])) {
227
+ self::_logErrors(
228
+ 'Auto update error message:',
229
+ 'Data array from source is not rendered.',
230
+ 1,
231
+ $cacheTable['table_id']
232
+ );
233
+ continue;
234
+ }
235
+
236
+ $cacheData = json_decode($cacheTable['data'], true);
237
+
238
+ if (!isset($cacheData[0])) {
239
+ self::_logErrors(
240
+ 'Auto update error message:',
241
+ 'Data array from cache is empty.',
242
+ 1,
243
+ $cacheTable['table_id']
244
+ );
245
+ continue;
246
+ }
247
+
248
+ if (!isset($result['data'][0])) {
249
+ self::_logErrors(
250
+ 'Auto update error message:',
251
+ 'Data array from source is not rendered.',
252
+ 1,
253
+ $cacheTable['table_id']
254
+ );
255
+ continue;
256
+ }
257
+
258
+ if (count($cacheData[0]) !== count($result['data'][0])) {
259
+ self::_logErrors(
260
+ 'Auto update error message:',
261
+ 'Data array from source and cache do not have same number of keys(columns).',
262
+ 1,
263
+ $cacheTable['table_id']
264
+ );
265
+ continue;
266
+ }
267
+
268
+ if (array_keys($cacheData[0]) !== array_keys($result['data'][0])) {
269
+ self::_logErrors(
270
+ 'Auto update error message:',
271
+ 'Data array from source and cache do not have same keys(columns).',
272
+ 1,
273
+ $cacheTable['table_id']
274
+ );
275
+ continue;
276
+ }
277
+
278
+ if ($cacheTable['data'] === json_encode($result['data'])) continue;
279
+
280
+ self::updateData($cacheTable['table_id'], $result['data']);
281
+ }
282
+ }
283
+ }
284
+
285
+ private static function _renderDataFromSource($table_id, $source_type, $source)
286
+ {
287
+ if (empty($source)) {
288
+ return [
289
+ 'status' => 'error',
290
+ 'error' => 'Source is empty.',
291
+ 'data' => []
292
+ ];
293
+ }
294
+ try {
295
+ if (in_array($source_type, ['xls', 'csv'])) {
296
+ $tableData = WDTConfigController::loadTableFromDB($table_id);
297
+ $params = array(
298
+ 'dateInputFormat' => array(),
299
+ 'data_types' => array(),
300
+ );
301
+ if ($tableData) {
302
+ foreach ($tableData->columns as $column) {
303
+ if ($column->type !== 'autodetect') {
304
+ $params['data_types'][$column->orig_header] = $column->type;
305
+ }
306
+ $params['dateInputFormat'][$column->orig_header] =
307
+ isset($column->dateInputFormat) ? $column->dateInputFormat : null;
308
+ }
309
+ }
310
+
311
+ }
312
+ $dataArray = array();
313
+ switch ($source_type) {
314
+ case 'ods':
315
+ case 'xlsx':
316
+ case 'xls':
317
+ case 'csv':
318
+ ini_set('memory_limit', '2048M');
319
+ if (!file_exists($source)) {
320
+ self::_logErrors(
321
+ 'Error message:',
322
+ 'Provided file ' . stripcslashes($source) . ' does not exist!',
323
+ 1,
324
+ $table_id
325
+ );
326
+ }
327
+ $format = substr(strrchr($source, "."), 1);
328
+ $objReader = WPDataTable::createObjectReader($source);
329
+ $objPHPExcel = $objReader->load($source);
330
+ $objWorksheet = $objPHPExcel->getActiveSheet();
331
+ $highestRow = $objWorksheet->getHighestRow();
332
+ $highestColumn = $objWorksheet->getHighestDataColumn();
333
+
334
+ $headingsArray = $objWorksheet->rangeToArray('A1:' . $highestColumn . '1', null, true, true, true);
335
+ $headingsArray = array_map('trim', $headingsArray[1]);
336
+
337
+ $r = -1;
338
+
339
+ $dataRows = $objWorksheet->rangeToArray('A2:' . $highestColumn . $highestRow, null, true, true, true);
340
+ for ($row = 2; $row <= $highestRow; ++$row) {
341
+ if (max($dataRows[$row]) !== null) {
342
+ ++$r;
343
+ foreach ($headingsArray as $dataColumnIndex => $dataColumnHeading) {
344
+ $dataColumnHeading = trim(preg_replace('/\s\s+/', ' ', str_replace("\n", " ", $dataColumnHeading)));
345
+ $dataArray[$r][$dataColumnHeading] = $dataRows[$row][$dataColumnIndex];
346
+ $currentDateFormat = isset($params['dateInputFormat'][$dataColumnHeading]) ? $params['dateInputFormat'][$dataColumnHeading] : null;
347
+ if (!empty($params['data_types'][$dataColumnHeading]) && in_array($params['data_types'][$dataColumnHeading], array('date', 'datetime', 'time'))) {
348
+ if ($format === 'xls' || $format === 'ods') {
349
+ $cell = $objPHPExcel->getActiveSheet()->getCell($dataColumnIndex . '' . $row);
350
+ if (Date::isDateTime($cell) && $cell->getValue() !== null) {
351
+ $dataArray[$r][$dataColumnHeading] = Date::excelToTimestamp($cell->getValue());
352
+ } else {
353
+ $dataArray[$r][$dataColumnHeading] = WDTTools::wdtConvertStringToUnixTimestamp($dataRows[$row][$dataColumnIndex], $currentDateFormat);
354
+ }
355
+ } elseif ($format === 'csv') {
356
+ $dataArray[$r][$dataColumnHeading] = WDTTools::wdtConvertStringToUnixTimestamp($dataRows[$row][$dataColumnIndex], $currentDateFormat);
357
+ }
358
+ }
359
+ }
360
+ }
361
+ }
362
+ break;
363
+ case 'xml':
364
+ $dataArray = WPDataTable::xmlRenderData($source, $table_id);
365
+ break;
366
+ case 'json':
367
+ $dataArray = WPDataTable::jsonRenderData($source, $table_id);
368
+ break;
369
+ case 'serialized':
370
+ $dataArray = WPDataTable::serializedPhpRenderData($source, $table_id);
371
+ break;
372
+ default:
373
+ self::_logErrors('Error message:', 'Source type is unknown', 1, $table_id);
374
+ return [
375
+ 'status' => 'error',
376
+ 'error' => 'Source type is unknown',
377
+ 'data' => []
378
+ ];
379
+ }
380
+ } catch (Exception $e) {
381
+ self::_logErrors('Error message:', $e->getMessage(), 1, $table_id);
382
+ return [
383
+ 'status' => 'error',
384
+ 'error' => $e->getMessage(),
385
+ 'data' => []
386
+ ];
387
+ }
388
+
389
+ if (empty($dataArray)) {
390
+ self::_logErrors('Error message:', 'Data from source is empty', 1, $table_id);
391
+ return [
392
+ 'status' => 'error',
393
+ 'error' => 'Data from source is empty',
394
+ 'data' => []
395
+ ];
396
+ }
397
+
398
+ return [
399
+ 'status' => 'success',
400
+ 'error' => '',
401
+ 'data' => $dataArray
402
+ ];
403
+ }
404
+ }
405
+ WPDataTableCache::addAutoUpdateHooks();
templates/admin/dashboard/dashboard.inc.php CHANGED
@@ -342,8 +342,9 @@ $tableChartsCount = (int)WDTTools::getTablesCount('chart');
342
  <div class="alert alert-info m-b-0" role="alert">
343
  <i class="wpdt-icon-info-circle-full"></i>
344
  <ul>
345
- <li>CSS updates</li>
346
- <li>Other small bug fixes and stability improvements.</li>
 
347
  </ul>
348
  </div>
349
 
342
  <div class="alert alert-info m-b-0" role="alert">
343
  <i class="wpdt-icon-info-circle-full"></i>
344
  <ul>
345
+ <li><strong>Feature:</strong> Caching table data for non-server-side tables (Excel, CSV, Google sheet, XML, JSON, Nested JSON and PHP array).</li>
346
+ <li><strong>Feature:</strong> Auto update cache for non server-side tables (Excel, CSV, Google sheet, XML, JSON, Nested JSON and PHP array).</li>
347
+ <li>Other small bug fixes.</li>
348
  </ul>
349
  </div>
350
 
templates/admin/lite-vs-premium/lite_vs_premium.inc.php CHANGED
@@ -128,7 +128,6 @@
128
  </tr>
129
  <tr>
130
  <td data-title="Features"><?php esc_html_e('Create a Simple tables', 'wpdatatables'); ?>
131
- <span style="color: #ef8137;font-weight: bold;float: right;"><?php esc_html_e('NEW!', 'wpdatatables'); ?></span>
132
  <hr>
133
  </td>
134
  <td data-title="Lite" class="text-center bg-grey"><i class="wpdt-icon-check-full"></i>
@@ -141,6 +140,31 @@
141
  </tr>
142
  <tr>
143
  <td data-title="Features"><?php esc_html_e('Merge cells', 'wpdatatables'); ?>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
  <span style="color: #ef8137;font-weight: bold;float: right;"><?php esc_html_e('NEW!', 'wpdatatables'); ?></span>
145
  <hr>
146
  </td>
@@ -329,7 +353,6 @@
329
  </tr>
330
  <tr>
331
  <td data-title="Features"><?php esc_html_e('Table Customization', 'wpdatatables'); ?>
332
- <span style="color: #ef8137;font-weight: bold;float: right;"><?php esc_html_e('NEW!', 'wpdatatables'); ?></span>
333
  <hr>
334
  </td>
335
  <td data-title="Lite" class="text-center bg-grey"><i class="wpdt-icon-minus"></i>
128
  </tr>
129
  <tr>
130
  <td data-title="Features"><?php esc_html_e('Create a Simple tables', 'wpdatatables'); ?>
 
131
  <hr>
132
  </td>
133
  <td data-title="Lite" class="text-center bg-grey"><i class="wpdt-icon-check-full"></i>
140
  </tr>
141
  <tr>
142
  <td data-title="Features"><?php esc_html_e('Merge cells', 'wpdatatables'); ?>
143
+ <hr>
144
+ </td>
145
+ <td data-title="Lite" class="text-center bg-grey"><i class="wpdt-icon-check-full"></i>
146
+ <hr>
147
+ </td>
148
+ <td data-title="Premium" class="text-center bg-blue"><i
149
+ class="wpdt-icon-check-full"></i>
150
+ <hr>
151
+ </td>
152
+ </tr>
153
+ <tr>
154
+ <td data-title="Features"><?php esc_html_e('Caching data', 'wpdatatables'); ?>
155
+ <span style="color: #ef8137;font-weight: bold;float: right;"><?php esc_html_e('NEW!', 'wpdatatables'); ?></span>
156
+ <hr>
157
+ </td>
158
+ <td data-title="Lite" class="text-center bg-grey"><i class="wpdt-icon-check-full"></i>
159
+ <hr>
160
+ </td>
161
+ <td data-title="Premium" class="text-center bg-blue"><i
162
+ class="wpdt-icon-check-full"></i>
163
+ <hr>
164
+ </td>
165
+ </tr>
166
+ <tr>
167
+ <td data-title="Features"><?php esc_html_e('Auto update caching data', 'wpdatatables'); ?>
168
  <span style="color: #ef8137;font-weight: bold;float: right;"><?php esc_html_e('NEW!', 'wpdatatables'); ?></span>
169
  <hr>
170
  </td>
353
  </tr>
354
  <tr>
355
  <td data-title="Features"><?php esc_html_e('Table Customization', 'wpdatatables'); ?>
 
356
  <hr>
357
  </td>
358
  <td data-title="Lite" class="text-center bg-grey"><i class="wpdt-icon-minus"></i>
templates/admin/settings/settings.inc.php CHANGED
@@ -61,6 +61,10 @@
61
  <a href="#google-sheet-api-settings" aria-controls="google_sheet_settings" role="tab"
62
  data-toggle="html-input-premium-popover" data-placement="bottom" title="" data-content="content"><i class="wpdt-icon-star-full m-r-5" style="color: #FFC078;"></i><span class="opacity-6"><?php esc_html_e('Google Spreadsheet API settings', 'wpdatatables'); ?></span></a>
63
  </li>
 
 
 
 
64
  </ul>
65
 
66
  <div class="tab-content">
@@ -80,6 +84,10 @@
80
  <?php include 'tabs/custom_js_and_css.php' ?>
81
  <!-- /Custom JS and CSS settings tab-->
82
 
 
 
 
 
83
  </div>
84
  </div>
85
 
61
  <a href="#google-sheet-api-settings" aria-controls="google_sheet_settings" role="tab"
62
  data-toggle="html-input-premium-popover" data-placement="bottom" title="" data-content="content"><i class="wpdt-icon-star-full m-r-5" style="color: #FFC078;"></i><span class="opacity-6"><?php esc_html_e('Google Spreadsheet API settings', 'wpdatatables'); ?></span></a>
63
  </li>
64
+ <li class="cache_settings-tab">
65
+ <a href="#cache-settings" aria-controls="cache_settings" role="tab"
66
+ data-toggle="tab"><?php esc_html_e('Cache settings', 'wpdatatables'); ?></a>
67
+ </li>
68
  </ul>
69
 
70
  <div class="tab-content">
84
  <?php include 'tabs/custom_js_and_css.php' ?>
85
  <!-- /Custom JS and CSS settings tab-->
86
 
87
+ <!-- Cache settings tab-->
88
+ <?php include 'tabs/cache_settings.php' ?>
89
+ <!-- /Cache settings tab-->
90
+
91
  </div>
92
  </div>
93
 
templates/admin/settings/tabs/cache_settings.php ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php defined('ABSPATH') or die('Access denied.');
2
+ global $wpdb;
3
+ ?>
4
+
5
+ <div role="tabpanel" class="tab-pane" id="cache-settings">
6
+
7
+ <div class="row">
8
+ <div class="col-sm-6 auto-update-cache-option">
9
+ <h5 class="c-title-color m-b-2">
10
+ <?php esc_html_e('Auto update cache for tables', 'wpdatatables'); ?>
11
+ <i class=" wpdt-icon-info-circle-thin" data-toggle="tooltip" data-placement="right"
12
+ title="<?php esc_attr_e('When this is turn on, each non serverside datatables (created from Excel, CSV, XML, JSON, Nested JSON, Google Spreadsheet or PHP array), if table option "Cache table" is turn on, will be shown new option Auto update cache and you can turn on it for datatables that you need. By default it is turn off.', 'wpdatatables'); ?>"></i>
13
+ </h5>
14
+ <div class="toggle-switch" data-ts-color="blue">
15
+ <input type="checkbox" name="wdt-auto-update-option" id="wdt-auto-update-option"/>
16
+ <label for="wdt-auto-update-option" class="ts-label"><?php esc_html_e('Enable for all non-server side tables', 'wpdatatables'); ?></label>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ <div class="row auto-update-cache-instructions hidden">
21
+ <div class="col-sm-12">
22
+ <div class="alert alert-info alert-dismissible m-t-20" role="alert">
23
+ <i class="wpdt-icon-info-circle-full"></i>
24
+ <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
25
+ aria-hidden="true"><i
26
+ class="wpdt-icon-times-full"></i></span></button>
27
+ <span class="wdt-alert-title f-600">
28
+ <?php esc_html_e('Detail instruction how to set cache, auto update cache you can find on this', 'wpdatatables'); ?>
29
+ <a href="https://wpdatatables.com/documentation/table-features/caching-data-and-auto-update-cache-in-wordpress-tables/" target="_blank"><?php esc_html_e('link', 'wpdatatables'); ?></a>.
30
+ </span>
31
+ <span class="wdt-alert-subtitle m-t-20">
32
+ <p>First, you will need to create non-serverside table (created from Excel, CSV, XML, JSON, Nested JSON, Google Spreadsheet or PHP array). On <strong>"Data source"</strong> tab in table settings you will find new option <strong>"Cache Data"</strong>. When you turn on, new option will be shown <strong>"Auto update cache"</strong>. If you turn on this option in table, then you will need to set the cron job like it is explained below.</p>
33
+ <p>Auto update cache for tables requires a bit of additional configuration with your server cron scheduler. If you want to run a cron (do auto update cache) every 15 minutes, copy the command below and paste it into the cron file.</p>
34
+ <p class="m-l-20"><strong>*/15 * * * * <?php echo get_site_url(); ?>/wp-admin/admin-ajax.php?action=wdtable_update_cache&wdtable_cache_verify=<?php echo get_option('wdtAutoUpdateHash'); ?></strong></p>
35
+ <p>If that doesn’t work, please try these as well:</p>
36
+ <p class="m-l-20"><strong>*/15 * * * * wget -q -O – "<?php echo get_site_url(); ?>/wp-admin/admin-ajax.php?action=wdtable_update_cache&wdtable_cache_verify=<?php echo get_option('wdtAutoUpdateHash'); ?>"</strong></p>
37
+ <p class="m-l-20"><strong>*/15 * * * * /usr/local/bin/php ~/public_html/wp-cron.php –action='wdtable_update_cache' –wdtable_cache_verify='<?php echo get_option('wdtAutoUpdateHash'); ?>'</strong></p>
38
+ <p class="m-l-20"><strong>GET '<?php echo get_site_url(); ?>/wp-admin/admin-ajax.php?action=wdtable_update_cache&wdtable_cache_verify=<?php echo get_option('wdtAutoUpdateHash'); ?>' > /dev/null</strong></p>
39
+ <p>If you need different schedule time, you can see the more detailed tutorial on how to set up cron jobs on this <a href="https://www.taniarascia.com/setting-up-a-basic-cron-job-in-linux/" target="_blank">link</a>.</p>
40
+ <p>If you are not familiar with this, you can use the plugin <a href="https://wordpress.org/plugins/wp-crontrol/" target="_blank">WP Crontrol</a> for creating a cronjob.</p>
41
+ <p>First, copy this: <?php echo get_site_url(); ?>/wp-admin/admin-ajax.php?action=wdtable_update_cache&wdtable_cache_verify=<?php echo get_option('wdtAutoUpdateHash'); ?></p>
42
+ <p>Then, go to <strong>Tools -> Cron Events</strong> admin panel, and click on the <strong>“Cron Schedules”</strong> tab. In it, add a 15-minute interval.</p>
43
+ <p>Now go back to the <strong>“Cron Events”</strong> tab, and click on <strong>“Add New”</strong>.</p>
44
+ <p>Below it, select the <strong>“PHP Cron event”</strong> radio button, and add the URL you copied:</p>
45
+ <p class="m-l-20"><strong>file_get_contents("<?php echo get_site_url(); ?>/wp-admin/admin-ajax.php?action=wdtable_update_cache&wdtable_cache_verify=<?php echo get_option('wdtAutoUpdateHash'); ?>");</strong></p>
46
+ <p>You don’t need to provide the PHP opening tag ("&lt;?php").</p>
47
+ <p>Set the <strong>Event name</strong>, and set the next run to be <strong>“At”</strong>, and a few minutes in the future. Select the recurrence (the event you created as the first step, in WP Crontrol – the “every_15_minutes” interval) and that’s it.</p>
48
+ </span>
49
+ </div>
50
+ </div>
51
+ <div class="col-sm-12">
52
+ <div class="alert alert-info alert-dismissible" role="alert">
53
+ <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
54
+ aria-hidden="true"><i
55
+ class="wpdt-icon-times-full"></i></span></button>
56
+ <span class="wdt-alert-subtitle">
57
+ <p>If you use "Auto update cache for tables" option and your table cache is not updated, please follow these instructions for troubleshooting:</p>
58
+ <ul class="m-l-20" style="list-style: disc;">
59
+ <li>First, check in your table if options <strong>"Cache table"</strong> and <strong>"Auto update cache"</strong> are turned on.</li>
60
+ <li>Then, you can run manually this URL in browser:</li>
61
+ <li><strong><?php echo get_site_url(); ?>/wp-admin/admin-ajax.php?action=wdtable_update_cache&wdtable_cache_verify=<?php echo get_option('wdtAutoUpdateHash'); ?></strong></li>
62
+ <li>to check if auto update is working.</li>
63
+ <li>If data in table is updated, then check with your hosting provider if your cron job is set properly.</li>
64
+ <li>When that is set, you need to check if there are any errors after cron execution.</li>
65
+ <li>You can check error log on your server.</li>
66
+ <li>If you are facing some issues, contact us using this
67
+ <a href="https://tmsplugins.ticksy.com/" target="_blank"><?php esc_html_e('link', 'wpdatatables'); ?></a>.
68
+ </li>
69
+ </ul>
70
+ </span>
71
+
72
+ </div>
73
+ </div>
74
+ <div class="col-sm-12">
75
+ <button id="wdt-delete-log-errors-cache" class="btn btn-danger">
76
+ <?php esc_html_e('Delete errors log', 'wpdatatables'); ?>
77
+ </button>
78
+ </div>
79
+ </div>
80
+ </div>
81
+
82
+ <!-- Error modal -->
83
+ <?php include WDT_TEMPLATE_PATH . 'admin/common/error_modal.inc.php'; ?>
84
+ <!-- /Error modal -->
templates/admin/table-settings/table_settings_block.inc.php CHANGED
@@ -6,6 +6,7 @@
6
  * @author Alexander Gilmanov
7
  * @since 13.10.2016
8
  */
 
9
  ?>
10
 
11
  <div class="card wdt-table-settings">
@@ -198,6 +199,65 @@
198
  </div>
199
  <!-- /.row -->
200
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
  </div>
202
  <!-- /Main table settings -->
203
 
6
  * @author Alexander Gilmanov
7
  * @since 13.10.2016
8
  */
9
+ $globalAutoUpdateOption = get_option('wdtAutoUpdateOption');
10
  ?>
11
 
12
  <div class="card wdt-table-settings">
199
  </div>
200
  <!-- /.row -->
201
 
202
+ <div class="row" id="wdt-cache-block">
203
+ <div class="col-sm-3 m-b-16 hidden cache-settings-block">
204
+
205
+ <h4 class="c-title-color m-b-2">
206
+ <?php esc_html_e('Cache data', 'wpdatatables'); ?>
207
+ <i class=" wpdt-icon-info-circle-thin" data-popover-content="#cache-source-data-hint"
208
+ data-toggle="html-popover" data-trigger="hover" data-placement="right"></i>
209
+ </h4>
210
+
211
+ <!-- Hidden popover with image hint -->
212
+ <div class="hidden" id="cache-source-data-hint">
213
+ <div class="popover-heading">
214
+ <?php esc_html_e('Cache data from source', 'wpdatatables'); ?>
215
+ </div>
216
+
217
+ <div class="popover-body">
218
+ <?php esc_html_e('Enable this to cache data from source file. Available for tables created from existing data source like Excel, CSV, JSON, Nested JSON, Google Spredsheet and PHP array.', 'wpdatatables'); ?>
219
+ </div>
220
+ </div>
221
+ <!-- /Hidden popover with image hint -->
222
+
223
+ <div class="toggle-switch" data-ts-color="blue">
224
+ <input id="wpdt-cache-source-data" type="checkbox">
225
+ <label for="wpdt-cache-source-data"
226
+ class="ts-label"><?php esc_html_e('Cache data from source', 'wpdatatables'); ?></label>
227
+ </div>
228
+
229
+ </div>
230
+ <?php if ($globalAutoUpdateOption) { ?>
231
+ <div class="col-sm-3 m-b-16 hidden auto-update-cache-block">
232
+
233
+ <h4 class="c-title-color m-b-2">
234
+ <?php esc_html_e('Auto update cache', 'wpdatatables'); ?>
235
+ <i class=" wpdt-icon-info-circle-thin" data-popover-content="#auto-update-cache-hint"
236
+ data-toggle="html-popover" data-trigger="hover" data-placement="right"></i>
237
+ </h4>
238
+
239
+ <!-- Hidden popover with image hint -->
240
+ <div class="hidden" id="auto-update-cache-hint">
241
+ <div class="popover-heading">
242
+ <?php esc_html_e('Auto update cache from source', 'wpdatatables'); ?>
243
+ </div>
244
+
245
+ <div class="popover-body">
246
+ <?php esc_html_e('Enable this to auto update cache from source file.', 'wpdatatables'); ?>
247
+ </div>
248
+ </div>
249
+ <!-- /Hidden popover with image hint -->
250
+
251
+ <div class="toggle-switch" data-ts-color="blue">
252
+ <input id="wpdt-auto-update-cache" type="checkbox">
253
+ <label for="wpdt-auto-update-cache"
254
+ class="ts-label"><?php esc_html_e('Auto update cache from source', 'wpdatatables'); ?></label>
255
+ </div>
256
+
257
+ </div>
258
+ <?php } ?>
259
+ </div>
260
+
261
  </div>
262
  <!-- /Main table settings -->
263
 
wpdatatables.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: wpDataTables - Tables & Table Charts
4
  Plugin URI: https://wpdatatables.com
5
  Description: Create responsive, sortable tables & charts from Excel, CSV or PHP. Add tables & charts to any post in minutes with DataTables.
6
- Version: 2.1.41
7
  Author: TMS-Plugins
8
  Author URI: https://tms-outsource.com
9
  Text Domain: wpdatatables
@@ -51,6 +51,7 @@ function wpdatatables_load()
51
  require_once(WDT_ROOT_PATH . 'source/class.wpdatatable.php');
52
  require_once(WDT_ROOT_PATH . 'source/class.wpdatacolumn.php');
53
  require_once(WDT_ROOT_PATH . 'source/class.wpdatatablerows.php');
 
54
  require_once(WDT_ROOT_PATH . 'source/class.wpdatachart.php');
55
  require_once(WDT_ROOT_PATH . 'source/class.wdtbrowsetable.php');
56
  require_once(WDT_ROOT_PATH . 'source/class.wdtbrowsechartstable.php');
3
  Plugin Name: wpDataTables - Tables & Table Charts
4
  Plugin URI: https://wpdatatables.com
5
  Description: Create responsive, sortable tables & charts from Excel, CSV or PHP. Add tables & charts to any post in minutes with DataTables.
6
+ Version: 2.1.42
7
  Author: TMS-Plugins
8
  Author URI: https://tms-outsource.com
9
  Text Domain: wpdatatables
51
  require_once(WDT_ROOT_PATH . 'source/class.wpdatatable.php');
52
  require_once(WDT_ROOT_PATH . 'source/class.wpdatacolumn.php');
53
  require_once(WDT_ROOT_PATH . 'source/class.wpdatatablerows.php');
54
+ require_once(WDT_ROOT_PATH . 'source/class.wpdatatablecache.php');
55
  require_once(WDT_ROOT_PATH . 'source/class.wpdatachart.php');
56
  require_once(WDT_ROOT_PATH . 'source/class.wdtbrowsetable.php');
57
  require_once(WDT_ROOT_PATH . 'source/class.wdtbrowsechartstable.php');