PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 2.6.0
Independent Analytics – WordPress Analytics Plugin v2.6.0
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 / Tables / Table.php
independent-analytics / IAWP / Tables Last commit date
Columns 2 years ago Groups 2 years ago Table.php 2 years ago Table_Campaigns.php 2 years ago Table_Devices.php 2 years ago Table_Geo.php 2 years ago Table_Pages.php 2 years ago Table_Referrers.php 2 years ago
Table.php
515 lines
1 <?php
2
3 namespace IAWP\Tables;
4
5 use IAWP\Campaign_Builder;
6 use IAWP\Dashboard_Options;
7 use IAWP\Date_Range\Relative_Date_Range;
8 use IAWP\Filters;
9 use IAWP\Form_Submissions\Form;
10 use IAWP\Icon_Directory_Factory;
11 use IAWP\Plugin_Group;
12 use IAWP\Rows\Filter;
13 use IAWP\Sort_Configuration;
14 use IAWP\Statistics\Statistics;
15 use IAWP\Tables\Columns\Column;
16 use IAWP\Tables\Groups\Group;
17 use IAWP\Tables\Groups\Groups;
18 use IAWP\Utils\CSV;
19 use IAWP\Utils\Currency;
20 use IAWP\Utils\Number_Formatter;
21 use IAWP\Utils\Security;
22 use IAWP\Utils\URL;
23 use IAWP\Utils\WordPress_Site_Date_Format_Pattern;
24 use IAWPSCOPED\Illuminate\Support\Str;
25 use IAWPSCOPED\Proper\Timezone;
26 /** @internal */
27 abstract class Table
28 {
29 private $filters;
30 private $visible_columns;
31 private $group;
32 private $is_new_group;
33 /** @var ?Statistics */
34 private $statistics;
35 /**
36 * @param string|null $group_id
37 * @param bool $is_new_group
38 */
39 public function __construct(?string $group_id = null, bool $is_new_group = \false)
40 {
41 $this->visible_columns = Dashboard_Options::getInstance()->visible_columns();
42 $this->group = $this->groups()->find_by_id($group_id);
43 $this->is_new_group = $is_new_group;
44 $this->filters = new Filters();
45 }
46 protected abstract function groups() : Groups;
47 /**
48 * @return array<Column>
49 */
50 protected abstract function local_columns() : array;
51 protected abstract function table_name() : string;
52 public function visible_column_ids()
53 {
54 $visible_columns = [];
55 foreach ($this->get_columns() as $column) {
56 if ($column->is_visible()) {
57 $visible_columns[] = $column->id();
58 }
59 }
60 return $visible_columns;
61 }
62 public function group() : Group
63 {
64 return $this->group;
65 }
66 public function column_picker_html() : string
67 {
68 return \IAWPSCOPED\iawp_blade()->run('plugin-group-options', ['option_type' => 'columns', 'option_name' => \__('Toggle Columns', 'independent-analytics'), 'option_icon' => 'columns', 'plugin_groups' => Plugin_Group::get_plugin_groups(), 'options' => $this->get_columns(\true)]);
69 }
70 public function get_table_toolbar_markup()
71 {
72 return \IAWPSCOPED\iawp_blade()->run('tables.table-toolbar', ['plugin_groups' => Plugin_Group::get_plugin_groups(), 'columns' => $this->get_columns(\true), 'groups' => $this->groups(), 'current_group' => $this->group()]);
73 }
74 public function get_table_markup(string $sort_column, string $sort_direction)
75 {
76 return \IAWPSCOPED\iawp_blade()->run('tables.table', ['table' => $this, 'table_name' => $this->table_name(), 'all_columns' => $this->get_columns(), 'visible_column_count' => $this->visible_column_count(), 'number_of_shown_rows' => 0, 'rows' => [], 'render_skeleton' => \true, 'page_size' => \IAWPSCOPED\iawp()->pagination_page_size(), 'sort_column' => $sort_column, 'sort_direction' => $sort_direction, 'has_campaigns' => Campaign_Builder::has_campaigns()]);
77 }
78 public function set_statistics(Statistics $statistics)
79 {
80 $this->statistics = $statistics;
81 }
82 public function get_row_data_attributes($row)
83 {
84 $html = '';
85 foreach ($this->get_columns() as $column) {
86 $id = $column->id();
87 $data_val = $row->{$id}();
88 $html .= ' data-' . \esc_attr($column->id()) . '="' . \esc_attr($data_val) . '"';
89 }
90 return $html;
91 }
92 public function get_cell_content($row, Column $column)
93 {
94 $column_id = $column->id();
95 if (\is_null($row->{$column_id}())) {
96 return '-';
97 }
98 if ($column_id == 'title' && $row->is_deleted()) {
99 return Security::string($row->{$column_id}()) . ' <span class="deleted-label">' . \esc_html__('(deleted)', 'independent-analytics') . '</span>';
100 } elseif ($column_id == 'views') {
101 $views = Number_Formatter::decimal($row->views());
102 // Getting a divide by zero error from the line below?
103 // It's likely an issue with $this->views which is an instance of Views. Make sure the queries there are working.
104 $views_percentage = Number_Formatter::percent($row->views() / $this->statistics->get_statistic('views')->value() * 100, 2);
105 return '<span class="no-wrap">' . Security::string($views) . '</span> <span class="percentage">(' . Security::string($views_percentage) . ')</span>';
106 } elseif ($column_id == 'visitors') {
107 $visitors = Number_Formatter::decimal($row->visitors());
108 $visitors_percentage = Number_Formatter::percent($row->visitors() / $this->statistics->get_statistic('visitors')->value() * 100, 2);
109 return '<span class="no-wrap">' . Security::string($visitors) . '</span> <span class="percentage">(' . Security::string($visitors_percentage) . ')</span>';
110 } elseif ($column_id == 'sessions') {
111 $sessions = Number_Formatter::decimal($row->sessions());
112 $sessions_percentage = Number_Formatter::percent($row->sessions() / $this->statistics->get_statistic('sessions')->value() * 100, 2);
113 return '<span class="no-wrap">' . Security::string($sessions) . '</span> <span class="percentage">(' . Security::string($sessions_percentage) . ')</span>';
114 } elseif ($column_id === 'entrances') {
115 $entrances = Number_Formatter::decimal($row->entrances());
116 $entrances_percentage = Number_Formatter::percent($row->entrances() / $this->statistics->get_statistic('sessions')->value() * 100, 2);
117 return '<span class="no-wrap">' . Security::string($entrances) . '</span> <span class="percentage">(' . Security::string($entrances_percentage) . ')</span>';
118 } elseif ($column_id === 'exits') {
119 $exits = Number_Formatter::decimal($row->exits());
120 $exits_percentage = Number_Formatter::percent($row->exits() / $this->statistics->get_statistic('sessions')->value() * 100, 2);
121 return '<span class="no-wrap">' . Security::string($exits) . '</span> <span class="percentage">(' . Security::string($exits_percentage) . ')</span>';
122 } elseif ($column_id === 'bounce_rate') {
123 return Security::string(Number_Formatter::percent($row->bounce_rate()));
124 } elseif ($column_id === 'average_session_duration' || $column_id === 'average_view_duration') {
125 return Number_Formatter::second_to_minute_timestamp($row->{$column_id}());
126 } elseif ($column_id === 'views_growth' || $column_id === 'visitors_growth' || $column_id === 'wc_conversion_rate' || $column_id === 'exit_percent' || Str::startsWith($column_id, 'form_conversion_rate')) {
127 return Number_Formatter::percent($row->{$column_id}(), 2);
128 } elseif ($column_id == 'url') {
129 if ($row->is_deleted()) {
130 return \urldecode(\esc_url($row->url()));
131 } else {
132 return '<a href="' . \esc_url($row->url(\true)) . '" target="_blank" class="external-link">' . \urldecode(\esc_url($row->url())) . '<span class="dashicons dashicons-external"></span></a>';
133 }
134 } elseif ($column_id == 'author') {
135 return Security::html($row->avatar()) . ' ' . Security::string($row->author());
136 } elseif ($column_id == 'date') {
137 return Security::string(\date(WordPress_Site_Date_Format_Pattern::for_php(), \strtotime($row->date())));
138 } elseif ($column_id == 'type' && \method_exists($row, 'icon') && \method_exists($row, 'type')) {
139 return $row->icon(0) . ' ' . Security::string($row->type());
140 } elseif ($column_id == 'referrer' && $row->has_link()) {
141 return '<a href="' . \esc_url($row->referrer_url()) . '" target="_blank" class="external-link">' . Security::string($row->referrer()) . '<span class="dashicons dashicons-external"></span></a>';
142 } elseif ($column_id === 'device_type') {
143 return Icon_Directory_Factory::device_types()->find($row->device_type()) . Security::string($row->device_type());
144 } elseif ($column_id === 'browser') {
145 return Icon_Directory_Factory::browsers()->find($row->browser()) . Security::string($row->browser());
146 } elseif ($column_id === 'os') {
147 return Icon_Directory_Factory::operating_systems()->find($row->os()) . Security::string($row->os());
148 } elseif ($column_id === 'country') {
149 return Icon_Directory_Factory::flags()->find($row->country_code()) . Security::string($row->country());
150 } elseif ($column_id === 'wc_gross_sales' || $column_id === 'wc_refunded_amount' || $column_id === 'wc_net_sales' || $column_id === 'wc_average_order_volume') {
151 return Security::string(Currency::format($row->{$column_id}()));
152 } elseif ($column_id === 'wc_earnings_per_visitor') {
153 return Security::string(Currency::format($row->{$column_id}(), \false));
154 } elseif ($column_id === 'views_per_session') {
155 return Number_Formatter::decimal($row->{$column_id}(), 2);
156 } else {
157 return Security::string($row->{$column_id}());
158 }
159 }
160 public function output_report_toolbar()
161 {
162 $options = Dashboard_Options::getInstance();
163 $exact_start = $options->get_date_range()->start()->setTimezone(Timezone::site_timezone())->format('Y-m-d');
164 $exact_end = $options->get_date_range()->end()->setTimezone(Timezone::site_timezone())->format('Y-m-d');
165 ?>
166 <div id="toolbar" class="toolbar" data-filter-count="<?php
167 echo \count($options->filters());
168 ?>">
169 <div class="date-picker-parent">
170 <div class="modal-parent dates"
171 data-controller="dates"
172 data-dates-relative-range-id-value="<?php
173 echo \esc_attr($options->relative_range_id());
174 ?>"
175 data-dates-exact-start-value="<?php
176 echo \esc_attr($exact_start);
177 ?>"
178 data-dates-exact-end-value="<?php
179 echo \esc_attr($exact_end);
180 ?>"
181 data-dates-first-day-of-week-value="<?php
182 echo \absint(\IAWPSCOPED\iawp()->get_option('iawp_dow', 0));
183 ?>"
184 data-dates-css-url-value="<?php
185 echo \esc_url(\IAWPSCOPED\iawp_url_to('dist/styles/easepick/datepicker.css'));
186 ?>"
187 data-dates-format-value="<?php
188 echo \esc_attr(WordPress_Site_Date_Format_Pattern::for_javascript());
189 ?>"
190 >
191 <button id="dates-button"
192 data-testid="open-calendar"
193 class="iawp-button"
194 data-action="dates#toggleModal"
195 data-dates-target="modalButton"
196 >
197 <span class="dashicons dashicons-calendar-alt"></span>
198 <span class="iawp-label"><?php
199 echo \esc_html($options->get_date_range()->label());
200 ?></span>
201 </button>
202 <div id="modal-dates"
203 class="iawp-modal large dates"
204 data-dates-target="modal"
205 >
206 <div class="modal-inner">
207 <div id="easepick-picker"
208 data-dates-target="easepick"
209 style="display: none;"
210 >
211 </div>
212 <div class="relative-dates">
213 <?php
214 foreach (Relative_Date_Range::ranges() as $date_range) {
215 ?>
216 <?php
217 $exact_start = $date_range->start()->setTimezone(Timezone::site_timezone())->format('Y-m-d');
218 ?>
219 <?php
220 $exact_end = $date_range->end()->setTimezone(Timezone::site_timezone())->format('Y-m-d');
221 ?>
222 <button class="iawp-button"
223 data-dates-target="relativeRange"
224 data-action="dates#relativeRangeSelected"
225 data-relative-range-id="<?php
226 echo \esc_attr($date_range->relative_range_id());
227 ?>"
228 data-relative-range-label="<?php
229 echo \esc_attr($date_range->label());
230 ?>"
231 data-relative-range-start="<?php
232 echo \esc_attr($exact_start);
233 ?>"
234 data-relative-range-end="<?php
235 echo \esc_attr($exact_end);
236 ?>"
237 >
238 <?php
239 echo \esc_html($date_range->label());
240 ?>
241 </button>
242 <?php
243 }
244 ?>
245 </div>
246 <div class="apply-buttons">
247 <button class="iawp-button purple"
248 data-dates-target="apply"
249 data-action="dates#apply"
250 data-testid="apply-dates"
251 >
252 <?php
253 \esc_html_e('Apply', 'independent-analytics');
254 ?>
255 </button>
256 <button class="iawp-button ghost-purple"
257 data-action="dates#closeModal"
258 data-testid="close-calendar"
259 >
260 <?php
261 \esc_html_e('Cancel', 'independent-analytics');
262 ?>
263 </button>
264 </div>
265 </div>
266 </div>
267 </div>
268 </div>
269 <div class="filter-parent">
270 <?php
271 echo $this->filters()->get_filters_html($this->get_columns());
272 ?>
273 </div>
274 <div class="download-options-parent" data-controller="modal">
275 <div class="modal-parent downloads">
276 <button id="download-options" data-modal-target="modalButton" data-action="click->modal#toggleModal" class="download-options">
277 <?php
278 \esc_html_e('Download Report', 'independent-analytics');
279 ?>
280 </button>
281 <div class="iawp-modal small downloads" data-modal-target="modal">
282 <div class="modal-inner">
283 <div class="title-small"><?php
284 \esc_html_e('Choose a format', 'independent-analytics');
285 ?></div>
286 <button id="download-csv" class="iawp-button" data-report-target="exportCSV" data-action="report#exportCSV">
287 <span class="dashicons dashicons-media-spreadsheet"></span>
288 <span class="iawp-label">
289 <?php
290 \esc_html_e('Download CSV', 'independent-analytics');
291 ?>
292 </span>
293 </button>
294 <button id="download-pdf" class="iawp-button" data-report-target="exportPDF" data-action="report#exportPDF" disabled="disabled">
295 <span class="dashicons dashicons-pdf"></span>
296 <span class="iawp-label">
297 <?php
298 \esc_html_e('Download PDF', 'independent-analytics');
299 ?>
300 </span>
301 </button>
302 </div>
303 </div>
304 </div>
305 </div>
306 </div><?php
307 }
308 public function filters_template_html() : string
309 {
310 return $this->filters()->get_condition_html($this->get_columns());
311 }
312 public function filters_condition_buttons_html(array $filters) : string
313 {
314 return $this->filters()->condition_buttons_html($filters);
315 }
316 public final function csv(array $rows, bool $is_dashboard_export = \false) : CSV
317 {
318 $columns = $this->get_columns();
319 $csv_header = [];
320 $csv_rows = [];
321 foreach ($columns as $column) {
322 if (!$this->include_column_in_csv($column, $is_dashboard_export)) {
323 continue;
324 }
325 $csv_header[] = $column->name();
326 }
327 foreach ($rows as $row) {
328 $csv_row = [];
329 foreach ($columns as $column) {
330 if (!$this->include_column_in_csv($column, $is_dashboard_export)) {
331 continue;
332 }
333 $column_id = $column->id();
334 $value = $row->{$column_id}();
335 // Todo - This logic is similar to the rendering logic for table cells. This should
336 // all be handled via the column class itself.
337 if (\is_null($value)) {
338 $csv_row[] = '-';
339 } elseif ($column_id === 'date') {
340 $csv_row[] = \date(WordPress_Site_Date_Format_Pattern::for_php(), \strtotime($value));
341 } elseif ($column_id === 'average_session_duration' || $column_id === 'average_view_duration') {
342 $csv_row[] = Number_Formatter::second_to_minute_timestamp($value);
343 } elseif ($column_id === 'views_per_session') {
344 $csv_row[] = Number_Formatter::decimal($value, 2);
345 } else {
346 $csv_row[] = $row->{$column_id}();
347 }
348 }
349 $csv_rows[] = $csv_row;
350 }
351 $csv = new CSV($csv_header, $csv_rows);
352 return $csv;
353 }
354 /**
355 * @param array[] $filters Raw filter associative arrays
356 *
357 * @return Filter[]
358 */
359 public function sanitize_filters(array $filters) : array
360 {
361 return \array_values(\array_filter(\array_map(function ($filter) {
362 return $this->sanitize_filter($filter);
363 }, $filters)));
364 }
365 public function sanitize_filter(array $filter) : ?Filter
366 {
367 $column = $this->get_column($filter['column']);
368 if (\is_null($column)) {
369 return null;
370 }
371 $valid_inclusions = ['include', 'exclude'];
372 if (!\in_array($filter['inclusion'], $valid_inclusions)) {
373 return null;
374 }
375 if (!$column->is_valid_filter_operator($filter['operator'])) {
376 return null;
377 }
378 if (!$column->is_enabled_for_group($this->group())) {
379 return null;
380 }
381 $operand = \trim(Security::string($filter['operand']));
382 if (\strlen($operand) === 0) {
383 return null;
384 }
385 if ($column->database_column() === 'cached_url' && $filter['operator'] === 'exact') {
386 $url = new URL($filter['operand']);
387 if (!$url->is_valid_url()) {
388 $filter['operand'] = \site_url($filter['operand']);
389 }
390 }
391 return new Filter(['inclusion' => Security::string($filter['inclusion']), 'column' => $column->id(), 'operator' => Security::string($filter['operator']), 'operand' => Security::string($filter['operand']), 'database_column' => $column->database_column()]);
392 }
393 public function get_column(string $id) : ?Column
394 {
395 $matches = \array_filter($this->local_columns(), function (Column $column) use($id) {
396 return $column->id() === $id;
397 });
398 return \count($matches) === 1 ? \reset($matches) : null;
399 }
400 public function sanitize_sort_parameters(?string $sort_column, ?string $sort_direction) : Sort_Configuration
401 {
402 $column = $this->get_column($sort_column);
403 if (\is_null($column) || !$column->is_enabled_for_group($this->group)) {
404 return new Sort_Configuration();
405 }
406 return new Sort_Configuration($sort_column, $sort_direction, $column->is_nullable());
407 }
408 public function get_rendered_template($rows, $just_rows = \false, string $sort_column = 'visitors', string $sort_direction = 'desc')
409 {
410 if ($just_rows) {
411 return \IAWPSCOPED\iawp_blade()->run('tables.rows', ['table' => $this, 'table_name' => $this->table_name(), 'all_columns' => $this->get_columns(), 'visible_column_count' => $this->visible_column_count(), 'number_of_shown_rows' => \count($rows), 'rows' => $rows, 'render_skeleton' => \false, 'page_size' => \IAWPSCOPED\iawp()->pagination_page_size(), 'sort_column' => $sort_column, 'sort_direction' => $sort_direction, 'has_campaigns' => Campaign_Builder::has_campaigns()]);
412 }
413 return \IAWPSCOPED\iawp_blade()->run('tables.table', ['table' => $this, 'table_name' => $this->table_name(), 'all_columns' => $this->get_columns(), 'visible_column_count' => $this->visible_column_count(), 'number_of_shown_rows' => \count($rows), 'rows' => $rows, 'render_skeleton' => \false, 'page_size' => \IAWPSCOPED\iawp()->pagination_page_size(), 'sort_column' => $sort_column, 'sort_direction' => $sort_direction, 'has_campaigns' => Campaign_Builder::has_campaigns()]);
414 }
415 protected function get_woocommerce_columns() : array
416 {
417 return [new Column(['id' => 'wc_orders', 'name' => \__('Orders', 'independent-analytics'), 'plugin_group' => 'woocommerce', 'type' => 'int']), new Column(['id' => 'wc_gross_sales', 'name' => \__('Gross Sales', 'independent-analytics'), 'plugin_group' => 'woocommerce', 'type' => 'int']), new Column(['id' => 'wc_refunds', 'name' => \__('Refunds', 'independent-analytics'), 'plugin_group' => 'woocommerce', 'type' => 'int']), new Column(['id' => 'wc_refunded_amount', 'name' => \__('Refunded Amount', 'independent-analytics'), 'plugin_group' => 'woocommerce', 'type' => 'int']), new Column(['id' => 'wc_net_sales', 'name' => \__('Net Sales', 'independent-analytics'), 'plugin_group' => 'woocommerce', 'type' => 'int']), new Column(['id' => 'wc_conversion_rate', 'name' => \__('Conversion Rate', 'independent-analytics'), 'plugin_group' => 'woocommerce', 'type' => 'int']), new Column(['id' => 'wc_earnings_per_visitor', 'name' => \__('Earnings Per Visitor', 'independent-analytics'), 'plugin_group' => 'woocommerce', 'type' => 'int']), new Column(['id' => 'wc_average_order_volume', 'name' => \__('Average Order Volume', 'independent-analytics'), 'plugin_group' => 'woocommerce', 'type' => 'int'])];
418 }
419 protected function get_form_columns() : array
420 {
421 $columns = [new Column(['id' => 'form_submissions', 'name' => \__('Submissions', 'independent-analytics'), 'plugin_group' => 'forms', 'type' => 'int']), new Column(['id' => 'form_conversion_rate', 'name' => \__('Conversion Rate', 'independent-analytics'), 'plugin_group' => 'forms', 'type' => 'int'])];
422 foreach (Form::get_forms() as $form) {
423 $columns[] = new Column(['id' => $form->submissions_column(), 'name' => $form->title() . ' ' . \__('Submissions', 'independent-analytics'), 'plugin_group' => 'forms', 'is_subgroup_plugin_active' => $form->is_plugin_active(), 'plugin_group_header' => $form->plugin_name(), 'type' => 'int']);
424 $columns[] = new Column(['id' => $form->conversion_rate_column(), 'name' => $form->title() . ' ' . \__('Conversion Rate', 'independent-analytics'), 'plugin_group' => 'forms', 'is_subgroup_plugin_active' => $form->is_plugin_active(), 'plugin_group_header' => $form->plugin_name(), 'type' => 'int']);
425 }
426 return $columns;
427 }
428 private function include_column_in_csv(Column $column, bool $is_dashboard_export) : bool
429 {
430 if (!$column->is_visible() && $is_dashboard_export) {
431 return \false;
432 }
433 if (!$column->exportable() && !$is_dashboard_export) {
434 return \false;
435 }
436 if (!$column->is_group_plugin_enabled()) {
437 return \false;
438 }
439 return \true;
440 }
441 /**
442 * @return Column[]
443 */
444 private function get_columns($show_disabled_columns = \false) : array
445 {
446 $columns_for_group = \array_filter($this->local_columns(), function (Column $column) {
447 return $column->is_enabled_for_group($this->group) && $column->is_subgroup_plugin_enabled();
448 });
449 if ($show_disabled_columns === \true) {
450 } else {
451 $columns_for_group = \array_filter($columns_for_group, function (Column $column) {
452 return $column->is_group_plugin_enabled();
453 });
454 }
455 if (\is_null($this->visible_columns) || \count($this->visible_columns) === 0) {
456 return $columns_for_group;
457 }
458 if (!$this->is_new_group) {
459 return \array_map(function ($column) {
460 $column->set_visibility(\in_array($column->id(), $this->visible_columns));
461 return $column;
462 }, $columns_for_group);
463 }
464 return \array_map(function ($column) {
465 if ($column->is_group_dependent()) {
466 $column->set_visibility(\true);
467 } elseif (!\in_array($column->id(), $this->visible_columns)) {
468 $column->set_visibility(\false);
469 }
470 return $column;
471 }, $columns_for_group);
472 }
473 /**
474 * Get the number of visible columns
475 *
476 * @return int
477 */
478 private function visible_column_count() : int
479 {
480 $visible_columns = 0;
481 foreach ($this->get_columns() as $column) {
482 if ($column->is_visible()) {
483 $visible_columns++;
484 }
485 }
486 return $visible_columns;
487 }
488 private function filters()
489 {
490 return $this->filters;
491 }
492 /**
493 * @param string $type
494 *
495 * @return ?class-string<Table>
496 */
497 public static function get_table_by_type(string $type) : ?string
498 {
499 switch ($type) {
500 case 'views':
501 return \IAWP\Tables\Table_Pages::class;
502 case 'referrers':
503 return \IAWP\Tables\Table_Referrers::class;
504 case 'geo':
505 return \IAWP\Tables\Table_Geo::class;
506 case 'campaigns':
507 return \IAWP\Tables\Table_Campaigns::class;
508 case 'devices':
509 return \IAWP\Tables\Table_Devices::class;
510 default:
511 return null;
512 }
513 }
514 }
515