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

GenerateGraphData.php « ViewDataTable « core - github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: af5f9ef132add55fefad8ad7881542458747ba86 (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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
<?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
 */
use Piwik\Piwik;
use Piwik\Common;

/**
 * Reads data from the API and prepares data to give to the renderer Piwik_Visualization_Chart.
 * This class is used to generate the data for the graphs.
 * You can set the number of elements to appear in the graph using: setGraphLimit();
 * Example:
 * <pre>
 *    function getWebsites( $fetch = false)
 *    {
 *        $view = Piwik_ViewDataTable::factory();
 *        $view->init( $this->pluginName, 'getWebsites', 'Referers.getWebsites', 'getUrlsFromWebsiteId' );
 *        $view->setColumnsToDisplay( array('label','nb_visits') );
 *        $view->setLimit(10);
 *        $view->setGraphLimit(12);
 *        return $this->renderView($view, $fetch);
 *    }
 * </pre>
 *
 * @package Piwik
 * @subpackage Piwik_ViewDataTable
 */
abstract class Piwik_ViewDataTable_GenerateGraphData extends Piwik_ViewDataTable
{
    protected $yAxisUnit = '';

    // used for the series picker
    protected $selectableColumns = array();

    public function __construct()
    {
        parent::__construct();
        $this->viewProperties['graph_limit'] = null;
        
        $labelIdx = array_search('label', $this->viewProperties['columns_to_display']);
        unset($this->viewProperties[$labelIdx]);
    }
    
    public function init($currentControllerName,
                           $currentControllerAction,
                           $apiMethodToRequestDataTable,
                           $controllerActionCalledWhenRequestSubTable = null,
                           $defaultProperties = array())
    {
        parent::init($currentControllerName,
                     $currentControllerAction,
                     $apiMethodToRequestDataTable,
                     $controllerActionCalledWhenRequestSubTable,
                     $defaultProperties);
        
        $columns = Common::getRequestVar('columns', false);
        if ($columns !== false) {
            $columns = Piwik::getArrayFromApiParameter($columns);
        } else {
            $columns = $this->viewProperties['columns_to_display'];
        }
        
        // do not sort if sorted column was initially "label" or eg. it would make "Visits by Server time" not pretty
        if ($this->getSortedColumn() != 'label') {
            $firstColumn = reset($columns);
            if ($firstColumn == 'label') {
                $firstColumn = next($columns);
            }
            
            $this->setSortedColumn($firstColumn);
        }
        
        // selectable columns
        if ($this->getViewDataTableId() != 'generateDataChartEvolution') {
            $selectableColumns = array('nb_visits', 'nb_actions');
            if (Common::getRequestVar('period', false) == 'day') {
                $selectableColumns[] = 'nb_uniq_visitors';
            }
            $this->setSelectableColumns($selectableColumns);
        }
    }

    public function setAxisYUnit($unit)
    {
        $this->yAxisUnit = $unit;
    }

    /**
     * Sets the number max of elements to display (number of pie slice, vertical bars, etc.)
     * If the data has more elements than $limit then the last part of the data will be the sum of all the remaining data.
     *
     * @param int $limit
     */
    public function setGraphLimit($limit)
    {
        $this->viewProperties['graph_limit'] = $limit;
    }

    /**
     * Returns numbers of elemnts to display in the graph
     *
     * @return int
     */
    public function getGraphLimit()
    {
        return $this->viewProperties['graph_limit'];
    }

    protected $displayPercentageInTooltip = true;

    /**
     * The percentage in tooltips is computed based on the sum of all values for the plotted column.
     * If the sum of the column in the data set is not the number of elements in the data set,
     * for example when plotting visits that have a given plugin enabled:
     * one visit can have several plugins, hence the sum is much greater than the number of visits.
     * In this case displaying the percentage doesn't make sense.
     */
    public function disallowPercentageInGraphTooltip()
    {
        $this->displayPercentageInTooltip = false;
    }

    /**
     * Sets the columns that can be added/removed by the user
     * This is done on data level (not html level) because the columns might change after reloading via sparklines
     * @param array $columnsNames Array of column names eg. array('nb_visits','nb_hits')
     */
    public function setSelectableColumns($columnsNames)
    {
        // the array contains values if enableShowGoals() has been used
        // add $columnsNames to the beginning of the array
        $this->selectableColumns = array_merge($columnsNames, $this->selectableColumns);
    }

    /**
     * The implementation of this method in Piwik_ViewDataTable passes to the graph whether the
     * goals icon should be displayed or not. Here, we use it to implicitly add the goal metrics
     * to the metrics picker.
     */
    public function enableShowGoals()
    {
        parent::enableShowGoals();

        $goalMetrics = array('nb_conversions', 'revenue');
        $this->selectableColumns = array_merge($this->selectableColumns, $goalMetrics);

        $this->setColumnTranslation('nb_conversions', Piwik_Translate('Goals_ColumnConversions'));
        $this->setColumnTranslation('revenue', Piwik_Translate('General_TotalRevenue'));
    }

    /**
     * Used in initChartObjectData to add the series picker config to the view object
     * @param bool $multiSelect
     */
    protected function addSeriesPickerToView($multiSelect = true)
    {
        if (count($this->selectableColumns)
            && Common::getRequestVar('showSeriesPicker', 1) == 1
        ) {
            // build the final configuration for the series picker
            $columnsToDisplay = $this->getColumnsToDisplay();
            $selectableColumns = array();

            foreach ($this->selectableColumns as $column) {
                $selectableColumns[] = array(
                    'column'      => $column,
                    'translation' => $this->getColumnTranslation($column),
                    'displayed'   => in_array($column, $columnsToDisplay)
                );
            }
            $this->view->setSelectableColumns($selectableColumns, $multiSelect);
        }
    }

    protected function getUnitsForColumnsToDisplay()
    {
        // derive units from column names
        $idSite = Common::getRequestVar('idSite', null, 'int');
        $units = $this->deriveUnitsFromRequestedColumnNames($this->getColumnsToDisplay(), $idSite);
        if (!empty($this->yAxisUnit)) {
            // force unit to the value set via $this->setAxisYUnit()
            foreach ($units as &$unit) {
                $unit = $this->yAxisUnit;
            }
        }

        return $units;
    }

    protected function deriveUnitsFromRequestedColumnNames($requestedColumnNames, $idSite)
    {
        $units = array();
        foreach ($requestedColumnNames as $columnName) {
            $derivedUnit = Piwik_Metrics::getUnit($columnName, $idSite);
            $units[$columnName] = empty($derivedUnit) ? false : $derivedUnit;
        }
        return $units;
    }

    public function main()
    {
        if ($this->mainAlreadyExecuted) {
            return;
        }
        $this->mainAlreadyExecuted = true;

        // Graphs require the full dataset, setting limit to null (same as 'no limit')
        $this->setLimit(null);

        // the queued filters will be manually applied later. This is to ensure that filtering using search
        // will be done on the table before the labels are enhanced (see ReplaceColumnNames)
        $this->disableQueuedFilters();

        // throws exception if no view access
        $this->loadDataTableFromAPI();
        $this->checkStandardDataTable();
        $this->postDataTableLoadedFromAPI();

        $graphLimit = $this->getGraphLimit();
        if (!empty($graphLimit)) {
            $offsetStartSummary = $this->getGraphLimit() - 1;
            $this->dataTable->filter('AddSummaryRow',
                array($offsetStartSummary,
                      Piwik_Translate('General_Others'),

                      // Column to sort by, before truncation
                      $this->dataTable->getSortedByColumnName()
                          ? $this->dataTable->getSortedByColumnName()
                          : Piwik_Metrics::INDEX_NB_VISITS
                )
            );
        }
        $this->isDataAvailable = $this->dataTable->getRowsCount() != 0;

        // if addTotalRow was called in GenerateGraphHTML, add a row containing totals of
        // different metrics
        if (Common::getRequestVar('add_total_row', 0) == 1) {
            $this->dataTable->queueFilter('AddSummaryRow', array(0, Piwik_Translate('General_Total'), null, false));
        }

        if ($this->isDataAvailable) {
            $this->initChartObjectData();
        }
        $this->view->customizeChartProperties();
    }

    protected function initChartObjectData()
    {
        $this->dataTable->applyQueuedFilters();

        // We apply a filter to the DataTable, decoding the label column (useful for keywords for example)
        $this->dataTable->filter('ColumnCallbackReplace', array('label', 'urldecode'));

        $xLabels = $this->dataTable->getColumn('label');
        $columnNames = parent::getColumnsToDisplay();
        if (($labelColumnFound = array_search('label', $columnNames)) !== false) {
            unset($columnNames[$labelColumnFound]);
        }

        $columnNameToTranslation = $columnNameToValue = array();
        foreach ($columnNames as $columnName) {
            $columnNameToTranslation[$columnName] = $this->getColumnTranslation($columnName);
            $columnNameToValue[$columnName] = $this->dataTable->getColumn($columnName);
        }
        $this->view->setAxisXLabels($xLabels);
        $this->view->setAxisYValues($columnNameToValue);
        $this->view->setAxisYLabels($columnNameToTranslation);
        $this->view->setAxisYUnit($this->yAxisUnit);
        $this->view->setDisplayPercentageInTooltip($this->displayPercentageInTooltip);

        // show_all_ticks is not real query param, it is set by GenerateGraphHTML.
        if (Common::getRequestVar('show_all_ticks', 0) == 1) {
            $this->view->showAllTicks();
        }

        $units = $this->getUnitsForColumnsToDisplay();
        $this->view->setAxisYUnits($units);

        $this->addSeriesPickerToView();
    }
}