Skip to content
Extraits de code Groupes Projets
Valider c25f396c rédigé par Thomas Steur's avatar Thomas Steur
Parcourir les fichiers

refs #57 started to work on movers and shakers and lots of minor improvements

parent 8601c094
Aucune branche associée trouvée
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
Affichage de
avec 439 ajouts et 200 suppressions
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
namespace Piwik; namespace Piwik;
use Exception; use Exception;
use Piwik\Period\Range;
use Piwik\Translate; use Piwik\Translate;
use Piwik\Visualization\Sparkline; use Piwik\Visualization\Sparkline;
use Piwik\View\RenderTokenParser; use Piwik\View\RenderTokenParser;
...@@ -63,6 +64,7 @@ class Twig ...@@ -63,6 +64,7 @@ class Twig
$this->addFilter_truncate(); $this->addFilter_truncate();
$this->addFilter_notificiation(); $this->addFilter_notificiation();
$this->addFilter_percentage(); $this->addFilter_percentage();
$this->addFilter_prettyDate();
$this->twig->addFilter(new Twig_SimpleFilter('implode', 'implode')); $this->twig->addFilter(new Twig_SimpleFilter('implode', 'implode'));
$this->twig->addFilter(new Twig_SimpleFilter('ucwords', 'ucwords')); $this->twig->addFilter(new Twig_SimpleFilter('ucwords', 'ucwords'));
...@@ -187,6 +189,14 @@ class Twig ...@@ -187,6 +189,14 @@ class Twig
$this->twig->addFilter($notificationFunction); $this->twig->addFilter($notificationFunction);
} }
protected function addFilter_prettyDate()
{
$prettyDate = new Twig_SimpleFilter('prettyDate', function ($dateString, $period) {
return Range::factory($period, $dateString)->getLocalizedShortString();
});
$this->twig->addFilter($prettyDate);
}
protected function addFilter_percentage() protected function addFilter_percentage()
{ {
$percentage = new Twig_SimpleFilter('percentage', function ($string, $totalValue, $precision = 1) { $percentage = new Twig_SimpleFilter('percentage', function ($string, $totalValue, $precision = 1) {
......
...@@ -31,39 +31,57 @@ class API extends \Piwik\Plugin\API ...@@ -31,39 +31,57 @@ class API extends \Piwik\Plugin\API
const ORDER_BY_ABSOLUTE = 'absolute'; const ORDER_BY_ABSOLUTE = 'absolute';
const ORDER_BY_IMPORTANCE = 'importance'; const ORDER_BY_IMPORTANCE = 'importance';
public function getInsightsOverview($idSite, $period, $date) private $reportIds = array(
'Actions_getPageUrls',
'Actions_getPageTitles',
'Actions_getDownloads',
'Referrers_getAll',
'Referrers_getKeywords',
'Referrers_getCampaigns',
'Referrers_getSocials',
'Referrers_getSearchEngines',
'UserCountry_getCountry',
);
public function getInsightsOverview($idSite, $period, $date, $segment = false)
{ {
Piwik::checkUserHasViewAccess(array($idSite)); Piwik::checkUserHasViewAccess(array($idSite));
$reportTableIds = array();
/** @var DataTable[] $tables */ /** @var DataTable[] $tables */
$reports = array( $tables = array();
'Actions_getPageUrls', foreach ($this->reportIds as $reportId) {
'Actions_getPageTitles', $firstTableId = DataTable\Manager::getInstance()->getMostRecentTableId();
'Actions_getDownloads', $table = $this->getInsights($idSite, $period, $date, $reportId, $segment, 3, 3, '', 2, 25);
'Referrers_getAll', $reportTableIds[] = $table->getId();
'Referrers_getKeywords', $this->deleteDataTables($firstTableId, $reportTableIds);
'Referrers_getCampaigns',
'Referrers_getSocials',
'Referrers_getSearchEngines',
'UserCountry_getCountry',
);
// post event to add other reports?
$reportTableIds = array(); $tables[] = $table;
$dataTableManager = DataTable\Manager::getInstance(); }
$map = new DataTable\Map();
foreach ($tables as $table) {
$map->addTable($table, $table->getMetadata('reportName'));
}
return $map;
}
public function getOverallMoversAndShakers($idSite, $period, $date, $segment = false)
{
Piwik::checkUserHasViewAccess(array($idSite));
$reportTableIds = array();
/** @var DataTable[] $tables */
$tables = array(); $tables = array();
foreach ($reports as $report) { foreach ($this->reportIds as $reportId) {
$firstTableId = $dataTableManager->getMostRecentTableId(); $firstTableId = DataTable\Manager::getInstance()->getMostRecentTableId();
$table = $this->getInsightOverview($idSite, $period, $date, $report); $table = $this->getMoversAndShakers($idSite, $period, $date, $reportId, $segment, 4, 4);
$reportTableIds[] = $table->getId(); $reportTableIds[] = $table->getId();
$lastTableId = $dataTableManager->getMostRecentTableId(); $this->deleteDataTables($firstTableId, $reportTableIds);
for ($index = $firstTableId; $index <= $lastTableId; $index++) {
if (!in_array($index, $reportTableIds)) {
$dataTableManager->deleteTable($index);
}
}
$tables[] = $table; $tables[] = $table;
} }
...@@ -77,18 +95,21 @@ class API extends \Piwik\Plugin\API ...@@ -77,18 +95,21 @@ class API extends \Piwik\Plugin\API
return $map; return $map;
} }
public function getInsightOverview($idSite, $period, $date, $reportUniqueId, $segment = false, $limitIncreaser = 4, public function getMoversAndShakers($idSite, $period, $date, $reportUniqueId, $segment = false,
$limitDecreaser = 4, $minVisitsPercent = 3, $minGrowthPercent = 25, $orderBy = 'absolute', $limitIncreaser = 4, $limitDecreaser = 4)
$considerMovers = true, $considerNew = true, $considerDisappeared = false)
{ {
$orderBy = 'absolute';
$minVisitsPercent = 2;
$minGrowthPercent = 30;
$minMoversPercent = 2;
$minNewPercent = 2;
$minDisappearedPercent = 2;
Piwik::checkUserHasViewAccess(array($idSite)); Piwik::checkUserHasViewAccess(array($idSite));
$metric = 'nb_visits'; $metric = 'nb_visits';
// consider disappeared if impact > 10%?
$totalValue = $this->getTotalValue($idSite, $period, $date, $metric);
$minVisits = $this->getMinVisits($totalValue, $minVisitsPercent);
$totalValue = $this->getTotalValue($idSite, $period, $date, $metric);
$report = $this->getReportByUniqueId($idSite, $reportUniqueId); $report = $this->getReportByUniqueId($idSite, $reportUniqueId);
$currentReport = $this->requestReport($idSite, $period, $date, $report, $metric, $segment); $currentReport = $this->requestReport($idSite, $period, $date, $report, $metric, $segment);
...@@ -97,28 +118,29 @@ class API extends \Piwik\Plugin\API ...@@ -97,28 +118,29 @@ class API extends \Piwik\Plugin\API
// for faster performance just compare against last week? // for faster performance just compare against last week?
$pastDate = Date::factory($date); $pastDate = Date::factory($date);
$pastDate = $pastDate->subDay(7); $pastDate = $pastDate->subDay(7);
$lastDate = $pastDate->toString(); $pastDate = $pastDate->toString();
$lastReport = $this->requestReport($idSite, 'week', $lastDate, $report, $metric, $segment); $lastReport = $this->requestReport($idSite, 'week', $pastDate, $report, $metric, $segment);
$lastReport->filter('Piwik\Plugins\Insights\DataTable\Filter\Average', array($metric, 7)); $lastReport->filter('Piwik\Plugins\Insights\DataTable\Filter\Average', array($metric, 7));
$lastDate = Range::factory('week', $pastDate);
$lastDate = $lastDate->getRangeString();
} else { } else {
$pastDate = Range::getLastDate($date, $period); $pastDate = Range::getLastDate($date, $period);
if (empty($pastDate[0])) { if (empty($pastDate[0])) {
return new DataTable(); throw new \Exception('Not possible to calculate movers and shakers for this date/period combination');
} }
$lastDate = $pastDate[0]; $lastDate = $pastDate[0];
$lastReport = $this->requestReport($idSite, $period, $lastDate, $report, $metric, $segment); $lastReport = $this->requestReport($idSite, $period, $lastDate, $report, $metric, $segment);
} }
return $this->buildInsightsReport($period, $date, $limitIncreaser, $limitDecreaser, $minGrowthPercent, $orderBy, $currentReport, $lastReport, $metric, $considerMovers, $considerNew, $considerDisappeared, $minVisits, $report, $lastDate, $totalValue); return $this->buildDataTable($report, $period, $date, $lastDate, $metric, $currentReport, $lastReport, $totalValue, $minVisitsPercent, $minMoversPercent, $minNewPercent, $minDisappearedPercent, $minGrowthPercent, $orderBy, $limitIncreaser, $limitDecreaser);
} }
// force $limitX and ignore minVisitsPercent, minGrowthPercent
public function getInsights( public function getInsights(
$idSite, $period, $date, $reportUniqueId, $limitIncreaser = 5, $limitDecreaser = 5, $idSite, $period, $date, $reportUniqueId, $segment = false, $limitIncreaser = 5, $limitDecreaser = 5,
$filterBy = '', $minVisitsPercent = 2, $minGrowthPercent = 20, $filterBy = '', $minVisitsPercent = 2, $minGrowthPercent = 20,
$comparedToXPeriods = 1, $orderBy = 'absolute', $segment = false) $comparedToXPeriods = 1, $orderBy = 'absolute')
{ {
Piwik::checkUserHasViewAccess(array($idSite)); Piwik::checkUserHasViewAccess(array($idSite));
...@@ -127,33 +149,36 @@ class API extends \Piwik\Plugin\API ...@@ -127,33 +149,36 @@ class API extends \Piwik\Plugin\API
$lastDate = Range::getDateXPeriodsAgo(abs($comparedToXPeriods), $date, $period); $lastDate = Range::getDateXPeriodsAgo(abs($comparedToXPeriods), $date, $period);
if (empty($lastDate[0])) {
throw new \Exception('Not possible to calculate movers and shakers for this date/period combination');
}
$currentReport = $this->requestReport($idSite, $period, $date, $report, $metric, $segment); $currentReport = $this->requestReport($idSite, $period, $date, $report, $metric, $segment);
$lastReport = $this->requestReport($idSite, $period, $lastDate[0], $report, $metric, $segment); $lastReport = $this->requestReport($idSite, $period, $lastDate[0], $report, $metric, $segment);
$totalValue = $this->getRelevantTotalValue($idSite, $period, $date, $currentReport, $metric); $totalValue = $this->getRelevantTotalValue($idSite, $period, $date, $currentReport, $metric);
$minVisits = $this->getMinVisits($totalValue, $minVisitsPercent);
$considerMovers = false; $minMoversPercent = -1;
$considerNew = false; $minNewPercent = -1;
$considerDisappeared = false; $minDisappearedPercent = -1;
switch ($filterBy) { switch ($filterBy) {
case self::FILTER_BY_MOVERS: case self::FILTER_BY_MOVERS:
$considerMovers = true; $minMoversPercent = 0;
break; break;
case self::FILTER_BY_NEW: case self::FILTER_BY_NEW:
$considerNew = true; $minNewPercent = 0;
break; break;
case self::FILTER_BY_DISAPPEARED: case self::FILTER_BY_DISAPPEARED:
$considerDisappeared = true; $minDisappearedPercent = 0;
break; break;
default: default:
$considerMovers = true; $minMoversPercent = 0;
$considerNew = true; $minNewPercent = 0;
$considerDisappeared = true; $minDisappearedPercent = 0;
} }
return $this->buildInsightsReport($period, $date, $limitIncreaser, $limitDecreaser, $minGrowthPercent, $orderBy, $currentReport, $lastReport, $metric, $considerMovers, $considerNew, $considerDisappeared, $minVisits, $report, $lastDate[0], $totalValue); return $this->buildDataTable($report, $period, $date, $lastDate[0], $metric, $currentReport, $lastReport, $totalValue, $minVisitsPercent, $minMoversPercent, $minNewPercent, $minDisappearedPercent, $minGrowthPercent, $orderBy, $limitIncreaser, $limitDecreaser);
} }
private function requestReport($idSite, $period, $date, $report, $metric, $segment) private function requestReport($idSite, $period, $date, $report, $metric, $segment)
...@@ -197,9 +222,9 @@ class API extends \Piwik\Plugin\API ...@@ -197,9 +222,9 @@ class API extends \Piwik\Plugin\API
return $orderByColumn; return $orderByColumn;
} }
private function getMinVisits($totalValue, $minVisitsPercent) private function getMinVisits($totalValue, $percent)
{ {
$minVisits = ceil(($totalValue / 100) * $minVisitsPercent); $minVisits = ceil(($totalValue / 100) * $percent);
return (int) $minVisits; return (int) $minVisits;
} }
...@@ -218,8 +243,9 @@ class API extends \Piwik\Plugin\API ...@@ -218,8 +243,9 @@ class API extends \Piwik\Plugin\API
private function getTotalValue($idSite, $period, $date, $metric) private function getTotalValue($idSite, $period, $date, $metric)
{ {
$visits = VisitsSummaryAPI::getInstance()->get($idSite, $period, $date, false, array($metric)); $visits = VisitsSummaryAPI::getInstance()->get($idSite, $period, $date, false, array($metric));
$totalValue = $visits->getFirstRow()->getColumn($metric); $totalValue = $visits->getFirstRow()->getColumn($metric);
return $totalValue; return $totalValue;
} }
...@@ -236,8 +262,36 @@ class API extends \Piwik\Plugin\API ...@@ -236,8 +262,36 @@ class API extends \Piwik\Plugin\API
return $totalValue; return $totalValue;
} }
private function buildInsightsReport($period, $date, $limitIncreaser, $limitDecreaser, $minGrowthPercent, $orderBy, $currentReport, $lastReport, $metric, $considerMovers, $considerNew, $considerDisappeared, $minVisits, $report, $lastDate, $totalValue) /**
* @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 $minVisitsPercent Row must have at least min percent visits of totalVisits
* @param int $minVisitsMoversPercent Exclude rows who moved and the difference is not at least min percent
* visits of totalVisits. -1 excludes movers.
* @param int $minVisitsNewPercent Exclude rows who are new and the difference is not at least min percent
* visits of totalVisits. -1 excludes all new.
* @param int $minVisitsDisappearedPercent Exclude rows who are disappeared and the difference is not at least min
* percent visits of totalVisits. -1 excludes all disappeared.
* @param int $minGrowthPercent The actual growth of a row must be at least 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
*/
private function buildDataTable($reportMetadata, $period, $date, $lastDate, $metric, $currentReport, $lastReport, $totalValue, $minVisitsPercent, $minVisitsMoversPercent, $minVisitsNewPercent, $minVisitsDisappearedPercent, $minGrowthPercent, $orderBy, $limitIncreaser, $limitDecreaser)
{ {
$minVisits = $this->getMinVisits($totalValue, $minVisitsPercent);
$minChangeMovers = 0;
$minIncreaseNew = 0;
$minDecreaseDisappeared = 0;
$dataTable = new DataTable(); $dataTable = new DataTable();
$dataTable->filter( $dataTable->filter(
'Piwik\Plugins\Insights\DataTable\Filter\Insight', 'Piwik\Plugins\Insights\DataTable\Filter\Insight',
...@@ -245,9 +299,9 @@ class API extends \Piwik\Plugin\API ...@@ -245,9 +299,9 @@ class API extends \Piwik\Plugin\API
$currentReport, $currentReport,
$lastReport, $lastReport,
$metric, $metric,
$considerMovers, $considerMovers = (-1 !== $minVisitsMoversPercent),
$considerNew, $considerNew = (-1 !== $minVisitsNewPercent),
$considerDisappeared $considerDisappeared = (-1 !== $minVisitsDisappearedPercent)
) )
); );
...@@ -255,7 +309,7 @@ class API extends \Piwik\Plugin\API ...@@ -255,7 +309,7 @@ class API extends \Piwik\Plugin\API
'Piwik\Plugins\Insights\DataTable\Filter\MinGrowth', 'Piwik\Plugins\Insights\DataTable\Filter\MinGrowth',
array( array(
'growth_percent_numeric', 'growth_percent_numeric',
$minGrowthPercent $minGrowthPercent,
) )
); );
...@@ -267,6 +321,42 @@ class API extends \Piwik\Plugin\API ...@@ -267,6 +321,42 @@ class API extends \Piwik\Plugin\API
) )
); );
if ($minVisitsNewPercent) {
$minIncreaseNew = $this->getMinVisits($totalValue, $minVisitsNewPercent);
$dataTable->filter(
'Piwik\Plugins\Insights\DataTable\Filter\ExcludeLowValue',
array(
'difference',
$minIncreaseNew,
'isNew'
)
);
}
if ($minVisitsMoversPercent) {
$minChangeMovers = $this->getMinVisits($totalValue, $minVisitsMoversPercent);
$dataTable->filter(
'Piwik\Plugins\Insights\DataTable\Filter\ExcludeLowValue',
array(
'difference',
$minChangeMovers,
'isMover'
)
);
}
if ($minVisitsDisappearedPercent) {
$minDecreaseDisappeared = $this->getMinVisits($totalValue, $minVisitsDisappearedPercent);
$dataTable->filter(
'Piwik\Plugins\Insights\DataTable\Filter\ExcludeLowValue',
array(
'difference',
$minDecreaseDisappeared,
'isDisappeared'
)
);
}
$dataTable->filter( $dataTable->filter(
'Piwik\Plugins\Insights\DataTable\Filter\OrderBy', 'Piwik\Plugins\Insights\DataTable\Filter\OrderBy',
array( array(
...@@ -284,14 +374,22 @@ class API extends \Piwik\Plugin\API ...@@ -284,14 +374,22 @@ class API extends \Piwik\Plugin\API
); );
$dataTable->setMetadataValues(array( $dataTable->setMetadataValues(array(
'reportName' => $report['name'], 'reportName' => $reportMetadata['name'],
'metricName' => $report['metrics'][$metric], 'metricName' => $reportMetadata['metrics'][$metric],
'date' => $date, 'date' => $date,
'lastDate' => $lastDate, 'lastDate' => $lastDate,
'period' => $period, 'period' => $period,
'report' => $report, 'report' => $reportMetadata,
'totalValue' => $totalValue, 'totalValue' => $totalValue,
'minVisits' => $minVisits 'minValue' => $minVisits,
'minChangeMovers' => $minChangeMovers,
'minIncreaseNew' => $minIncreaseNew,
'minDecreaseDisappeared' => $minDecreaseDisappeared,
'minValuePercent' => $minVisitsPercent,
'minGrowthPercent' => $minGrowthPercent,
'minVisitsMoversPercent' => $minVisitsMoversPercent,
'minVisitsNewPercent' => $minVisitsNewPercent,
'minVisitsDisappearedPercent' => $minVisitsDisappearedPercent
)); ));
return $dataTable; return $dataTable;
...@@ -301,6 +399,19 @@ class API extends \Piwik\Plugin\API ...@@ -301,6 +399,19 @@ class API extends \Piwik\Plugin\API
{ {
$processedReport = new ProcessedReport(); $processedReport = new ProcessedReport();
$report = $processedReport->getReportMetadataByUniqueId($idSite, $reportUniqueId); $report = $processedReport->getReportMetadataByUniqueId($idSite, $reportUniqueId);
return $report; return $report;
} }
private function deleteDataTables($firstTableId, $dataTableIdsToBeIgnored)
{
$dataTableManager = DataTable\Manager::getInstance();
$lastTableId = $dataTableManager->getMostRecentTableId();
for ($index = $firstTableId; $index <= $lastTableId; $index++) {
if (!in_array($index, $dataTableIdsToBeIgnored)) {
$dataTableManager->deleteTable($index);
}
}
}
} }
...@@ -18,7 +18,21 @@ use Piwik\View; ...@@ -18,7 +18,21 @@ use Piwik\View;
class Controller extends \Piwik\Plugin\Controller class Controller extends \Piwik\Plugin\Controller
{ {
public function getInsightOverview() public function getInsightsOverview()
{
$view = $this->prepareWidget($apiReport = 'getInsightsOverview');
return $view->render();
}
public function getOverallMoversAndShakers()
{
$view = $this->prepareWidget($apiReport = 'getOverallMoversAndShakers');
return $view->render();
}
private function prepareWidget($apiReport)
{ {
$idSite = Common::getRequestVar('idSite', null, 'int'); $idSite = Common::getRequestVar('idSite', null, 'int');
$period = Common::getRequestVar('period', null, 'string'); $period = Common::getRequestVar('period', null, 'string');
...@@ -26,18 +40,14 @@ class Controller extends \Piwik\Plugin\Controller ...@@ -26,18 +40,14 @@ class Controller extends \Piwik\Plugin\Controller
Piwik::checkUserHasViewAccess(array($idSite)); Piwik::checkUserHasViewAccess(array($idSite));
$view = new View('@Insights/index.twig'); $view = new View('@Insights/overviewWidget.twig');
$this->setBasicVariablesView($view); $this->setBasicVariablesView($view);
$view->moversAndShakers = API::getInstance()->getInsightsOverview($idSite, $period, $date); $view->reports = API::getInstance()->$apiReport($idSite, $period, $date);
$view->showNoDataMessage = false;
$view->showInsightsControls = false;
$view->properties = array( $view->properties = array(
'show_increase' => true,
'show_decrease' => true,
'order_by' => 'absolute' 'order_by' => 'absolute'
); );
return $view->render(); return $view;
} }
} }
...@@ -14,11 +14,21 @@ class ExcludeLowValue extends DataTable\BaseFilter ...@@ -14,11 +14,21 @@ class ExcludeLowValue extends DataTable\BaseFilter
{ {
private $minimumValue; private $minimumValue;
private $columnToRead; private $columnToRead;
private $columnToCheckToBeTrue;
public function __construct($table, $columnToRead, $minimumValue) /**
* @param DataTable $table
* @param string $columnToRead
* @param int $minimumValue
* @param string $columnToCheckToBeTrue if set, we will delete a row only if this column evaluates to true. If
* column does not evaluate to true we will not delete the row even if
* the value is lower than the minimumValue.
*/
public function __construct($table, $columnToRead, $minimumValue, $columnToCheckToBeTrue = '')
{ {
$this->columnToRead = $columnToRead; $this->columnToRead = $columnToRead;
$this->minimumValue = $minimumValue; $this->minimumValue = $minimumValue;
$this->columnToCheckToBeTrue = $columnToCheckToBeTrue;
} }
public function filter($table) public function filter($table)
...@@ -27,11 +37,17 @@ class ExcludeLowValue extends DataTable\BaseFilter ...@@ -27,11 +37,17 @@ class ExcludeLowValue extends DataTable\BaseFilter
return; return;
} }
$minimumValue = $this->minimumValue; foreach ($table->getRows() as $key => $row) {
$isValueLowPopulation = function ($value) use ($minimumValue) {
return $value < $minimumValue;
};
$table->filter('ColumnCallbackDeleteRow', array($this->columnToRead, $isValueLowPopulation)); if ($this->columnToCheckToBeTrue && !$row->getColumn($this->columnToCheckToBeTrue)) {
continue;
}
$value = $row->getColumn($this->columnToRead);
if ($this->minimumValue > $value) {
$table->deleteRow($key);
}
}
} }
} }
\ No newline at end of file
...@@ -30,53 +30,69 @@ class Insight extends DataTable\Filter\CalculateEvolutionFilter ...@@ -30,53 +30,69 @@ class Insight extends DataTable\Filter\CalculateEvolutionFilter
public function filter($table) public function filter($table)
{ {
foreach ($this->currentDataTable->getRows() as $key => $row) { foreach ($this->currentDataTable->getRows() as $row) {
$pastRow = $this->getPastRowFromCurrent($row); $this->addRowIfNewOrMover($table, $row);
$oldValue = 0; }
if (!$pastRow && !$this->considerNew) { if ($this->considerDisappeared) {
continue; foreach ($this->pastDataTable->getRows() as $row) {
$this->addRowIfDisappeared($table, $row);
} }
}
}
if ($pastRow && $this->considerMovers) { private function addRowIfDisappeared(DataTable $table, DataTable\Row $row)
$oldValue = $pastRow->getColumn($this->columnValueToRead); {
} elseif ($pastRow) { if ($this->getRowFromTable($this->currentDataTable, $row)) {
continue; return;
} }
$difference = $this->getDividend($row); $newValue = 0;
if ($difference === false) { $oldValue = $row->getColumn($this->columnValueToRead);
continue; $difference = $newValue - $oldValue;
}
if ($oldValue == 0 && $newValue == 0) {
$growthPercentage = '0%';
} else {
$growthPercentage = '-100%';
}
$newValue = $row->getColumn($this->columnValueToRead); $this->addRow($table, $row, $growthPercentage, $newValue, $oldValue, $difference, $isDisappeared = true);
$divisor = $this->getDivisor($row); }
$growthPercentage = $this->formatValue($difference, $divisor); private function addRowIfNewOrMover(DataTable $table, DataTable\Row $row)
{
$pastRow = $this->getPastRowFromCurrent($row);
$this->addRow($table, $row, $growthPercentage, $newValue, $oldValue, $difference); if (!$pastRow && !$this->considerNew) {
return;
} elseif ($pastRow && !$this->considerMovers) {
return;
} }
if ($this->considerDisappeared) { $isNew = false;
foreach ($this->pastDataTable->getRows() as $key => $row) { $isMover = false;
$isDisappeared = false;
if (!$pastRow) {
$isNew = true;
$oldValue = 0;
} else {
$isMover = true;
$oldValue = $pastRow->getColumn($this->columnValueToRead);
}
if ($this->getRowFromTable($this->currentDataTable, $row)) { $difference = $this->getDividend($row);
continue; if ($difference === false) {
} return;
}
$newValue = 0; $newValue = $row->getColumn($this->columnValueToRead);
$oldValue = $row->getColumn($this->columnValueToRead); $divisor = $this->getDivisor($row);
$difference = $newValue - $oldValue;
if ($oldValue == 0 && $newValue == 0) { $growthPercentage = $this->formatValue($difference, $divisor);
$growthPercentage = '0%';
} else {
$growthPercentage = '-100%';
}
$this->addRow($table, $row, $growthPercentage, $newValue, $oldValue, $difference); $this->addRow($table, $row, $growthPercentage, $newValue, $oldValue, $difference, $isDisappeared, $isNew, $isMover);
}
}
} }
private function getRowFromTable(DataTable $table, DataTable\Row $row) private function getRowFromTable(DataTable $table, DataTable\Row $row)
...@@ -84,7 +100,7 @@ class Insight extends DataTable\Filter\CalculateEvolutionFilter ...@@ -84,7 +100,7 @@ class Insight extends DataTable\Filter\CalculateEvolutionFilter
return $table->getRowFromLabel($row->getColumn('label')); return $table->getRowFromLabel($row->getColumn('label'));
} }
private function addRow(DataTable $table, DataTable\Row $row, $growthPercentage, $newValue, $oldValue, $difference) private function addRow(DataTable $table, DataTable\Row $row, $growthPercentage, $newValue, $oldValue, $difference, $disappeared = false, $isNew = false, $isMover = false)
{ {
$columns = $row->getColumns(); $columns = $row->getColumns();
$columns['growth_percent'] = $growthPercentage; $columns['growth_percent'] = $growthPercentage;
...@@ -94,6 +110,9 @@ class Insight extends DataTable\Filter\CalculateEvolutionFilter ...@@ -94,6 +110,9 @@ class Insight extends DataTable\Filter\CalculateEvolutionFilter
$columns['value_new'] = $newValue; $columns['value_new'] = $newValue;
$columns['difference'] = $difference; $columns['difference'] = $difference;
$columns['importance'] = abs($difference); $columns['importance'] = abs($difference);
$columns['isDisappeared'] = $disappeared;
$columns['isNew'] = $isNew;
$columns['isMover'] = $isMover;
$table->addRowFromArray(array(DataTable\Row::COLUMNS => $columns)); $table->addRowFromArray(array(DataTable\Row::COLUMNS => $columns));
} }
......
...@@ -34,7 +34,8 @@ class Insights extends \Piwik\Plugin ...@@ -34,7 +34,8 @@ class Insights extends \Piwik\Plugin
public function addWidgets() public function addWidgets()
{ {
WidgetsList::add('Insights_Category', 'Insights_OverviewWidgetTitle', 'Insights', 'getInsightOverview'); WidgetsList::add('Insights_WidgetCategory', 'Insights_OverviewWidgetTitle', 'Insights', 'getInsightsOverview');
WidgetsList::add('Insights_WidgetCategory', 'Insights_MoversAndShakersWidgetTitle', 'Insights', 'getOverallMoversAndShakers');
} }
public function getStylesheetFiles(&$stylesheets) public function getStylesheetFiles(&$stylesheets)
......
...@@ -25,7 +25,7 @@ class Insight extends Visualization ...@@ -25,7 +25,7 @@ class Insight extends Visualization
{ {
const ID = 'insightsVisualization'; const ID = 'insightsVisualization';
const TEMPLATE_FILE = '@Insights/insightVisualization.twig'; const TEMPLATE_FILE = '@Insights/insightVisualization.twig';
const FOOTER_ICON_TITLE = 'InsightsVisualization'; const FOOTER_ICON_TITLE = 'Insights';
const FOOTER_ICON = 'plugins/Insights/images/idea.png'; const FOOTER_ICON = 'plugins/Insights/images/idea.png';
public function beforeLoadDataTable() public function beforeLoadDataTable()
...@@ -80,8 +80,6 @@ class Insight extends Visualization ...@@ -80,8 +80,6 @@ class Insight extends Visualization
public function afterAllFiltersAreApplied() public function afterAllFiltersAreApplied()
{ {
$this->assignTemplateVar('showNoDataMessage', true);
$this->assignTemplateVar('showInsightsControls', true);
$this->assignTemplateVar('period', Common::getRequestVar('period', null, 'string')); $this->assignTemplateVar('period', Common::getRequestVar('period', null, 'string'));
} }
......
{ {
"Insights": { "Insights": {
"OverviewWidgetTitle": "Insights Overview", "OverviewWidgetTitle": "Insights Overview",
"Category": "Insights", "WidgetCategory": "Insights",
"NoResultMatchesCriteria": "No rows match the criteria" "NoResultMatchesCriteria": "No rows match the criteria",
"MoversAndShakersWidgetTitle": "Movers and Shakers",
"TitleConsideredVisits": "Considered rows having at least %s visits (%s%% of %s visits) with a growth of at least %s%% compared to %s.",
"TitleConsideredChanges": "Considered movers only if they increased or decreased by more than %s visits, new entries only if they increase by more than %s visits, and disappeared rows if they decreased by more than %s visits.",
"TitleReportBasedOn": "Based on %s %s, rows less than %s %s were ignored",
"TitleRowChangeDetails": "'%s' changed from %s (%s) to %s (%s) %s"
} }
} }
\ No newline at end of file
...@@ -25,4 +25,11 @@ ...@@ -25,4 +25,11 @@
.notGrown { .notGrown {
color:red; color:red;
} }
table td {
&.labelodd, &.labeleven {
background-image: none;
}
}
} }
\ No newline at end of file
{% for dataTable in moversAndShakers.getDataTables() %}
{% include "@Insights/insightVisualization.twig" %}
{% endfor %}
\ No newline at end of file
<div style="padding: 10px;padding-bottom: 0px;"> <div style="padding: 10px;padding-bottom: 0px;">
Minimum impact of Minimum visits of
<select name="minVisitsPercent" title="Based on a total of {{ dataTable.getMetadata('totalValue') }} visitors or metricname"> <select name="minVisitsPercent" title="Based on a total of {{ dataTable.getMetadata('totalValue') }} visitors or metricname">
{% for i in range(0, 10) %} {% for i in range(0, 10) %}
<option {% if i == properties.min_visits_percent %}selected{% endif %} value="{{ i }}">{{ i }}%</option> <option {% if i == properties.min_visits_percent %}selected{% endif %} value="{{ i }}">{{ i }}%</option>
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
{% for i in range(12, 30, 2) %} {% for i in range(12, 30, 2) %}
<option {% if i == properties.min_visits_percent %}selected{% endif %} value="{{ i }}">{{ i }}%</option> <option {% if i == properties.min_visits_percent %}selected{% endif %} value="{{ i }}">{{ i }}%</option>
{% endfor %} {% endfor %}
{% for i in range(35, 100, 5) %} {% for i in range(40, 100, 10) %}
<option {% if i == properties.min_visits_percent %}selected{% endif %} value="{{ i }}">{{ i }}%</option> <option {% if i == properties.min_visits_percent %}selected{% endif %} value="{{ i }}">{{ i }}%</option>
{% endfor %} {% endfor %}
</select> </select>
...@@ -25,28 +25,30 @@ ...@@ -25,28 +25,30 @@
{% endfor %} {% endfor %}
</select> </select>
compared to {% if period == 'day' or period == 'month' %}
{% if period == 'day' %} compared to
<select size="1" name="comparedToXPeriodsAgo"> {% if period == 'day' %}
<option value="1" {% if properties.compared_to_x_periods_ago == 1 %}selected{% endif %}> <select size="1" name="comparedToXPeriodsAgo">
previous day <option value="1" {% if properties.compared_to_x_periods_ago == 1 %}selected{% endif %}>
</option> previous day
<option value="7" {% if properties.compared_to_x_periods_ago == 7 %}selected{% endif %}> </option>
same day in previous week <option value="7" {% if properties.compared_to_x_periods_ago == 7 %}selected{% endif %}>
</option> same day in previous week
<option value="365" {% if properties.compared_to_x_periods_ago == 365 %}selected{% endif %}> </option>
same day in previous year <option value="365" {% if properties.compared_to_x_periods_ago == 365 %}selected{% endif %}>
</option> same day in previous year
</select> </option>
{% elseif period == 'month' %} </select>
<select size="1" name="comparedToXPeriodsAgo"> {% elseif period == 'month' %}
<option value="1" {% if properties.compared_to_x_periods_ago == 1 %}selected{% endif %}> <select size="1" name="comparedToXPeriodsAgo">
previous month <option value="1" {% if properties.compared_to_x_periods_ago == 1 %}selected{% endif %}>
</option> previous month
<option value="12" {% if properties.compared_to_x_periods_ago == 12 %}selected{% endif %}> </option>
same month in previous year <option value="12" {% if properties.compared_to_x_periods_ago == 12 %}selected{% endif %}>
</option> same month in previous year
</select> </option>
</select>
{% endif %}
{% endif %} {% endif %}
<hr style="height: 1px;border: 0px;background-color: #cccccc;" /> <hr style="height: 1px;border: 0px;background-color: #cccccc;" />
......
<div class="insightsDataTable"> {% set metadata = dataTable.getAllTableMetadata%}
{% set consideredVisits = 'Insights_TitleConsideredVisits'|translate(metadata.minValue, metadata.minValuePercent, metadata.totalValue, metadata.minGrowthPercent, metadata.lastDate|prettyDate(metadata.period)) %}
<div class="insightsDataTable" title="{{ consideredVisits|e('html_attr') }}">
{% if dataTable.getRowsCount > 0 %} {% if dataTable.getRowsCount > 0 %}
<table class="dataTable"> <table class="dataTable">
<thead> <thead>
<tr title="Based on {{ dataTable.getMetadata('totalValue') }} {{ dataTable.getMetadata('metricName') }}, rows less than {{ dataTable.getMetadata('minVisits') }} {{ dataTable.getMetadata('metricName') }} were ignored"> {% include "@Insights/table_header.twig" %}
<th class="label">
{{ dataTable.getMetadata('reportName') }}
</th>
<th class="label orderBy" name="orderBy" value="absolute"
style="{% if 'absolute' == properties.order_by %}font-weight:bold;{% endif %}">
{{ dataTable.getMetadata('metricName') }}
</th>
<th class="label orderBy" name="orderBy" value="relative"
style="{% if 'relative' == properties.order_by %}font-weight:bold;{% endif %}">
{{ 'MultiSites_Evolution'|translate }}
</th>
</tr>
</thead> </thead>
<tbody>
{% for row in dataTable.getRows %}
<tr title="{{ dataTable.getMetadata('metricName') }} changed from {{ row.getColumn('value_old') }} ({{ dataTable.getMetadata('lastDate') }}) to {{ row.getColumn('value_new') }} ({{ dataTable.getMetadata('date') }})">
<td>
<span class="title"
title="{{ row.getColumn('label') }}">
{{ row.getColumn('label') }}
</span>
</td>
{% if row.getColumn('grown') %}
<td>+{{ row.getColumn('difference') }}</td>
<td class="grown">
+{{ row.getColumn('growth_percent') }}
</td>
{% else %}
<td>{{ row.getColumn('difference') }}</td>
<td class="notGrown">
{{ row.getColumn('growth_percent') }}
</td>
{% endif %}
</tr>
{% endfor %}
<tbody>
{% for row in dataTable.getRows %}
{% include "@Insights/table_row.twig" %}
{% endfor %}
</tbody> </tbody>
</table> </table>
{% elseif showNoDataMessage %} {% else %}
<div class="pk-emptyDataTable"> <div class="pk-emptyDataTable">
{{ 'Insights_NoResultMatchesCriteria'|translate }} {{ 'Insights_NoResultMatchesCriteria'|translate }}
</div> </div>
{% endif %} {% endif %}
{% if showInsightsControls %} {% include "@Insights/insightControls.twig" %}
{% include "@Insights/insightControls.twig" %}
{% endif %}
</div> </div>
\ No newline at end of file
{% set allMetadata = reports.getFirstRow.getAllTableMetadata %}
{% set consideredVisits = 'Insights_TitleConsideredVisits'|translate(allMetadata.minValue, allMetadata.minValuePercent, allMetadata.totalValue, allMetadata.minGrowthPercent, allMetadata.lastDate|prettyDate(allMetadata.period)) %}
{% set consideredChanges = '' %}
{% if allMetadata.minChangeMovers or allMetadata.minIncreaseNew or allMetadata.minDecreaseDisappeared %}
{% set consideredChanges = 'Insights_TitleConsideredChanges'|translate(allMetadata.minChangeMovers, allMetadata.minIncreaseNew, allMetadata.minDecreaseDisappeared) %}
{% endif %}
<div class="insightsDataTable" title="{{ consideredVisits|e('html_attr') }} {{ consideredChanges|e('html_attr') }}">
{% if reports.getColumns|length > 0 %}
<table class="dataTable">
{% for dataTable in reports.getDataTables() if dataTable.getRowsCount > 0 %}
{% set metadata = dataTable.getAllTableMetadata %}
<thead>
{% include "@Insights/table_header.twig" %}
</thead>
<tbody>
{% for row in dataTable.getRows %}
{% include "@Insights/table_row.twig" %}
{% endfor %}
</tbody>
{% endfor %}
</table>
{% else %}
<div class="pk-emptyDataTable">
{{ 'Insights_NoResultMatchesCriteria'|translate }}
</div>
{% endif %}
</div>
\ No newline at end of file
<tr>
<th class="label">
{{ metadata.reportName }}
</th>
<th class="label orderBy" name="orderBy" value="absolute"
style="{% if 'absolute' == properties.order_by %}font-weight:bold;{% endif %}">
{{ metadata.metricName }}
</th>
<th class="label orderBy" name="orderBy" value="relative"
style="{% if 'relative' == properties.order_by %}font-weight:bold;{% endif %}">
{{ 'MultiSites_Evolution'|translate }}
</th>
</tr>
\ No newline at end of file
<tr title="{{ 'Insights_TitleRowChangeDetails'|translate(row.getColumn('label'), row.getColumn('value_old'), metadata.lastDate|prettyDate(metadata.period), row.getColumn('value_new'), metadata.date|prettyDate(metadata.period), metadata.metricName)|e('html_attr') }}">
<td>
<span class="title">
{{ row.getColumn('label') }}
</span>
</td>
{% if row.getColumn('grown') %}
<td>+{{ row.getColumn('difference') }}</td>
<td class="grown">+{{ row.getColumn('growth_percent') }}</td>
{% else %}
<td>{{ row.getColumn('difference') }}</td>
<td class="notGrown">{{ row.getColumn('growth_percent') }}</td>
{% endif %}
</tr>
\ No newline at end of file
...@@ -29,17 +29,17 @@ class FilterExcludeLowValueTest extends \PHPUnit_Framework_TestCase ...@@ -29,17 +29,17 @@ class FilterExcludeLowValueTest extends \PHPUnit_Framework_TestCase
{ {
$this->table = new DataTable(); $this->table = new DataTable();
$this->table->addRowsFromArray(array( $this->table->addRowsFromArray(array(
array(Row::COLUMNS => array('label' => 'val1', 'growth' => 22)), array(Row::COLUMNS => array('label' => 'val1', 'growth' => 22, 'isFooBar' => false)),
array(Row::COLUMNS => array('label' => 'val2', 'growth' => 14)), array(Row::COLUMNS => array('label' => 'val2', 'growth' => 14, 'isFooBar' => true)),
array(Row::COLUMNS => array('label' => 'val3', 'growth' => 18)), array(Row::COLUMNS => array('label' => 'val3', 'growth' => 18, 'isFooBar' => false)),
array(Row::COLUMNS => array('label' => 'val4', 'growth' => 20)), array(Row::COLUMNS => array('label' => 'val4', 'growth' => 20, 'isFooBar' => true)),
array(Row::COLUMNS => array('label' => 'val5', 'growth' => 22)), array(Row::COLUMNS => array('label' => 'val5', 'growth' => 22, 'isFooBar' => true)),
array(Row::COLUMNS => array('label' => 'val6', 'growth' => 25)), array(Row::COLUMNS => array('label' => 'val6', 'growth' => 25, 'isFooBar' => true)),
array(Row::COLUMNS => array('label' => 'val7', 'growth' => 17)), array(Row::COLUMNS => array('label' => 'val7', 'growth' => 17, 'isFooBar' => false)),
array(Row::COLUMNS => array('label' => 'val8', 'growth' => 20)), array(Row::COLUMNS => array('label' => 'val8', 'growth' => 20, 'isFooBar' => false)),
array(Row::COLUMNS => array('label' => 'val9', 'growth' => 0)), array(Row::COLUMNS => array('label' => 'val9', 'growth' => 0, 'isFooBar' => false)),
array(Row::COLUMNS => array('label' => 'val10', 'growth' => 15)), array(Row::COLUMNS => array('label' => 'val10', 'growth' => 15, 'isFooBar' => false)),
array(Row::COLUMNS => array('label' => 'val11', 'growth' => 16)) array(Row::COLUMNS => array('label' => 'val11', 'growth' => 16, 'isFooBar' => true))
)); ));
} }
...@@ -74,15 +74,22 @@ class FilterExcludeLowValueTest extends \PHPUnit_Framework_TestCase ...@@ -74,15 +74,22 @@ class FilterExcludeLowValueTest extends \PHPUnit_Framework_TestCase
$this->assertOrder(array()); $this->assertOrder(array());
} }
public function testShouldRemoveValuesOnlyIfColumnToCheckIsTrue()
{
$this->excludeLowValues(21, 'isFooBar');
$this->assertOrder(array('val1', 'val3', 'val5', 'val6', 'val7', 'val8', 'val9', 'val10'));
}
private function assertOrder($expectedOrder) private function assertOrder($expectedOrder)
{ {
$this->assertEquals($expectedOrder, $this->table->getColumn('label')); $this->assertEquals($expectedOrder, $this->table->getColumn('label'));
$this->assertEquals(count($expectedOrder), $this->table->getRowsCount()); $this->assertEquals(count($expectedOrder), $this->table->getRowsCount());
} }
private function excludeLowValues($minimumValue) private function excludeLowValues($minimumValue, $columnToCheck = null)
{ {
$filter = new ExcludeLowValue($this->table, 'growth', $minimumValue); $filter = new ExcludeLowValue($this->table, 'growth', $minimumValue, $columnToCheck);
$filter->filter($this->table); $filter->filter($this->table);
} }
......
...@@ -148,6 +148,29 @@ class FilterInsightTest extends \PHPUnit_Framework_TestCase ...@@ -148,6 +148,29 @@ class FilterInsightTest extends \PHPUnit_Framework_TestCase
$this->assertColumnValues($values); $this->assertColumnValues($values);
} }
public function testShouldDetectWhetherRowIsNewMoverOrDisappeared()
{
$this->applyInsightConsiderAll();
$values = array(
array('label' => 'val1', 'isNew' => false, 'isMover' => true, 'isDisappeared' => false),
array('label' => 'val2', 'isNew' => true, 'isMover' => false, 'isDisappeared' => false),
array('label' => 'val3', 'isNew' => true, 'isMover' => false, 'isDisappeared' => false),
array('label' => 'val4', 'isNew' => false, 'isMover' => true, 'isDisappeared' => false),
array('label' => 'val5', 'isNew' => true, 'isMover' => false, 'isDisappeared' => false),
array('label' => 'val6', 'isNew' => false, 'isMover' => true, 'isDisappeared' => false),
array('label' => 'val7', 'isNew' => true, 'isMover' => false, 'isDisappeared' => false),
array('label' => 'val8', 'isNew' => false, 'isMover' => true, 'isDisappeared' => false),
array('label' => 'val9', 'isNew' => false, 'isMover' => true, 'isDisappeared' => false),
array('label' => 'val10', 'isNew' => false, 'isMover' => true, 'isDisappeared' => false),
array('label' => 'val102', 'isNew' => false, 'isMover' => false, 'isDisappeared' => true),
array('label' => 'val109', 'isNew' => false, 'isMover' => false, 'isDisappeared' => true),
array('label' => 'val107', 'isNew' => false, 'isMover' => false, 'isDisappeared' => true)
);
$this->assertColumnValues($values);
}
public function testShouldCalculateDifferenceAndGrowthPercentage() public function testShouldCalculateDifferenceAndGrowthPercentage()
{ {
$this->applyInsightConsiderAll(); $this->applyInsightConsiderAll();
......
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter