PluginProbe
wpDataTables – WordPress Data Table, Dynamic Tables & Table Charts Plugin / trunk
wpDataTables – WordPress Data Table, Dynamic Tables & Table Charts Plugin vtrunk
6.5.1.6 6.5.1.5 6.5.1.4 6.5.1.3 6.5.1.2 6.5.1.1 6.5.0.9 6.5.0.8 6.5.0.7 6.5.0.6 trunk 3.4.2.40 3.4.2.41 3.4.2.42 3.4.2.43 3.4.2.44 3.4.2.45 3.4.2.46 3.4.2.47 3.4.2.48 3.4.2.49 3.4.2.50 6.3.2 6.3.3.1 6.3.3.10 All 46 releases
wpdatatables / source / class.wpdatatable.php

class.wpdatatable.php in wpDataTables – WordPress Data Table, Dynamic Tables & Table Charts Plugin trunk, at source/class.wpdatatable.php

3,116 lines 109.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use PhpOffice\PhpSpreadsheet\Reader\Xlsx;
4 use PhpOffice\PhpSpreadsheet\Reader\Xls;
5 use PhpOffice\PhpSpreadsheet\Reader\Ods;
6 use PhpOffice\PhpSpreadsheet\Reader\Csv;
7 use PhpOffice\PhpSpreadsheet\Shared\Date;
8
9 defined('ABSPATH') or die("Cannot access pages directly.");
10
11
12 /**
13 * Main engine of wpDataTables plugin
14 */
15 class WPDataTable
16 {
17
18 protected static $_columnClass = 'WDTColumn';
19 protected $_wdtIndexedColumns = array();
20 private $_wdtNamedColumns = array();
21 private $_defaultSortColumn;
22 private $_defaultSortDirection = 'ASC';
23 private $_tableContent = '';
24 private $_tableType = '';
25 private $_fileLocation = 'wp_media_lib';
26 private $_title = '';
27 private $_table_description = '';
28 private $_show_table_description = false;
29 private $_interfaceLanguage;
30 private $_responsive = false;
31 private $_responsiveAction = 'icon';
32 private $_scrollable = false;
33 private $_inlineEditing = false;
34 private $_popoverTools = false;
35 private $_no_data = false;
36 private $_filtering_form = false;
37 private $_hide_before_load = false;
38 public static $wdt_internal_idcount = 0;
39 public static $modalRendered = false;
40 private $_showFilter = true;
41 private $_firstOnPage = false;
42 private $_groupingEnabled = false;
43 private $_wdtColumnGroupIndex = 0;
44 private $_cache_source_data = false;
45 private $_auto_update_cache = false;
46 private $_showAdvancedFilter = false;
47 private $_wdtTableSort = true;
48 private $_serverProcessing = false;
49 private $_wdtColumnTypes = array();
50 private $_dataRows = array();
51 public $_cacheHash = '';
52 private $_showTT = true;
53 private $_lengthDisplay = 10;
54 private $_cssClassArray = array();
55 private $_style = '';
56 private $_editable = false;
57 private $_id;
58 private $_idColumnKey = '';
59 private $_db;
60 private $_wpId = '';
61 private $_onlyOwnRows = false;
62 private $_userIdColumn = 0;
63 private $_defaultSearchValue = '';
64 protected $_sumColumns = array();
65 protected $_avgColumns = array();
66 protected $_minColumns = array();
67 protected $_maxColumns = array();
68 protected $_sumFooterColumns = array();
69 protected $_avgFooterColumns = array();
70 protected $_minFooterColumns = array();
71 protected $_maxFooterColumns = array();
72 protected $_columnsDecimalPlaces = array();
73 protected $_columnsThousandsSeparator = array();
74 protected $_conditionalFormattingColumns = array();
75 private $_fixedLayout = false;
76 private $_wordWrap = false;
77 private $_columnsCSS = '';
78 private $_showTableToolsIncludeHTML = 0;
79 private $_showTableToolsIncludeTitle = 0;
80 private $_tableToolsConfig = array();
81 private $_autoRefreshInterval = 0;
82 private $_infoBlock = true;
83 private $_pagination = true;
84 private $_paginationAlign = 'right';
85 private $_paginationLayout = 'full_numbers';
86 private $_paginationLayoutMobile = 'simple';
87
88 private $_simpleResponsive = false;
89 private $_verticalScroll = false;
90 private $_simpleHeader = false;
91 private $_stripeTable= false;
92 private $_cellPadding= 10;
93 private $_removeBorders = false;
94 private $_borderCollapse = 'collapse';
95 private $_borderSpacing = 0;
96 private $_verticalScrollHeight= 600;
97 private $_globalSearch = true;
98 private $_showRowsPerPage = true;
99 private $_aggregateFuncsRes = array();
100 private $_ajaxReturn = false;
101 private $_clearFilters = false;
102 private $_pdfPaperSize = 'A4';
103 private $_pdfPageOrientation = 'portrait';
104 private $_table_wcag = 0;
105 public $column_id;
106 private $_simple_template_id = 0;
107 private $_pagination_top = 0;
108 public static $allowedTableTypes = array('xls', 'csv', 'manual', 'mysql', 'json','nested_json', 'google_spreadsheet', 'xml', 'serialized', 'simple');
109
110 /**
111 * @return bool
112 */
113 public function isClearFilters()
114 {
115 return $this->_clearFilters;
116 }
117
118 /**
119 * @return array
120 */
121 public function getWdtColumnTypes()
122 {
123 return $this->_wdtColumnTypes;
124 }
125
126 /**
127 * @param bool $clearFilters
128 */
129 public function setClearFilters($clearFilters)
130 {
131 $this->_clearFilters = $clearFilters;
132 }
133
134 /**
135 * @return bool
136 */
137 public function isFixedLayout()
138 {
139 return $this->_fixedLayout;
140 }
141
142 /**
143 * @param bool $fixedLayout
144 */
145 public function setFixedLayout($fixedLayout)
146 {
147 $this->_fixedLayout = $fixedLayout;
148 }
149
150 /**
151 * @return bool
152 */
153 public function isWordWrap()
154 {
155 return $this->_wordWrap;
156 }
157
158 /**
159 * @param bool $wordWrap
160 */
161 public function setWordWrap($wordWrap)
162 {
163 $this->_wordWrap = $wordWrap;
164 }
165
166 /**
167 * @return bool
168 */
169 public function isAjaxReturn()
170 {
171 return $this->_ajaxReturn;
172 }
173
174 /**
175 * @param bool $ajaxReturn
176 */
177 public function setAjaxReturn($ajaxReturn)
178 {
179 $this->_ajaxReturn = $ajaxReturn;
180 }
181
182 public function setNoData($no_data)
183 {
184 $this->_no_data = $no_data;
185 }
186
187 public function getNoData()
188 {
189 return $this->_no_data;
190 }
191
192 public function getId()
193 {
194 return $this->_id;
195 }
196
197 public function setId($id)
198 {
199 $this->_id = $id;
200 }
201
202 /**
203 * @return string
204 */
205 public function getTableContent()
206 {
207 return $this->_tableContent;
208 }
209
210 /**
211 * @param string $tableContent
212 */
213 public function setTableContent($tableContent)
214 {
215 $this->_tableContent = $tableContent;
216 }
217
218 /**
219 * @return string
220 */
221
222 public function getFileLocation() {
223 return $this->_fileLocation;
224 }
225
226 /**
227 * @param string $fileLocation
228 */
229 public function setFileLocation($fileLocation) {
230 $this->_fileLocation = $fileLocation;
231 }
232
233 /**
234 * @return string
235 */
236 public function getTableType()
237 {
238 return $this->_tableType;
239 }
240
241 /**
242 * @param string $tableType
243 */
244 public function setTableType($tableType)
245 {
246 $this->_tableType = $tableType;
247 }
248
249 public function setDefaultSearchValue($value)
250 {
251 if (!empty($value)) {
252 $this->_defaultSearchValue = urlencode($value);
253 }
254 }
255
256 public function getDefaultSearchValue()
257 {
258 return urldecode($this->_defaultSearchValue);
259 }
260
261 public function sortEnabled()
262 {
263 return $this->_wdtTableSort;
264 }
265
266 public function sortEnable()
267 {
268 $this->_wdtTableSort = true;
269 }
270
271 public function sortDisable()
272 {
273 $this->_wdtTableSort = false;
274 }
275
276 public function addSumColumn($columnKey)
277 {
278 $this->_sumColumns[] = $columnKey;
279 }
280
281 public function setSumColumns($sumColumns)
282 {
283 $this->_sumColumns = $sumColumns;
284 }
285
286 public function getSumColumns()
287 {
288 return $this->_sumColumns;
289 }
290
291 public function addAvgColumn($columnKey)
292 {
293 $this->_avgColumns[] = $columnKey;
294 }
295
296 public function setAvgColumns($avgColumns)
297 {
298 $this->_avgColumns = $avgColumns;
299 }
300
301 public function getAvgColumns()
302 {
303 return $this->_avgColumns;
304 }
305
306 public function addMinColumn($columnKey)
307 {
308 $this->_minColumns[] = $columnKey;
309 }
310
311 public function setMinColumns($minColumns)
312 {
313 $this->_minColumns = $minColumns;
314 }
315
316 public function getMinColumns()
317 {
318 return $this->_minColumns;
319 }
320
321 public function addMaxColumn($columnKey)
322 {
323 $this->_maxColumns[] = $columnKey;
324 }
325
326 public function setMaxColumns($maxColumns)
327 {
328 $this->_maxColumns = $maxColumns;
329 }
330
331 public function getMaxColumns()
332 {
333 return $this->_maxColumns;
334 }
335
336 public function addSumFooterColumn($columnKey)
337 {
338 $this->_sumFooterColumns[] = $columnKey;
339 }
340
341 public function setSumFooterColumns($sumColumns)
342 {
343 $this->_sumFooterColumns = $sumColumns;
344 }
345
346 public function getSumFooterColumns()
347 {
348 return $this->_sumFooterColumns;
349 }
350
351 public function addAvgFooterColumn($columnKey)
352 {
353 $this->_avgFooterColumns[] = $columnKey;
354 }
355
356 public function setAvgFooterColumns($avgColumns)
357 {
358 $this->_avgFooterColumns = $avgColumns;
359 }
360
361 public function getAvgFooterColumns()
362 {
363 return $this->_avgFooterColumns;
364 }
365
366 public function addMinFooterColumn($columnKey)
367 {
368 $this->_minFooterColumns[] = $columnKey;
369 }
370
371 public function setMinFooterColumns($minColumns)
372 {
373 $this->_minFooterColumns = $minColumns;
374 }
375
376 public function getMinFooterColumns()
377 {
378 return $this->_minFooterColumns;
379 }
380
381 public function addMaxFooterColumn($columnKey)
382 {
383 $this->_maxFooterColumns[] = $columnKey;
384 }
385
386 public function setMaxFooterColumns($maxColumns)
387 {
388 $this->_maxFooterColumns = $maxColumns;
389 }
390
391 public function getMaxFooterColumns()
392 {
393 return $this->_maxFooterColumns;
394 }
395
396 public function addColumnsDecimalPlaces($columnKey, $decimalPlaces)
397 {
398 $this->_columnsDecimalPlaces[$columnKey] = $decimalPlaces;
399 }
400
401 public function addColumnsThousandsSeparator($columnKey, $thousandsSeparator)
402 {
403 $this->_columnsThousandsSeparator[$columnKey] = $thousandsSeparator;
404 }
405
406 public function getColumnsCSS()
407 {
408 return $this->_columnsCSS;
409 }
410
411 public function setColumnsCss($css)
412 {
413 $this->_columnsCSS = $css;
414 }
415
416 public function reorderColumns($posArray)
417 {
418 if (!is_array($posArray)) {
419 throw new WDTException('Invalid position data provided!');
420 }
421 $resultArray = array();
422 $resultByKeys = array();
423
424 foreach ($posArray as $pos => $dataColumnIndex) {
425 $resultArray[$pos] = $this->_wdtNamedColumns[$dataColumnIndex];
426 $resultByKeys[$dataColumnIndex] = $this->_wdtNamedColumns[$dataColumnIndex];
427 }
428 $this->_wdtIndexedColumns = $resultArray;
429 $this->_wdtNamedColumns = $resultByKeys;
430 }
431
432 public function getWpId()
433 {
434 return $this->_wpId;
435 }
436
437 public function setWpId($wpId)
438 {
439 $this->_wpId = $wpId;
440 }
441 public function isTableWCAG()
442 {
443 return $this->_table_wcag;
444 }
445 public function setTableWCAG($tableWCAG)
446 {
447 $this->_table_wcag = $tableWCAG;
448 }
449 public function getCssClassesArr()
450 {
451 $classesStr = $this->_cssClassArray;
452 $classesStr = apply_filters('wpdatatables_filter_table_cssClassArray', $classesStr, $this->getWpId());
453 return implode(' ', $classesStr);
454 }
455
456 public function getCSSClasses()
457 {
458 return implode(' ', $this->_cssClassArray);
459 }
460
461 public function addCSSClass($cssClass)
462 {
463 $this->_cssClassArray[] = $cssClass;
464 }
465
466 public function getCSSStyle()
467 {
468 return $this->_style;
469 }
470
471 public function setCSSStyle($style)
472 {
473 $this->_style = $style;
474 }
475
476 public function setTitle($title)
477 {
478 $this->_title = $title;
479 }
480
481 public function getName()
482 {
483 return $this->_title;
484 }
485 public function setDescription($description) {
486 $this->_table_description = $description;
487 }
488
489 public function getDescription() {
490 return $this->_table_description;
491 }
492 public function setShowDescription($show_description) {
493 if ($show_description) {
494 $this->_show_table_description = true;
495 } else {
496 $this->_show_table_description = false;
497 }
498 }
499 public function getShowDescription() {
500 return $this->_show_table_description ;
501 }
502 public function setScrollable($scrollable)
503 {
504 if ($scrollable) {
505 $this->_scrollable = true;
506 } else {
507 $this->_scrollable = false;
508 }
509 }
510
511 public function isScrollable()
512 {
513 return $this->_scrollable;
514 }
515
516 public function setVerticalScroll($verticalScroll) {
517 if ($verticalScroll) {
518 $this->_verticalScroll = true;
519 } else {
520 $this->_verticalScroll = false;
521 }
522 }
523
524 public function isVerticalScroll() {
525 return $this->_verticalScroll;
526 }
527
528 /**
529 * @throws WDTException
530 */
531 public function setInterfaceLanguage($lang)
532 {
533 if (empty($lang)) {
534 throw new WDTException('Incorrect language parameter!');
535 }
536
537 // Security Fix: Prevent Path Traversal / LFI attacks (CVE-2026-28039)
538 // Remove any path traversal attempts and allow only valid filenames
539 $lang = basename($lang);
540
541 // Additional security: Only allow .inc.php extension
542 if (substr($lang, -8) !== '.inc.php') {
543 throw new WDTException('Invalid language file format!');
544 }
545
546 // Build the safe path
547 $safePath = WDT_ROOT_PATH . 'source/lang/' . $lang;
548
549 // Verify the resolved path is still within the lang directory
550 $realPath = realpath($safePath);
551 $realLangDir = rtrim(realpath(WDT_ROOT_PATH . 'source/lang/'), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
552
553 if ($realPath === false || strpos($realPath, $realLangDir) !== 0) {
554 throw new WDTException('Language file not found or path traversal detected!');
555 }
556
557 $this->_interfaceLanguage = $realPath;
558 }
559
560 public function getInterfaceLanguage()
561 {
562 return $this->_interfaceLanguage;
563 }
564
565 public function setAutoRefresh($refresh_interval)
566 {
567 $this->_autoRefreshInterval = (int)$refresh_interval;
568 }
569
570 public function getRefreshInterval()
571 {
572 return (int)$this->_autoRefreshInterval;
573 }
574
575 /**
576 * @param boolean $paginationOnTop
577 */
578 public function setPaginationOnTop($paginationOnTop)
579 {
580 $this->_pagination_top = (int)$paginationOnTop;
581 }
582 public function getPaginationOnTop()
583 {
584 return $this->_pagination_top;
585 }
586
587 public function paginationEnabled()
588 {
589 return $this->_pagination;
590 }
591
592 public function enablePagination()
593 {
594 $this->_pagination = true;
595 }
596
597 public function disablePagination()
598 {
599 $this->_pagination = false;
600 }
601
602 public function enableTT()
603 {
604 $this->_showTT = true;
605 }
606
607 public function disableTT()
608 {
609 $this->_showTT = false;
610 }
611
612 public function TTEnabled()
613 {
614 return $this->_showTT;
615 }
616
617 public function getTableToolsIncludeHTML()
618 {
619 return $this->_showTableToolsIncludeHTML;
620 }
621 public function setTableToolsIncludeHTML($showTableToolsIncludeHTML)
622 {
623 $this->_showTableToolsIncludeHTML = $showTableToolsIncludeHTML;
624 }
625
626 public function getTableToolsIncludeTitle()
627 {
628 return $this->_showTableToolsIncludeTitle;
629 }
630
631 public function setTableToolsIncludeTitle($showTableToolsIncludeTitle)
632 {
633 $this->_showTableToolsIncludeTitle = $showTableToolsIncludeTitle;
634 }
635
636 public function hideToolbar()
637 {
638 $this->_toolbar = false;
639 }
640
641 public function setDefaultSortColumn($key)
642 {
643 if (!isset($this->_wdtIndexedColumns[$key])
644 && !isset($this->_wdtNamedColumns[$key])
645 ) {
646 throw new WDTException('Incorrect column index');
647 }
648
649 if (!is_numeric($key)) {
650 $key = array_search($key, array_keys($this->_wdtNamedColumns));
651 }
652 $this->_defaultSortColumn = $key;
653 }
654
655 public function getDefaultSortColumn()
656 {
657 return $this->_defaultSortColumn;
658 }
659
660 public function setDefaultSortDirection($direction)
661 {
662 if (
663 !in_array(
664 $direction,
665 array(
666 'ASC',
667 'DESC'
668 )
669 )
670 ) {
671 return false;
672 }
673 $this->_defaultSortDirection = $direction;
674 }
675
676 public function getDefaultSortDirection()
677 {
678 return $this->_defaultSortDirection;
679 }
680
681 public function hideBeforeLoad()
682 {
683 $this->setCSSStyle('display: none; ');
684 $this->_hide_before_load = true;
685 }
686
687 public function showBeforeLoad()
688 {
689 $this->_hide_before_load = false;
690 }
691
692 public function doHideBeforeLoad()
693 {
694 return $this->_hide_before_load;
695 }
696
697 public function getDisplayLength()
698 {
699 return $this->_lengthDisplay;
700 }
701
702 public function setDisplayLength($length)
703 {
704 if (!in_array($length, array(1, 5, 10, 20, 25, 30, 50, 100, 200, -1))) {
705 return false;
706 }
707 $this->_lengthDisplay = $length;
708 }
709
710 public function setIdColumnKey($key)
711 {
712 $this->_idColumnKey = $key;
713 }
714
715 public function getIdColumnKey()
716 {
717 return $this->_idColumnKey;
718 }
719
720 /**
721 * @return boolean
722 */
723 public function isInfoBlock()
724 {
725 return $this->_infoBlock;
726 }
727
728 /**
729 * @param boolean $infoBlock
730 */
731 public function setInfoBlock($infoBlock)
732 {
733 $this->_infoBlock = (bool)$infoBlock;
734 }
735
736 /**
737 * @return bool
738 */
739 public function isPagination()
740 {
741 return $this->_pagination;
742 }
743
744 /**
745 * @param bool $pagination
746 */
747 public function setPagination($pagination)
748 {
749 $this->_pagination = $pagination;
750 }
751
752 /**
753 * @return string
754 */
755 public function getPaginationAlign()
756 {
757 return $this->_paginationAlign;
758 }
759
760 /**
761 * @param string $paginationAlign
762 */
763 public function setPaginationAlign($paginationAlign)
764 {
765 $this->_paginationAlign = $paginationAlign;
766 if (wp_is_mobile()) {
767 $this->_paginationAlign = 'center';
768 }
769 }
770
771 /**
772 * @return string
773 */
774 public function getPaginationLayout()
775 {
776 return $this->_paginationLayout;
777 }
778
779 /**
780 * @param string $paginationLayout
781 */
782 public function setPaginationLayout($paginationLayout)
783 {
784 $this->_paginationLayout = $paginationLayout;
785 }
786
787 /**
788 * @return string
789 */
790 public function getPaginationLayoutMobile()
791 {
792 return $this->_paginationLayoutMobile;
793 }
794
795 /**
796 * @param string $paginationLayout
797 */
798 public function setPaginationLayoutMobile($paginationLayout)
799 {
800 $this->_paginationLayoutMobile = $paginationLayout;
801 }
802
803 /**
804 * @return boolean
805 */
806 public function isSimpleResponsive() {
807 return $this->_simpleResponsive;
808 }
809
810 /**
811 * @param boolean $simpleResponsive
812 */
813 public function setSimpleResponsive($simpleResponsive) {
814 $this->_simpleResponsive = (bool)$simpleResponsive;
815 }
816
817 /**
818 * @return boolean
819 */
820 public function isSimpleHeader() {
821 return $this->_simpleHeader;
822 }
823
824 /**
825 * @param boolean $simpleHeader
826 */
827 public function setSimpleHeader($simpleHeader) {
828 $this->_simpleHeader = (bool)$simpleHeader;
829 }
830
831 /**
832 * @return boolean
833 */
834 public function isStripeTable() {
835 return $this->_stripeTable;
836 }
837
838 /**
839 * @param boolean $stripeTable
840 */
841 public function setStripeTable($stripeTable) {
842 $this->_stripeTable = (bool)$stripeTable;
843 }
844
845 /**
846 * @return boolean
847 */
848 public function getCellPadding() {
849 return $this->_cellPadding;
850 }
851
852 /**
853 * @param boolean $cellPadding
854 */
855 public function setCellPadding($cellPadding) {
856 $this->_cellPadding = (bool)$cellPadding;
857 }
858
859 /**
860 * @return boolean
861 */
862 public function isRemoveBorders()
863 {
864 return $this->_removeBorders;
865 }
866
867 /**
868 * @param boolean $removeBorders
869 */
870 public function setRemoveBorders($removeBorders)
871 {
872 $this->_removeBorders = (bool)$removeBorders;
873 }
874
875 /**
876 * @return string
877 */
878 public function getBorderCollapse()
879 {
880 return $this->_borderCollapse;
881 }
882
883 /**
884 * @param string $borderCollapse
885 */
886 public function setBorderCollapse($borderCollapse)
887 {
888 $this->_borderCollapse = $borderCollapse;
889 }
890
891 /**
892 * @return int
893 */
894 public function getBorderSpacing()
895 {
896 return $this->_borderSpacing;
897 }
898
899 /**
900 * @param int $borderSpacing
901 */
902 public function setBorderSpacing($borderSpacing)
903 {
904 $this->_borderSpacing = (int)$borderSpacing;
905 }
906 /**
907 * @return boolean
908 */
909 public function getVerticalScrollHeight() {
910 return $this->_verticalScrollHeight;
911 }
912
913 /**
914 * @param boolean $verticalScrollHeight
915 */
916 public function setVerticalScrollHeight($verticalScrollHeight) {
917 $this->_verticalScrollHeight = (bool)$verticalScrollHeight;
918 }
919
920 /**
921 * @return boolean
922 */
923 public function isGlobalSearch()
924 {
925 return $this->_globalSearch;
926 }
927
928 /**
929 * @param boolean $globalSearch
930 */
931 public function setGlobalSearch($globalSearch)
932 {
933 $this->_globalSearch = (bool)$globalSearch;
934 }
935
936 /**
937 * @return boolean
938 */
939 public function isShowRowsPerPage()
940 {
941 return $this->_showRowsPerPage;
942 }
943
944 /**
945 * @param boolean $showRowsPerPage
946 */
947 public function setShowRowsPerPage($showRowsPerPage)
948 {
949 $this->_showRowsPerPage = (bool)$showRowsPerPage;
950 }
951
952 /**
953 * @return string
954 */
955 public function getPdfPaperSize()
956 {
957 return $this->_pdfPaperSize;
958 }
959
960 /**
961 * @param string $pdfPaperSize
962 */
963 public function setPdfPaperSize($pdfPaperSize)
964 {
965 $this->_pdfPaperSize = $pdfPaperSize;
966 }
967
968 /**
969 * @return string
970 */
971 public function getPdfPageOrientation()
972 {
973 return $this->_pdfPageOrientation;
974 }
975
976 /**
977 * @param string $pdfPageOrientation
978 */
979 public function setPdfPageOrientation($pdfPageOrientation)
980 {
981 $this->_pdfPageOrientation = $pdfPageOrientation;
982 }
983
984 public function getSimpleTemplateId()
985 {
986 return $this->_simple_template_id;
987 }
988
989 public function setSimpleTemplateId($simple_template_id)
990 {
991 $this->_simple_template_id = $simple_template_id;
992 }
993
994 public function __construct()
995 {
996 if (self::$wdt_internal_idcount == 0) {
997 $this->_firstOnPage = true;
998 }
999 self::$wdt_internal_idcount++;
1000 $this->_id = 'table_' . self::$wdt_internal_idcount;
1001 }
1002
1003 public function wdtDefineColumnsWidth($widthsArray)
1004 {
1005 if (empty($this->_wdtIndexedColumns)) {
1006 throw new WDTException('wpDataTable reports no columns are defined!');
1007 }
1008 if (!is_array($widthsArray)) {
1009 throw new WDTException('Incorrect parameter passed!');
1010 }
1011 if (wdtTools::isArrayAssoc($widthsArray)) {
1012 foreach ($widthsArray as $name => $value) {
1013 if (!isset($this->_wdtNamedColumns[$name])) {
1014 continue;
1015 }
1016 $this->_wdtNamedColumns[$name]->setWidth($value);
1017 }
1018 } else {
1019 // if width is provided in indexed array
1020 foreach ($widthsArray as $name => $value) {
1021 $this->_wdtIndexedColumns[$name]->setWidth($value);
1022 }
1023 }
1024 }
1025
1026 public function setColumnsPossibleValues($valuesArray)
1027 {
1028 if (empty($this->_wdtIndexedColumns)) {
1029 throw new WDTException('No columns in the table!');
1030 }
1031 if (!is_array($valuesArray)) {
1032 throw new WDTException('Valid array of width values is required!');
1033 }
1034 if (WDTTools::isArrayAssoc($valuesArray)) {
1035 foreach ($valuesArray as $key => $value) {
1036 if (!isset($this->_wdtNamedColumns[$key])) {
1037 continue;
1038 }
1039 $possibleValues = $this->_wdtNamedColumns[$key]->getPossibleValues();
1040 if (empty($possibleValues)) {
1041 $this->_wdtNamedColumns[$key]->setPossibleValues($value);
1042 }
1043 }
1044 } else {
1045 foreach ($valuesArray as $key => $value) {
1046 $this->_wdtIndexedColumns[$key]->setPossibleValues($value);
1047 }
1048 }
1049 }
1050
1051 public function getHiddenColumnCount()
1052 {
1053 $count = 0;
1054 foreach ($this->_wdtIndexedColumns as $dataColumn) {
1055 if (!$dataColumn->isVisible()) {
1056 $count++;
1057 }
1058 }
1059 return $count;
1060 }
1061
1062 public function setResponsive($responsive) {
1063 if ($responsive) {
1064 $this->_responsive = true;
1065 } else {
1066 $this->_responsive = false;
1067 }
1068 }
1069
1070 public function isResponsive() {
1071 return $this->_responsive;
1072 }
1073
1074 /**
1075 * @return string
1076 */
1077 public function getResponsiveAction()
1078 {
1079 return $this->_responsiveAction;
1080 }
1081
1082 /**
1083 * @param string $responsiveAction
1084 */
1085 public function setResponsiveAction($responsiveAction)
1086 {
1087 $this->_responsiveAction = $responsiveAction;
1088 }
1089
1090 public function setCacheSourceData($cacheSourceData) {
1091 $this->_cache_source_data = (bool)$cacheSourceData;
1092 }
1093
1094 public function getCacheSourceData() {
1095 return $this->_cache_source_data;
1096 }
1097
1098 public function setAutoUpdateCache($autoUpdateCache) {
1099 $this->_auto_update_cache = (bool)$autoUpdateCache;
1100 }
1101
1102 public function getAutoUpdateCache() {
1103 return $this->_auto_update_cache;
1104 }
1105
1106
1107 public function enableGrouping()
1108 {
1109 $this->_groupingEnabled = true;
1110 }
1111
1112 public function disableGrouping()
1113 {
1114 $this->_groupingEnabled = false;
1115 }
1116
1117 public function groupingEnabled()
1118 {
1119 return $this->_groupingEnabled;
1120 }
1121
1122 public function groupByColumn($key)
1123 {
1124 if (!isset($this->_wdtIndexedColumns[$key])
1125 && !isset($this->_wdtNamedColumns[$key])
1126 ) {
1127 throw new WDTException('Column not found!');
1128 }
1129
1130 if (!is_numeric($key)) {
1131 $key = array_search(
1132 $key,
1133 array_keys($this->_wdtNamedColumns)
1134 );
1135 }
1136
1137 $this->enableGrouping();
1138 $this->_wdtColumnGroupIndex = $key;
1139 }
1140
1141 /**
1142 * Returns the index of grouping column
1143 */
1144 public function groupingColumnIndex()
1145 {
1146 return $this->_wdtColumnGroupIndex;
1147 }
1148
1149 /**
1150 * Returns the grouping column index
1151 */
1152 public function groupingColumn()
1153 {
1154 return $this->_wdtColumnGroupIndex;
1155 }
1156
1157 public function countColumns()
1158 {
1159 return count($this->_wdtIndexedColumns);
1160 }
1161
1162 public function getColumnKeys()
1163 {
1164 return array_keys($this->_wdtNamedColumns);
1165 }
1166
1167 public function setOnlyOwnRows($ownRows)
1168 {
1169 $this->_onlyOwnRows = (bool)$ownRows;
1170 }
1171
1172 public function getOnlyOwnRows()
1173 {
1174 return $this->_onlyOwnRows;
1175 }
1176
1177 public function setUserIdColumn($column)
1178 {
1179 $this->_userIdColumn = $column;
1180 }
1181
1182 public function getUserIdColumn()
1183 {
1184 return $this->_userIdColumn;
1185 }
1186
1187 public function getColumns()
1188 {
1189 return $this->_wdtIndexedColumns;
1190 }
1191
1192 public function getColumnsByHeaders()
1193 {
1194 return $this->_wdtNamedColumns;
1195 }
1196
1197 public function addConditionalFormattingColumn($column)
1198 {
1199 $this->_conditionalFormattingColumns[] = $column;
1200 }
1201
1202 public function getConditionalFormattingColumns()
1203 {
1204 return $this->_conditionalFormattingColumns;
1205 }
1206
1207 public function createColumnsFromArr($headerArr, $wdtParameters, $wdtColumnTypes)
1208 {
1209 foreach ($headerArr as $key) {
1210 $dataColumnProperties = array();
1211 $dataColumnProperties['title'] = isset($wdtParameters['columnTitles'][$key]) ? $wdtParameters['columnTitles'][$key] : $key;
1212 $dataColumnProperties['width'] = !empty($wdtParameters['columnWidths'][$key]) ? $wdtParameters['columnWidths'][$key] : '';
1213 $dataColumnProperties['sorting'] = isset($wdtParameters['sorting'][$key]) ? $wdtParameters['sorting'][$key] : true;
1214 $dataColumnProperties['decimalPlaces'] = isset($wdtParameters['decimalPlaces'][$key]) ? $wdtParameters['decimalPlaces'][$key] : get_option('wdtDecimalPlaces');
1215 $dataColumnProperties['orig_header'] = $key;
1216 $dataColumnProperties['exactFiltering'] = !empty($wdtParameters['exactFiltering'][$key]) ? $wdtParameters['exactFiltering'][$key] : false;
1217 $dataColumnProperties['filterLabel'] = isset($wdtParameters['filterLabel'][$key]) ? $wdtParameters['filterLabel'][$key] : null;
1218 $dataColumnProperties['filterDefaultValue'] = isset($wdtParameters['filterDefaultValue'][$key]) ? $wdtParameters['filterDefaultValue'][$key] : null;
1219 $dataColumnProperties['possibleValuesType'] = !empty($wdtParameters['possibleValuesType'][$key]) ? $wdtParameters['possibleValuesType'][$key] : 'read';
1220 $dataColumnProperties['possibleValuesAddEmpty'] = !empty($wdtParameters['possibleValuesAddEmpty'][$key]) ? $wdtParameters['possibleValuesAddEmpty'][$key] : false;
1221 $dataColumnProperties['foreignKeyRule'] = isset($wdtParameters['foreignKeyRule'][$key]) ? $wdtParameters['foreignKeyRule'][$key] : '';
1222 $dataColumnProperties['editingDefaultValue'] = isset($wdtParameters['editingDefaultValue'][$key]) ? $wdtParameters['editingDefaultValue'][$key] : '';
1223 $dataColumnProperties['linkTargetAttribute'] = isset($wdtParameters['linkTargetAttribute'][$key]) ? $wdtParameters['linkTargetAttribute'][$key] : '';
1224 $dataColumnProperties['linkNofollowAttribute'] = isset($wdtParameters['linkNofollowAttribute'][$key]) ? $wdtParameters['linkNofollowAttribute'][$key] : false;
1225 $dataColumnProperties['linkNoreferrerAttribute'] = isset($wdtParameters['linkNoreferrerAttribute'][$key]) ? $wdtParameters['linkNoreferrerAttribute'][$key] : false;
1226 $dataColumnProperties['linkSponsoredAttribute'] = isset($wdtParameters['linkSponsoredAttribute'][$key]) ? $wdtParameters['linkSponsoredAttribute'][$key] : false;
1227 $dataColumnProperties['linkButtonAttribute'] = isset($wdtParameters['linkButtonAttribute'][$key]) ? $wdtParameters['linkButtonAttribute'][$key] : false;
1228 $dataColumnProperties['linkButtonLabel'] = isset($wdtParameters['linkButtonLabel'][$key]) ? $wdtParameters['linkButtonLabel'][$key] : '';
1229 $dataColumnProperties['linkButtonClass'] = isset($wdtParameters['linkButtonClass'][$key]) ? $wdtParameters['linkButtonClass'][$key] : '';
1230 $dataColumnProperties['globalSearchColumn'] = isset($wdtParameters['globalSearchColumn'][$key]) ? $wdtParameters['globalSearchColumn'][$key] : false;
1231 $dataColumnProperties['parentTable'] = $this;
1232
1233 /** @var WDTColumn $tableColumnClass */
1234 $tableColumnClass = static::$_columnClass;
1235
1236 if (isset($wdtColumnTypes[$key])) {
1237 /** @var WDTColumn $dataColumn */
1238 $dataColumn = $tableColumnClass::generateColumn($wdtColumnTypes[$key], $dataColumnProperties);
1239
1240 if ($wdtColumnTypes[$key] === 'formula') {
1241 /** @var FormulaWDTColumn $dataColumn */
1242 if (!empty($wdtParameters['columnFormulas'][$key])) {
1243 $dataColumn->setFormula($wdtParameters['columnFormulas'][$key]);
1244 if ($this->serverSide()) {
1245 $dataColumn->setSorting(false);
1246 $dataColumn->setSearchable(false);
1247 }
1248 } else {
1249 $dataColumn->setFormula('');
1250 }
1251 }
1252 }
1253
1254 if ($dataColumn && $dataColumn->getPossibleValuesType() == 'foreignkey' && $dataColumn->getForeignKeyRule() != null) {
1255 $foreignKeyData = $this->joinWithForeignWpDataTable($dataColumn->getOriginalHeader(), $dataColumn->getForeignKeyRule(), $this->getDataRows());
1256 $this->_dataRows = $foreignKeyData['dataRows'];
1257 $dataColumn->setPossibleValues($foreignKeyData['distinctValues']);
1258 }
1259
1260 $this->_wdtIndexedColumns[] = $dataColumn;
1261 $this->_wdtNamedColumns[$key] = &$this->_wdtIndexedColumns[count($this->_wdtIndexedColumns) - 1];
1262 }
1263
1264 }
1265
1266 public function getColumnHeaderOffset($key)
1267 {
1268 $keys = $this->getColumnKeys();
1269 if (!empty($key) && in_array($key, $keys)) {
1270 return array_search($key, $keys);
1271 } else {
1272 return -1;
1273 }
1274 }
1275
1276 public function getColumnDefinitions()
1277 {
1278 $defs = array();
1279 foreach ($this->_wdtIndexedColumns as $key => &$dataColumn) {
1280 $def = $dataColumn->getColumnJSON($key);
1281 $def->aTargets = array($key);
1282 $defs[] = json_encode($def);
1283 }
1284 return implode(', ', $defs);
1285 }
1286
1287 /**
1288 * Get column filter definitions
1289 *
1290 * @return string
1291 */
1292 public function getColumnFilterDefinitions()
1293 {
1294 $columnDefinitions = array();
1295 foreach ($this->_wdtIndexedColumns as $key => $dataColumn) {
1296
1297 /** @var WDTColumn $dataColumn */
1298 $columnDefinition = $dataColumn->getJSFilterDefinition();
1299
1300 if ($this->getFilteringForm()) {
1301 $columnDefinition->sSelector = '#' . $this->getId() . '_' . $key . '_filter';
1302 }
1303
1304 $columnDefinitions[] = json_encode($columnDefinition);
1305 }
1306 return implode(', ', $columnDefinitions);
1307 }
1308
1309
1310 /**
1311 * Get WDTColumn by column original header
1312 *
1313 * @param $originalHeader
1314 * @return bool|mixed
1315 */
1316 public function getColumn($originalHeader)
1317 {
1318 if (!isset($originalHeader)
1319 || (!isset($this->_wdtNamedColumns[$originalHeader])
1320 && !isset($this->_wdtIndexedColumns[$originalHeader]))
1321 ) {
1322 return false;
1323 }
1324 if (!is_int($originalHeader)) {
1325 return $this->_wdtNamedColumns[$originalHeader];
1326 }
1327
1328 return $this->_wdtIndexedColumns[$originalHeader];
1329 }
1330
1331 /**
1332 * Generates the structure in memory needed to render the tables
1333 *
1334 * @param array $rawDataArr Array of data for the table content
1335 * @param array $wdtParameters Array of rendering parameters
1336 * @return bool Result of generation
1337 */
1338 public function arrayBasedConstruct($rawDataArr, $wdtParameters)
1339 {
1340
1341 if (empty($rawDataArr)) {
1342 if (!isset($wdtParameters['data_types'])) {
1343 $rawDataArr = array(0 => array('No data' => 'No data'));
1344 } else {
1345 $arrayEntry = array();
1346 foreach ($wdtParameters['data_types'] as $cKey => $cType) {
1347 $arrayEntry[$cKey] = $cKey;
1348 }
1349 $rawDataArr[] = $arrayEntry;
1350 }
1351 $this->setNoData(true);
1352 }
1353
1354 $headerArr = WDTTools::extractHeaders($rawDataArr);
1355
1356 if (!empty($wdtParameters['columnTitles'])) {
1357 $headerArr = array_unique(
1358 array_merge(
1359 $headerArr,
1360 array_keys($wdtParameters['columnTitles'])
1361 )
1362 );
1363 }
1364
1365 $wdtColumnTypes = isset($wdtParameters['data_types']) ? $wdtParameters['data_types'] : array();
1366
1367 if (empty($wdtColumnTypes)) {
1368 $wdtColumnTypes = WDTTools::detectColumnDataTypes($rawDataArr, $headerArr);
1369 }
1370
1371 if (empty($wdtColumnTypes)) {
1372 foreach ($headerArr as $key) {
1373 $wdtColumnTypes[$key] = 'string';
1374 }
1375 }
1376
1377 $this->_wdtColumnTypes = $wdtColumnTypes;
1378
1379 if (!$this->getNoData()) {
1380 $this->_dataRows = $rawDataArr;
1381 }
1382
1383 $this->createColumnsFromArr($headerArr, $wdtParameters, $wdtColumnTypes);
1384
1385 if (empty($wdtParameters['dates_detected'])
1386 && count(array_intersect(array('date', 'datetime', 'time'), $wdtColumnTypes))
1387 ) {
1388 foreach ($wdtColumnTypes as $key => $columnType) {
1389 $currentDateFormat = isset($wdtParameters['dateInputFormat'][$key]) ? $wdtParameters['dateInputFormat'][$key] : null;
1390 if (in_array($columnType, array('date', 'datetime', 'time'))) {
1391 foreach ($this->_dataRows as &$dataRow) {
1392 $dataRow[$key] = WDTTools::wdtConvertStringToUnixTimestamp($dataRow[$key], $currentDateFormat);
1393 }
1394 }
1395 }
1396 }
1397
1398 if (!in_array($wdtParameters['tableType'], array('mysql', 'manual')) && count(array_intersect(array('float', 'int'), $wdtColumnTypes))) {
1399 $numberFormat = get_option('wdtNumberFormat') ? get_option('wdtNumberFormat') : 1;
1400 foreach ($wdtColumnTypes as $key => $columnType) {
1401 if ($columnType === 'float') {
1402 foreach ($this->_dataRows as &$dataRow) {
1403 if ($numberFormat == 1) {
1404 $dataRow[$key] = str_replace(',', '.', str_replace('.', '', $dataRow[$key]));
1405 } else {
1406 $dataRow[$key] = str_replace(',', '', $dataRow[$key]);
1407 }
1408 }
1409 }
1410 if ($columnType === 'int') {
1411 foreach ($this->_dataRows as &$dataRow) {
1412 if ($numberFormat == 1) {
1413 $dataRow[$key] = str_replace('.', '', $dataRow[$key]);
1414 } else {
1415 $dataRow[$key] = str_replace(',', '', $dataRow[$key]);
1416 }
1417 }
1418 }
1419 if ($columnType === 'string') {
1420 foreach ($this->_dataRows as &$dataRow) {
1421 if (is_float($dataRow[$key]) || is_int($dataRow[$key])) {
1422 $dataRow[$key] = strval($dataRow[$key]);
1423 }
1424 }
1425 }
1426 }
1427 }
1428
1429 foreach ($wdtColumnTypes as $key => $columnType){
1430 foreach ($this->_dataRows as &$dataRow) {
1431 if (isset($dataRow[$key])) {
1432 $dataRow[$key] = wp_kses_post($dataRow[$key]);
1433 }
1434 }
1435 }
1436
1437 return true;
1438
1439 }
1440
1441
1442 public function hideColumn($dataColumnIndex)
1443 {
1444 if (!isset($dataColumnIndex)
1445 || !isset($this->_wdtNamedColumns[$dataColumnIndex])
1446 ) {
1447 throw new WDTException('A column with provided header does not exist.');
1448 }
1449 $this->_wdtNamedColumns[$dataColumnIndex]->setIsVisible(false);
1450 }
1451
1452 public function showColumn($dataColumnIndex)
1453 {
1454 if (!isset($dataColumnIndex)
1455 || !isset($this->_wdtNamedColumns[$dataColumnIndex])
1456 ) {
1457 throw new WDTException('A column with provided header does not exist.');
1458 }
1459 $this->_wdtNamedColumns[$dataColumnIndex]->setIsVisible(true);
1460 }
1461
1462
1463 public function getCell($dataColumnIndex, $rowKey)
1464 {
1465 if (!isset($dataColumnIndex)
1466 || !isset($rowKey)
1467 ) {
1468 throw new WDTException('Please provide the column key and the row key');
1469 }
1470 if (!isset($this->_dataRows[$rowKey])) {
1471 throw new WDTException('Row does not exist.');
1472 }
1473 if (!isset($this->_wdtNamedColumns[$dataColumnIndex])
1474 && !isset($this->_wdtIndexedColumns[$dataColumnIndex])
1475 ) {
1476 throw new WDTException('Column does not exist.');
1477 }
1478 return $this->_dataRows[$rowKey][$dataColumnIndex];
1479 }
1480
1481 public function returnCellValue($cellContent, $wdtColumnIndex)
1482 {
1483 if (!isset($wdtColumnIndex)) {
1484 throw new WDTException('Column index not provided!');
1485 }
1486 if (!isset($this->_wdtNamedColumns[$wdtColumnIndex])) {
1487 throw new WDTException('Column index out of bounds!');
1488 }
1489 return $this->_wdtNamedColumns[$wdtColumnIndex]->returnCellValue($cellContent);
1490 }
1491
1492 public function getDataRows()
1493 {
1494 return $this->_dataRows;
1495 }
1496
1497 public function setDataRows($dataRows) {
1498 return $this->_dataRows= $dataRows;
1499 }
1500
1501 public function getDataRowsFormatted()
1502 {
1503 $dataRowsFormatted = array();
1504 foreach ($this->_dataRows as $dataRow) {
1505 $formattedRow = array();
1506 foreach ($dataRow as $colHeader => $cellValue) {
1507 $formattedRow[$colHeader] = $this->returnCellValue($cellValue, $colHeader);
1508 }
1509 $dataRowsFormatted[] = $formattedRow;
1510 }
1511 return $dataRowsFormatted;
1512 }
1513
1514 public function getRow($index)
1515 {
1516 if (!isset($index) || !isset($this->_dataRows[$index])) {
1517 throw new WDTException('Invalid row index!');
1518 }
1519 $rowArray = &$this->_dataRows[$index];
1520 apply_filters('wdt_get_row', $rowArray);
1521 return $rowArray;
1522 }
1523
1524 public function addDataColumn(&$dataColumn)
1525 {
1526 if (!($dataColumn instanceof WDTColumn)) {
1527 throw new WDTException('Please provide a wpDataTable column.');
1528 }
1529 apply_filters('wdt_add_column', $dataColumn);
1530 $this->_wdtIndexedColumns[] = &$dataColumn;
1531 return true;
1532 }
1533
1534 public function addColumns(&$dataColumns)
1535 {
1536 if (!is_array($dataColumns)) {
1537 throw new WDTException('Please provide an array of wpDataTable column objects.');
1538 }
1539 apply_filters('wdt_add_columns', $dataColumns);
1540 foreach ($dataColumns as &$dataColumn) {
1541 $this->addDataColumn($dataColumn);
1542 }
1543 }
1544
1545 /**
1546 * Helper method to calculate value for the specified column and function
1547 *
1548 * @param $columnKey
1549 * @param $function
1550 * @return float|int
1551 */
1552 public function calcColumnFunction($columnKey, $function)
1553 {
1554 $result = null;
1555 if ($function == 'sum' || $function == 'avg') {
1556 foreach ($this->getDataRows() as $wdtRowDataArr) {
1557 $result += $wdtRowDataArr[$columnKey];
1558 }
1559
1560 if ($function == 'avg') {
1561 $result = $result / count($this->getDataRows());
1562
1563 require_once(WDT_ROOT_PATH . 'source/class.float.wpdatacolumn.php');
1564 $floatCol = new FloatWDTColumn();
1565 $floatCol->setParentTable($this);
1566 return $floatCol->prepareCellOutput($result);
1567 }
1568
1569 } else if ($function == 'min') {
1570 foreach ($this->getDataRows() as $wdtRowDataArr) {
1571 if (!isset($result) || $wdtRowDataArr[$columnKey] < $result) {
1572 $result = $wdtRowDataArr[$columnKey];
1573 }
1574 }
1575 } else if ($function == 'max') {
1576 foreach ($this->getDataRows() as $wdtRowDataArr) {
1577 if (!isset($result) || $wdtRowDataArr[$columnKey] > $result) {
1578 $result = $wdtRowDataArr[$columnKey];
1579 }
1580 }
1581 }
1582
1583 return $this->returnCellValue($result, $columnKey);
1584
1585 }
1586
1587 /**
1588 * Helper method to generate values for SUM, MIN, MAX, AVG
1589 */
1590 private function calcColumnsAggregateFuncs()
1591 {
1592 if (empty($this->_aggregateFuncsRes)) {
1593 $this->_aggregateFuncsRes = array(
1594 'sum' => array(),
1595 'avg' => array(),
1596 'min' => array(),
1597 'max' => array()
1598 );
1599 }
1600 foreach ($this->getColumnKeys() as $columnKey) {
1601 if (
1602 in_array(
1603 $columnKey,
1604 array_unique(
1605 array_merge(
1606 $this->getSumColumns(),
1607 $this->getAvgColumns(),
1608 $this->getMinColumns(),
1609 $this->getMaxColumns()
1610 )
1611 )
1612 )
1613 )
1614 foreach ($this->getDataRows() as $wdtRowDataArr) {
1615 if (
1616 in_array(
1617 $columnKey,
1618 array_unique(
1619 array_merge(
1620 $this->getSumColumns(),
1621 $this->getAvgColumns()
1622 )
1623
1624 )
1625 )
1626 ) {
1627 if (!isset($this->_aggregateFuncsRes['sum'][$columnKey])) {
1628 $this->_aggregateFuncsRes['sum'][$columnKey] = 0;
1629 }
1630
1631 $this->_aggregateFuncsRes['sum'][$columnKey] += $wdtRowDataArr[$columnKey];
1632 }
1633 if (
1634 in_array(
1635 $columnKey,
1636 $this->getMinColumns()
1637 )
1638 ) {
1639 if (
1640 !isset($this->_aggregateFuncsRes['min'][$columnKey])
1641 || ($wdtRowDataArr[$columnKey] < $this->_aggregateFuncsRes['min'][$columnKey])
1642 ) {
1643 $this->_aggregateFuncsRes['min'][$columnKey] = $wdtRowDataArr[$columnKey];
1644 }
1645 }
1646
1647 if (
1648 in_array(
1649 $columnKey,
1650 $this->getMaxColumns()
1651 )
1652 ) {
1653 if (
1654 !isset($this->_aggregateFuncsRes['max'][$columnKey])
1655 || ($wdtRowDataArr[$columnKey] > $this->_aggregateFuncsRes['max'][$columnKey])
1656 ) {
1657 $this->_aggregateFuncsRes['max'][$columnKey] = $wdtRowDataArr[$columnKey];
1658 }
1659 }
1660 }
1661
1662 if (in_array($columnKey, $this->getAvgColumns())) {
1663 $this->_aggregateFuncsRes['avg'][$columnKey] = $this->_aggregateFuncsRes['sum'][$columnKey] / count($this->getDataRows());
1664 }
1665 }
1666 }
1667
1668 /**
1669 * Return aggregate function results
1670 *
1671 * @param $columnKey
1672 * @param $function
1673 * @return mixed
1674 */
1675 public function getColumnsAggregateFuncsResult($columnKey, $function)
1676 {
1677 if (!isset($this->_aggregateFuncsRes[$function][$columnKey])) {
1678 $this->calcColumnsAggregateFuncs();
1679 }
1680 return $this->_aggregateFuncsRes[$function][$columnKey];
1681 }
1682
1683
1684 /**
1685 * Formatting row data structure for ajax display table
1686 * @param $row - key => value pairs as column name and cell value of a row
1687 * @return array
1688 */
1689 protected function formatAjaxQueryResultRow($row)
1690 {
1691 return array_values($row);
1692 }
1693
1694 public function customBasedConstruct($tableData, $wdtParameters = array()) {
1695 if (has_action('wpdatatables_generate_' . $tableData->table_type)) {
1696 do_action(
1697 'wpdatatables_generate_' . $tableData->table_type,
1698 $this,
1699 $tableData->content,
1700 $wdtParameters
1701 );
1702 } else {
1703 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'));
1704 }
1705 }
1706
1707
1708 /**
1709 * @throws Exception
1710 */
1711 public function jsonBasedConstruct($json, $wdtParameters = array()) {
1712 $cache = WPDataTableCache::maybeCache($this->getCacheSourceData(), (int)$this->getWpId());
1713 if (!$cache){
1714 $jsonArray = self::sourceRenderData($this, 'json', $json);
1715 } else {
1716 $jsonArray = $cache;
1717 }
1718
1719 $jsonArray = apply_filters('wpdatatables_filter_json_array', $jsonArray, $this->getWpId(), $json);
1720
1721 return $this->arrayBasedConstruct($jsonArray, $wdtParameters);
1722 }
1723
1724 /**
1725 * @throws Exception
1726 */
1727 public function serializedPHPBasedConstruct($url, $wdtParameters = array()) {
1728 $cache = WPDataTableCache::maybeCache($this->getCacheSourceData(), (int)$this->getWpId());
1729 if (!$cache){
1730 $PHPArray = self::sourceRenderData($this, 'serialized', $url);
1731 } else {
1732 $PHPArray = $cache;
1733 }
1734
1735 $PHPArray = apply_filters('wpdatatables_filter_php_array', $PHPArray, $this->getWpId(), $url);
1736
1737 return $this->arrayBasedConstruct($PHPArray, $wdtParameters);
1738 }
1739
1740 /**
1741 * @throws Exception
1742 */
1743 public function nestedJsonBasedConstruct($jsonParams, $wdtParameters = array()) {
1744 $cache = WPDataTableCache::maybeCache($this->getCacheSourceData(), (int)$this->getWpId());
1745 if (!$cache){
1746 $jsonArray = self::sourceRenderData($this, 'nested_json', $jsonParams);
1747 } else {
1748 $jsonArray = $cache;
1749 }
1750
1751 $jsonArray = apply_filters('wpdatatables_filter_nested_json_array', $jsonArray, $this->getWpId(), $jsonParams);
1752
1753 return $this->arrayBasedConstruct($jsonArray, $wdtParameters);
1754 }
1755
1756 /**
1757 * @throws WDTException
1758 */
1759 public function XMLBasedConstruct($xml, $wdtParameters = array()) {
1760 $cache = WPDataTableCache::maybeCache($this->getCacheSourceData(), (int)$this->getWpId());
1761 if (!$cache){
1762 if (!$xml) {
1763 throw new WDTException('File you provided cannot be found.');
1764 }
1765 $XMLArray = self::sourceRenderData($this, 'xml', $xml);
1766 } else {
1767 $XMLArray = $cache;
1768 }
1769
1770 $XMLArray = apply_filters('wpdatatables_filter_xml_array', $XMLArray, $this->getWpId(), $xml);
1771
1772 return $this->arrayBasedConstruct($XMLArray, $wdtParameters);
1773 }
1774
1775 /**
1776 * @throws WDTException
1777 * @throws \PhpOffice\PhpSpreadsheet\Exception
1778 * @throws \PhpOffice\PhpSpreadsheet\Reader\Exception
1779 * @throws Exception
1780 */
1781 public function excelBasedConstruct($xls_url, $wdtParameters = array()) {
1782 $cache = WPDataTableCache::maybeCache($this->getCacheSourceData(), (int)$this->getWpId());
1783 if (!$cache) {
1784 ini_set('memory_limit', '2048M');
1785 $fileLocation = $this->getFileLocation();
1786 if (!$xls_url) {
1787 throw new WDTException(esc_html__('Excel file not found!', 'wpdatatables'));
1788 }
1789 if ($fileLocation == 'wp_media_lib' && !file_exists($xls_url)) {
1790 throw new WDTException('Provided file ' . stripcslashes($xls_url) . ' does not exist!');
1791 }
1792
1793 $format = substr(strrchr($xls_url, "."), 1);
1794 $objReader = self::createObjectReader($xls_url);
1795 $xls_url = apply_filters('wpdatatables_filter_excel_based_data_url', $xls_url, $this->getWpId());
1796 if ($fileLocation == 'wp_any_url') {
1797 $xls_url_original = $xls_url;
1798 $data = WDTTools::curlGetData($xls_url);
1799 if ($data == null)
1800 throw new WDTException(esc_html__("File from provided URL is empty."));
1801 $tempFileName = 'tempfile' . $this->getWpId() . '.' . $format;
1802 $fillFileWithData = file_put_contents($tempFileName, $data);
1803 if ($fillFileWithData === false)
1804 throw new WDTException(esc_html__("File from provided URL is empty."));
1805 $xls_url = $tempFileName;
1806 }
1807 $objPHPExcel = $objReader->load($xls_url);
1808 if ($fileLocation == 'wp_any_url') {
1809 $xls_url = $xls_url_original;
1810 unlink($tempFileName);
1811 }
1812 $objWorksheet = $objPHPExcel->getActiveSheet();
1813 $objWorksheet = apply_filters('wpdatatables_before_get_excel_headers', $objWorksheet, $this->getWpId(), $xls_url);
1814 $highestRow = $objWorksheet->getHighestRow();
1815 $highestColumn = $objWorksheet->getHighestDataColumn();
1816
1817 $headingsArray = $objWorksheet->rangeToArray('A1:' . $highestColumn . '1', null, true, true, true);
1818 while (!end($headingsArray[1])) {
1819 array_pop($headingsArray[1]);
1820 };
1821 foreach ($headingsArray[1] as $heading) {
1822 if ($heading === '' || $heading === null)
1823 throw new WDTException(esc_html__('One or more columns doesn\'t have a header. Please enter headers for all columns in order to proceed.'));
1824 }
1825 $headingsArray = array_map('trim', $headingsArray[1]);
1826
1827 $r = -1;
1828 $namedDataArray = array();
1829
1830 $dataRows = $objWorksheet->rangeToArray('A2:' . $highestColumn . $highestRow, null, true, true, true);
1831 for ($row = 2; $row <= $highestRow; ++$row) {
1832 if (max($dataRows[$row]) !== null) {
1833 ++$r;
1834 foreach ($headingsArray as $dataColumnIndex => $dataColumnHeading) {
1835 $dataColumnHeading = trim(preg_replace('/\s\s+/', ' ', str_replace("\n", " ", $dataColumnHeading)));
1836 $namedDataArray[$r][$dataColumnHeading] = trim(isset($dataRows[$row][$dataColumnIndex]) ? $dataRows[$row][$dataColumnIndex] : '');
1837 $namedDataArray[$r][$dataColumnHeading] = wp_kses_post($namedDataArray[$r][$dataColumnHeading]);
1838 $currentDateFormat = isset($wdtParameters['dateInputFormat'][$dataColumnHeading]) ? $wdtParameters['dateInputFormat'][$dataColumnHeading] : null;
1839 if (!empty($wdtParameters['data_types'][$dataColumnHeading]) && in_array($wdtParameters['data_types'][$dataColumnHeading], array('date', 'datetime', 'time'))) {
1840 if ($format === 'xls' || $format === 'ods') {
1841 $cell = $objPHPExcel->getActiveSheet()->getCell($dataColumnIndex . '' . $row);
1842 if (Date::isDateTime($cell) && $cell->getValue() !== null) {
1843 $namedDataArray[$r][$dataColumnHeading] = Date::excelToTimestamp($cell->getValue());
1844 } else {
1845 $namedDataArray[$r][$dataColumnHeading] = WDTTools::wdtConvertStringToUnixTimestamp($dataRows[$row][$dataColumnIndex], $currentDateFormat);
1846 }
1847 } elseif ($format === 'csv') {
1848 $namedDataArray[$r][$dataColumnHeading] = WDTTools::wdtConvertStringToUnixTimestamp($dataRows[$row][$dataColumnIndex], $currentDateFormat);
1849 }
1850 }
1851 }
1852 }
1853 }
1854 if (empty($namedDataArray)) {
1855 throw new WDTException(esc_html__('There is no data in your source file. Please check your source file and try again.','wpdatatables'));
1856 }
1857
1858 WPDataTableCache::maybeSaveData(
1859 (int)$this->getWpId(),
1860 $format,
1861 $xls_url,
1862 $this->getAutoUpdateCache(),
1863 $namedDataArray,
1864 $this->getCacheSourceData()
1865 );
1866
1867 } else {
1868 $namedDataArray = $cache;
1869 }
1870
1871 // Let arrayBasedConstruct know that dates have been converted to timestamps
1872 $wdtParameters['dates_detected'] = true;
1873
1874 $namedDataArray = apply_filters('wpdatatables_filter_excel_array', $namedDataArray, $this->getWpId(), $xls_url);
1875
1876 return $this->arrayBasedConstruct($namedDataArray, $wdtParameters);
1877 }
1878
1879 /**
1880 * Helper method to get data from source URL
1881 * @param $sourceObj
1882 * @param $sourceType
1883 * @param $source
1884 * @return array|mixed|string|void|null
1885 * @throws WDTException
1886 * @throws Exception
1887 */
1888 public static function sourceRenderData($sourceObj, $sourceType, $source) {
1889 $wpId = $sourceObj->getWpId();
1890 $sourceArray = array();
1891 if ($sourceType == 'json') {
1892 $sourceArray = self::jsonRenderData($source, $wpId);
1893 }
1894
1895 if ($sourceType == 'nested_json') {
1896 $sourceArray = self::nestedJsonRenderData($source, $wpId);
1897 }
1898
1899 if ($sourceType == 'serialized') {
1900 $sourceArray = self::serializedPhpRenderData($source, $wpId);
1901 }
1902
1903 if ($sourceType == 'xml') {
1904 $sourceArray = self::xmlRenderData($source, $wpId);
1905 }
1906
1907 WPDataTableCache::maybeSaveData(
1908 (int)$wpId,
1909 $sourceType,
1910 $source,
1911 $sourceObj->getAutoUpdateCache(),
1912 $sourceArray,
1913 $sourceObj->getCacheSourceData()
1914 );
1915
1916 return $sourceArray;
1917 }
1918
1919 /**
1920 * Helper method to get data from source URL
1921 * @param $json
1922 * @param $id
1923 * @return mixed|null
1924 * @throws Exception
1925 */
1926 public static function jsonRenderData($json, $id) {
1927 $json = WDTTools::curlGetData($json);
1928 $json = apply_filters('wpdatatables_filter_json', $json, $id);
1929 return json_decode($json, true);
1930 }
1931
1932 /**
1933 * Helper method to get data from source URL
1934 * @param $jsonParams
1935 * @param $id
1936 * @return mixed|void
1937 * @throws Exception
1938 */
1939 public static function nestedJsonRenderData($jsonParams, $id) {
1940 if (!is_object($jsonParams))
1941 $jsonParams = json_decode($jsonParams);
1942 $nestedJSON = new WDTNestedJson($jsonParams);
1943 return $nestedJSON->getData($id);
1944 }
1945
1946 /**
1947 * Helper method to get data from source URL
1948 * @param $url
1949 * @param $id
1950 * @return mixed
1951 */
1952 public static function serializedPhpRenderData($url, $id) {
1953 $url = apply_filters('wpdatatables_filter_url_php_array', $url, $id);
1954 $serialized_content = apply_filters('wpdatatables_filter_serialized', WDTTools::curlGetData($url), $id);
1955 return unserialize($serialized_content, ["allowed_classes" => false]);
1956 }
1957
1958 /**
1959 * Helper method to get data from source URL
1960 * @param $xml
1961 * @return array|string
1962 */
1963 public static function xmlRenderData( $xml, $id) {
1964 $XMLObject = simplexml_load_file($xml);
1965 $XMLObject = apply_filters('wpdatatables_filter_simplexml', $XMLObject, $id);
1966 $XMLArray = WDTTools::convertXMLtoArr($XMLObject);
1967 foreach ($XMLArray as &$xml_el) {
1968 if (is_array($xml_el) && array_key_exists('attributes', $xml_el)) {
1969 $xml_el = $xml_el['attributes'];
1970 }
1971 }
1972 return $XMLArray;
1973 }
1974
1975 /**
1976 * Creates a reader depending on the file extension
1977 * @param $file
1978 * @return Csv|Ods|Xls|Xlsx
1979 * @throws WDTException
1980 */
1981 public static function createObjectReader($file) {
1982 if (strpos(strtolower($file), '.xlsx')) {
1983 $objReader = new Xlsx();
1984 } elseif (strpos(strtolower($file), '.xls')) {
1985 $objReader = new Xls();
1986 } elseif (strpos(strtolower($file), '.ods')) {
1987 $objReader = new Ods();
1988 } elseif (strpos(strtolower($file), '.csv')) {
1989 $objReader = new Csv();
1990 $objReader->setTestAutoDetect(false);
1991 $csvDelimiter = stripcslashes(get_option('wdtCSVDelimiter')) ? stripcslashes(get_option('wdtCSVDelimiter')) : WDTTools::detectCSVDelimiter($file);
1992 $objReader->setDelimiter($csvDelimiter);
1993 } else {
1994 throw new WDTException('File format not supported!');
1995 }
1996
1997 return $objReader;
1998 }
1999
2000 /**
2001 * Helper method that renders the modal
2002 */
2003 public static function renderModal()
2004 {
2005 include_once WDT_TEMPLATE_PATH . 'frontend/modal.inc.php';
2006 include_once WDT_TEMPLATE_PATH . 'common/delete_modal.inc.php';
2007 }
2008
2009 /**
2010 * Generates table HTML
2011 * @return string
2012 */
2013 public function generateTable()
2014 {
2015 /** @noinspection PhpUnusedLocalVariableInspection */
2016 $tableContent = $this->renderWithJSAndStyles();
2017
2018 ob_start();
2019 include WDT_TEMPLATE_PATH . 'frontend/wrap_template.inc.php';
2020 if (!self::$modalRendered) {
2021 if (!is_admin()) {
2022 add_action('wp_footer', array('WPDataTable', 'renderModal'));
2023 }
2024 self::$modalRendered = true;
2025 }
2026 $returnData = ob_get_contents();
2027 ob_end_clean();
2028
2029 // Generate the style block
2030 $returnData .= "<style>\n";
2031 // Columns text before and after
2032 $returnData .= $this->getColumnsCSS();
2033
2034 // Table layout
2035 $customCss = get_option('wdtCustomCss');
2036
2037 $returnData .= $this->isFixedLayout() ? "table.wpDataTable { table-layout: fixed !important; }\n" : '';
2038 $returnData .= $this->isWordWrap() ? "table.wpDataTable td, table.wpDataTable th { white-space: normal !important; }\n" : '';
2039
2040 if ($customCss) {
2041 $returnData .= stripslashes_deep($customCss);
2042 }
2043 if (get_option('wdtNumbersAlign')) {
2044 $returnData .= "table.wpDataTable td.numdata { text-align: right !important; }\n";
2045 }
2046 if (get_option('wdtBorderRemoval')) {
2047 $returnData .= ".wpDataTablesWrapper table.wpDataTable > tbody > tr > td{ border: none !important; }\n";
2048 }
2049 if (get_option('wdtBorderRemovalHeader')) {
2050 $returnData .= ".wpDataTablesWrapper table.wpDataTable > thead > tr > th{ border: none !important; }\n";
2051 }
2052 $returnData .= "</style>\n";
2053
2054 $returnData .= wdtRenderScriptStyleBlock($this->getWpId());
2055 return $returnData;
2056 }
2057
2058 /**
2059 * Function that return table HTML content and
2060 * enqueue all necessary JS and CSS files
2061 * @return string
2062 */
2063 protected function renderWithJSAndStyles()
2064 {
2065
2066 $this->enqueueJSAndStyles();
2067
2068 $this->addCSSClass('data-t');
2069
2070 /** @noinspection PhpUnusedLocalVariableInspection */
2071 $advancedFilterPosition = get_option('wdtRenderFilter');
2072 /** @noinspection PhpUnusedLocalVariableInspection */
2073 $wdtSumFunctionsLabel = get_option('wdtSumFunctionsLabel');
2074 /** @noinspection PhpUnusedLocalVariableInspection */
2075 $wdtAvgFunctionsLabel = get_option('wdtAvgFunctionsLabel');
2076 /** @noinspection PhpUnusedLocalVariableInspection */
2077 $wdtMinFunctionsLabel = get_option('wdtMinFunctionsLabel');
2078 /** @noinspection PhpUnusedLocalVariableInspection */
2079 $wdtMaxFunctionsLabel = get_option('wdtMaxFunctionsLabel');
2080
2081 ob_start();
2082 include WDT_TEMPLATE_PATH . 'frontend/table_main.inc.php';
2083 $tableContent = ob_get_contents();
2084 ob_end_clean();
2085
2086 return $tableContent;
2087 }
2088
2089 /**
2090 * Function that enqueue all necessary JS and CSS files for wpDataTable
2091 */
2092 protected function enqueueJSAndStyles()
2093 {
2094
2095 WDTTools::wdtUIKitEnqueue();
2096
2097 wp_enqueue_script('wdt-common', WDT_ROOT_URL . 'assets/js/wpdatatables/admin/common.js', array(), false, true);
2098 if (get_option('wdtMinifiedJs')) {
2099 wp_enqueue_style('wdt-wpdatatables', WDT_CSS_PATH . 'wdt.frontend.min.css');
2100
2101 wp_enqueue_script('wdt-wpdatatables', WDT_JS_PATH . 'wpdatatables/wdt.frontend.min.js', array('wdt-common'), false, true);
2102 } else {
2103 wp_enqueue_style('wdt-wpdatatables', WDT_CSS_PATH . 'wpdatatables.min.css');
2104 wp_enqueue_style('wdt-table-tools', WDT_CSS_PATH . 'TableTools.css');
2105 if ($this->isResponsive()) {
2106 wp_enqueue_style('wdt-datatables-responsive', WDT_CSS_PATH . 'datatables.responsive.css', array(), WDT_CURRENT_VERSION);
2107 }
2108 if (WDT_INCLUDE_DATATABLES_CORE) {
2109 wp_enqueue_script('wdt-datatables', WDT_JS_PATH . 'jquery-datatables/jquery.dataTables.min.js', array(), false, true);
2110 }
2111
2112
2113 if ($this->groupingEnabled()) {
2114 wp_enqueue_script('wdt-row-grouping', WDT_JS_PATH . 'jquery-datatables/jquery.dataTables.rowGrouping.js', array('jquery', 'wdt-datatables'), false, true);
2115 }
2116 if ($this->TTEnabled()) {
2117 wp_enqueue_script('wdt-buttons', WDT_JS_PATH . 'export-tools/dataTables.buttons.min.js', array('jquery', 'wdt-datatables'), WDT_CURRENT_VERSION, true);
2118
2119 wp_enqueue_script('wdt-buttons-html5', WDT_JS_PATH . 'export-tools/buttons.html5.min.js', array('jquery', 'wdt-datatables'), WDT_CURRENT_VERSION, true);
2120 !empty($this->_tableToolsConfig['print']) ? wp_enqueue_script('wdt-button-print', WDT_JS_PATH . 'export-tools/buttons.print.min.js', array('jquery', 'wdt-datatables'), WDT_CURRENT_VERSION, true) : null;
2121 !empty($this->_tableToolsConfig['columns']) ? wp_enqueue_script('wdt-button-vis', WDT_JS_PATH . 'export-tools/buttons.colVis.min.js', array('jquery', 'wdt-datatables'), WDT_CURRENT_VERSION, true) : null;
2122
2123 }
2124 if ($this->isResponsive()) {
2125 wp_enqueue_script('wdt-responsive', WDT_JS_PATH . 'responsive/datatables.responsive.js', array(), WDT_CURRENT_VERSION, true);
2126 }
2127 wp_enqueue_script('wdt-funcs-js', WDT_JS_PATH . 'wpdatatables/wdt.funcs.js', array('jquery', 'wdt-datatables', 'wdt-common'), false, true);
2128 wp_enqueue_script('wdt-wpdatatables', WDT_JS_PATH . 'wpdatatables/wpdatatables.js', array('jquery', 'wdt-datatables'), false, true);
2129 }
2130
2131 $skin = get_option('wdtBaseSkin');
2132 if (empty($skin)) {
2133 $skin = 'skin1';
2134 }
2135 switch ($skin) {
2136 case "skin0":
2137 $renderSkin = WDT_ASSETS_PATH . 'css/wdt-skins/material.css';
2138 break;
2139 case "skin1":
2140 $renderSkin = WDT_ASSETS_PATH . 'css/wdt-skins/light.css';
2141 break;
2142 case "skin2":
2143 $renderSkin = WDT_ASSETS_PATH . 'css/wdt-skins/graphite.css';
2144 break;
2145 case "aqua":
2146 $renderSkin = WDT_ASSETS_PATH . 'css/wdt-skins/aqua.css';
2147 break;
2148 case "purple":
2149 $renderSkin = WDT_ASSETS_PATH . 'css/wdt-skins/purple.css';
2150 break;
2151 case "dark":
2152 $renderSkin = WDT_ASSETS_PATH . 'css/wdt-skins/dark.css';
2153 break;
2154 case "mojito":
2155 $renderSkin = WDT_ASSETS_PATH . 'css/wdt-skins/mojito.css';
2156 break;
2157 case "raspberry-cream":
2158 $renderSkin = WDT_ASSETS_PATH . 'css/wdt-skins/raspberry-cream.css';
2159 break;
2160 case "dark-mojito":
2161 $renderSkin = WDT_ASSETS_PATH . 'css/wdt-skins/darkmojito.css';
2162 break;
2163 default:
2164 $renderSkin = WDT_ASSETS_PATH . 'css/wdt-skins/material.css';
2165 break;
2166 }
2167 wp_enqueue_style('wdt-skin', $renderSkin, array(), WDT_CURRENT_VERSION);
2168 wp_enqueue_style('dashicons');
2169
2170 wp_enqueue_script('underscore');
2171 !empty($this->_tableToolsConfig['excel']) ? wp_enqueue_script('wdt-js-zip', WDT_JS_PATH . 'export-tools/jszip.min.js', array('jquery'), false, true) : null;
2172 !empty($this->_tableToolsConfig['pdf']) ? wp_enqueue_script('wdt-pdf-make', WDT_JS_PATH . 'export-tools/pdfmake.min.js', array('jquery'), false, true) : null;
2173 !empty($this->_tableToolsConfig['pdf']) ? wp_enqueue_script('wdt-vfs-fonts', WDT_JS_PATH . 'export-tools/vfs_fonts.js', array('jquery'), false, true) : null;
2174
2175
2176 wp_localize_script('wdt-common', 'wpdatatables_edit_strings', WDTTools::getTranslationStrings());
2177 wp_localize_script('wdt-common', 'wdtWpDataTablesPopoverStrings',WDTTools::getWpDataTablesPopoverStrings());
2178 wp_localize_script('wdt-wpdatatables', 'wpdatatables_settings', WDTTools::getDateTimeSettings());
2179 wp_localize_script('wdt-wpdatatables', 'wpdatatables_frontend_strings', WDTTools::getTranslationStrings());
2180 wp_localize_script('wdt-advanced-filter', 'wpdatatables_frontend_strings', WDTTools::getTranslationStrings());
2181 }
2182
2183 /**
2184 * * Helper method which prepares the column data from values stored in DB
2185 * @param $tableData
2186 * @return array
2187 */
2188 public function prepareColumnData($tableData)
2189 {
2190
2191 $returnArray = array(
2192 'dateInputFormat' => array(),
2193 'columnFormulas' => array(),
2194 'columnOrder' => array(),
2195 'columnTitles' => array(),
2196 'columnTypes' => array(),
2197 'columnWidths' => array(),
2198 'decimalPlaces' => array(),
2199 'editingDefaultValue' => array(),
2200 'exactFiltering' => array(),
2201 'filterDefaultValue' => array(),
2202 'filterLabel' => array(),
2203 'foreignKeyRule' => array(),
2204 'possibleValues' => array(),
2205 'possibleValuesAddEmpty' => array(),
2206 'possibleValuesType' => array(),
2207 'sorting' => array(),
2208 'userIdColumnHeader' => NULL,
2209 'linkTargetAttribute' => array(),
2210 'linkNofollowAttribute' => array(),
2211 'linkNoreferrerAttribute' => array(),
2212 'linkSponsoredAttribute' => array(),
2213 'linkButtonAttribute' => array(),
2214 'linkButtonLabel' => array(),
2215 'linkButtonClass' => array(),
2216 'globalSearchColumn' => array(),
2217 );
2218
2219 if ($tableData) {
2220 foreach ($tableData->columns as $column) {
2221 $returnArray['columnOrder'][(int)$column->pos] = $column->orig_header;
2222 if ($column->display_header) {
2223 $returnArray['columnTitles'][$column->orig_header] = $column->display_header;
2224 }
2225 if ($column->width) {
2226 $returnArray['columnWidths'][$column->orig_header] = $column->width;
2227 }
2228 if ($column->type != 'autodetect') {
2229 $returnArray['columnTypes'][$column->orig_header] = $column->type;
2230 }
2231 if ($column->type == 'formula') {
2232 $returnArray['columnFormulas'][$column->orig_header] = $column->formula;
2233 }
2234 if ($tableData->edit_only_own_rows && $tableData->userid_column_id == $column->id) {
2235 $returnArray['userIdColumnHeader'] = $column->orig_header;
2236 }
2237 if ($column->filterDefaultValue) {
2238 $returnArray['filterDefaultValue'][$column->orig_header] = $column->filterDefaultValue;
2239 }
2240
2241 $returnArray['dateInputFormat'][$column->orig_header] = isset($column->dateInputFormat) ? $column->dateInputFormat : null;
2242 $returnArray['decimalPlaces'][$column->orig_header] = isset($column->decimalPlaces) ? $column->decimalPlaces : null;
2243 $returnArray['editingDefaultValue'][$column->orig_header] = isset($column->editingDefaultValue) ? $column->editingDefaultValue : null;
2244 $returnArray['exactFiltering'][$column->orig_header] = isset($column->exactFiltering) ? $column->exactFiltering : null;
2245 $returnArray['filterLabel'][$column->orig_header] = isset($column->filterLabel) ? $column->filterLabel : null;
2246 $returnArray['foreignKeyRule'][$column->orig_header] = isset($column->foreignKeyRule) ? $column->foreignKeyRule : null;
2247 $returnArray['possibleValues'][$column->orig_header] = isset($column->valuesList) ? $column->valuesList : null;
2248 $returnArray['possibleValuesAddEmpty'][$column->orig_header] = isset($column->possibleValuesAddEmpty) ? $column->possibleValuesAddEmpty : null;
2249 $returnArray['possibleValuesType'][$column->orig_header] = isset($column->possibleValuesType) ? $column->possibleValuesType : null;
2250 $returnArray['column_align_fields'][$column->orig_header] = isset($column->column_align_fields) ? $column->column_align_fields : '';
2251 $returnArray['sorting'][$column->orig_header] = isset($column->sorting) ? $column->sorting : null;
2252 $returnArray['linkTargetAttribute'][$column->orig_header] = isset($column->linkTargetAttribute) ? $column->linkTargetAttribute : null;
2253 $returnArray['linkNofollowAttribute'][$column->orig_header] = isset($column->linkNofollowAttribute) ? $column->linkNofollowAttribute : null;
2254 $returnArray['linkNoreferrerAttribute'][$column->orig_header] = isset($column->linkNoreferrerAttribute) ? $column->linkNoreferrerAttribute : null;
2255 $returnArray['linkSponsoredAttribute'][$column->orig_header] = isset($column->linkSponsoredAttribute) ? $column->linkSponsoredAttribute : null;
2256 $returnArray['linkButtonAttribute'][$column->orig_header] = isset($column->linkButtonAttribute) ? $column->linkButtonAttribute : null;
2257 $returnArray['linkButtonLabel'][$column->orig_header] = isset($column->linkButtonLabel) ? $column->linkButtonLabel : null;
2258 $returnArray['linkButtonClass'][$column->orig_header] = isset($column->linkButtonClass) ? $column->linkButtonClass : null;
2259 $returnArray['globalSearchColumn'][$column->orig_header] = isset($column->globalSearchColumn) ? $column->globalSearchColumn : null;
2260 $returnArray['column_align_header'][$column->orig_header] = isset($column->column_align_header) ? $column->column_align_header : '';
2261 $returnArray['column_align_fields'][$column->orig_header] = isset($column->column_align_fields) ? $column->column_align_fields : '';
2262 }
2263 }
2264 return $returnArray;
2265 }
2266
2267
2268 /**
2269 * Helper method which populates the wpdatatables object with passed in parameters and data (stored in DB)
2270 *
2271 * @param $tableData
2272 * @param $columnData
2273 * @throws WDTException
2274 * @throws Exception
2275 */
2276
2277 public function fillFromData($tableData, $columnData)
2278 {
2279 if (empty($tableData->table_type)) {
2280 return;
2281 }
2282 global $wdtVar1, $wdtVar2, $wdtVar3;
2283
2284 // Set placeholders
2285 $wdtVar1 = $wdtVar1 === '' ? $tableData->var1 : $wdtVar1;
2286 $wdtVar2 = $wdtVar2 === '' ? $tableData->var2 : $wdtVar2;
2287 $wdtVar3 = $wdtVar3 === '' ? $tableData->var3 : $wdtVar3;
2288
2289 // Defining column parameters if provided
2290 $params = array();
2291 if (isset($tableData->limit)) {
2292 $params['limit'] = $tableData->limit;
2293 }
2294 if (isset($tableData->table_type)) {
2295 $params['tableType'] = $tableData->table_type;
2296 }
2297 if (isset($columnData['columnTypes'])) {
2298 $params['data_types'] = $columnData['columnTypes'];
2299 }
2300 if (isset($columnData['columnTitles'])) {
2301 $params['columnTitles'] = $columnData['columnTitles'];
2302 }
2303 if (isset($columnData['columnFormulas'])) {
2304 $params['columnFormulas'] = $columnData['columnFormulas'];
2305 }
2306 if (isset($columnData['sorting'])) {
2307 $params['sorting'] = $columnData['sorting'];
2308 }
2309 if (isset($columnData['decimalPlaces'])) {
2310 $params['decimalPlaces'] = $columnData['decimalPlaces'];
2311 }
2312 if (isset($columnData['exactFiltering'])) {
2313 $params['exactFiltering'] = $columnData['exactFiltering'];
2314 }
2315 if (isset($columnData['globalSearchColumn'])) {
2316 $params['globalSearchColumn'] = $columnData['globalSearchColumn'];
2317 }
2318 if (isset($columnData['filterDefaultValue'])) {
2319 $params['filterDefaultValue'] = $columnData['filterDefaultValue'];
2320 }
2321 if (isset($columnData['filterLabel'])) {
2322 $params['filterLabel'] = $columnData['filterLabel'];
2323 }
2324 if (isset($columnData['possibleValuesType'])) {
2325 $params['possibleValuesType'] = $columnData['possibleValuesType'];
2326 }
2327 if (isset($columnData['possibleValuesAddEmpty'])) {
2328 $params['possibleValuesAddEmpty'] = $columnData['possibleValuesAddEmpty'];
2329 }
2330 if (isset($columnData['foreignKeyRule'])) {
2331 $params['foreignKeyRule'] = $columnData['foreignKeyRule'];
2332 }
2333 if (isset($columnData['editingDefaultValue'])) {
2334 $params['editingDefaultValue'] = $columnData['editingDefaultValue'];
2335 }
2336 if (isset($columnData['dateInputFormat'])) {
2337 $params['dateInputFormat'] = $columnData['dateInputFormat'];
2338 }
2339 if (isset($columnData['linkTargetAttribute'])) {
2340 $params['linkTargetAttribute'] = $columnData['linkTargetAttribute'];
2341 }
2342 if (isset($columnData['linkNofollowAttribute'])) {
2343 $params['linkNofollowAttribute'] = $columnData['linkNofollowAttribute'];
2344 }
2345 if (isset($columnData['linkNoreferrerAttribute'])) {
2346 $params['linkNoreferrerAttribute'] = $columnData['linkNoreferrerAttribute'];
2347 }
2348 if (isset($columnData['linkSponsoredAttribute'])) {
2349 $params['linkSponsoredAttribute'] = $columnData['linkSponsoredAttribute'];
2350 }
2351 if (isset($columnData['linkButtonAttribute'])) {
2352 $params['linkButtonAttribute'] = $columnData['linkButtonAttribute'];
2353 }
2354 if (isset($columnData['linkButtonLabel'])) {
2355 $params['linkButtonLabel'] = $columnData['linkButtonLabel'];
2356 }
2357 if (isset($columnData['linkButtonClass'])) {
2358 $params['linkButtonClass'] = $columnData['linkButtonClass'];
2359 }
2360
2361 if (isset($tableData->display_length) && $tableData->display_length != 0) {
2362 $this->setDisplayLength($tableData->display_length);
2363 } else {
2364 $this->disablePagination();
2365 }
2366 if (isset($tableData->file_location)) {
2367 $this->setFileLocation($tableData->file_location);
2368 }
2369 $this->setCacheSourceData(!empty($tableData->cache_source_data));
2370 $this->setAutoUpdateCache(!empty($tableData->auto_update_cache));
2371
2372 switch ($tableData->table_type) {
2373
2374 case 'xls':
2375 case 'csv':
2376 $this->excelBasedConstruct(
2377 $tableData->content,
2378 $params
2379 );
2380 break;
2381 case 'xml':
2382 $this->XMLBasedConstruct(
2383 $tableData->content,
2384 $params
2385 );
2386 break;
2387 case 'json':
2388 $this->jsonBasedConstruct(
2389 $tableData->content,
2390 $params
2391 );
2392 break;
2393 case 'nested_json':
2394 $this->nestedJsonBasedConstruct(
2395 $tableData->content,
2396 $params
2397 );
2398 break;
2399 case 'serialized':
2400 $this->serializedPHPBasedConstruct(
2401 $tableData->content,
2402 $params
2403 );
2404 break;
2405 default:
2406 // Solution for addons
2407 $this->customBasedConstruct(
2408 $tableData,
2409 $params
2410 );
2411
2412 break;
2413 }
2414 if (!empty($tableData->content)) {
2415 $this->setTableContent($tableData->content);
2416 }
2417 if (!empty($tableData->table_type)) {
2418 $this->setTableType($tableData->table_type);
2419 }
2420 if (!empty($tableData->title)) {
2421 $this->setTitle($tableData->title);
2422 }
2423 if (!empty($tableData->table_description)) {
2424 $this->setDescription($tableData->table_description);
2425 }
2426 if (!empty($tableData->hide_before_load)) {
2427 $this->hideBeforeLoad();
2428 } else {
2429 $this->showBeforeLoad();
2430 }
2431 if (!empty($tableData->fixed_layout)) {
2432 $this->setFixedLayout(true);
2433 }
2434 if (!empty($tableData->word_wrap)) {
2435 $this->setWordWrap(true);
2436 }
2437
2438 if (!empty($tableData->responsive)) {
2439 $this->setResponsive(true);
2440 }
2441 if (!empty($tableData->scrollable)) {
2442 $this->setScrollable(true);
2443 }
2444 if (empty($tableData->sorting)) {
2445 $this->sortDisable();
2446 }
2447 if (empty($tableData->tools)) {
2448 $this->disableTT();
2449 } else {
2450 $this->enableTT();
2451 if (isset($tableData->tabletools_config)) {
2452 $this->_tableToolsConfig = $tableData->tabletools_config;
2453 } else {
2454 $this->_tableToolsConfig = array(
2455 'print' => 1,
2456 'copy' => 1,
2457 'excel' => 1,
2458 'csv' => 1,
2459 'pdf' => 0
2460 );
2461 }
2462 }
2463 if (get_option('wdtInterfaceLanguage') != '') {
2464 $this->setInterfaceLanguage(get_option('wdtInterfaceLanguage'));
2465 }
2466
2467 if (!empty($tableData->advanced_settings)) {
2468 $advancedSettings = json_decode($tableData->advanced_settings);
2469 isset($advancedSettings->info_block) ? $this->setInfoBlock($advancedSettings->info_block) : $this->setInfoBlock(true);
2470 isset($advancedSettings->global_search) ? $this->setGlobalSearch($advancedSettings->global_search) :$this->setGlobalSearch(true);
2471 isset($advancedSettings->showRowsPerPage) ? $this->setShowRowsPerPage($advancedSettings->showRowsPerPage) : $this->setShowRowsPerPage(true);
2472 isset($advancedSettings->simpleResponsive) ? $this->setSimpleResponsive($advancedSettings->simpleResponsive) : $this->setSimpleResponsive(false);
2473 isset($advancedSettings->simpleHeader) ? $this->setSimpleHeader($advancedSettings->simpleHeader) : $this->setSimpleHeader(false);
2474 isset($advancedSettings->stripeTable) ? $this->setStripeTable($advancedSettings->stripeTable) : $this->setStripeTable(false);
2475 isset($advancedSettings->cellPadding) ? $this->setCellPadding($advancedSettings->cellPadding) : $this->setCellPadding(10);
2476 isset($advancedSettings->removeBorders) ? $this->setRemoveBorders($advancedSettings->removeBorders) : $this->setRemoveBorders(false);
2477 isset($advancedSettings->borderCollapse) ? $this->setBorderCollapse($advancedSettings->borderCollapse) : $this->setBorderCollapse('collapse');
2478 isset($advancedSettings->borderSpacing) ? $this->setBorderSpacing($advancedSettings->borderSpacing) : $this->setBorderSpacing(0);
2479 isset($advancedSettings->verticalScroll) ? $this->setVerticalScroll($advancedSettings->verticalScroll) : $this->setVerticalScroll(false);
2480 isset($advancedSettings->verticalScrollHeight) ? $this->setVerticalScrollHeight($advancedSettings->verticalScrollHeight) : $this->setVerticalScrollHeight(600);
2481 isset($advancedSettings->responsiveAction) ? $this->setResponsiveAction($advancedSettings->responsiveAction) : $this->setResponsiveAction('icon');
2482 isset($advancedSettings->pagination) ? $this->setPagination($advancedSettings->pagination) : $this->setPagination(true);
2483 isset($advancedSettings->paginationAlign) ? $this->setPaginationAlign($advancedSettings->paginationAlign) : $this->setPaginationAlign('right');
2484 isset($advancedSettings->paginationLayout) ? $this->setPaginationLayout($advancedSettings->paginationLayout) : $this->setPaginationLayout('full_numbers');
2485 isset($advancedSettings->paginationLayoutMobile) ? $this->setPaginationLayoutMobile($advancedSettings->paginationLayoutMobile) : $this->setPaginationLayoutMobile('simple');
2486 isset($advancedSettings->showTableToolsIncludeHTML) ? $this->setTableToolsIncludeHTML($advancedSettings->showTableToolsIncludeHTML) : $this->setTableToolsIncludeHTML(false);
2487 isset($advancedSettings->showTableToolsIncludeTitle) ? $this->setTableToolsIncludeTitle($advancedSettings->showTableToolsIncludeTitle) : $this->setTableToolsIncludeTitle(false);
2488 isset($advancedSettings->pdfPaperSize) ? $this->setPdfPaperSize($advancedSettings->pdfPaperSize) : $this->setPdfPaperSize('A4');
2489 isset($advancedSettings->pdfPageOrientation) ? $this->setPdfPageOrientation($advancedSettings->pdfPageOrientation) : $this->setPdfPageOrientation('portrait');
2490 isset($advancedSettings->show_table_description) ? $this->setShowDescription($advancedSettings->show_table_description) : $this->setShowDescription(false);
2491 isset($advancedSettings->table_description) ? $this->setDescription($advancedSettings->table_description) : $this->setDescription('');
2492 isset($advancedSettings->table_wcag) ? $this->setTableWCAG($advancedSettings->table_wcag) : $this->setTableWCAG(0);
2493 isset($advancedSettings->simple_template_id) ? $this->setSimpleTemplateId($advancedSettings->simple_template_id) : $this->setSimpleTemplateId(0);
2494 isset($advancedSettings->pagination_top) ? $this->setPaginationOnTop($advancedSettings->pagination_top) : $this->setPaginationOnTop(0);
2495 } else {
2496 $this->setInfoBlock(true);
2497 $this->setGlobalSearch(true);
2498 $this->setShowRowsPerPage(true);
2499 $this->setSimpleHeader(false);
2500 $this->setSimpleResponsive(false);
2501 $this->setStripeTable(false);
2502 $this->setCellPadding(10);
2503 $this->setRemoveBorders(false);
2504 $this->setBorderCollapse('collapse');
2505 $this->setBorderSpacing(0);
2506 $this->setVerticalScroll(false);
2507 $this->setVerticalScrollHeight(600);
2508 $this->setPagination(true);
2509 $this->setPaginationAlign('right');
2510 $this->setPaginationLayout('full_numbers');
2511 $this->setPaginationLayoutMobile('simple');
2512 $this->setTableToolsIncludeHTML(false);
2513 $this->setTableToolsIncludeTitle(false);
2514 $this->setPdfPaperSize('A4');
2515 $this->setPdfPageOrientation('portrait');
2516 $this->setShowDescription(false);
2517 $this->setDescription('');
2518 $this->setTableWCAG(0);
2519 $this->setPaginationOnTop(0);
2520 }
2521
2522 if (!empty($columnData['columnOrder'])) {
2523 $this->reorderColumns($columnData['columnOrder']);
2524 }
2525 if (!empty($columnData['columnWidths'])) {
2526 $this->wdtDefineColumnsWidth($columnData['columnWidths']);
2527 }
2528 if (!empty($columnData['possibleValues'])) {
2529 $this->setColumnsPossibleValues($columnData['possibleValues']);
2530 }
2531 if (!empty($tableData->columns)) {
2532 $this->prepareRenderingRules($tableData->columns);
2533 }
2534
2535 }
2536
2537 /**
2538 * Helper method that prepares the rendering rules
2539 * @param array $columnData
2540 */
2541 public function prepareRenderingRules($columnData)
2542 {
2543 $columnIndex = 1;
2544 // Check the search values passed from URL
2545 if (isset($_GET['wdt_search'])) {
2546 $this->setDefaultSearchValue(sanitize_text_field(wp_unslash($_GET['wdt_search'])));
2547 }
2548
2549 // Define all column-dependent rendering rules
2550 foreach ($columnData as $key => $column) {
2551
2552 $this->column_id = $key;
2553 // Set filter types
2554 $this->getColumn($column->orig_header)->setFilterType($column->filter_type);
2555 // Set CSS class
2556 $this->getColumn($column->orig_header)->addCSSClass($column->css_class);
2557 // Set visibility
2558 if (!$column->visible) {
2559 $this->getColumn($column->orig_header)->setIsVisible(false);
2560 }
2561 // Set hiding on phones and tablets for responsiveness
2562 if ($this->isResponsive()) {
2563 if ($column->hide_on_mobiles) {
2564 $this->getColumn($column->orig_header)->setHiddenOnPhones(true);
2565 }
2566 if ($column->hide_on_tablets) {
2567 $this->getColumn($column->orig_header)->setHiddenOnTablets(true);
2568 }
2569 }
2570
2571 // if grouping enabled for this column, passing it to table class
2572 if ($column->groupColumn) {
2573 $this->groupByColumn($column->orig_header);
2574 }
2575 if ($column->defaultSortingColumn != '0') {
2576 $this->setDefaultSortColumn($column->orig_header);
2577 if ($column->defaultSortingColumn == '1') {
2578 $this->setDefaultSortDirection('ASC');
2579 } elseif ($column->defaultSortingColumn == '2') {
2580 $this->setDefaultSortDirection('DESC');
2581 }
2582 }
2583 // If thousands separator is disabled or column is "ID column for editing"
2584 // pass it to the column class instance
2585 if ($column->type == 'int') {
2586 if ($column->skip_thousands_separator || $column->id_column) {
2587 $this->getColumn($column->orig_header)->setShowThousandsSeparator(false);
2588 $this->addColumnsThousandsSeparator($column->orig_header, 0);
2589 } else {
2590 $this->addColumnsThousandsSeparator($column->orig_header, 1);
2591 }
2592 }
2593
2594 // Set ID column if specified
2595 if ($column->id_column) {
2596 $this->setIdColumnKey($column->orig_header);
2597 }
2598 // Set front-end editor input type
2599 $this->getColumn($column->orig_header)
2600 ->setInputType($column->editor_type);
2601 // Define if input cannot be empty
2602 $this->getColumn($column->orig_header)
2603 ->setNotNull((bool)$column->input_mandatory);
2604
2605 // Get display before/after and color
2606 if (sanitize_html_class(strtolower(str_replace(' ', '-', $column->orig_header))) === '') {
2607 $cssColumnHeader = 'column-' . $this->column_id;
2608 } else {
2609 $cssColumnHeader = 'column-' . sanitize_html_class(strtolower(str_replace(' ', '-', $column->orig_header)));
2610 }
2611 if ($column->text_before != '') {
2612 $this->_columnsCSS .= "\n#{$this->getId()} > tbody > tr > td.{$cssColumnHeader}:not(:empty):before,
2613 \n#{$this->getId()} > tbody > tr.row-detail ul li.{$cssColumnHeader} span.columnValue:before
2614 { content: '{$column->text_before}' }";
2615 }
2616 if ($column->text_after != '') {
2617 $this->_columnsCSS .= "\n#{$this->getId()} > tbody > tr > td.{$cssColumnHeader}:not(:empty):after,
2618 \n#{$this->getId()} > tbody > tr.row-detail ul li.{$cssColumnHeader} span.columnValue:after
2619 { content: '{$column->text_after}' }";
2620 }
2621 if ($column->color != '') {
2622 $this->_columnsCSS .= "\n#{$this->getId()} > tbody > tr > td.{$cssColumnHeader}, "
2623 . "#{$this->getId()} > tbody > tr.row-detail ul li.{$cssColumnHeader}, "
2624 . "#{$this->getId()} > thead > tr > th.{$cssColumnHeader}, "
2625 . "#{$this->getId()} > tfoot > tr > th.{$cssColumnHeader} { background-color: {$column->color} !important; }";
2626 }
2627 if ($column->column_align_fields != '') {
2628 $this->_columnsCSS .= "\n#{$this->getId()} > tbody > tr > td.{$cssColumnHeader} { text-align: {$column->column_align_fields} !important; }";
2629 }
2630
2631 if ($column->column_align_header != '') {
2632 $this->_columnsCSS .= "\n#{$this->getId()} > thead > tr > th.{$cssColumnHeader} { text-align: {$column->column_align_header} !important; }";
2633 }
2634
2635 $columnIndex++;
2636 }
2637
2638 }
2639
2640 /**
2641 * Returns JSON object for table description
2642 */
2643 public function getJsonDescription()
2644 {
2645
2646 global $wdtExportFileName;
2647
2648 $obj = new stdClass();
2649 $obj->tableId = $this->getId();
2650 $obj->tableType = $this->getTableType();
2651 $obj->selector = '#' . $this->getId();
2652 $obj->responsive = $this->isResponsive();
2653 $obj->responsiveAction = $this->getResponsiveAction();
2654 $obj->infoBlock = $this->isInfoBlock();
2655 $obj->pagination = $this->isPagination();
2656 $obj->paginationAlign = $this->getPaginationAlign();
2657 $obj->paginationLayout = $this->getPaginationLayout();
2658 $obj->paginationLayoutMobile = $this->getPaginationLayoutMobile();
2659 $obj->file_location = $this->getFileLocation();
2660 $obj->table_wcag = $this->isTableWCAG();
2661 $obj->simple_template_id = $this->getSimpleTemplateId();
2662 $obj->scrollable = $this->isScrollable();
2663 $obj->globalSearch = $this->isGlobalSearch();
2664 $obj->showRowsPerPage = $this->isShowRowsPerPage();
2665 $obj->hideBeforeLoad = $this->doHideBeforeLoad();
2666 $obj->pagination_top = $this->getPaginationOnTop();
2667 $obj->number_format = (int)(get_option('wdtNumberFormat') ? get_option('wdtNumberFormat') : 1);
2668 $obj->decimalPlaces = (int)(get_option('wdtDecimalPlaces') ? get_option('wdtDecimalPlaces') : 2);
2669
2670 $obj->spinnerSrc = WDT_ASSETS_PATH . '/img/spinner.gif';
2671 $obj->groupingEnabled = $this->groupingEnabled();
2672 if ($this->groupingEnabled()) {
2673 $obj->groupingColumnIndex = $this->groupingColumn();
2674 }
2675 $obj->tableWpId = $this->getWpId();
2676 $obj->dataTableParams = new StdClass();
2677
2678 $currentSkin = get_option('wdtBaseSkin');
2679 $obj->currentSkin = $currentSkin;
2680 $infoBlock = ($obj->infoBlock == true) ? 'i' : '';
2681 $pagination = ($obj->pagination == true) ? 'p' : '';
2682 $globalSearch = ($obj->globalSearch == true) ? 'f' : '';
2683 $showRowsPerPage = ($obj->showRowsPerPage == true) ? 'l' : '';
2684 $scrollable = ($this->isScrollable() == true) ? "<'wdtscroll't>" : 't';
2685 if (in_array($currentSkin, ['mojito', 'dark-mojito'])) {
2686 $obj->dataTableParams->sDom = "<'wdt_wrapper_for_buttons'{$globalSearch}{$showRowsPerPage}BT>{$scrollable}{$infoBlock}{$pagination}";
2687 } else {
2688 $obj->dataTableParams->sDom = "BT<'clear'>{$showRowsPerPage}{$globalSearch}{$scrollable}{$infoBlock}{$pagination}";
2689 }
2690
2691 $obj->dataTableParams->bSortCellsTop = false;
2692
2693 if ($this->paginationEnabled()) {
2694 $obj->dataTableParams->bPaginate = true;
2695 if (wp_is_mobile()) {
2696 $obj->dataTableParams->sPaginationType = $this->getPaginationLayoutMobile();
2697 } else {
2698 $obj->dataTableParams->sPaginationType = $this->getPaginationLayout();
2699 }
2700 $obj->dataTableParams->aLengthMenu = json_decode('[[1,5,10,25,50,100,-1],[1,5,10,25,50,100,"' . __('All', 'wpdatatables') . '"]]');
2701 $obj->dataTableParams->iDisplayLength = (int)$this->getDisplayLength();
2702 } else {
2703 $obj->dataTableParams->aLengthMenu = json_decode('[[1,5,10,25,50,100,-1],[1,5,10,25,50,100,"' . __('All', 'wpdatatables') . '"]]');
2704 $obj->dataTableParams->iDisplayLength = (int)$this->getDisplayLength();
2705 if ($this->groupingEnabled()) {
2706 $obj->dataTableParams->aaSortingFixed = json_decode('[[' . $this->groupingColumn() . ', "asc"]]');
2707 }
2708 }
2709 if (get_option('wdtTabletWidth')) {
2710 $obj->tabletWidth = get_option('wdtTabletWidth');
2711 }
2712 if (get_option('wdtMobileWidth')) {
2713 $obj->mobileWidth = get_option('wdtMobileWidth');
2714 }
2715 $obj->dataTableParams->columnDefs = json_decode('[' . $this->getColumnDefinitions() . ']');
2716 $obj->dataTableParams->bAutoWidth = false;
2717
2718 if (!is_null($this->getDefaultSortColumn())) {
2719 $obj->dataTableParams->order = json_decode('[[' . $this->getDefaultSortColumn() . ', "' . strtolower($this->getDefaultSortDirection()) . '" ]]');
2720 } else {
2721 $orderColumn = '';
2722 foreach ($obj->dataTableParams->columnDefs as $columnKey => $column) {
2723 if ($column->orderable === true) {
2724 $orderColumn = $columnKey;
2725 break;
2726 }
2727 }
2728 $obj->dataTableParams->order = json_decode('[[' . $orderColumn . ' ,"asc"]]');
2729 }
2730
2731 if ($this->sortEnabled()) {
2732 $obj->dataTableParams->ordering = true;
2733 } else {
2734 $obj->dataTableParams->ordering = false;
2735 }
2736
2737 if ($this->getInterfaceLanguage()) {
2738 $obj->dataTableParams->oLanguage = json_decode(file_get_contents($this->getInterfaceLanguage()));
2739 }
2740
2741 if (empty($wdtExportFileName)) {
2742 if (!empty($this->_title)) {
2743 $wdtExportFileName = $this->_title;
2744 } else {
2745 $wdtExportFileName = 'wpdt_export';
2746 }
2747 }
2748
2749 $skinsWithNewTableToolsButtons = ['aqua','purple','dark','raspberry-cream', 'mojito', 'dark-mojito'];
2750 $tableToolsIncludeHTML = !$this->getTableToolsIncludeHTML();
2751 $printBttnText = in_array($currentSkin, ['mojito','raspberry-cream', 'dark-mojito']) ? '' : __('Print', 'wpdatatables');
2752 $tableToolsExportTitle = $this->getTableToolsIncludeTitle() ? $this->getName() : null;
2753 $exportBttnText = $currentSkin == in_array($currentSkin, ['mojito', 'dark-mojito']) ? '' : __('Export', 'wpdatatables');
2754 $pdfPaperSize = $this->getPdfPaperSize();
2755 $pdfPageOrientation = $this->getPdfPageOrientation();
2756 $columnsBttnText = $currentSkin == in_array($currentSkin, ['mojito', 'dark-mojito']) ? '' : __('Columns', 'wpdatatables');
2757
2758 if ($this->TTEnabled()) {
2759 (!isset($obj->dataTableParams->buttons)) ? $obj->dataTableParams->buttons = array() : '';
2760 if (in_array($currentSkin, $skinsWithNewTableToolsButtons)) {
2761
2762 if (!empty($this->_tableToolsConfig['columns'])) {
2763 $obj->dataTableParams->buttons[] =
2764 array(
2765 'extend' => 'colvis',
2766 'className' => 'DTTT_button DTTT_button_colvis',
2767 'text' => $columnsBttnText,
2768 'collectionLayout' => 'wdt-skin-' . $currentSkin
2769 );
2770 }
2771 if (!empty($this->_tableToolsConfig['print'])) {
2772 $obj->dataTableParams->buttons[] =
2773 array(
2774 'extend' => 'print',
2775 'exportOptions' => array(
2776 'columns' => ':visible',
2777 'stripHtml' => $tableToolsIncludeHTML
2778 ),
2779 'className' => 'DTTT_button DTTT_button_print',
2780 'text' => $printBttnText,
2781 'title' => $wdtExportFileName
2782 );
2783 }
2784
2785 if (!empty($this->_tableToolsConfig['excel'])) {
2786 $exportButtons[] =
2787 array(
2788 'extend' => 'excelHtml5',
2789 'exportOptions' => array(
2790 'columns' => ':visible',
2791 'stripHtml' => $tableToolsIncludeHTML
2792 ),
2793 'filename' => $wdtExportFileName,
2794 'title' => $tableToolsExportTitle,
2795 'text' => __('Excel', 'wpdatatables')
2796 );
2797 }
2798 if (!empty($this->_tableToolsConfig['csv'])) {
2799 $exportButtons[] =
2800 array(
2801 'extend' => 'csvHtml5',
2802 'exportOptions' => array(
2803 'columns' => ':visible',
2804 'stripHtml' => $tableToolsIncludeHTML
2805 ),
2806 'title' => $wdtExportFileName,
2807 'text' => __('CSV', 'wpdatatables')
2808 );
2809 }
2810 if (!empty($this->_tableToolsConfig['copy'])) {
2811 $exportButtons[] =
2812 array(
2813 'extend' => 'copyHtml5',
2814 'exportOptions' => array(
2815 'columns' => ':visible',
2816 'stripHtml' => $tableToolsIncludeHTML
2817 ),
2818 'filename' => $wdtExportFileName,
2819 'title' => $tableToolsExportTitle,
2820 'text' => __('Copy', 'wpdatatables')
2821 );
2822 }
2823 if (!empty($this->_tableToolsConfig['pdf'])) {
2824 $exportButtons[] =
2825 array(
2826 'extend' => 'pdfHtml5',
2827 'exportOptions' => array('columns' => ':visible'),
2828 'orientation' => $pdfPageOrientation,
2829 'pageSize' => $pdfPaperSize,
2830 'title' => $wdtExportFileName,
2831 'text' => __('PDF', 'wpdatatables')
2832 );
2833 }
2834
2835 if (!empty($exportButtons)) {
2836 $obj->dataTableParams->buttons[] = array(
2837 'extend' => 'collection',
2838 'className' => 'DTTT_button DTTT_button_export',
2839 'text' => $exportBttnText,
2840 'buttons' => $exportButtons
2841 );
2842 }
2843
2844 } else {
2845
2846 if (!empty($this->_tableToolsConfig['columns'])) {
2847 $obj->dataTableParams->buttons[] =
2848 array(
2849 'extend' => 'colvis',
2850 'className' => 'DTTT_button DTTT_button_colvis',
2851 'text' => $columnsBttnText,
2852 'collectionLayout' => 'wdt-skin-' . $currentSkin
2853 );
2854 }
2855 if (!empty($this->_tableToolsConfig['print'])) {
2856 $obj->dataTableParams->buttons[] =
2857 array(
2858 'extend' => 'print',
2859 'exportOptions' => array(
2860 'columns' => ':visible',
2861 'stripHtml' => $tableToolsIncludeHTML
2862 ),
2863 'className' => 'DTTT_button DTTT_button_print',
2864 'title' => $wdtExportFileName,
2865 'text' => $printBttnText,
2866 );
2867 }
2868
2869 if (!empty($this->_tableToolsConfig['excel'])) {
2870 $obj->dataTableParams->buttons[] =
2871 array(
2872 'extend' => 'excelHtml5',
2873 'exportOptions' => array(
2874 'columns' => ':visible',
2875 'stripHtml' => $tableToolsIncludeHTML
2876 ),
2877 'className' => 'DTTT_button DTTT_button_xls',
2878 'filename' => $wdtExportFileName,
2879 'title' => $tableToolsExportTitle,
2880 'text' => __('Excel', 'wpdatatables')
2881 );
2882 }
2883 if (!empty($this->_tableToolsConfig['csv'])) {
2884 $obj->dataTableParams->buttons[] =
2885 array(
2886 'extend' => 'csvHtml5',
2887 'exportOptions' => array(
2888 'columns' => ':visible',
2889 'stripHtml' => $tableToolsIncludeHTML
2890 ),
2891 'className' => 'DTTT_button DTTT_button_csv',
2892 'title' => $wdtExportFileName,
2893 'text' => __('CSV', 'wpdatatables')
2894 );
2895 }
2896 if (!empty($this->_tableToolsConfig['copy'])) {
2897 $obj->dataTableParams->buttons[] =
2898 array(
2899 'extend' => 'copyHtml5',
2900 'exportOptions' => array(
2901 'columns' => ':visible',
2902 'stripHtml' => $tableToolsIncludeHTML
2903 ),
2904 'className' => 'DTTT_button DTTT_button_copy',
2905 'filename' => $wdtExportFileName,
2906 'title' => $tableToolsExportTitle,
2907 'text' => __('Copy', 'wpdatatables')
2908 );
2909 }
2910 if (!empty($this->_tableToolsConfig['pdf'])) {
2911 $obj->dataTableParams->buttons[] =
2912 array(
2913 'extend' => 'pdfHtml5',
2914 'exportOptions' => array('columns' => ':visible'),
2915 'className' => 'DTTT_button DTTT_button_pdf',
2916 'orientation' => $pdfPageOrientation,
2917 'pageSize' => $pdfPaperSize,
2918 'title' => $wdtExportFileName,
2919 'text' => __('PDF', 'wpdatatables')
2920 );
2921 }
2922 }
2923 }
2924
2925 if (in_array($currentSkin, $skinsWithNewTableToolsButtons)) {
2926
2927 if (!isset($obj->dataTableParams->oLanguage)) {
2928 $obj->dataTableParams->oLanguage = new stdClass();
2929 }
2930
2931 $obj->dataTableParams->oLanguage->sSearch = '<span class="wdt-search-icon"></span>';
2932 $obj->dataTableParams->oLanguage->sSearchPlaceholder = __('Search table', 'wpdatatables');
2933 $obj->dataTableParams->oLanguage->sLengthMenu = __('Showing _MENU_ Entries', 'wpdatatables');
2934 }
2935
2936
2937 if (!isset($obj->dataTableParams->buttons)) {
2938 $obj->dataTableParams->buttons = array();
2939 }
2940
2941 $obj->columnsFixed = 0;
2942
2943
2944 $init_format = get_option('wdtDateFormat');
2945 $datepick_format = str_replace('d', 'dd', $init_format);
2946 $datepick_format = str_replace('m', 'mm', $datepick_format);
2947 $datepick_format = str_replace('Y', 'yy', $datepick_format);
2948
2949 $obj->timeFormat = get_option('wdtTimeFormat');
2950 $obj->datepickFormat = $datepick_format;
2951
2952 $obj->dataTableParams->oSearch = array('bSmart' => false, 'bRegex' => false, 'sSearch' => $this->getDefaultSearchValue());
2953
2954 $obj = apply_filters('wpdatatables_filter_table_description', $obj, $this->getWpId(), $this);
2955
2956 return json_encode($obj, JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP);
2957 }
2958
2959
2960 /**
2961 * @param $columnKey
2962 * @param $foreignKeyRule
2963 * @param $dataRows
2964 * @return mixed
2965 */
2966 public function joinWithForeignWpDataTable($columnKey, $foreignKeyRule, $dataRows)
2967 {
2968 $joinedTable = WPDataTable::loadWpDataTable($foreignKeyRule->tableId);
2969 $distinctValues = $joinedTable->getDistinctValuesForColumns($foreignKeyRule);
2970 foreach ($dataRows as &$dataRow) {
2971 $dataRow[$columnKey] = isset($distinctValues[$dataRow[$columnKey]]) ? $distinctValues[$dataRow[$columnKey]] : $dataRow[$columnKey];
2972 }
2973
2974 return array(
2975 'dataRows' => $dataRows,
2976 'distinctValues' => $distinctValues
2977 );
2978
2979 }
2980
2981 /**
2982 * Function that returns related values (ID's and strings) for Foreign Key feature
2983 * by provided foreign key rule
2984 * @param $foreignKeyRule stdClass that contains tableId, tableName, displayColumnId, displayColumnName,
2985 * storeColumnId and storeColumnName
2986 * @return array
2987 */
2988 public function getDistinctValuesForColumns($foreignKeyRule)
2989 {
2990 $distinctValues = array();
2991 $storeColumnName = $foreignKeyRule->storeColumnName;
2992 $displayColumnName = $foreignKeyRule->displayColumnName;
2993 $tableType = $this->getTableType();
2994
2995 if ($tableType == 'mysql' || $tableType == 'manual') {
2996 $tableContent = $this->getTableContent();
2997
2998 $distValuesQuery = "SELECT(`$storeColumnName`) AS `$storeColumnName`, (`$displayColumnName`) AS `$displayColumnName` FROM ($tableContent) tbl GROUP BY $storeColumnName ORDER BY $displayColumnName";
2999
3000 if (!get_option('wdtUseSeparateCon')) {
3001 global $wpdb;
3002 $mySqlResult = $wpdb->get_results($distValuesQuery);
3003
3004 foreach ($mySqlResult as $dataRow) {
3005 $distinctValues[$dataRow->$storeColumnName] = $dataRow->$displayColumnName;
3006 }
3007 } else {
3008 $sql = new PDTSql(WDT_MYSQL_HOST, WDT_MYSQL_DB, WDT_MYSQL_USER, WDT_MYSQL_PASSWORD, WDT_MYSQL_PORT);
3009 $mySqlResult = $sql->getArray($distValuesQuery);
3010
3011 foreach ($mySqlResult as $dataRow) {
3012 $distinctValues[$dataRow[$storeColumnName]] = $dataRow[$displayColumnName];
3013 }
3014 }
3015 } else {
3016 foreach ($this->getDataRows() as $dataRow) {
3017 $distinctValues[$dataRow[$storeColumnName]] = $dataRow[$displayColumnName];
3018 }
3019 }
3020
3021 return $distinctValues;
3022 }
3023
3024
3025 /**
3026 * Delete table by ID
3027 * @param $tableId
3028 * @return bool
3029 */
3030 public static function deleteTable($tableId)
3031 {
3032 global $wpdb;
3033
3034 if (!isset($_REQUEST['wdtNonce']) || empty($tableId) || !current_user_can('manage_options') || !wp_verify_nonce($_REQUEST['wdtNonce'], 'wdtDeleteTableNonce')) {
3035 return false;
3036 }
3037
3038 $table = WDTConfigController::loadTableFromDB($tableId);
3039
3040 if (!$table) {
3041 return false;
3042 }
3043
3044 if (!empty($table->table_type)) {
3045 if ($table->table_type == 'manual') {
3046 if (!get_option('wdtUseSeparateCon')) {
3047 $wpdb->query("DROP TABLE {$table->mysql_table_name}");
3048 } else {
3049 $sql = new PDTSql(WDT_MYSQL_HOST, WDT_MYSQL_DB, WDT_MYSQL_USER, WDT_MYSQL_PASSWORD, WDT_MYSQL_PORT);
3050 $sql->doQuery("DROP TABLE {$table->mysql_table_name}");
3051 }
3052 }
3053 }
3054
3055 $wpdb->delete("{$wpdb->prefix}wpdatatables", array('id' => (int)$tableId));
3056 $wpdb->delete("{$wpdb->prefix}wpdatatables_columns", array('table_id' => (int)$tableId));
3057 $wpdb->delete("{$wpdb->prefix}wpdatatables_rows", array('table_id' => (int)$tableId));
3058 $wpdb->delete("{$wpdb->prefix}wpdatatables_cache", array('table_id' => (int)$tableId));
3059 $wpdb->delete("{$wpdb->prefix}wpdatacharts", array('wpdatatable_id' => (int)$tableId));
3060
3061 return true;
3062 }
3063
3064 /**
3065 * Get all tables
3066 * @return array|null|object
3067 */
3068 public static function getAllTables()
3069 {
3070 global $wpdb;
3071 $query = "SELECT id, title, table_type, server_side FROM {$wpdb->prefix}wpdatatables ORDER BY id";
3072 $allTables = $wpdb->get_results($query, ARRAY_A);
3073 return $allTables;
3074 }
3075
3076 /**
3077 * Get all tables except simple tables
3078 * @return array|null|object
3079 */
3080 public static function getAllTablesExceptSimple() {
3081 global $wpdb;
3082
3083 $query = "SELECT id, title FROM {$wpdb->prefix}wpdatatables WHERE NOT table_type = 'simple' ORDER BY id";
3084
3085 $allTables = $wpdb->get_results($query, ARRAY_A);
3086 return $allTables;
3087 }
3088
3089 /**
3090 * Helper method that load wpDataTable object by given table ID
3091 * and return array with $wpDataTable object and $tableData object
3092 * @param $tableId
3093 * @param null $tableView
3094 * @param bool $disableLimit
3095 * @return WPDataTable|WPExcelDataTable|bool
3096 */
3097 public static function loadWpDataTable($tableId, $tableView = null, $disableLimit = false)
3098 {
3099 $tableData = WDTConfigController::loadTableFromDB($tableId);
3100
3101 if ($tableData) {
3102 $tableData->disable_limit = $disableLimit;
3103 }
3104
3105 $wpDataTable = $tableView == 'excel' ? new WPExcelDataTable() : new self();
3106 $wpDataTable->setWpId($tableId);
3107
3108 $columnDataPrepared = $wpDataTable->prepareColumnData($tableData);
3109
3110 $wpDataTable->fillFromData($tableData, $columnDataPrepared);
3111
3112 return $wpDataTable;
3113 }
3114
3115 }
3116