PluginProbe ʕ •ᴥ•ʔ
Matomo Analytics – Powerful, Privacy-First Insights for WordPress / 4.15.2
Matomo Analytics – Powerful, Privacy-First Insights for WordPress v4.15.2
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 / Plugin / ComputedMetric.php
matomo / app / core / Plugin Last commit date
Dimension 3 years ago API.php 3 years ago AggregatedMetric.php 5 years ago ArchivedMetric.php 3 years ago Archiver.php 3 years ago Categories.php 5 years ago ComponentFactory.php 5 years ago ComputedMetric.php 3 years ago ConsoleCommand.php 5 years ago Controller.php 3 years ago ControllerAdmin.php 3 years ago Dependency.php 4 years ago LogTablesProvider.php 5 years ago Manager.php 4 years ago Menu.php 5 years ago MetadataLoader.php 4 years ago Metric.php 3 years ago PluginException.php 5 years ago ProcessedMetric.php 5 years ago ReleaseChannels.php 5 years ago Report.php 2 years ago ReportsProvider.php 3 years ago RequestProcessors.php 5 years ago Segment.php 3 years ago SettingsProvider.php 5 years ago Tasks.php 3 years ago ThemeStyles.php 5 years ago ViewDataTable.php 5 years ago Visualization.php 2 years ago WidgetsProvider.php 5 years ago
ComputedMetric.php
268 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\Plugin;
9
10 use Piwik\Archive\DataTableFactory;
11 use Piwik\Columns\Dimension;
12 use Piwik\Columns\MetricsList;
13 use Piwik\Common;
14 use Piwik\DataTable;
15 use Piwik\DataTable\Row;
16 use Piwik\Metrics\Formatter;
17 use Piwik\Piwik;
18
19 class ComputedMetric extends ProcessedMetric
20 {
21 const AGGREGATION_AVG = 'avg';
22 const AGGREGATION_RATE = 'rate';
23
24 /**
25 * @var string
26 */
27 private $aggregation;
28
29 /**
30 * @var int
31 */
32 protected $idSite;
33
34 private $name = '';
35 private $type = '';
36 private $translatedName = '';
37 private $documentation = '';
38 private $metric1 = '';
39 private $metric2 = '';
40 private $category = '';
41
42 private $metricsList;
43
44 public function __construct($metric1, $metric2, $aggregation = 'avg')
45 {
46 $nameShort1 = str_replace(array('nb_'), '', $metric1);
47 $nameShort2 = str_replace(array('nb_'), '', $metric2);
48
49 if ($aggregation === ComputedMetric::AGGREGATION_AVG) {
50 $this->name = 'avg_' . $nameShort1 . '_per_' . $nameShort2;
51 } elseif ($aggregation === ComputedMetric::AGGREGATION_RATE) {
52 $this->name = $nameShort1 . '_' . $nameShort2 . '_rate';
53 } else {
54 throw new \Exception('Not supported aggregation type');
55 }
56
57 $this->setMetric1($metric1);
58 $this->setMetric2($metric2);
59 $this->aggregation = $aggregation;
60 }
61
62 public function getDependentMetrics()
63 {
64 return array($this->metric1, $this->metric2);
65 }
66
67 public function setCategory($category)
68 {
69 $this->category = $category;
70 return $this;
71 }
72
73 public function getCategoryId()
74 {
75 return $this->category;
76 }
77
78 public function setMetric1($metric1)
79 {
80 $this->metric1 = $metric1;
81 return $this;
82 }
83
84 public function setMetric2($metric2)
85 {
86 $this->metric2 = $metric2;
87 return $this;
88 }
89
90 public function setDocumentation($documentation)
91 {
92 $this->documentation = $documentation;
93 return $this;
94 }
95
96 public function setTranslatedName($name)
97 {
98 $this->translatedName = $name;
99 return $this;
100 }
101
102 public function setType($type)
103 {
104 $this->type = $type;
105 return $this;
106 }
107
108 public function setName($name)
109 {
110 $this->name = $name;
111 return $this;
112 }
113
114 public function getName()
115 {
116 return $this->name;
117 }
118
119 public function compute(Row $row)
120 {
121 $metric1 = $this->getMetric($row, $this->metric1);
122 $metric2 = $this->getMetric($row, $this->metric2);
123
124 $precision = 2;
125 if ($this->aggregation === self::AGGREGATION_RATE) {
126 $precision = 3;
127 }
128
129 return Piwik::getQuotientSafe($metric1, $metric2, $precision);
130 }
131
132 private function getDetectedType()
133 {
134 if (!$this->type) {
135 if ($this->aggregation === self::AGGREGATION_RATE) {
136 $this->type = Dimension::TYPE_PERCENT;
137 } else {
138 $this->type = Dimension::TYPE_NUMBER; // default to number
139 $metric1 = $this->getMetricsList()->getMetric($this->metric1);
140 if ($metric1) {
141 $dimension = $metric1->getDimension();
142 if ($dimension && $dimension->getType() != Dimension::TYPE_BOOL) {
143 $this->type = $dimension->getType();
144 }
145 }
146 }
147 }
148
149 return $this->type;
150 }
151
152 public function format($value, Formatter $formatter)
153 {
154 if ($this->aggregation === self::AGGREGATION_RATE) {
155 return $formatter->getPrettyPercentFromQuotient($value);
156 }
157
158 $type = $this->getDetectedType();
159
160 switch ($type) {
161 case Dimension::TYPE_MONEY:
162 return $formatter->getPrettyMoney($value, $this->idSite);
163 case Dimension::TYPE_FLOAT:
164 return $formatter->getPrettyNumber($value, $precision = 2);
165 case Dimension::TYPE_NUMBER:
166 return $formatter->getPrettyNumber($value, 1); // we still need to round to have somewhat more accurate result
167 case Dimension::TYPE_DURATION_S:
168 return $formatter->getPrettyTimeFromSeconds(round($value), $displayAsSentence = true);
169 case Dimension::TYPE_DURATION_MS:
170 $val = round(($value / 1000), ($value / 1000) > 60 ? 0 : 2);
171 return $formatter->getPrettyTimeFromSeconds($val, $displayAsSentence = true);
172 case Dimension::TYPE_PERCENT:
173 return $formatter->getPrettyPercentFromQuotient($value);
174 case Dimension::TYPE_BYTE:
175 return $formatter->getPrettySizeFromBytes($value);
176 }
177
178 return $value;
179 }
180
181 public function getTranslatedName()
182 {
183 if (!$this->translatedName) {
184 $metric = $this->getMetricsList();
185 $metric1 = $metric->getMetric($this->metric1);
186 $metric2 = $metric->getMetric($this->metric2);
187
188 if ($this->aggregation === self::AGGREGATION_AVG) {
189 if ($metric1 && $metric1 instanceof ArchivedMetric && $metric2 && $metric2 instanceof ArchivedMetric) {
190
191 $metric1Name = $metric1->getDimension()->getName();
192 $metric2Name = $metric2->getDimension()->getName();
193 return Piwik::translate('General_ComputedMetricAverage', array($metric1Name, $metric2Name));
194 }
195
196 if ($metric1 && $metric1 instanceof ArchivedMetric) {
197 $metric1Name = $metric1->getDimension()->getName();
198 return Piwik::translate('General_AverageX', array($metric1Name));
199 }
200
201 if ($metric1 && $metric2) {
202 return $metric1->getTranslatedName() . ' per ' . $metric2->getTranslatedName();
203 }
204
205 return $this->metric1 . ' per ' . $this->metric2;
206 } else if ($this->aggregation === self::AGGREGATION_RATE) {
207 if ($metric1 && $metric1 instanceof ArchivedMetric) {
208 return Piwik::translate('General_ComputedMetricRate', array($metric1->getTranslatedName()));
209 } else {
210 return Piwik::translate('General_ComputedMetricRate', array($this->metric1));
211 }
212 }
213 }
214 return $this->translatedName;
215 }
216
217 public function getDocumentation()
218 {
219 if (!$this->documentation) {
220 $metric = $this->getMetricsList();
221 $metric1 = $metric->getMetric($this->metric1);
222 $metric2 = $metric->getMetric($this->metric2);
223
224 if ($this->aggregation === self::AGGREGATION_AVG) {
225 if ($metric1 && $metric1 instanceof ArchivedMetric && $metric2 && $metric2 instanceof ArchivedMetric) {
226 return Piwik::translate('General_ComputedMetricAverageDocumentation', array($metric1->getDimension()->getName(), $metric2->getTranslatedName()));
227 }
228
229 if ($metric1 && $metric1 instanceof ArchivedMetric) {
230 return Piwik::translate('General_ComputedMetricAverageShortDocumentation', array($metric1->getDimension()->getName()));
231 }
232
233 return Piwik::translate('General_ComputedMetricAverageDocumentation', array($this->metric1, $this->metric2));
234
235 } else if ($this->aggregation === self::AGGREGATION_RATE) {
236 if ($metric1 && $metric1 instanceof ArchivedMetric) {
237 return Piwik::translate('General_ComputedMetricRateDocumentation', array($metric1->getDimension()->getNamePlural(), $metric2->getDimension()->getNamePlural()));
238 } else {
239 return Piwik::translate('General_ComputedMetricRateShortDocumentation', array($this->metric1));
240 }
241 }
242 }
243 return $this->documentation;
244 }
245
246 private function getMetricsList()
247 {
248 if (!$this->metricsList) {
249 $this->metricsList = MetricsList::get();
250 }
251 return $this->metricsList;
252 }
253
254 public function beforeFormat($report, DataTable $table)
255 {
256 $this->idSite = DataTableFactory::getSiteIdFromMetadata($table);
257 if (empty($this->idSite)) {
258 $this->idSite = Common::getRequestVar('idSite', 0, 'int');
259 }
260 return !empty($this->idSite); // skip formatting if there is no site to get currency info from
261 }
262
263 public function getSemanticType(): ?string
264 {
265 return $this->getDetectedType();
266 }
267 }
268