PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.3.0
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.3.0
5.11.1 5.11.0 5.10.2 5.10.1 trunk 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.3.0 1.3.1 1.3.2 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.1.0 4.1.1 4.1.2 4.1.3 4.10.0 4.11.0 4.12.0 4.13.0 4.13.2 4.13.3 4.13.4 4.13.5 4.14.0 4.14.1 4.14.2 4.15.0 4.15.1 4.15.2 4.15.3 4.2.0 4.3.0 4.3.1 4.4.1 4.4.2 4.5.0 4.6.0 5.0.1 5.0.2 5.0.3 5.0.4 5.0.5 5.0.6 5.0.7 5.0.8 5.1.0 5.1.1 5.1.2 5.1.3 5.1.4 5.1.5 5.1.6 5.1.7 5.10.0 5.2.0 5.2.1 5.2.2 5.3.0 5.3.1 5.3.2 5.3.3 5.6.0 5.6.1 5.7.0 5.7.1 5.8.0 5.8.1 5.8.2
matomo / app / core / Metrics / Sorter.php
matomo / app / core / Metrics Last commit date
Formatter 5 years ago Sorter 5 years ago Formatter.php 5 years ago Sorter.php 5 years ago
Sorter.php
236 lines
1 <?php
2 /**
3 * Matomo - free/libre analytics platform
4 *
5 * @link https://matomo.org
6 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
7 */
8 namespace Piwik\Metrics;
9
10 use Piwik\DataTable;
11 use Piwik\DataTable\Row;
12 use Piwik\Metrics;
13 use Piwik\Plugin\Metric;
14
15 class Sorter
16 {
17 /**
18 * @var Sorter\Config
19 */
20 private $config;
21
22 public function __construct(Sorter\Config $config)
23 {
24 $this->config = $config;
25 }
26
27 /**
28 * Sorts the DataTable rows using the supplied callback function.
29 *
30 * @param DataTable $table The table to sort.
31 */
32 public function sort(DataTable $table)
33 {
34 // all that code is in here and not in separate methods for best performance. It does make a difference once
35 // php has to copy many (eg 50k) rows otherwise.
36
37 $table->setTableSortedBy($this->config->primaryColumnToSort);
38
39 $rows = $table->getRowsWithoutSummaryRow();
40
41 // we need to sort rows that have a value separately from rows that do not have a value since we always want
42 // to append rows that do not have a value at the end.
43 $rowsWithValues = array();
44 $rowsWithoutValues = array();
45
46 $valuesToSort = array();
47 foreach ($rows as $key => $row) {
48 $value = $this->getColumnValue($row);
49 if (isset($value)) {
50 $valuesToSort[] = $value;
51 $rowsWithValues[] = $row;
52 } else {
53 $rowsWithoutValues[] = $row;
54 }
55 }
56
57 unset($rows);
58
59 if ($this->config->isSecondaryColumnSortEnabled && $this->config->secondaryColumnToSort) {
60 $secondaryValues = array();
61 foreach ($rowsWithValues as $key => $row) {
62 $secondaryValues[$key] = $row->getColumn($this->config->secondaryColumnToSort);
63 }
64
65 array_multisort($valuesToSort, $this->config->primarySortOrder, $this->config->primarySortFlags, $secondaryValues, $this->config->secondarySortOrder, $this->config->secondarySortFlags, $rowsWithValues);
66
67 } else {
68 array_multisort($valuesToSort, $this->config->primarySortOrder, $this->config->primarySortFlags, $rowsWithValues);
69 }
70
71 if (!empty($rowsWithoutValues) && $this->config->secondaryColumnToSort) {
72 $secondaryValues = array();
73 foreach ($rowsWithoutValues as $key => $row) {
74 $secondaryValues[$key] = $row->getColumn($this->config->secondaryColumnToSort);
75 }
76
77 array_multisort($secondaryValues, $this->config->secondarySortOrder, $this->config->secondarySortFlags, $rowsWithoutValues);
78 }
79
80 unset($secondaryValues);
81
82 foreach ($rowsWithoutValues as $row) {
83 $rowsWithValues[] = $row;
84 }
85
86 $table->setRows(array_values($rowsWithValues));
87 }
88
89 private function getColumnValue(Row $row)
90 {
91 $value = $row->getColumn($this->config->primaryColumnToSort);
92
93 if ($value === false || is_array($value)) {
94 return null;
95 }
96
97 return $value;
98 }
99
100 /**
101 * @param string $order 'asc' or 'desc'
102 * @return int
103 */
104 public function getPrimarySortOrder($order)
105 {
106 if ($order === 'asc') {
107 return SORT_ASC;
108 }
109
110 return SORT_DESC;
111 }
112
113 /**
114 * @param string $order 'asc' or 'desc'
115 * @param string|int $secondarySortColumn column name or column id
116 * @return int
117 */
118 public function getSecondarySortOrder($order, $secondarySortColumn)
119 {
120 if ($secondarySortColumn === 'label') {
121
122 $secondaryOrder = SORT_ASC;
123 if ($order === 'asc') {
124 $secondaryOrder = SORT_DESC;
125 }
126
127 return $secondaryOrder;
128 }
129
130 return $this->getPrimarySortOrder($order);
131 }
132
133 /**
134 * Detect the column to be used for sorting
135 *
136 * @param DataTable $table
137 * @param string|int $columnToSort column name or column id
138 * @return int
139 */
140 public function getPrimaryColumnToSort(DataTable $table, $columnToSort)
141 {
142 // we fallback to nb_visits in case columnToSort does not exist
143 $columnsToCheck = array($columnToSort, 'nb_visits');
144
145 $row = $table->getFirstRow();
146
147 foreach ($columnsToCheck as $column) {
148 $column = Metric::getActualMetricColumn($table, $column);
149
150 if ($row->hasColumn($column)) {
151 // since getActualMetricColumn() returns a default value, we need to make sure it actually has that column
152 return $column;
153 }
154 }
155
156 return $columnToSort;
157 }
158
159 /**
160 * Detect the secondary sort column to be used for sorting
161 *
162 * @param Row $row
163 * @param int|string $primaryColumnToSort
164 * @return int
165 */
166 public function getSecondaryColumnToSort(Row $row, $primaryColumnToSort)
167 {
168 $defaultSecondaryColumn = array(Metrics::INDEX_NB_VISITS, 'nb_visits');
169
170 if (in_array($primaryColumnToSort, $defaultSecondaryColumn)) {
171 // if sorted by visits, then sort by label as a secondary column
172 $column = 'label';
173 $value = $row->hasColumn($column);
174 if ($value !== false) {
175 return $column;
176 }
177
178 return null;
179 }
180
181 if ($primaryColumnToSort !== 'label') {
182 // we do not add this by default to make sure we do not sort by label as a first and secondary column
183 $defaultSecondaryColumn[] = 'label';
184 }
185
186 foreach ($defaultSecondaryColumn as $column) {
187 $value = $row->hasColumn($column);
188 if ($value !== false) {
189 return $column;
190 }
191 }
192 }
193
194 /**
195 * @param DataTable $table
196 * @param string|int $columnToSort A column name or column id. Make sure that column actually exists in the row.
197 * You might want to get a valid column via {@link getPrimaryColumnToSort()} or
198 * {@link getSecondaryColumnToSort()}
199 * @return int
200 */
201 public function getBestSortFlags(DataTable $table, $columnToSort)
202 {
203 // when column is label we always to sort by string or natural
204 if (isset($columnToSort) && $columnToSort !== 'label') {
205 foreach ($table->getRowsWithoutSummaryRow() as $row) {
206 $value = $row->getColumn($columnToSort);
207
208 if ($value !== false && $value !== null && !is_array($value)) {
209
210 if (is_numeric($value)) {
211 $sortFlags = SORT_NUMERIC;
212 } else {
213 $sortFlags = $this->getStringSortFlags();
214 }
215
216 return $sortFlags;
217 }
218 }
219 }
220
221 return $this->getStringSortFlags();
222 }
223
224 private function getStringSortFlags()
225 {
226 if ($this->config->naturalSort) {
227 $sortFlags = SORT_NATURAL | SORT_FLAG_CASE;
228 } else {
229 $sortFlags = SORT_STRING | SORT_FLAG_CASE;
230 }
231
232 return $sortFlags;
233 }
234
235
236 }