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:
authorMatthieu Aubry <mattab@users.noreply.github.com>2016-09-26 06:26:55 +0300
committerGitHub <noreply@github.com>2016-09-26 06:26:55 +0300
commita8f682a6039e9b765e248c6be531cce54a7903d1 (patch)
treed242720e47a1aaff0c0cd020d238a1e7715c564f
parent10486f8e9e4cae49be7202cf797105fbd58555b5 (diff)
Release 2.16.3-b4 (#10558)2.16.3-b4
* Fix Scheduled Reports sent one hour late in daylight saving timezones (#10443) * convert hour to send report to/from UTC, to ensure it isn't affected by daylight savings * adds update script to change existing scheduled reports to use utc time * code improvement * adds missing param * Added new event Archiving.makeNewArchiverObject to allow customising plugin archiving (#10366) * added hook to alllow plugin archiving prevention * cr code style notes * reworked PR to fit CR suggestions * added PHPDoc for hook * Event description more consistent * UI tests: minor changes * Adds test checking if all screenshots are stored in lfs * removed screenshots not stored in lfs * readds screenshots to lfs * 2.16.3-b4
-rw-r--r--core/ArchiveProcessor/PluginsArchiver.php38
-rw-r--r--core/Plugin/Archiver.php13
-rw-r--r--core/Updates/2.16.3-b3.php41
-rw-r--r--core/Version.php2
-rw-r--r--plugins/ScheduledReports/Controller.php6
-rw-r--r--plugins/ScheduledReports/Tasks.php4
-rw-r--r--plugins/ScheduledReports/javascripts/pdf.js15
-rw-r--r--plugins/ScheduledReports/lang/en.json1
-rw-r--r--plugins/ScheduledReports/stylesheets/scheduledreports.less3
-rw-r--r--plugins/ScheduledReports/templates/_addReport.twig15
-rw-r--r--plugins/ScheduledReports/templates/index.twig1
-rw-r--r--plugins/ScheduledReports/tests/Integration/ApiTest.php17
-rw-r--r--tests/PHPUnit/Integration/ReleaseCheckListTest.php19
-rw-r--r--tests/UI/expected-screenshots/CoreUpdaterDb_main.pngbin125710 -> 131 bytes
-rw-r--r--tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png4
-rw-r--r--tests/UI/expected-screenshots/UIIntegrationTest_email_reports.png4
m---------tests/travis0
17 files changed, 155 insertions, 28 deletions
diff --git a/core/ArchiveProcessor/PluginsArchiver.php b/core/ArchiveProcessor/PluginsArchiver.php
index 28c90cb15c..325b529aa3 100644
--- a/core/ArchiveProcessor/PluginsArchiver.php
+++ b/core/ArchiveProcessor/PluginsArchiver.php
@@ -10,10 +10,12 @@
namespace Piwik\ArchiveProcessor;
use Piwik\ArchiveProcessor;
+use Piwik\Common;
use Piwik\DataAccess\ArchiveWriter;
use Piwik\DataAccess\LogAggregator;
use Piwik\DataTable\Manager;
use Piwik\Metrics;
+use Piwik\Piwik;
use Piwik\Plugin\Archiver;
use Piwik\Log;
use Piwik\Timer;
@@ -50,8 +52,8 @@ class PluginsArchiver
public function __construct(Parameters $params, $isTemporaryArchive)
{
$this->params = $params;
-
- $this->archiveWriter = new ArchiveWriter($this->params, $isTemporaryArchive);
+ $this->isTemporaryArchive = $isTemporaryArchive;
+ $this->archiveWriter = new ArchiveWriter($this->params, $this->isTemporaryArchive);
$this->archiveWriter->initNewArchive();
$this->logAggregator = new LogAggregator($params);
@@ -106,7 +108,7 @@ class PluginsArchiver
$latestUsedTableId = Manager::getInstance()->getMostRecentTableId();
/** @var Archiver $archiver */
- $archiver = new $archiverClass($this->archiveProcessor);
+ $archiver = $this->makeNewArchiverObject($archiverClass, $pluginName);
if (!$archiver->isEnabled()) {
Log::debug("PluginsArchiver::%s: Skipping archiving for plugin '%s'.", __FUNCTION__, $pluginName);
@@ -198,9 +200,9 @@ class PluginsArchiver
return true;
}
if (Rules::shouldProcessReportsAllPlugins(
- $this->params->getIdSites(),
- $this->params->getSegment(),
- $this->params->getPeriod()->getLabel())) {
+ $this->params->getIdSites(),
+ $this->params->getSegment(),
+ $this->params->getPeriod()->getLabel())) {
return true;
}
@@ -236,4 +238,28 @@ class PluginsArchiver
$metrics = $this->archiveProcessor->aggregateNumericMetrics($toSum);
return $metrics;
}
+
+
+ /**
+ * @param $archiverClass
+ * @return Archiver
+ */
+ private function makeNewArchiverObject($archiverClass, $pluginName)
+ {
+ $archiver = new $archiverClass($this->archiveProcessor);
+
+ /**
+ * Triggered right after a new **plugin archiver instance** is created.
+ * Subscribers to this event can configure the plugin archiver, for example prevent the archiving of a plugin's data
+ * by calling `$archiver->disable()` method.
+ *
+ * @param \Piwik\Plugin\Archiver &$archiver The newly created plugin archiver instance.
+ * @param string $pluginName The name of plugin of which archiver instance was created.
+ * @param array $this->params Array containing archive parameters (Site, Period, Date and Segment)
+ * @param bool $this->isTemporaryArchive Flag indicating whether the archive being processed is temporary (ie. the period isn't finished yet) or final (the period is already finished and in the past).
+ */
+ Piwik::postEvent('Archiving.makeNewArchiverObject', array($archiver, $pluginName, $this->params, $this->isTemporaryArchive));
+
+ return $archiver;
+ }
}
diff --git a/core/Plugin/Archiver.php b/core/Plugin/Archiver.php
index 7cc9fe26f5..90e325bc8e 100644
--- a/core/Plugin/Archiver.php
+++ b/core/Plugin/Archiver.php
@@ -60,6 +60,11 @@ abstract class Archiver
private $processor;
/**
+ * @var bool
+ */
+ private $enabled;
+
+ /**
* Constructor.
*
* @param ArchiveProcessor $processor The ArchiveProcessor instance to use when persisting archive
@@ -69,6 +74,7 @@ abstract class Archiver
{
$this->maximumRows = PiwikConfig::getInstance()->General['datatable_archiving_maximum_rows_standard'];
$this->processor = $processor;
+ $this->enabled = true;
}
/**
@@ -121,6 +127,11 @@ abstract class Archiver
return $this->getProcessor()->getLogAggregator();
}
+ public function disable()
+ {
+ $this->enabled = false;
+ }
+
/**
* Whether this Archiver should be used or not.
*
@@ -128,6 +139,6 @@ abstract class Archiver
*/
public function isEnabled()
{
- return true;
+ return $this->enabled;
}
}
diff --git a/core/Updates/2.16.3-b3.php b/core/Updates/2.16.3-b3.php
new file mode 100644
index 0000000000..a1175c9f4d
--- /dev/null
+++ b/core/Updates/2.16.3-b3.php
@@ -0,0 +1,41 @@
+<?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\Updates;
+
+use Piwik\Plugins\ScheduledReports\API as ScheduledReportsAPI;
+use Piwik\Plugins\ScheduledReports\Model as ScheduledReportsModel;
+use Piwik\Site;
+use Piwik\Updater;
+use Piwik\Updates as PiwikUpdates;
+
+/**
+ * Update for version 2.16.3-b3.
+ *
+ * Update existing scheduled reports to use UTC timezone for hour setting
+ */
+class Updates_2_16_3_b3 extends PiwikUpdates
+{
+ public function doUpdate(Updater $updater)
+ {
+ $model = new ScheduledReportsModel();
+ $allReports = ScheduledReportsAPI::getInstance()->getReports();
+ foreach ($allReports as $report) {
+ $report['hour'] = $this->adjustTimezoneBySite($report['hour'], $report['idsite']);
+ $model->updateReport($report['idreport'], $report);
+ }
+ }
+
+ protected function adjustTimezoneBySite($hour, $idSite)
+ {
+ $timezone = Site::getTimezoneFor($idSite);
+ $dateTimeZone = new \DateTimeZone($timezone);
+ $timeZoneDifference = -ceil($dateTimeZone->getOffset(new \DateTime()) / 3600);
+ return (24 + $hour + $timeZoneDifference) % 24;
+ }
+}
diff --git a/core/Version.php b/core/Version.php
index c96dce0e86..2cf7565c10 100644
--- a/core/Version.php
+++ b/core/Version.php
@@ -20,7 +20,7 @@ final class Version
* The current Piwik version.
* @var string
*/
- const VERSION = '2.16.3-b3';
+ const VERSION = '2.16.3-b4';
public function isStableVersion($version)
{
diff --git a/plugins/ScheduledReports/Controller.php b/plugins/ScheduledReports/Controller.php
index 3192a3cfc4..7316f6283d 100644
--- a/plugins/ScheduledReports/Controller.php
+++ b/plugins/ScheduledReports/Controller.php
@@ -26,7 +26,11 @@ class Controller extends \Piwik\Plugin\Controller
$view = new View('@ScheduledReports/index');
$this->setGeneralVariablesView($view);
- $view->countWebsites = count(APISitesManager::getInstance()->getSitesIdWithAtLeastViewAccess());
+ $siteTimezone = $this->site->getTimezone();
+ $dateTimeZone = new \DateTimeZone($siteTimezone);
+
+ $view->timeZoneDifference = $dateTimeZone->getOffset(new \DateTime()) / 3600;
+ $view->countWebsites = count(APISitesManager::getInstance()->getSitesIdWithAtLeastViewAccess());
// get report types
$reportTypes = API::getReportTypes();
diff --git a/plugins/ScheduledReports/Tasks.php b/plugins/ScheduledReports/Tasks.php
index be61e0d793..44a13e1b57 100644
--- a/plugins/ScheduledReports/Tasks.php
+++ b/plugins/ScheduledReports/Tasks.php
@@ -18,11 +18,9 @@ class Tasks extends \Piwik\Plugin\Tasks
foreach (API::getInstance()->getReports() as $report) {
if (!$report['deleted'] && $report['period'] != Schedule::PERIOD_NEVER) {
- $timezone = Site::getTimezoneFor($report['idsite']);
-
$schedule = Schedule::getScheduledTimeForPeriod($report['period']);
$schedule->setHour($report['hour']);
- $schedule->setTimezone($timezone);
+ $schedule->setTimezone('UTC'); // saved hour is UTC always
$this->custom(API::getInstance(), 'sendReport', $report['idreport'], $schedule);
}
diff --git a/plugins/ScheduledReports/javascripts/pdf.js b/plugins/ScheduledReports/javascripts/pdf.js
index 2b86809517..5ddff3654f 100644
--- a/plugins/ScheduledReports/javascripts/pdf.js
+++ b/plugins/ScheduledReports/javascripts/pdf.js
@@ -9,6 +9,10 @@ var getReportParametersFunctions = Object();
var updateReportParametersFunctions = Object();
var resetReportParametersFunctions = Object();
+function adjustHourToTimezone(hour, difference) {
+ return (24 + parseInt(hour) + difference) % 24;
+}
+
function formSetEditReport(idReport) {
var report = {
'type': ReportPlugin.defaultReportType,
@@ -29,11 +33,16 @@ function formSetEditReport(idReport) {
toggleReportType(report.type);
+ var hour = adjustHourToTimezone(report.hour, timeZoneDifference);
+
$('#report_description').html(report.description);
$('#report_segment').find('option[value=' + report.idsegment + ']').prop('selected', 'selected');
$('#report_type').find('option[value=' + report.type + ']').prop('selected', 'selected');
$('#report_period').find('option[value=' + report.period + ']').prop('selected', 'selected');
- $('#report_hour').val(report.hour);
+ $('#report_hour').val(hour).bind('change', function() {
+ $('#hour_utc').text(adjustHourToTimezone($(this).val(), -timeZoneDifference));
+ });
+ $('#hour_utc').text(report.hour);
$('[name=report_format].' + report.type + ' option[value=' + report.format + ']').prop('selected', 'selected');
$('select[name=report_type]').change( toggleDisplayOptionsByFormat );
@@ -122,10 +131,12 @@ function initManagePdf() {
apiParameters.parameters = getReportParametersFunctions[apiParameters.reportType]();
+ var hour = adjustHourToTimezone($('#report_hour').val(), -timeZoneDifference);
+
var ajaxHandler = new ajaxHelper();
ajaxHandler.addParams(apiParameters, 'POST');
ajaxHandler.addParams({period: $('#report_period').find('option:selected').val()}, 'GET');
- ajaxHandler.addParams({hour: $('#report_hour').val()}, 'GET');
+ ajaxHandler.addParams({hour: hour}, 'GET');
ajaxHandler.redirectOnSuccess();
ajaxHandler.setLoadingElement();
if (idReport) {
diff --git a/plugins/ScheduledReports/lang/en.json b/plugins/ScheduledReports/lang/en.json
index a1ef702c9a..60f0254a0d 100644
--- a/plugins/ScheduledReports/lang/en.json
+++ b/plugins/ScheduledReports/lang/en.json
@@ -29,6 +29,7 @@
"PluginDescription": "Create custom reports and schedule them to be emailed daily, weekly or monthly to one or several people. Several report formats are supported (html, pdf, csv, images).",
"ReportFormat": "Report Format",
"ReportHour": "Send report at %s o'clock",
+ "ReportHourWithUTC": "Send report at %1$s o'clock (%2$s o'clock UTC)",
"ReportIncludeNWebsites": "The report will include main metrics for all websites that have at least one visit (from the %s websites currently available).",
"ReportSent": "Report sent",
"ReportsIncluded": "Statistics included",
diff --git a/plugins/ScheduledReports/stylesheets/scheduledreports.less b/plugins/ScheduledReports/stylesheets/scheduledreports.less
index 871b89da3c..27d2d1557d 100644
--- a/plugins/ScheduledReports/stylesheets/scheduledreports.less
+++ b/plugins/ScheduledReports/stylesheets/scheduledreports.less
@@ -7,5 +7,6 @@
#report_hour {
height: 0.9em;
padding: 0 0 0 5px;
- width: 35px;
+ width: 45px;
+ background-position: 25px center;
}
diff --git a/plugins/ScheduledReports/templates/_addReport.twig b/plugins/ScheduledReports/templates/_addReport.twig
index 24f97ad19f..7ed8a0c588 100644
--- a/plugins/ScheduledReports/templates/_addReport.twig
+++ b/plugins/ScheduledReports/templates/_addReport.twig
@@ -59,7 +59,20 @@
<br/>
{{ 'ScheduledReports_MonthlyScheduleHelp'|translate }}
<br/>
- {{ 'ScheduledReports_ReportHour'|translate('<input type="text" id="report_hour" class="inp" size="2">')|raw }}
+
+ {% set hourInput %}
+ <select id="report_hour">
+ {% for i in 0..23 %}
+ <option value="{{ i }}">{{ i }}</option>
+ {% endfor %}
+ </select>
+ {% endset %}
+
+ {% if timeZoneDifference != 0 %}
+ {{ 'ScheduledReports_ReportHourWithUTC'|translate(hourInput, '<span id="hour_utc"></span>')|raw }}
+ {% else %}
+ {{ 'ScheduledReports_ReportHour'|translate(hourInput)|raw }}
+ {% endif %}
</div>
</td>
</tr>
diff --git a/plugins/ScheduledReports/templates/index.twig b/plugins/ScheduledReports/templates/index.twig
index 542fab8e70..b98ee70fc5 100644
--- a/plugins/ScheduledReports/templates/index.twig
+++ b/plugins/ScheduledReports/templates/index.twig
@@ -32,6 +32,7 @@
</div>
<script type="text/javascript">
+ var timeZoneDifference = {{ timeZoneDifference }};
var ReportPlugin = {};
ReportPlugin.defaultPeriod = '{{ defaultPeriod }}';
ReportPlugin.defaultHour = '{{ defaultHour }}';
diff --git a/plugins/ScheduledReports/tests/Integration/ApiTest.php b/plugins/ScheduledReports/tests/Integration/ApiTest.php
index e2d242581f..07d851a694 100644
--- a/plugins/ScheduledReports/tests/Integration/ApiTest.php
+++ b/plugins/ScheduledReports/tests/Integration/ApiTest.php
@@ -371,21 +371,22 @@ class ApiTest extends IntegrationTestCase
));
// expected tasks
+ // NOTE: scheduled reports are always saved with UTC, to avoid daylight saving issues
$scheduleTask1 = Schedule::factory('daily');
- $scheduleTask1->setHour(0); // paris is UTC-1, period ends at 23h UTC
- $scheduleTask1->setTimezone('Europe/Paris');
+ $scheduleTask1->setHour(0);
+ $scheduleTask1->setTimezone('UTC');
$scheduleTask2 = new Monthly();
- $scheduleTask2->setHour(0); // site is UTC-6.5, period ends at 6h30 UTC, smallest resolution is hour
- $scheduleTask2->setTimezone('UTC-6.5');
+ $scheduleTask2->setHour(0);
+ $scheduleTask2->setTimezone('UTC');
$scheduleTask3 = new Monthly();
- $scheduleTask3->setHour(8); // paris is UTC-1, configured to be sent at 8h
- $scheduleTask3->setTimezone('Europe/Paris');
+ $scheduleTask3->setHour(8);
+ $scheduleTask3->setTimezone('UTC');
$scheduleTask4 = new Monthly();
- $scheduleTask4->setHour(8); // site is UTC-6.5, configured to be sent at 8h
- $scheduleTask4->setTimezone('UTC-6.5');
+ $scheduleTask4->setHour(8);
+ $scheduleTask4->setTimezone('UTC');
$expectedTasks = array(
new Task(APIScheduledReports::getInstance(), 'sendReport', 1, $scheduleTask1),
diff --git a/tests/PHPUnit/Integration/ReleaseCheckListTest.php b/tests/PHPUnit/Integration/ReleaseCheckListTest.php
index 88bbb8e1b7..b90e5c2732 100644
--- a/tests/PHPUnit/Integration/ReleaseCheckListTest.php
+++ b/tests/PHPUnit/Integration/ReleaseCheckListTest.php
@@ -91,6 +91,25 @@ class ReleaseCheckListTest extends \PHPUnit_Framework_TestCase
$this->checkFilesAreInJpgFormat($files);
}
+ public function test_screenshotsStoredInLfs()
+ {
+ $screenshots = Filesystem::globr(PIWIK_INCLUDE_PATH . '/tests/UI/expected-screenshots', '*.png');
+ $cleanPath = function ($value) {
+ return str_replace(PIWIK_INCLUDE_PATH . '/', '', $value);
+ };
+ $screenshots = array_map($cleanPath, $screenshots);
+
+ $storedLfsFiles = explode("\n", `git lfs ls-files`);
+ $cleanRevision = function ($value) {
+ $parts = explode(' - ', $value);
+ return array_pop($parts);
+ };
+ $storedLfsFiles = array_map($cleanRevision, $storedLfsFiles);
+
+ $diff = array_diff($screenshots, $storedLfsFiles);
+ $this->assertEmpty($diff, 'Some Screenshots are not stored in LFS: ' . implode("\n", $diff));
+ }
+
public function testCheckThatConfigurationValuesAreProductionValues()
{
$this->_checkEqual(array('Debug' => 'always_archive_data_day'), '0');
diff --git a/tests/UI/expected-screenshots/CoreUpdaterDb_main.png b/tests/UI/expected-screenshots/CoreUpdaterDb_main.png
index 1d6c95541a..e0d8eee6a2 100644
--- a/tests/UI/expected-screenshots/CoreUpdaterDb_main.png
+++ b/tests/UI/expected-screenshots/CoreUpdaterDb_main.png
Binary files differ
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png b/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png
index 25d961246e..78ce53c3c5 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png
+++ b/tests/UI/expected-screenshots/UIIntegrationTest_api_listing.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:bbfcce8a0c674db8f725104077ffdca606292f746de18dd7443dab68d9d56618
-size 2480230
+oid sha256:0a3ca67fd0848a4c3ac8d0fde79d385adec65115eff3b0df6cf534bc1c851282
+size 2494420
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_email_reports.png b/tests/UI/expected-screenshots/UIIntegrationTest_email_reports.png
index 6dfc2e26d1..7e1ed37236 100644
--- a/tests/UI/expected-screenshots/UIIntegrationTest_email_reports.png
+++ b/tests/UI/expected-screenshots/UIIntegrationTest_email_reports.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a06b95792a06fd8f3585c6a347381765fb891a59bf7b76138b15fc551bb55972
-size 52520
+oid sha256:b60aa9a3254e6209a08bd76f38a6e0ed15aee0a85018937eecfefa7cddb82d46
+size 48768
diff --git a/tests/travis b/tests/travis
-Subproject e0d3e68c0310e605bd654748676e8cb4c9bf0c1
+Subproject e041bdf1a6b63024478852a58a69dd826e8aca4