PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 5.3.3
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v5.3.3
5.13.0 5.12.1 5.12.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 1 year ago Sorter 1 year ago Formatter.php 1 year ago Sorter.php 1 year ago
Sorter.php
195 lines
1 <?php
2
3 /**
4 * Matomo - free/libre analytics platform
5 *
6 * @link https://matomo.org
7 * @license https://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
8 */
9 namespace Piwik\Metrics;
10
11 use Piwik\DataTable;
12 use Piwik\DataTable\Row;
13 use Piwik\Metrics;
14 use Piwik\Plugin\Metric;
15 class Sorter
16 {
17 /**
18 * @var Sorter\Config
19 */
20 private $config;
21 public function __construct(\Piwik\Metrics\Sorter\Config $config)
22 {
23 $this->config = $config;
24 }
25 /**
26 * Sorts the DataTable rows using the supplied callback function.
27 *
28 * @param DataTable $table The table to sort.
29 */
30 public function sort(DataTable $table)
31 {
32 // all that code is in here and not in separate methods for best performance. It does make a difference once
33 // php has to copy many (eg 50k) rows otherwise.
34 $table->setTableSortedBy($this->config->primaryColumnToSort);
35 $rows = $table->getRowsWithoutSummaryRow();
36 // we need to sort rows that have a value separately from rows that do not have a value since we always want
37 // to append rows that do not have a value at the end.
38 $rowsWithValues = array();
39 $rowsWithoutValues = array();
40 $valuesToSort = array();
41 foreach ($rows as $key => $row) {
42 $value = $this->getColumnValue($row);
43 if (isset($value)) {
44 $valuesToSort[] = $value;
45 $rowsWithValues[] = $row;
46 } else {
47 $rowsWithoutValues[] = $row;
48 }
49 }
50 unset($rows);
51 if ($this->config->isSecondaryColumnSortEnabled && $this->config->secondaryColumnToSort) {
52 $secondaryValues = array();
53 foreach ($rowsWithValues as $key => $row) {
54 $secondaryValues[$key] = $row->getColumn($this->config->secondaryColumnToSort);
55 }
56 array_multisort($valuesToSort, $this->config->primarySortOrder, $this->config->primarySortFlags, $secondaryValues, $this->config->secondarySortOrder, $this->config->secondarySortFlags, $rowsWithValues);
57 } else {
58 array_multisort($valuesToSort, $this->config->primarySortOrder, $this->config->primarySortFlags, $rowsWithValues);
59 }
60 if (!empty($rowsWithoutValues) && $this->config->secondaryColumnToSort) {
61 $secondaryValues = array();
62 foreach ($rowsWithoutValues as $key => $row) {
63 $secondaryValues[$key] = $row->getColumn($this->config->secondaryColumnToSort);
64 }
65 array_multisort($secondaryValues, $this->config->secondarySortOrder, $this->config->secondarySortFlags, $rowsWithoutValues);
66 }
67 unset($secondaryValues);
68 foreach ($rowsWithoutValues as $row) {
69 $rowsWithValues[] = $row;
70 }
71 $table->setRows(array_values($rowsWithValues));
72 }
73 private function getColumnValue(Row $row)
74 {
75 $value = $row->getColumn($this->config->primaryColumnToSort);
76 if ($value === \false || is_array($value)) {
77 return null;
78 }
79 return $value;
80 }
81 /**
82 * @param string $order 'asc' or 'desc'
83 * @return int
84 */
85 public function getPrimarySortOrder($order)
86 {
87 if ($order === 'asc') {
88 return \SORT_ASC;
89 }
90 return \SORT_DESC;
91 }
92 /**
93 * @param string $order 'asc' or 'desc'
94 * @param string|int $secondarySortColumn column name or column id
95 * @return int
96 */
97 public function getSecondarySortOrder($order, $secondarySortColumn)
98 {
99 if ($secondarySortColumn === 'label') {
100 $secondaryOrder = \SORT_ASC;
101 if ($order === 'asc') {
102 $secondaryOrder = \SORT_DESC;
103 }
104 return $secondaryOrder;
105 }
106 return $this->getPrimarySortOrder($order);
107 }
108 /**
109 * Detect the column to be used for sorting
110 *
111 * @param DataTable $table
112 * @param string|int $columnToSort column name or column id
113 * @return int
114 */
115 public function getPrimaryColumnToSort(DataTable $table, $columnToSort)
116 {
117 // we fallback to nb_visits in case columnToSort does not exist
118 $columnsToCheck = array($columnToSort, 'nb_visits');
119 $row = $table->getFirstRow();
120 foreach ($columnsToCheck as $column) {
121 $column = Metric::getActualMetricColumn($table, $column);
122 if ($row->hasColumn($column)) {
123 // since getActualMetricColumn() returns a default value, we need to make sure it actually has that column
124 return $column;
125 }
126 }
127 return $columnToSort;
128 }
129 /**
130 * Detect the secondary sort column to be used for sorting
131 *
132 * @param Row $row
133 * @param int|string $primaryColumnToSort
134 * @return ?string
135 */
136 public function getSecondaryColumnToSort(Row $row, $primaryColumnToSort)
137 {
138 $defaultSecondaryColumn = array(Metrics::INDEX_NB_VISITS, 'nb_visits');
139 if (in_array($primaryColumnToSort, $defaultSecondaryColumn)) {
140 // if sorted by visits, then sort by label as a secondary column
141 $column = 'label';
142 $value = $row->hasColumn($column);
143 if ($value !== \false) {
144 return $column;
145 }
146 return null;
147 }
148 if ($primaryColumnToSort !== 'label') {
149 // we do not add this by default to make sure we do not sort by label as a first and secondary column
150 $defaultSecondaryColumn[] = 'label';
151 }
152 foreach ($defaultSecondaryColumn as $column) {
153 $value = $row->hasColumn($column);
154 if ($value !== \false) {
155 return $column;
156 }
157 }
158 return null;
159 }
160 /**
161 * @param DataTable $table
162 * @param string|int $columnToSort A column name or column id. Make sure that column actually exists in the row.
163 * You might want to get a valid column via {@link getPrimaryColumnToSort()} or
164 * {@link getSecondaryColumnToSort()}
165 * @return int
166 */
167 public function getBestSortFlags(DataTable $table, $columnToSort)
168 {
169 // when column is label we always to sort by string or natural
170 if (isset($columnToSort) && $columnToSort !== 'label') {
171 foreach ($table->getRowsWithoutSummaryRow() as $row) {
172 $value = $row->getColumn($columnToSort);
173 if ($value !== \false && $value !== null && !is_array($value)) {
174 if (is_numeric($value)) {
175 $sortFlags = \SORT_NUMERIC;
176 } else {
177 $sortFlags = $this->getStringSortFlags();
178 }
179 return $sortFlags;
180 }
181 }
182 }
183 return $this->getStringSortFlags();
184 }
185 private function getStringSortFlags()
186 {
187 if ($this->config->naturalSort) {
188 $sortFlags = \SORT_NATURAL | \SORT_FLAG_CASE;
189 } else {
190 $sortFlags = \SORT_STRING | \SORT_FLAG_CASE;
191 }
192 return $sortFlags;
193 }
194 }
195