PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / trunk
Matomo Analytics – Powerful, Privacy-First Insights for WordPress vtrunk
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 3 months ago Sorter.php 3 months ago
Sorter.php
192 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 string|int $columnToSort column name or column id
112 * @return int
113 */
114 public function getPrimaryColumnToSort(DataTable $table, $columnToSort)
115 {
116 // we fallback to nb_visits in case columnToSort does not exist
117 $columnsToCheck = array($columnToSort, 'nb_visits');
118 $row = $table->getFirstRow();
119 foreach ($columnsToCheck as $column) {
120 $column = Metric::getActualMetricColumn($table, $column);
121 if ($row->hasColumn($column)) {
122 // since getActualMetricColumn() returns a default value, we need to make sure it actually has that column
123 return $column;
124 }
125 }
126 return $columnToSort;
127 }
128 /**
129 * Detect the secondary sort column to be used for sorting
130 *
131 * @param int|string $primaryColumnToSort
132 * @return ?string
133 */
134 public function getSecondaryColumnToSort(Row $row, $primaryColumnToSort)
135 {
136 $defaultSecondaryColumn = array(Metrics::INDEX_NB_VISITS, 'nb_visits');
137 if (in_array($primaryColumnToSort, $defaultSecondaryColumn)) {
138 // if sorted by visits, then sort by label as a secondary column
139 $column = 'label';
140 $value = $row->hasColumn($column);
141 if ($value !== \false) {
142 return $column;
143 }
144 return null;
145 }
146 if ($primaryColumnToSort !== 'label') {
147 // we do not add this by default to make sure we do not sort by label as a first and secondary column
148 $defaultSecondaryColumn[] = 'label';
149 }
150 foreach ($defaultSecondaryColumn as $column) {
151 $value = $row->hasColumn($column);
152 if ($value !== \false) {
153 return $column;
154 }
155 }
156 return null;
157 }
158 /**
159 * @param string|int|null $columnToSort A column name or column id. Make sure that column actually exists in the row.
160 * You might want to get a valid column via {@link getPrimaryColumnToSort()} or
161 * {@link getSecondaryColumnToSort()}
162 * @return int
163 */
164 public function getBestSortFlags(DataTable $table, $columnToSort)
165 {
166 // when column is label we always to sort by string or natural
167 if (isset($columnToSort) && $columnToSort !== 'label') {
168 foreach ($table->getRowsWithoutSummaryRow() as $row) {
169 $value = $row->getColumn($columnToSort);
170 if ($value !== \false && $value !== null && !is_array($value)) {
171 if (is_numeric($value)) {
172 $sortFlags = \SORT_NUMERIC;
173 } else {
174 $sortFlags = $this->getStringSortFlags();
175 }
176 return $sortFlags;
177 }
178 }
179 }
180 return $this->getStringSortFlags();
181 }
182 private function getStringSortFlags()
183 {
184 if ($this->config->naturalSort) {
185 $sortFlags = \SORT_NATURAL | \SORT_FLAG_CASE;
186 } else {
187 $sortFlags = \SORT_STRING | \SORT_FLAG_CASE;
188 }
189 return $sortFlags;
190 }
191 }
192