/plugins/Insights/InsightReport.php
PHP | 288 lines | 192 code | 36 blank | 60 comment | 18 complexity | ae427f0dbf5e4712ada47bc1e592b76c MD5 | raw file
Possible License(s): LGPL-3.0, JSON, MIT, GPL-3.0, LGPL-2.1, GPL-2.0, AGPL-1.0, BSD-2-Clause, BSD-3-Clause
- <?php
- /**
- * Piwik - free/libre analytics platform
- *
- * @link http://piwik.org
- * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
- *
- */
- namespace Piwik\Plugins\Insights;
- use Piwik\DataTable;
- use Piwik\Piwik;
- /**
- * Insight report generator
- */
- class InsightReport
- {
- const ORDER_BY_RELATIVE = 'relative';
- const ORDER_BY_ABSOLUTE = 'absolute';
- const ORDER_BY_IMPORTANCE = 'importance';
- /**
- * @param array $reportMetadata
- * @param string $period
- * @param string $date
- * @param string $lastDate
- * @param string $metric
- * @param DataTable $currentReport
- * @param DataTable $lastReport
- * @param int $totalValue
- * @param int $lastTotalValue
- * @param string $orderBy
- * @param int $limitIncreaser
- * @param int $limitDecreaser
- * @return DataTable
- */
- public function generateMoverAndShaker($reportMetadata, $period, $date, $lastDate, $metric, $currentReport, $lastReport, $totalValue, $lastTotalValue, $orderBy, $limitIncreaser, $limitDecreaser)
- {
- $totalEvolution = $this->getTotalEvolution($totalValue, $lastTotalValue);
- $minMoversPercent = 1;
- if ($totalEvolution >= 100) {
- // eg change from 50 to 150 = 200%
- $factor = (int) ceil($totalEvolution / 500);
- $minGrowthPercentPositive = $totalEvolution + ($factor * 40); // min +240%
- $minGrowthPercentNegative = -70; // min -70%
- $minDisappearedPercent = 8; // min 12
- $minNewPercent = min(($totalEvolution / 100) * 3, 10); // min 6% = min 10 of total visits up to max 10%
- } elseif ($totalEvolution >= 0) {
- // eg change from 50 to 75 = 50%
- $minGrowthPercentPositive = $totalEvolution + 20; // min 70%
- $minGrowthPercentNegative = -1 * $minGrowthPercentPositive; // min -70%
- $minDisappearedPercent = 7;
- $minNewPercent = 5;
- } else {
- // eg change from 50 to 25 = -50%
- $minGrowthPercentNegative = $totalEvolution - 20; // min -70%
- $minGrowthPercentPositive = abs($minGrowthPercentNegative); // min 70%
- $minDisappearedPercent = 7;
- $minNewPercent = 5;
- }
- if ($totalValue < 200 && $totalValue != 0) {
- // force at least a change of 2 visits
- $minMoversPercent = (int) ceil(2 / ($totalValue / 100));
- $minNewPercent = max($minNewPercent, $minMoversPercent);
- $minDisappearedPercent = max($minDisappearedPercent, $minMoversPercent);
- }
- $dataTable = $this->generateInsight($reportMetadata, $period, $date, $lastDate, $metric, $currentReport, $lastReport, $totalValue, $minMoversPercent, $minNewPercent, $minDisappearedPercent, $minGrowthPercentPositive, $minGrowthPercentNegative, $orderBy, $limitIncreaser, $limitDecreaser);
- $this->addMoversAndShakersMetadata($dataTable, $totalValue, $lastTotalValue);
- return $dataTable;
- }
- /**
- * Extends an already generated insight report by adding a column "isMoverAndShaker" whether a row is also a
- * "Mover and Shaker" or not.
- *
- * Avoids the need to fetch all reports again when we already have the currentReport/lastReport
- */
- public function markMoversAndShakers(DataTable $insight, $currentReport, $lastReport, $totalValue, $lastTotalValue)
- {
- if (!$insight->getRowsCount()) {
- return;
- }
- $limitIncreaser = max($insight->getRowsCount(), 3);
- $limitDecreaser = max($insight->getRowsCount(), 3);
- $lastDate = $insight->getMetadata('lastDate');
- $date = $insight->getMetadata('date');
- $period = $insight->getMetadata('period');
- $metric = $insight->getMetadata('metric');
- $orderBy = $insight->getMetadata('orderBy');
- $reportMetadata = $insight->getMetadata('report');
- $shakers = $this->generateMoverAndShaker($reportMetadata, $period, $date, $lastDate, $metric, $currentReport, $lastReport, $totalValue, $lastTotalValue, $orderBy, $limitIncreaser, $limitDecreaser);
- foreach ($insight->getRows() as $row) {
- $label = $row->getColumn('label');
- if ($shakers->getRowFromLabel($label)) {
- $row->setColumn('isMoverAndShaker', true);
- } else {
- $row->setColumn('isMoverAndShaker', false);
- }
- }
- $this->addMoversAndShakersMetadata($insight, $totalValue, $lastTotalValue);
- }
- /**
- * @param array $reportMetadata
- * @param string $period
- * @param string $date
- * @param string $lastDate
- * @param string $metric
- * @param DataTable $currentReport
- * @param DataTable $lastReport
- * @param int $totalValue
- * @param int $minMoversPercent Exclude rows who moved and the difference is not at least min percent
- * visits of totalVisits. -1 excludes movers.
- * @param int $minNewPercent Exclude rows who are new and the difference is not at least min percent
- * visits of totalVisits. -1 excludes all new.
- * @param int $minDisappearedPercent Exclude rows who are disappeared and the difference is not at least min
- * percent visits of totalVisits. -1 excludes all disappeared.
- * @param int $minGrowthPercentPositive The actual growth of a row must be at least percent compared to the
- * previous value (not total value)
- * @param int $minGrowthPercentNegative The actual growth of a row must be lower percent compared to the
- * previous value (not total value)
- * @param string $orderBy Order by absolute, relative, importance
- * @param int $limitIncreaser
- * @param int $limitDecreaser
- *
- * @return DataTable
- */
- public function generateInsight($reportMetadata, $period, $date, $lastDate, $metric, $currentReport, $lastReport, $totalValue, $minMoversPercent, $minNewPercent, $minDisappearedPercent, $minGrowthPercentPositive, $minGrowthPercentNegative, $orderBy, $limitIncreaser, $limitDecreaser)
- {
- $minChangeMovers = $this->getMinVisits($totalValue, $minMoversPercent);
- $minIncreaseNew = $this->getMinVisits($totalValue, $minNewPercent);
- $minDecreaseDisappeared = $this->getMinVisits($totalValue, $minDisappearedPercent);
- $dataTable = new DataTable();
- $dataTable->filter(
- 'Piwik\Plugins\Insights\DataTable\Filter\Insight',
- array(
- $currentReport,
- $lastReport,
- $metric,
- $considerMovers = (-1 !== $minMoversPercent),
- $considerNew = (-1 !== $minNewPercent),
- $considerDisappeared = (-1 !== $minDisappearedPercent)
- )
- );
- $dataTable->filter(
- 'Piwik\Plugins\Insights\DataTable\Filter\MinGrowth',
- array(
- 'growth_percent_numeric',
- $minGrowthPercentPositive,
- $minGrowthPercentNegative
- )
- );
- if ($minIncreaseNew) {
- $dataTable->filter(
- 'Piwik\Plugins\Insights\DataTable\Filter\ExcludeLowValue',
- array(
- 'difference',
- $minIncreaseNew,
- 'isNew'
- )
- );
- }
- if ($minChangeMovers) {
- $dataTable->filter(
- 'Piwik\Plugins\Insights\DataTable\Filter\ExcludeLowValue',
- array(
- 'difference',
- $minChangeMovers,
- 'isMover'
- )
- );
- }
- if ($minDecreaseDisappeared) {
- $dataTable->filter(
- 'Piwik\Plugins\Insights\DataTable\Filter\ExcludeLowValue',
- array(
- 'difference',
- $minDecreaseDisappeared,
- 'isDisappeared'
- )
- );
- }
- $dataTable->filter(
- 'Piwik\Plugins\Insights\DataTable\Filter\OrderBy',
- array(
- $this->getOrderByColumn($orderBy),
- $orderBy === self::ORDER_BY_RELATIVE ? $this->getOrderByColumn(self::ORDER_BY_ABSOLUTE) : $this->getOrderByColumn(self::ORDER_BY_RELATIVE),
- $metric
- )
- );
- $dataTable->filter(
- 'Piwik\Plugins\Insights\DataTable\Filter\Limit',
- array(
- 'growth_percent_numeric',
- $limitIncreaser,
- $limitDecreaser
- )
- );
- $metricName = $metric;
- if (!empty($reportMetadata['metrics'][$metric])) {
- $metricName = $reportMetadata['metrics'][$metric];
- }
- $dataTable->setMetadataValues(array(
- 'reportName' => $reportMetadata['name'],
- 'metricName' => $metricName,
- 'date' => $date,
- 'lastDate' => $lastDate,
- 'period' => $period,
- 'report' => $reportMetadata,
- 'totalValue' => $totalValue,
- 'orderBy' => $orderBy,
- 'metric' => $metric,
- 'minChangeMovers' => $minChangeMovers,
- 'minIncreaseNew' => $minIncreaseNew,
- 'minDecreaseDisappeared' => $minDecreaseDisappeared,
- 'minGrowthPercentPositive' => $minGrowthPercentPositive,
- 'minGrowthPercentNegative' => $minGrowthPercentNegative,
- 'minMoversPercent' => $minMoversPercent,
- 'minNewPercent' => $minNewPercent,
- 'minDisappearedPercent' => $minDisappearedPercent
- ));
- return $dataTable;
- }
- private function getOrderByColumn($orderBy)
- {
- if (self::ORDER_BY_RELATIVE == $orderBy) {
- $orderByColumn = 'growth_percent_numeric';
- } elseif (self::ORDER_BY_ABSOLUTE == $orderBy) {
- $orderByColumn = 'difference';
- } elseif (self::ORDER_BY_IMPORTANCE == $orderBy) {
- $orderByColumn = 'importance';
- } else {
- throw new \Exception('Unsupported orderBy');
- }
- return $orderByColumn;
- }
- private function getMinVisits($totalValue, $percent)
- {
- if ($percent <= 0) {
- return 0;
- }
- $minVisits = ceil(($totalValue / 100) * $percent);
- return (int) $minVisits;
- }
- private function addMoversAndShakersMetadata(DataTable $dataTable, $totalValue, $lastTotalValue)
- {
- $totalEvolution = $this->getTotalEvolution($totalValue, $lastTotalValue);
- $dataTable->setMetadata('lastTotalValue', $lastTotalValue);
- $dataTable->setMetadata('evolutionTotal', $totalEvolution);
- $dataTable->setMetadata('evolutionDifference', $totalValue - $lastTotalValue);
- }
- private function getTotalEvolution($totalValue, $lastTotalValue)
- {
- return Piwik::getPercentageSafe($totalValue - $lastTotalValue, $lastTotalValue, 1);
- }
- }