PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.13.6
Independent Analytics – WordPress Analytics Plugin v2.13.6
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 / Rows / Filter.php
independent-analytics / IAWP / Rows Last commit date
Campaign_Landing_Pages.php 10 months ago Campaign_UTM_Campaigns.php 10 months ago Campaign_UTM_Mediums.php 10 months ago Campaign_UTM_Sources.php 10 months ago Campaigns.php 10 months ago Cities.php 10 months ago Countries.php 10 months ago Device_Browsers.php 10 months ago Device_OSS.php 10 months ago Device_Types.php 10 months ago Filter.php 9 months ago Forms.php 10 months ago Link_Patterns.php 9 months ago Links.php 9 months ago Pages.php 10 months ago Referrer_Types.php 10 months ago Referrers.php 10 months ago Rows.php 10 months ago
Filter.php
212 lines
1 <?php
2
3 namespace IAWP\Rows;
4
5 use IAWP\ColumnOptions\Author_Filter_List;
6 use IAWP\ColumnOptions\Category_Filter_List;
7 use IAWP\ColumnOptions\Device_Browser_Filter_List;
8 use IAWP\ColumnOptions\Device_OS_Filter_List;
9 use IAWP\ColumnOptions\Device_Type_Filter_List;
10 use IAWP\ColumnOptions\Link_Name_Filter_List;
11 use IAWP\ColumnOptions\Page_Type_Filter_List;
12 use IAWP\ColumnOptions\Referrer_Type_Filter_List;
13 use IAWP\Form_Submissions\Form;
14 use IAWP\Tables\Columns\Column;
15 use IAWP\Utils\String_Util;
16 use IAWP\Utils\WordPress_Site_Date_Format_Pattern;
17 use IAWPSCOPED\Illuminate\Database\Query\Builder;
18 use IAWPSCOPED\Illuminate\Support\Str;
19 /** @internal */
20 class Filter
21 {
22 public static string $RECORD_FILTER = 'record';
23 public static string $AGGREGATE_FILTER = 'aggregate';
24 public static string $OUTER_FILTER = 'outer';
25 private string $inclusion;
26 private string $operator;
27 private string $operand;
28 private Column $column;
29 public function __construct(array $filter)
30 {
31 $this->inclusion = $filter['inclusion'];
32 $this->operator = $filter['operator'];
33 $this->operand = $filter['operand'];
34 $this->column = $filter['column'];
35 }
36 public function apply_to_query(Builder $query, string $filter_type, bool $in_or_chain = \false) : void
37 {
38 if ($this->column->id() === 'category') {
39 $this->apply_category_filter($query, $in_or_chain);
40 return;
41 }
42 $method = $this->query_method($in_or_chain, $filter_type);
43 $query->{$method}($this->query_column($filter_type), $this->query_operator(), $this->query_value_to_match());
44 }
45 public function html_description() : string
46 {
47 $condition = $this->as_associative_array();
48 $full_string = '';
49 foreach ($condition as $key => $value) {
50 if (!\in_array($key, ['inclusion', 'column', 'operator', 'operand', 'name'])) {
51 continue;
52 }
53 if ($key == 'column') {
54 continue;
55 }
56 $condition_string = '';
57 if ($key == 'inclusion' && $value == 'include') {
58 $condition_string = \esc_html__('Include', 'independent-analytics');
59 } elseif ($key == 'inclusion' && $value == 'exclude') {
60 $condition_string = \esc_html__('Exclude', 'independent-analytics');
61 } elseif ($key == 'operator' && $value == 'lesser') {
62 $condition_string = '<';
63 } elseif ($key == 'operator' && $value == 'greater') {
64 $condition_string = '>';
65 } elseif ($key == 'operator' && $value == 'equal') {
66 $condition_string = '=';
67 } elseif ($key == 'operator' && $value == 'on') {
68 $condition_string = \esc_html__('On', 'independent-analytics');
69 } elseif ($key == 'operator' && $value == 'before') {
70 $condition_string = \esc_html__('Before', 'independent-analytics');
71 } elseif ($key == 'operator' && $value == 'after') {
72 $condition_string = \esc_html__('After', 'independent-analytics');
73 } elseif ($key == 'operator' && $value == 'contains') {
74 $condition_string = \esc_html__('Contains', 'independent-analytics');
75 } elseif ($key == 'operator' && $value == 'exact') {
76 $condition_string = \esc_html__('Exactly matches', 'independent-analytics');
77 } elseif ($key == 'operator' && $value == 'is') {
78 $condition_string = \esc_html__('Is', 'independent-analytics');
79 } elseif ($key == 'operator' && $value == 'isnt') {
80 $condition_string = \esc_html__("Isn't", 'independent-analytics');
81 } elseif ($key == 'operand' && $this->column->options()) {
82 $condition_string = $this->column->options()->label_for($value);
83 } elseif ($key == 'operand' && $condition['column'] == 'date') {
84 try {
85 $date = \DateTime::createFromFormat('U', $value);
86 $condition_string = $date->format(WordPress_Site_Date_Format_Pattern::for_php());
87 } catch (\Throwable $e) {
88 $condition_string = $value;
89 }
90 } else {
91 $condition_string = $value;
92 }
93 if ($key == 'name' || $key == 'operand') {
94 $condition_string = '<strong>' . $condition_string . '</strong> ';
95 }
96 $full_string .= $condition_string . ' ';
97 }
98 return \trim($full_string);
99 }
100 public function column() : string
101 {
102 return $this->column->id();
103 }
104 public function is_concrete_column() : bool
105 {
106 return $this->column->is_concrete_column();
107 }
108 public function is_calculated_column() : bool
109 {
110 return !$this->column->is_concrete_column();
111 }
112 public function as_associative_array() : array
113 {
114 // The order of the elements here matters
115 return ['inclusion' => $this->inclusion, 'name' => $this->column->name(), 'column' => $this->column->id(), 'operator' => $this->operator, 'operand' => $this->operand];
116 }
117 private function query_method(bool $in_or_chain, string $filter_type) : string
118 {
119 if ($filter_type === \IAWP\Rows\Filter::$AGGREGATE_FILTER) {
120 if ($in_or_chain) {
121 return 'orHaving';
122 }
123 return 'having';
124 }
125 if ($in_or_chain) {
126 return 'orWhere';
127 }
128 return 'where';
129 }
130 private function query_column(string $filter_type) : string
131 {
132 $column = $this->column->separate_database_column() ?? $this->column->separate_filter_column() ?? $this->column->id();
133 if ($filter_type === \IAWP\Rows\Filter::$OUTER_FILTER) {
134 $column = Str::afterLast($column, '.');
135 }
136 return $column;
137 }
138 // Use early returns here to make it more obvious what $result value is actually used
139 // without reading to the end
140 private function query_operator() : string
141 {
142 $operator = $this->operator;
143 $result = '';
144 if ($operator === 'equal' || $operator === 'is' || $operator === 'exact' || $operator === 'on') {
145 $result = '=';
146 }
147 if ($operator === 'contains') {
148 $result = 'like';
149 }
150 if ($operator === 'isnt') {
151 $result = '!=';
152 }
153 if ($operator === 'greater' || $operator === 'after') {
154 $result = '>';
155 }
156 if ($operator === 'lesser' || $operator === 'before') {
157 $result = '<';
158 }
159 if ($this->inclusion === 'exclude') {
160 if ($result === '=') {
161 return '!=';
162 } elseif ($result === '!=') {
163 return '=';
164 } elseif ($result === '>') {
165 return '<=';
166 } elseif ($result === '<') {
167 return '>=';
168 } elseif ($result === 'like') {
169 return 'not like';
170 }
171 }
172 return $result;
173 }
174 private function query_value_to_match() : string
175 {
176 if ($this->operator === 'contains') {
177 return '%' . $this->operand . '%';
178 }
179 // if ($this->column->id() === 'cached_date') {
180 if ($this->column->id() === 'date') {
181 try {
182 $date = \DateTime::createFromFormat('U', $this->operand);
183 } catch (\Throwable $e) {
184 $date = new \DateTime();
185 }
186 return $date->format('Y-m-d');
187 }
188 // ID is fine here, but should use whatever method gives the database column
189 if (\in_array($this->column->id(), ['wc_gross_sales', 'wc_refunded_amount', 'wc_net_sales', 'wc_earnings_per_visitor', 'wc_average_order_volume'])) {
190 return \strval(\floatval($this->operand) * 100);
191 }
192 return $this->operand;
193 }
194 private function apply_category_filter(Builder $query, bool $in_or_chain) : void
195 {
196 $wp_query = new \WP_Query(['posts_per_page' => -1, 'cat' => $this->operand, 'fields' => 'ids']);
197 $post_ids = $wp_query->posts;
198 $include = $this->inclusion === 'include';
199 $is = $this->operator === 'is';
200 $method = $in_or_chain ? 'orWhere' : 'where';
201 if ($include === $is) {
202 $query->{$method}(function (Builder $query) use($post_ids) {
203 $query->whereIn('singular_id', $post_ids);
204 });
205 } else {
206 $query->{$method}(function (Builder $query) use($post_ids) {
207 $query->whereNotIn('singular_id', $post_ids)->orWhereNull('singular_id');
208 });
209 }
210 }
211 }
212