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

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordiosmosis <diosmosis@users.noreply.github.com>2018-11-12 05:19:57 +0300
committerGitHub <noreply@github.com>2018-11-12 05:19:57 +0300
commit66148cca359a6aca6123edb899544f43e90be0b7 (patch)
tree19ace7e5d4261c977a701362fdfb4e2778f41ad6 /plugins/ScheduledReports
parent28d290cecf5b6cbdb42f93491dfd90248c6b34a1 (diff)
Ability to change periods over which evolution graphs display in scheduled reports (#13501)
* Add options to UI and start on backend code. * Handle new evolution feature in ScheduledReports & add new INI config to control lastN used in ImageGraph evolution. * Add tests for new feature. * Give new scheduled reports different names. * Add tests to SystemTestCase. * Add test. * Update expected system test files. * Apply PR review & fix issue pointed out. * Add Config::setSetting() convenience method & use. * fix some tests * fix test
Diffstat (limited to 'plugins/ScheduledReports')
-rw-r--r--plugins/ScheduledReports/API.php214
-rw-r--r--plugins/ScheduledReports/Controller.php8
-rw-r--r--plugins/ScheduledReports/Model.php4
-rw-r--r--plugins/ScheduledReports/ScheduledReports.php20
-rw-r--r--plugins/ScheduledReports/angularjs/manage-scheduled-report/manage-scheduled-report.controller.js23
-rw-r--r--plugins/ScheduledReports/lang/en.json4
-rw-r--r--plugins/ScheduledReports/stylesheets/scheduledreports.less19
-rw-r--r--plugins/ScheduledReports/templates/_addReport.twig19
-rw-r--r--plugins/ScheduledReports/templates/index.twig2
-rw-r--r--plugins/ScheduledReports/tests/Integration/ApiTest.php202
10 files changed, 426 insertions, 89 deletions
diff --git a/plugins/ScheduledReports/API.php b/plugins/ScheduledReports/API.php
index 922c97ad39..c63b197f04 100644
--- a/plugins/ScheduledReports/API.php
+++ b/plugins/ScheduledReports/API.php
@@ -22,6 +22,7 @@ use Piwik\Http;
use Piwik\Log;
use Piwik\NoAccessException;
use Piwik\Piwik;
+use Piwik\Plugins\ImageGraph\ImageGraph;
use Piwik\Plugins\LanguagesManager\LanguagesManager;
use Piwik\Plugins\SegmentEditor\API as APISegmentEditor;
use Piwik\Plugins\SitesManager\API as SitesManagerApi;
@@ -86,10 +87,14 @@ class API extends \Piwik\Plugin\API
* @param array $reports array of reports
* @param array $parameters array of parameters
* @param bool|int $idSegment Segment Identifier
+ * @param string $evolutionPeriodFor If set to 'each', the evolution graphs cover each day within the period. If set to 'prev',
+ * evolution graphs cover the previous N periods.
+ * @param int|null $evolutionPeriodN The previous N periods to query in evolution graphs if $evolutionPeriodFor is 'each'.
*
* @return int idReport generated
*/
- public function addReport($idSite, $description, $period, $hour, $reportType, $reportFormat, $reports, $parameters, $idSegment = false)
+ public function addReport($idSite, $description, $period, $hour, $reportType, $reportFormat, $reports, $parameters, $idSegment = false, $evolutionPeriodFor = 'prev',
+ $evolutionPeriodN = null)
{
Piwik::checkUserIsNotAnonymous();
Piwik::checkUserHasViewAccess($idSite);
@@ -97,7 +102,7 @@ class API extends \Piwik\Plugin\API
$currentUser = Piwik::getCurrentUserLogin();
self::ensureLanguageSetForUser($currentUser);
- self::validateCommonReportAttributes($period, $hour, $description, $idSegment, $reportType, $reportFormat);
+ self::validateCommonReportAttributes($period, $hour, $description, $idSegment, $reportType, $reportFormat, $evolutionPeriodFor, $evolutionPeriodN);
// report parameters validations
$parameters = self::validateReportParameters($reportType, $parameters);
@@ -118,6 +123,8 @@ class API extends \Piwik\Plugin\API
'reports' => $reports,
'ts_created' => Date::now()->getDatetime(),
'deleted' => 0,
+ 'evolution_graph_within_period' => $evolutionPeriodFor == 'each',
+ 'evolution_graph_period_n' => $evolutionPeriodN ?: ImageGraph::getDefaultGraphEvolutionLastPeriods(),
));
return $idReport;
@@ -142,7 +149,8 @@ class API extends \Piwik\Plugin\API
*
* @see addReport()
*/
- public function updateReport($idReport, $idSite, $description, $period, $hour, $reportType, $reportFormat, $reports, $parameters, $idSegment = false)
+ public function updateReport($idReport, $idSite, $description, $period, $hour, $reportType, $reportFormat, $reports, $parameters, $idSegment = false, $evolutionPeriodFor = 'prev',
+ $evolutionPeriodN = null)
{
Piwik::checkUserIsNotAnonymous();
Piwik::checkUserHasViewAccess($idSite);
@@ -154,7 +162,7 @@ class API extends \Piwik\Plugin\API
$currentUser = Piwik::getCurrentUserLogin();
self::ensureLanguageSetForUser($currentUser);
- self::validateCommonReportAttributes($period, $hour, $description, $idSegment, $reportType, $reportFormat);
+ self::validateCommonReportAttributes($period, $hour, $description, $idSegment, $reportType, $reportFormat, $evolutionPeriodFor, $evolutionPeriodN);
// report parameters validations
$parameters = self::validateReportParameters($reportType, $parameters);
@@ -171,6 +179,8 @@ class API extends \Piwik\Plugin\API
'format' => $reportFormat,
'parameters' => $parameters,
'reports' => $reports,
+ 'evolution_graph_within_period' => $evolutionPeriodFor == 'each',
+ 'evolution_graph_period_n' => $evolutionPeriodN ?: ImageGraph::getDefaultGraphEvolutionLastPeriods(),
));
self::$cache = array();
@@ -268,6 +278,10 @@ class API extends \Piwik\Plugin\API
if (!empty($report['parameters']['additionalEmails']) && is_array($report['parameters']['additionalEmails'])) {
$report['parameters']['additionalEmails'] = array_values($report['parameters']['additionalEmails']);
}
+
+ if (empty($report['evolution_graph_period_n'])) {
+ $report['evolution_graph_period_n'] = ImageGraph::getDefaultGraphEvolutionLastPeriods();
+ }
}
// static cache
@@ -329,104 +343,114 @@ class API extends \Piwik\Plugin\API
true
);
- // available reports
- $availableReportMetadata = \Piwik\Plugins\API\API::getInstance()->getReportMetadata($idSite);
+ $originalShowEvolutionWithinSelectedPeriod = Config::getInstance()->General['graphs_show_evolution_within_selected_period'];
+ $originalDefaultEvolutionGraphLastPeriodsAmount = Config::getInstance()->General['graphs_default_evolution_graph_last_days_amount'];
+ try {
+ Config::setSetting('General', 'graphs_show_evolution_within_selected_period', (bool)$report['evolution_graph_within_period']);
+ Config::setSetting('General', 'graphs_default_evolution_graph_last_days_amount', $report['evolution_graph_period_n']);
- // we need to lookup which reports metadata are registered in this report
- $reportMetadata = array();
- foreach ($availableReportMetadata as $metadata) {
- if (in_array($metadata['uniqueId'], $report['reports'])) {
- $reportMetadata[] = $metadata;
- }
- }
+ // available reports
+ $availableReportMetadata = \Piwik\Plugins\API\API::getInstance()->getReportMetadata($idSite);
- // the report will be rendered with the first 23 rows and will aggregate other rows in a summary row
- // 23 rows table fits in one portrait page
- $initialFilterTruncate = Common::getRequestVar('filter_truncate', false);
- $_GET['filter_truncate'] = Config::getInstance()->General['scheduled_reports_truncate'];
-
- $prettyDate = null;
- $processedReports = array();
- $segment = self::getSegment($report['idsegment']);
- foreach ($reportMetadata as $action) {
- $apiModule = $action['module'];
- $apiAction = $action['action'];
- $apiParameters = array();
- if (isset($action['parameters'])) {
- $apiParameters = $action['parameters'];
+ // we need to lookup which reports metadata are registered in this report
+ $reportMetadata = array();
+ foreach ($availableReportMetadata as $metadata) {
+ if (in_array($metadata['uniqueId'], $report['reports'])) {
+ $reportMetadata[] = $metadata;
+ }
}
- $mustRestoreGET = false;
-
- // all Websites dashboard should not be truncated in the report
- if ($apiModule == 'MultiSites') {
- $mustRestoreGET = $_GET;
- $_GET['enhanced'] = true;
-
- if ($apiAction == 'getAll') {
- $_GET['filter_truncate'] = false;
- $_GET['filter_limit'] = -1; // show all websites in all websites report
+ // the report will be rendered with the first 23 rows and will aggregate other rows in a summary row
+ // 23 rows table fits in one portrait page
+ $initialFilterTruncate = Common::getRequestVar('filter_truncate', false);
+ $_GET['filter_truncate'] = Config::getInstance()->General['scheduled_reports_truncate'];
+
+ $prettyDate = null;
+ $processedReports = array();
+ $segment = self::getSegment($report['idsegment']);
+ foreach ($reportMetadata as $action) {
+ $apiModule = $action['module'];
+ $apiAction = $action['action'];
+ $apiParameters = array();
+ if (isset($action['parameters'])) {
+ $apiParameters = $action['parameters'];
+ }
- // when a view/admin user created a report, workaround the fact that "Super User"
- // is enforced in Scheduled tasks, and ensure Multisites.getAll only return the websites that this user can access
- $userLogin = $report['login'];
- if (!empty($userLogin)
- && !Piwik::hasTheUserSuperUserAccess($userLogin)
- ) {
- $_GET['_restrictSitesToLogin'] = $userLogin;
+ $mustRestoreGET = false;
+
+ // all Websites dashboard should not be truncated in the report
+ if ($apiModule == 'MultiSites') {
+ $mustRestoreGET = $_GET;
+ $_GET['enhanced'] = true;
+
+ if ($apiAction == 'getAll') {
+ $_GET['filter_truncate'] = false;
+ $_GET['filter_limit'] = -1; // show all websites in all websites report
+
+ // when a view/admin user created a report, workaround the fact that "Super User"
+ // is enforced in Scheduled tasks, and ensure Multisites.getAll only return the websites that this user can access
+ $userLogin = $report['login'];
+ if (!empty($userLogin)
+ && !Piwik::hasTheUserSuperUserAccess($userLogin)
+ ) {
+ $_GET['_restrictSitesToLogin'] = $userLogin;
+ }
}
}
- }
- $params = array(
- 'idSite' => $idSite,
- 'period' => $period,
- 'date' => $date,
- 'apiModule' => $apiModule,
- 'apiAction' => $apiAction,
- 'apiParameters' => $apiParameters,
- 'flat' => 1,
- 'idGoal' => false,
- 'language' => $language,
- 'serialize' => 0,
- 'format' => 'original'
- );
+ $params = array(
+ 'idSite' => $idSite,
+ 'period' => $period,
+ 'date' => $date,
+ 'apiModule' => $apiModule,
+ 'apiAction' => $apiAction,
+ 'apiParameters' => $apiParameters,
+ 'flat' => 1,
+ 'idGoal' => false,
+ 'language' => $language,
+ 'serialize' => 0,
+ 'format' => 'original'
+ );
- if ($segment != null) {
- $params['segment'] = urlencode($segment['definition']);
- } else {
- $params['segment'] = false;
- }
+ if ($segment != null) {
+ $params['segment'] = urlencode($segment['definition']);
+ } else {
+ $params['segment'] = false;
+ }
- try {
- $processedReport = Request::processRequest('API.getProcessedReport', $params);
- } catch (\Exception $ex) {
- // NOTE: can't use warning or error because the log message will appear in the UI as a notification
- $this->logger->info("Error getting '?{report}' when generating scheduled report: {exception}", array(
- 'report' => Http::buildQuery($params),
- 'exception' => $ex->getMessage(),
- ));
+ try {
+ $processedReport = Request::processRequest('API.getProcessedReport', $params);
+ } catch (\Exception $ex) {
+ // NOTE: can't use warning or error because the log message will appear in the UI as a notification
+ $this->logger->info("Error getting '?{report}' when generating scheduled report: {exception}", array(
+ 'report' => Http::buildQuery($params),
+ 'exception' => $ex->getMessage(),
+ ));
- $this->logger->debug($ex);
+ $this->logger->debug($ex);
- continue;
- }
+ continue;
+ }
- $processedReport['segment'] = $segment;
+ $processedReport['segment'] = $segment;
- // TODO add static method getPrettyDate($period, $date) in Period
- $prettyDate = $processedReport['prettyDate'];
+ // TODO add static method getPrettyDate($period, $date) in Period
+ $prettyDate = $processedReport['prettyDate'];
- if ($mustRestoreGET) {
- $_GET = $mustRestoreGET;
- }
+ if ($mustRestoreGET) {
+ $_GET = $mustRestoreGET;
+ }
- $processedReports[] = $processedReport;
- }
+ $processedReports[] = $processedReport;
+ }
+ } finally {
+ Config::setSetting('General', 'graphs_show_evolution_within_selected_period', $originalShowEvolutionWithinSelectedPeriod);
+ Config::setSetting('General', 'graphs_default_evolution_graph_last_days_amount', $originalDefaultEvolutionGraphLastPeriodsAmount);
- // restore filter truncate parameter value
- if ($initialFilterTruncate !== false) {
- $_GET['filter_truncate'] = $initialFilterTruncate;
+ // restore filter truncate parameter value
+ if ($initialFilterTruncate !== false) {
+ $_GET['filter_truncate'] = $initialFilterTruncate;
+ }
}
/**
@@ -725,7 +749,7 @@ class API extends \Piwik\Plugin\API
return json_encode($requestedReports);
}
- private static function validateCommonReportAttributes($period, $hour, &$description, &$idSegment, $reportType, $reportFormat)
+ private static function validateCommonReportAttributes($period, $hour, &$description, &$idSegment, $reportType, $reportFormat, $evolutionPeriodFor, $evolutionPeriodN)
{
self::validateReportPeriod($period);
self::validateReportHour($hour);
@@ -733,6 +757,7 @@ class API extends \Piwik\Plugin\API
self::validateIdSegment($idSegment);
self::validateReportType($reportType);
self::validateReportFormat($reportType, $reportFormat);
+ self::validateEvolutionPeriod($evolutionPeriodFor, $evolutionPeriodN);
}
private static function validateReportPeriod($period)
@@ -789,6 +814,23 @@ class API extends \Piwik\Plugin\API
}
}
+ private static function validateEvolutionPeriod($evolutionPeriodFor, $evolutionPeriodN)
+ {
+ if ($evolutionPeriodFor !== 'prev' && $evolutionPeriodFor !== 'each') {
+ throw new \Exception('Invalid evolutionPeriodFor value, can only be "prev" or "each" (got ' . $evolutionPeriodFor . ').');
+ }
+
+ if ($evolutionPeriodFor === 'each' && !empty($evolutionPeriodN)) {
+ throw new \Exception('The evolutionPeriodN param has no effect when evolutionPeriodFor is "each".');
+ }
+
+ if (!empty($evolutionPeriodN)
+ && (!is_numeric($evolutionPeriodN) || (int)$evolutionPeriodN < 0)
+ ) {
+ throw new \Exception('Evolution period amount must be a positive number (got ' . $evolutionPeriodN . ').');
+ }
+ }
+
/**
* @ignore
*/
diff --git a/plugins/ScheduledReports/Controller.php b/plugins/ScheduledReports/Controller.php
index 988af1355f..f8f57ea107 100644
--- a/plugins/ScheduledReports/Controller.php
+++ b/plugins/ScheduledReports/Controller.php
@@ -8,12 +8,15 @@
*/
namespace Piwik\Plugins\ScheduledReports;
+use Faker\Provider\Image;
use Piwik\Access;
use Piwik\API\Request;
use Piwik\Common;
+use Piwik\Config;
use Piwik\Date;
use Piwik\Nonce;
use Piwik\Piwik;
+use Piwik\Plugins\ImageGraph\ImageGraph;
use Piwik\Plugins\LanguagesManager\LanguagesManager;
use Piwik\Plugins\SegmentEditor\API as APISegmentEditor;
use Piwik\Plugins\SitesManager\API as APISitesManager;
@@ -43,6 +46,7 @@ class Controller extends \Piwik\Plugin\Controller
$view->reportTypeOptions = $reportTypeOptions;
$view->defaultReportType = self::DEFAULT_REPORT_TYPE;
$view->defaultReportFormat = ScheduledReports::DEFAULT_REPORT_FORMAT;
+ $view->defaultEvolutionPeriodN = ImageGraph::getDefaultGraphEvolutionLastPeriods();
$view->displayFormats = ScheduledReports::getDisplayFormats();
$reportsByCategoryByType = array();
@@ -76,6 +80,9 @@ class Controller extends \Piwik\Plugin\Controller
if (!Piwik::isUserIsAnonymous()) {
$reports = API::getInstance()->getReports($this->idSite, $period = false, $idReport = false, $ifSuperUserReturnOnlySuperUserReports = true);
foreach ($reports as &$report) {
+ $report['evolutionPeriodFor'] = $report['evolution_graph_within_period'] ? 'each' : 'prev';
+ $report['evolutionPeriodN'] = (int) $report['evolution_graph_period_n'] ?: ImageGraph::getDefaultGraphEvolutionLastPeriods();
+
$report['recipients'] = API::getReportRecipients($report);
$reportsById[$report['idreport']] = $report;
}
@@ -88,6 +95,7 @@ class Controller extends \Piwik\Plugin\Controller
$view->periods = ScheduledReports::getPeriodToFrequency();
$view->defaultPeriod = ScheduledReports::DEFAULT_PERIOD;
$view->defaultHour = ScheduledReports::DEFAULT_HOUR;
+ $view->periodTranslations = ScheduledReports::getPeriodFrequencyTranslations();
$view->language = LanguagesManager::getLanguageCodeForCurrentUser();
diff --git a/plugins/ScheduledReports/Model.php b/plugins/ScheduledReports/Model.php
index 5c7856678a..27b6fc6433 100644
--- a/plugins/ScheduledReports/Model.php
+++ b/plugins/ScheduledReports/Model.php
@@ -15,7 +15,7 @@ use Piwik\ReportRenderer;
class Model
{
- private static $rawPrefix = 'report';
+ public static $rawPrefix = 'report';
private $table;
public function __construct()
@@ -85,6 +85,8 @@ class Model
`ts_created` TIMESTAMP NULL,
`ts_last_sent` TIMESTAMP NULL,
`deleted` tinyint(4) NOT NULL default 0,
+ `evolution_graph_within_period` TINYINT(4) NOT NULL DEFAULT 0,
+ `evolution_graph_period_n` INT(11) NOT NULL,
PRIMARY KEY (`idreport`)";
DbHelper::createTable(self::$rawPrefix, $reportTable);
diff --git a/plugins/ScheduledReports/ScheduledReports.php b/plugins/ScheduledReports/ScheduledReports.php
index edb0a3e691..575d771814 100644
--- a/plugins/ScheduledReports/ScheduledReports.php
+++ b/plugins/ScheduledReports/ScheduledReports.php
@@ -111,6 +111,8 @@ class ScheduledReports extends \Piwik\Plugin
$translationKeys[] = "ScheduledReports_ReportSent";
$translationKeys[] = "ScheduledReports_ReportUpdated";
$translationKeys[] = "ScheduledReports_ReportHourWithUTC";
+ $translationKeys[] = "ScheduledReports_EvolutionGraphsShowForEachInPeriod";
+ $translationKeys[] = "ScheduledReports_EvolutionGraphsShowForPreviousN";
}
/**
@@ -601,6 +603,24 @@ class ScheduledReports extends \Piwik\Plugin
);
}
+ public static function getPeriodFrequencyTranslations()
+ {
+ return [
+ Schedule::PERIOD_DAY => [
+ 'single' => Piwik::translate('Intl_PeriodDay'),
+ 'plural' => Piwik::translate('Intl_PeriodDays'),
+ ],
+ Schedule::PERIOD_WEEK => [
+ 'single' => Piwik::translate('Intl_PeriodWeek'),
+ 'plural' => Piwik::translate('Intl_PeriodWeeks'),
+ ],
+ Schedule::PERIOD_MONTH => [
+ 'single' => Piwik::translate('Intl_PeriodMonth'),
+ 'plural' => Piwik::translate('Intl_PeriodMonths'),
+ ],
+ ];
+ }
+
private function reportAlreadySent($report, Period $period)
{
$key = self::OPTION_KEY_LAST_SENT_DATERANGE . $report['idreport'];
diff --git a/plugins/ScheduledReports/angularjs/manage-scheduled-report/manage-scheduled-report.controller.js b/plugins/ScheduledReports/angularjs/manage-scheduled-report/manage-scheduled-report.controller.js
index 12ec6e6a94..ccb107b742 100644
--- a/plugins/ScheduledReports/angularjs/manage-scheduled-report/manage-scheduled-report.controller.js
+++ b/plugins/ScheduledReports/angularjs/manage-scheduled-report/manage-scheduled-report.controller.js
@@ -62,7 +62,9 @@
'description': '',
'period': ReportPlugin.defaultPeriod,
'hour': ReportPlugin.defaultHour,
- 'reports': []
+ 'reports': [],
+ 'evolutionPeriodFor': 'prev',
+ 'evolutionPeriodN': ReportPlugin.defaultEvolutionPeriodN,
};
if (idReport > 0) {
@@ -135,6 +137,10 @@
apiParameters.idSegment = this.report.idsegment;
apiParameters.reportType = this.report.type;
apiParameters.reportFormat = this.report['format' + this.report.type];
+ apiParameters.evolutionPeriodFor = this.report.evolutionPeriodFor;
+ if (apiParameters.evolutionPeriodFor !== 'each') {
+ apiParameters.evolutionPeriodN = this.report.evolutionPeriodN;
+ }
var period = self.report.period;
var hour = adjustHourToTimezone(this.report.hour, -getTimeZoneDifferenceInHours());
@@ -218,6 +224,21 @@
formSetEditReport(reportId);
};
+ this.getFrequencyPeriodSingle = function () {
+ var translation = ReportPlugin.periodTranslations[this.report.period];
+ if (!translation) {
+ translation = ReportPlugin.periodTranslations.day;
+ }
+ return translation.single;
+ };
+ this.getFrequencyPeriodPlural = function () {
+ var translation = ReportPlugin.periodTranslations[this.report.period];
+ if (!translation) {
+ translation = ReportPlugin.periodTranslations.day;
+ }
+ return translation.plural;
+ };
+
this.showListOfReports(false);
}
})(); \ No newline at end of file
diff --git a/plugins/ScheduledReports/lang/en.json b/plugins/ScheduledReports/lang/en.json
index 4fad5256f2..bfcaadfcf9 100644
--- a/plugins/ScheduledReports/lang/en.json
+++ b/plugins/ScheduledReports/lang/en.json
@@ -53,6 +53,8 @@
"SuccessfullyUnsubscribed": "You have been successfully unsubscribed from the report %1$s.",
"UnsubscribeFooter": "To unsubscribe from this report please follow this link: %1$s",
"NoTokenProvided": "No token was provided in the URL",
- "NoSubscriptionFound": "No subscription found. Maybe the report was already unsubscribed or removed."
+ "NoSubscriptionFound": "No subscription found. Maybe the report was already unsubscribed or removed.",
+ "EvolutionGraphsShowForEachInPeriod": "Evolution graphs show the evolution for %1$seach day%2$s in the last %3$s",
+ "EvolutionGraphsShowForPreviousN": "Evolution graphs show the evolution over the previous N %s"
}
}
diff --git a/plugins/ScheduledReports/stylesheets/scheduledreports.less b/plugins/ScheduledReports/stylesheets/scheduledreports.less
index 47b9fbed05..0ef23a13af 100644
--- a/plugins/ScheduledReports/stylesheets/scheduledreports.less
+++ b/plugins/ScheduledReports/stylesheets/scheduledreports.less
@@ -10,4 +10,23 @@
vertical-align: bottom;
}
}
+
+ input[name=report_evolution_period_n] {
+ display: inline;
+ width: 60px;
+ margin-bottom: 0;
+ height: 1.3rem;
+ }
+
+ .evolution-graph-period {
+ font-size: 1rem;
+
+ > div {
+ margin-top: 1rem;
+ }
+
+ label {
+ color: @color-black-piwik;
+ }
+ }
}
diff --git a/plugins/ScheduledReports/templates/_addReport.twig b/plugins/ScheduledReports/templates/_addReport.twig
index 64cb2456b4..5e87105cc9 100644
--- a/plugins/ScheduledReports/templates/_addReport.twig
+++ b/plugins/ScheduledReports/templates/_addReport.twig
@@ -92,6 +92,25 @@
ng-show="manageScheduledReport.report.displayFormat == '2' || manageScheduledReport.report.displayFormat == '3'"
title="{{ 'ScheduledReports_EvolutionGraph'|translate(5)|e('html_attr') }}">
</div>
+
+ <div
+ class="row evolution-graph-period"
+ ng-show="manageScheduledReport.report.displayFormat == '1' || manageScheduledReport.report.displayFormat == '2' || manageScheduledReport.report.displayFormat == '3'"
+ >
+ <div class="col s12">
+ <input id="report_evolution_period_for_each" name="report_evolution_period_for" type="radio" checked value="each" ng-model="manageScheduledReport.report.evolutionPeriodFor" />
+ <label for="report_evolution_period_for_each" piwik-translate="ScheduledReports_EvolutionGraphsShowForEachInPeriod">
+ <strong>::</strong>::{{ "{{ manageScheduledReport.getFrequencyPeriodSingle() }}" }}
+ </label>
+ </div>
+ <div class="col s12">
+ <input id="report_evolution_period_for_prev" name="report_evolution_period_for" type="radio" value="prev" ng-model="manageScheduledReport.report.evolutionPeriodFor" />
+ <label for="report_evolution_period_for_prev">
+ {{ "{{ 'ScheduledReports_EvolutionGraphsShowForPreviousN'|translate:manageScheduledReport.getFrequencyPeriodPlural() }}" }}:
+ <input type="number" name="report_evolution_period_n" ng-model="manageScheduledReport.report.evolutionPeriodN" />
+ </label>
+ </div>
+ </div>
</div>
<div class="row">
diff --git a/plugins/ScheduledReports/templates/index.twig b/plugins/ScheduledReports/templates/index.twig
index 1ba11502e6..191ca1c191 100644
--- a/plugins/ScheduledReports/templates/index.twig
+++ b/plugins/ScheduledReports/templates/index.twig
@@ -39,6 +39,8 @@
ReportPlugin.reportList = {{ reportsJSON | raw }};
ReportPlugin.createReportString = "{{ 'ScheduledReports_CreateReport'|translate }}";
ReportPlugin.updateReportString = "{{ 'ScheduledReports_UpdateReport'|translate }}";
+ ReportPlugin.defaultEvolutionPeriodN = {{ defaultEvolutionPeriodN|json_encode|raw }};
+ ReportPlugin.periodTranslations = {{ periodTranslations|json_encode|raw }};
</script>
<style type="text/css">
.reportCategory {
diff --git a/plugins/ScheduledReports/tests/Integration/ApiTest.php b/plugins/ScheduledReports/tests/Integration/ApiTest.php
index 6c3ee22169..fa7168c7e4 100644
--- a/plugins/ScheduledReports/tests/Integration/ApiTest.php
+++ b/plugins/ScheduledReports/tests/Integration/ApiTest.php
@@ -487,6 +487,208 @@ class ApiTest extends IntegrationTestCase
$this->assertNotContains('id="UserCountry_getCountry"', $result);
}
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Invalid evolutionPeriodFor value
+ */
+ public function test_addReport_validatesEvolutionPeriodForParam()
+ {
+ self::setSuperUser();
+
+ APIScheduledReports::getInstance()->addReport(
+ 1,
+ '',
+ Schedule::PERIOD_DAY,
+ 0,
+ ScheduledReports::EMAIL_TYPE,
+ ReportRenderer::HTML_FORMAT,
+ array(
+ 'VisitsSummary_get',
+ 'UserCountry_getCountry',
+ 'Referrers_getWebsites',
+ ),
+ array(ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_TABLES_ONLY),
+ false,
+ 'garbage'
+ );
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Evolution period amount must be a positive number
+ */
+ public function test_addReport_validatesEvolutionPeriodNParam()
+ {
+ self::setSuperUser();
+
+ APIScheduledReports::getInstance()->addReport(
+ 1,
+ '',
+ Schedule::PERIOD_DAY,
+ 0,
+ ScheduledReports::EMAIL_TYPE,
+ ReportRenderer::HTML_FORMAT,
+ array(
+ 'VisitsSummary_get',
+ 'UserCountry_getCountry',
+ 'Referrers_getWebsites',
+ ),
+ array(ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_TABLES_ONLY),
+ false,
+ 'prev',
+ -5
+ );
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage The evolutionPeriodN param has no effect when evolutionPeriodFor is "each".
+ */
+ public function test_addReport_throwsIfEvolutionPeriodNParamIsEach_AndLastNSupplied()
+ {
+ self::setSuperUser();
+
+ APIScheduledReports::getInstance()->addReport(
+ 1,
+ '',
+ Schedule::PERIOD_DAY,
+ 0,
+ ScheduledReports::EMAIL_TYPE,
+ ReportRenderer::HTML_FORMAT,
+ array(
+ 'VisitsSummary_get',
+ 'UserCountry_getCountry',
+ 'Referrers_getWebsites',
+ ),
+ array(ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_TABLES_ONLY),
+ false,
+ 'each',
+ 5
+ );
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Invalid evolutionPeriodFor value
+ */
+ public function test_updateReport_validatesEvolutionPeriodForParam()
+ {
+ self::setSuperUser();
+
+ $idReport = APIScheduledReports::getInstance()->addReport(
+ 1,
+ '',
+ Schedule::PERIOD_DAY,
+ 0,
+ ScheduledReports::EMAIL_TYPE,
+ ReportRenderer::HTML_FORMAT,
+ array(
+ 'VisitsSummary_get',
+ ),
+ array(ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_TABLES_ONLY)
+ );
+
+ APIScheduledReports::getInstance()->updateReport(
+ $idReport,
+ 1,
+ '',
+ Schedule::PERIOD_DAY,
+ 0,
+ ScheduledReports::EMAIL_TYPE,
+ ReportRenderer::HTML_FORMAT,
+ array(
+ 'VisitsSummary_get',
+ 'UserCountry_getCountry',
+ 'Referrers_getWebsites',
+ ),
+ array(ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_TABLES_ONLY),
+ false,
+ 'garbage'
+ );
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage Evolution period amount must be a positive number
+ */
+ public function test_updateReport_validatesEvolutionPeriodNParam()
+ {
+ self::setSuperUser();
+
+ $idReport = APIScheduledReports::getInstance()->addReport(
+ 1,
+ '',
+ Schedule::PERIOD_DAY,
+ 0,
+ ScheduledReports::EMAIL_TYPE,
+ ReportRenderer::HTML_FORMAT,
+ array(
+ 'VisitsSummary_get',
+ ),
+ array(ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_TABLES_ONLY)
+ );
+
+ APIScheduledReports::getInstance()->updateReport(
+ $idReport,
+ 1,
+ '',
+ Schedule::PERIOD_DAY,
+ 0,
+ ScheduledReports::EMAIL_TYPE,
+ ReportRenderer::HTML_FORMAT,
+ array(
+ 'VisitsSummary_get',
+ 'UserCountry_getCountry',
+ 'Referrers_getWebsites',
+ ),
+ array(ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_TABLES_ONLY),
+ false,
+ 'prev',
+ -5
+ );
+ }
+
+ /**
+ * @expectedException \Exception
+ * @expectedExceptionMessage The evolutionPeriodN param has no effect when evolutionPeriodFor is "each".
+ */
+ public function test_updateReport_throwsIfEvolutionPeriodNParamIsEach_AndLastNSupplied()
+ {
+ self::setSuperUser();
+
+ $idReport = APIScheduledReports::getInstance()->addReport(
+ 1,
+ '',
+ Schedule::PERIOD_DAY,
+ 0,
+ ScheduledReports::EMAIL_TYPE,
+ ReportRenderer::HTML_FORMAT,
+ array(
+ 'VisitsSummary_get',
+ ),
+ array(ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_TABLES_ONLY)
+ );
+
+ APIScheduledReports::getInstance()->updateReport(
+ $idReport,
+ 1,
+ '',
+ Schedule::PERIOD_DAY,
+ 0,
+ ScheduledReports::EMAIL_TYPE,
+ ReportRenderer::HTML_FORMAT,
+ array(
+ 'VisitsSummary_get',
+ 'UserCountry_getCountry',
+ 'Referrers_getWebsites',
+ ),
+ array(ScheduledReports::DISPLAY_FORMAT_PARAMETER => ScheduledReports::DISPLAY_FORMAT_TABLES_ONLY),
+ false,
+ 'each',
+ 5
+ );
+ }
+
private function assertReportsEqual($report, $data)
{
foreach ($data as $key => $value) {