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