PluginProbe ʕ •ᴥ•ʔ
Independent Analytics – WordPress Analytics Plugin / 1.19.0
Independent Analytics – WordPress Analytics Plugin v1.19.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
Column.php 3 years ago Table.php 3 years ago Table_Campaigns.php 3 years ago Table_Geo.php 3 years ago Table_Referrers.php 3 years ago Table_Views.php 3 years ago
Table.php
371 lines
1 <?php
2
3 namespace IAWP\Tables;
4
5 use IAWP\Dashboard_Options;
6 use IAWP\Filters;
7 use IAWP\Utils\Array_To_CSV;
8 use IAWP\Utils\Date_Format;
9 use IAWP\Utils\Number_Formatter;
10 use IAWP\Utils\Relative_Range;
11 use IAWP\Utils\Security;
12
13 abstract class Table
14 {
15 /**
16 * @return array<Column>
17 */
18 abstract protected function local_columns(): array;
19
20 abstract protected function table_name(): string;
21
22 private $filters;
23 private $visible_columns;
24 private $views;
25
26 public function __construct($visible_columns = null)
27 {
28 $this->filters = new Filters();
29 $this->visible_columns = $visible_columns;
30 }
31
32 public function get_columns(): array
33 {
34 if ($this->visible_columns === null) {
35 return $this->local_columns();
36 }
37
38 return array_map(function ($column) {
39 if (in_array($column->id(), $this->visible_columns)) {
40 $column->set_visible(true);
41 }
42
43 return $column;
44 }, $this->local_columns());
45 }
46
47 public function visible_column_ids()
48 {
49 $visible_columns = [];
50
51 foreach ($this->get_columns() as $column) {
52 if ($column->visible()) {
53 $visible_columns[] = $column->id();
54 }
55 }
56
57 return $visible_columns;
58 }
59
60 public function get_table_markup()
61 {
62 $opts = new Dashboard_Options();
63 $templates = iawp()->templates();
64
65 return $templates->render('table/index', [
66 'just_rows' => false,
67 'table_name' => $this->table_name(),
68 'all_columns' => $this->get_columns(),
69 'visible_columns' => $this->get_visible_columns(),
70 'row_count' => 0,
71 'rows' => [],
72 'render_skeleton' => true,
73 'page_size' => iawp()->pagination_page_size(),
74 'opts' => $opts,
75 ]);
76 }
77
78 public function set_views($views)
79 {
80 $this->views = $views;
81 }
82
83 public function get_row_markup($rows)
84 {
85 return $this->get_rendered_template($rows, true);
86 }
87
88 private function get_visible_columns(): int
89 {
90 $visible_columns = 0;
91 foreach ($this->get_columns() as $column) {
92 if ($column->visible()) {
93 $visible_columns++;
94 }
95 }
96
97 return $visible_columns;
98 }
99
100 private function get_rendered_template($rows, $just_rows = false)
101 {
102 $opts = new Dashboard_Options();
103 $templates = iawp()->templates();
104
105 $templates->registerFunction('row_data_attributes', [$this, 'get_row_data_attributes']);
106 $templates->registerFunction('cell_content', [$this, 'get_cell_content']);
107
108 return $templates->render('table/index', [
109 'just_rows' => $just_rows,
110 'table_name' => $this->table_name(),
111 'all_columns' => $this->get_columns(),
112 'visible_columns' => $this->get_visible_columns(),
113 'row_count' => count($rows),
114 'rows' => $rows,
115 'render_skeleton' => false,
116 'page_size' => iawp()->pagination_page_size(),
117 'opts' => $opts,
118 ]);
119 }
120
121 public function get_row_data_attributes($row)
122 {
123 $html = '';
124
125 foreach ($this->get_columns() as $column) {
126 $id = $column->id();
127 $data_val = $row->$id();
128 $html .= ' data-' . esc_attr($column->id()) . '="' . esc_attr($data_val) . '"';
129 }
130
131 return $html;
132 }
133
134 public function get_cell_content($row, $column_id)
135 {
136 if (is_null($row->$column_id())) {
137 return null;
138 }
139 if ($column_id == 'title' && $row->is_deleted()) {
140 return Security::string($row->$column_id()) . ' <span class="deleted-label">' . esc_html__('(deleted)', 'iawp') . '</span>';
141 } elseif ($column_id == 'views') {
142 $views = number_format($row->views(), 0);
143 // Getting a divide by zero error from the line below?
144 // It's likely an issue with $this->views which is an instance of Views. Make sure the queries there are working.
145 $views_percentage = Number_Formatter::format(($row->views() / $this->views->views()) * 100, 'percent', 2);
146
147 return Security::string($views) . ' <span class="percentage">(' . Security::string($views_percentage) . ')</span>';
148 } elseif ($column_id == 'visitors') {
149 $visitors = number_format($row->visitors(), 0);
150 $visitors_percentage = Number_Formatter::format(($row->visitors() / $this->views->visitors()) * 100, 'percent', 2);
151
152 return Security::string($visitors) . ' <span class="percentage">(' . Security::string($visitors_percentage) . ')</span>';
153 } elseif ($column_id == 'sessions') {
154 $sessions = number_format($row->sessions(), 0);
155 $sessions_percentage = Number_Formatter::format(($row->sessions() / $this->views->sessions()) * 100, 'percent', 2);
156
157 return Security::string($sessions) . ' <span class="percentage">(' . Security::string($sessions_percentage) . ')</span>';
158 } elseif ($column_id === 'views_growth' || $column_id === 'visitors_growth' || $column_id === 'woocommerce_conversion_rate') {
159 return Number_Formatter::format($row->$column_id(), 'percent', 2);
160 } elseif ($column_id == 'url') {
161 if ($row->is_deleted()) {
162 return Security::string(esc_url($row->url()));
163 } else {
164 return '<a href="' . Security::string(esc_url($row->url(true))) . '" target="_blank" class="external-link">' . Security::string(esc_url($row->url())) . '<span class="dashicons dashicons-external"></span></a>';
165 }
166 } elseif ($column_id == 'author') {
167 return Security::html($row->avatar()) . ' ' . Security::string($row->author());
168 } elseif ($column_id == 'date') {
169 return Security::string(date(Date_Format::php(), $row->date()));
170 } elseif ($column_id == 'type' && method_exists($row, 'icon')) {
171 return $row->icon(0) . ' ' . Security::string($row->type());
172 } elseif ($column_id == 'referrer' && !$row->is_direct()) {
173 return '<a href="' . esc_url($row->referrer_url()) . '" target="_blank" class="external-link">' . Security::string($row->referrer()) . '<span class="dashicons dashicons-external"></span></a>';
174 } elseif ($column_id === 'country') {
175 return '<img class="flag" alt="Country flag" src="' . Security::string($row->flag()) . '"/>' . Security::string($row->country());
176 } elseif (function_exists('wc_price') && ($column_id === 'wc_gross_sales' || $column_id === 'wc_refunded_amount' || $column_id === 'wc_net_sales' || $column_id === 'woocommerce_earnings_per_visitor' || $column_id === 'woocommerce_average_order_volume')) {
177 return Security::string(wc_price($row->$column_id()));
178 } else {
179 return Security::string($row->$column_id());
180 }
181 }
182
183 private function filters()
184 {
185 return $this->filters;
186 }
187
188 public function output_toolbar()
189 {
190 $opts = new Dashboard_Options(); ?>
191 <div class="toolbar">
192 <div class="buttons">
193 <div class="modal-parent"
194 data-controller="dates"
195 data-dates-relative-range-id-value="<?php echo $opts->relative_range() ?>"
196 data-dates-exact-start-value="<?php echo $opts->start() ?>"
197 data-dates-exact-end-value="<?php echo $opts->end() ?>"
198 data-dates-first-day-of-week-value="<?php echo absint(iawp()->get_option('iawp_dow', 0)) ?>"
199 data-dates-css-url-value="<?php echo esc_url(iawp_url_to('dist/styles/easepick/datepicker.css')) ?>"
200 data-dates-format-value="<?php echo esc_attr(Date_Format::js()) ?>"
201 >
202 <button id="dates-button"
203 class="iawp-button ghost-white"
204 data-action="dates#toggleModal"
205 data-dates-target="modalButton"
206 >
207 <span class="dashicons dashicons-calendar-alt"></span>
208 <span><?php echo $opts->date_label() ?></span>
209 </button>
210 <div id="modal-dates"
211 class="modal large flex"
212 data-dates-target="modal"
213 >
214 <div class="modal-inner">
215 <div id="easepick-picker"
216 data-dates-target="easepick"
217 style="display: none;"
218 >
219 </div>
220 <div class="relative-dates">
221 <?php foreach (Relative_Range::ranges() as $range): ?>
222 <button class="iawp-button ghost-purple"
223 data-dates-target="relativeRange"
224 data-action="dates#relativeRangeSelected"
225 data-relative-range-id="<?php echo $range->id ?>"
226 data-relative-range-label="<?php echo $range->label ?>"
227 data-relative-range-start="<?php echo $range->start->format('Y-m-d') ?>"
228 data-relative-range-end="<?php echo $range->end->format('Y-m-d') ?>"
229 >
230 <?php echo $range->label ?>
231 </button>
232 <?php endforeach ?>
233 </div>
234 <div>
235 <hr/>
236 </div>
237 <div>
238 <button class="iawp-button purple"
239 data-dates-target="apply"
240 data-action="dates#apply"
241 >
242 <?php esc_html_e('Apply', 'iawp'); ?>
243 </button>
244 <button class="iawp-button ghost-purple"
245 data-action="dates#closeModal"
246 >
247 <?php esc_html_e('Cancel', 'iawp'); ?>
248 </button>
249 </div>
250 </div>
251 </div>
252 </div>
253 <?php $this->filters()->output_filters($this->get_columns()) ?>
254 <?php $this->column_picker() ?>
255 </div>
256 <div class="buttons">
257 <button class="iawp-button ghost-white"
258 data-controller="clipboard"
259 data-action="clipboard#copy"
260 >
261 <span class="dashicons dashicons-admin-page"></span>
262 <span data-clipboard-target="statusTextElement">
263 <?php esc_html_e('Copy Dashboard URL', 'iawp'); ?>
264 </span>
265 </button>
266 <a class="learn-more"
267 href="https://independentwp.com/knowledgebase/dashboard/save-reports-revisit-later/"
268 target="_blank"><span class="dashicons dashicons-info-outline"></span></a>
269 </div>
270 </div><?php
271 }
272
273 private function column_picker()
274 {
275 ?>
276
277 <div class="customize-columns modal-parent small"
278 data-controller="columns"
279 >
280 <button id="customize-columns"
281 class="iawp-button ghost-white"
282 data-action="columns#toggleModal"
283 data-columns-target="modalButton"
284 >
285 <span class="dashicons dashicons-columns"></span>
286 <span><?php esc_html_e('Edit Columns', 'iawp'); ?></span>
287 </button>
288 <div id="modal-columns"
289 class="modal small"
290 data-columns-target="modal"
291 >
292 <div class="modal-inner">
293 <div class="title-small">
294 <?php esc_html_e('Columns', 'iawp'); ?>
295 </div>
296 <?php foreach ($this->get_columns() as $column): ?>
297 <?php if ($column->id() === 'wc_orders'): ?>
298 <p class="title-small wc-title">
299 <?php esc_html_e('WooCommerce', 'iawp') ?>
300 <?php if (iawp_is_free()) : ?>
301 <span class="pro-label"><?php esc_html_e('PRO', 'iawp') ?></span>
302 <?php endif; ?>
303 </p>
304 <?php endif; ?>
305
306 <label class="column-label"
307 for="iawp-column-<?php echo esc_attr($column->id()); ?>"
308 >
309 <input id="iawp-column-<?php echo esc_attr($column->id()); ?>"
310 <?php if ($column->requires_woocommerce() && iawp_is_free()): ?>
311 <?php checked(true, false, true); ?>
312 disabled="disabled"
313 data-locked-behind-pro="true"
314 <?php else: ?>
315 <?php checked(true, $column->visible(), true); ?>
316 data-columns-target="checkbox"
317 data-action="columns#check"
318 <?php endif; ?>
319 type="checkbox"
320 name="<?php esc_attr_e($column->id()) ?>"
321 data-test-visibility="<?php echo $column->visible() ? 'visible' : 'hidden'; ?>"
322 >
323 <span><?php echo esc_html($column->label()); ?></span>
324 </label>
325 <?php endforeach ?>
326 </div>
327 </div>
328 </div>
329 <?php
330 }
331
332 final public function csv($rows)
333 {
334 $columns = $this->get_columns();
335 $csv_header = [];
336 $csv_rows = [];
337
338 foreach ($columns as $column) {
339 if (!$column->exportable() || ($column->requires_woocommerce() && iawp_is_free())) {
340 continue;
341 }
342
343 $csv_header[] = $column->label();
344 }
345
346 foreach ($rows as $row) {
347 $csv_row = [];
348
349 foreach ($columns as $column) {
350 if (!$column->exportable() || ($column->requires_woocommerce() && iawp_is_free())) {
351 continue;
352 }
353
354 $column_id = $column->id();
355
356 if ($column_id === 'date') {
357 $csv_row[] = date(Date_Format::php(), $row->$column_id());
358 } else {
359 $csv_row[] = $row->$column_id();
360 }
361 }
362
363 $csv_rows[] = $csv_row;
364 }
365
366 $csv = array_merge([$csv_header], $csv_rows);
367
368 return Array_To_CSV::array2csv($csv);
369 }
370 }
371