PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 1.25.1
Independent Analytics – WordPress Analytics Plugin v1.25.1
2.15.5 2.15.4 2.15.3 2.15.2 2.15.1 2.15.0 2.14.10 trunk 1.1 1.10 1.10.1 1.11 1.12 1.13 1.14 1.15 1.16 1.17 1.17.1 1.17.2 1.17.3 1.17.4 1.18 1.18.1 1.19.0 1.19.1 1.2 1.20.0 1.21.0 1.22.0 1.22.1 1.23.0 1.23.1 1.24.0 1.24.1 1.25.0 1.25.1 1.26.0 1.27.0 1.28.0 1.28.1 1.28.2 1.28.3 1.29.0 1.3 1.30.0 1.30.1 1.4 1.5 1.6 1.7 1.8 1.9 2.0.0 2.0.1 2.1.4 2.1.5 2.1.6 2.10.0 2.10.1 2.10.2 2.10.3 2.10.4 2.11.0 2.11.1 2.11.10 2.11.2 2.11.3 2.11.4 2.11.5 2.11.6 2.11.7 2.11.8 2.11.9 2.12.0 2.12.1 2.12.2 2.13.1 2.13.2 2.13.5 2.13.6 2.14.0 2.14.1 2.14.2 2.14.4 2.14.6 2.14.7 2.14.8 2.14.9 2.2.0 2.2.1 2.3.1 2.3.2 2.4.2 2.4.3 2.5.0 2.5.1 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.7.1 2.7.2 2.7.3 2.8.2 2.8.3 2.8.4 2.8.5 2.8.6 2.8.7 2.8.8 2.8.9 2.9.2 2.9.3 2.9.4 2.9.5 2.9.6 2.9.7
independent-analytics / IAWP / Queries / Table_Data.php
independent-analytics / IAWP / Queries Last commit date
Campaigns.php 3 years ago Cities.php 3 years ago Countries.php 3 years ago Current_Traffic_Finder.php 3 years ago Referrers.php 3 years ago Resources.php 3 years ago Table_Data.php 3 years ago Visitors_Over_Time_Finder.php 3 years ago
Table_Data.php
202 lines
1 <?php
2
3 namespace IAWP_SCOPED\IAWP\Queries;
4
5 use IAWP_SCOPED\IAWP\Date_Range\Date_Range;
6 use IAWP_SCOPED\IAWP\Sort_Configuration;
7 use IAWP_SCOPED\IAWP\Statistics\Statistics;
8 abstract class Table_Data
9 {
10 private $results;
11 private $filtered_results;
12 private $date_range;
13 private $filters;
14 private $sort_configuration;
15 public function __construct(Date_Range $date_range, array $filters = [], ?Sort_Configuration $sort_configuration = null)
16 {
17 $this->date_range = $date_range;
18 $this->filters = $filters;
19 $this->sort_configuration = $sort_configuration ?? new Sort_Configuration();
20 $this->rows();
21 }
22 public function rows() : array
23 {
24 if (\is_null($this->results)) {
25 $this->results = $this->sort_rows($this->query());
26 $this->apply_filters();
27 }
28 if (!\is_null($this->filtered_results)) {
29 return \array_filter($this->filtered_results, function ($row) {
30 return $row->views() > 0;
31 });
32 }
33 return \array_filter($this->results, function ($row) {
34 return $row->views() > 0;
35 });
36 }
37 public function statistics() : ?Statistics
38 {
39 $statistics_class = $this->statistics_class();
40 if ($this->filters === []) {
41 return null;
42 }
43 $ids = $this->convert_results_to_ids($this->filtered_results);
44 return new $statistics_class($this->date_range, $ids);
45 }
46 public function unfiltered_statistics() : Statistics
47 {
48 $statistics_class = $this->statistics_class();
49 $unfiltered_ids = $this->convert_results_to_ids($this->results);
50 return new $statistics_class($this->date_range, $unfiltered_ids);
51 }
52 protected abstract function query() : array;
53 protected abstract function statistics_class() : string;
54 protected abstract function convert_results_to_ids($results) : array;
55 protected final function date_range() : Date_Range
56 {
57 return $this->date_range;
58 }
59 private function sort_rows($rows)
60 {
61 \usort($rows, function ($a, $b) {
62 $column = $this->sort_configuration->column();
63 if (\method_exists($a, $column) && \method_exists($b, $column)) {
64 $a_val = $a->{$column}();
65 $b_val = $b->{$column}();
66 $switch = $this->sort_configuration->is_ascending() ? 1 : -1;
67 // Null and empty values at bottom in asc and top in desc
68 $a_empty = \is_null($a_val) || \strlen($a_val) === 0;
69 $b_empty = \is_null($b_val) || \strlen($b_val) === 0;
70 if ($a_empty && !$b_empty) {
71 return 1;
72 } elseif ($b_empty && !$a_empty) {
73 return -1;
74 } elseif ($a_empty && $b_empty) {
75 return 0;
76 }
77 // Numbers below letters
78 $a_num = \is_numeric($a_val);
79 $b_num = \is_numeric($b_val);
80 if ($a_num && !$b_num) {
81 return $switch;
82 } elseif ($b_num && !$a_num) {
83 return $switch * -1;
84 }
85 return (\strtolower($a_val) <=> \strtolower($b_val)) * $switch;
86 } else {
87 return 0;
88 }
89 });
90 return $rows;
91 }
92 private function apply_filters()
93 {
94 if ($this->filters !== []) {
95 $this->filtered_results = $this->filter_rows($this->results, $this->filters);
96 }
97 }
98 private function filter_rows(array $rows, array $filters)
99 {
100 $filtered_rows = [];
101 foreach ($rows as $row) {
102 $match_count = 0;
103 foreach ($filters as $filter) {
104 if (self::include_row($row, $filter)) {
105 $match_count++;
106 }
107 }
108 if ($match_count == \count($filters)) {
109 $filtered_rows[] = $row;
110 }
111 }
112 return $filtered_rows;
113 }
114 private function include_row($row, $filter)
115 {
116 $inclusion = $filter['inclusion'];
117 $column = $filter['column'];
118 $operator = $filter['operator'];
119 $operand = \strtolower($filter['operand']);
120 $column_data_type = null;
121 $match = \false;
122 // This is a temporary way to get the type for a given column
123 if (\in_array($operator, ['contains', 'exact'])) {
124 $column_data_type = 'string';
125 } elseif (\in_array($operator, ['greater', 'lesser', 'equal'])) {
126 $column_data_type = 'int';
127 }
128 if ($column_data_type === 'int') {
129 if ($operator === 'greater') {
130 if ($row->{$column}() > $operand) {
131 $match = \true;
132 }
133 } elseif ($operator === 'lesser') {
134 if ($row->{$column}() < $operand && !\is_null($row->{$column}())) {
135 $match = \true;
136 }
137 } elseif ($operator === 'equal') {
138 if ($row->{$column}() == $operand) {
139 $match = \true;
140 }
141 }
142 } elseif ($column_data_type === 'string') {
143 $value = \strtolower($row->{$column}());
144 if ($operator == 'contains') {
145 if (\strpos($value, $operand) !== \false) {
146 $match = \true;
147 }
148 } elseif ($operator == 'exact') {
149 if ($value == $operand) {
150 $match = \true;
151 }
152 }
153 } elseif ($filter['column'] == 'referrer_type') {
154 $referrer_type = \strtolower($row->referrer_type());
155 if ($filter['operator'] == 'is' && $referrer_type == $operand) {
156 $match = \true;
157 } elseif ($filter['operator'] == 'isnt' && $referrer_type != $operand) {
158 $match = \true;
159 }
160 } elseif ($filter['column'] == 'author') {
161 if ($filter['operator'] == 'is' && $row->author_id() == $operand) {
162 $match = \true;
163 } elseif ($filter['operator'] == 'isnt' && $row->author_id() != $operand) {
164 $match = \true;
165 }
166 } elseif ($filter['column'] == 'type') {
167 if ($filter['operator'] == 'is' && $row->type(\true) == $operand) {
168 $match = \true;
169 } elseif ($filter['operator'] == 'isnt' && $row->type(\true) != $operand) {
170 $match = \true;
171 }
172 } elseif ($filter['column'] == 'date') {
173 // Don't "continue" or row won't be included when excluding
174 if ($row->date() != null) {
175 $date = new \DateTime($operand);
176 if ($filter['operator'] == 'before' && $row->date() < $date->format('U')) {
177 $match = \true;
178 } elseif ($filter['operator'] == 'after' && $row->date() > $date->format('U')) {
179 $match = \true;
180 } elseif ($filter['operator'] == 'on') {
181 $formatted_date = \DateTime::createFromFormat('U', $row->date());
182 $formatted_date = $formatted_date->format('Y-m-d');
183 if ($date->format('Y-m-d') == $formatted_date) {
184 $match = \true;
185 }
186 }
187 }
188 } elseif ($filter['column'] == 'category') {
189 if ($filter['operator'] == 'is' && \in_array($operand, $row->category(\false) ?? [])) {
190 $match = \true;
191 } elseif ($filter['operator'] == 'isnt' && !\in_array($operand, $row->category(\false) ?? [])) {
192 $match = \true;
193 }
194 }
195 if ($filter['inclusion'] == 'include' && $match || $filter['inclusion'] == 'exclude' && !$match) {
196 return \true;
197 } else {
198 return \false;
199 }
200 }
201 }
202