Welcome to mirror list, hosted at ThFree Co, Russian Federation.

CalculateEvolutionFilter.php « Filter « DataTable « core - github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: f8d5886d25d80a0bb05a53a5dd4f7bc88da0f479 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
<?php
/**
 * Piwik - Open source web analytics
 *
 * @link http://piwik.org
 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
 *
 * @category Piwik
 * @package Piwik
 */
namespace Piwik\DataTable\Filter;

use Piwik\DataTable;
use Piwik\DataTable\Row;
use Piwik\Site;
use Piwik\DataTable\Filter\ColumnCallbackAddColumnPercentage;

/**
 * A DataTable filter that calculates the evolution of a metric and adds
 * it to each row as a percentage.
 *
 * This filter cannot be used as a normal filter since it requires
 * corresponding data from another datatable. Instead, to use it,
 * you must manually perform a binary filter (see the MultiSites API).
 *
 * The evolution metric is calculated as:
 * <code>((currentValue - pastValue) / pastValue) * 100</code>
 */
class CalculateEvolutionFilter extends ColumnCallbackAddColumnPercentage
{
    /**
     * The the DataTable that contains past data.
     */
    private $pastDataTable;

    /**
     * Tells if column being added is the revenue evolution column.
     */
    private $isRevenueEvolution = null;

    /**
     * Constructor.
     *
     * @param DataTable $table The DataTable being filtered.
     * @param string $pastDataTable
     * @param string $columnToAdd
     * @param string $columnToRead
     * @param int $quotientPrecision
     */
    function __construct($table, $pastDataTable, $columnToAdd, $columnToRead, $quotientPrecision = 0)
    {
        parent::__construct(
            $table, $columnToAdd, $columnToRead, $columnToRead, $quotientPrecision, $shouldSkipRows = true);

        $this->pastDataTable = $pastDataTable;

        $this->isRevenueEvolution = $columnToAdd == 'revenue_evolution';
    }

    /**
     * Returns the difference between the column in the specific row and its
     * sister column in the past DataTable.
     *
     * @param Row $row
     * @return int|float
     */
    protected function getDividend($row)
    {
        $currentValue = $row->getColumn($this->columnValueToRead);

        // if the site this is for doesn't support ecommerce & this is for the revenue_evolution column,
        // we don't add the new column
        if ($currentValue === false
            && $this->isRevenueEvolution
            && !Site::isEcommerceEnabledFor($row->getColumn('label'))
        ) {
            return false;
        }

        $pastRow = $this->getPastRowFromCurrent($row);
        if ($pastRow) {
            $pastValue = $pastRow->getColumn($this->columnValueToRead);
        } else {
            $pastValue = 0;
        }

        return $currentValue - $pastValue;
    }

    /**
     * Returns the value of the column in $row's sister row in the past
     * DataTable.
     *
     * @param Row $row
     * @return int|float
     */
    protected function getDivisor($row)
    {
        $pastRow = $this->getPastRowFromCurrent($row);
        if (!$pastRow) return 0;

        return $pastRow->getColumn($this->columnNameUsedAsDivisor);
    }

    /**
     * Calculates and formats a quotient based on a divisor and dividend.
     *
     * Unlike ColumnCallbackAddColumnPercentage's,
     * version of this method, this method will return 100% if the past
     * value of a metric is 0, and the current value is not 0. For a
     * value representative of an evolution, this makes sense.
     *
     * @param int|float $value The dividend.
     * @param int|float $divisor
     * @return string
     */
    protected function formatValue($value, $divisor)
    {
        $value = self::getPercentageValue($value, $divisor, $this->quotientPrecision);
        $value = self::appendPercentSign($value);
        return $value;
    }

    /**
     * Utility function. Returns the current row in the past DataTable.
     *
     * @param Row $row The row in the 'current' DataTable.
     */
    private function getPastRowFromCurrent($row)
    {
        return $this->pastDataTable->getRowFromLabel($row->getColumn('label'));
    }

    /**
     * Calculates the evolution percentage for two arbitrary values.
     *
     * @param float|int $currentValue      The current metric value.
     * @param float|int $pastValue         The value of the metric in the past. We measure the % change
     *                                      from this value to $currentValue.
     * @param float|int $quotientPrecision The quotient precision to round to.
     *
     * @return string The evolution percent 15%
     */
    public static function calculate($currentValue, $pastValue, $quotientPrecision = 0)
    {
        $number = self::getPercentageValue($currentValue - $pastValue, $pastValue, $quotientPrecision);
        $number = self::appendPercentSign($number);
        return $number;
    }

    public static function appendPercentSign($number)
    {
        $number = $number . '%';
        return $number;
    }

    public static function prependPlusSignToNumber($number)
    {
        if ($number > 0) {
            $number = '+' . $number;
        }
        return $number;
    }

    /**
     * Returns an evolution percent based on a value & divisor.
     */
    private static function getPercentageValue($value, $divisor, $quotientPrecision)
    {
        if ($value == 0) {
            $evolution = 0;
        } elseif ($divisor == 0) {
            $evolution = 100;
        } else {
            $evolution = ($value / $divisor) * 100;
        }

        $evolution = round($evolution, $quotientPrecision);
        return $evolution;
    }
}