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