diff options
author | Ben Burgess <88810029+bx80@users.noreply.github.com> | 2021-12-01 05:27:48 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-01 05:27:48 +0300 |
commit | 74a6bb09477a175f06bffbef14cf533ba8744b69 (patch) | |
tree | d582cea51ba22234ab35a3f86d9d98bf2e061378 /plugins/Transitions | |
parent | 9efa63a654145fcb315d16c5e6d21ab3b96c6f01 (diff) |
Configuration option to disable transition periods (#18366)
* Added config option to disable transition periods
* Config section checks
* Hide transitions row action if period is not allowed
* Added system test
* Add default values for requests vars
* Do allowed period checks for transition row actions in javascript
* Code tidy up, fix for range get day count bug, improved tests
* Added UI test for disabled period
Diffstat (limited to 'plugins/Transitions')
-rw-r--r-- | plugins/Transitions/API.php | 53 | ||||
-rw-r--r-- | plugins/Transitions/Controller.php | 3 | ||||
-rw-r--r-- | plugins/Transitions/Transitions.php | 42 | ||||
-rw-r--r-- | plugins/Transitions/javascripts/transitions.js | 43 | ||||
-rw-r--r-- | plugins/Transitions/lang/en.json | 2 | ||||
-rw-r--r-- | plugins/Transitions/tests/Integration/TransitionsMaxAllowedPeriodTest.php | 133 | ||||
-rw-r--r-- | plugins/Transitions/tests/UI/Transitions_spec.js | 16 |
7 files changed, 288 insertions, 4 deletions
diff --git a/plugins/Transitions/API.php b/plugins/Transitions/API.php index 67a388eb8a..0dc1c726c5 100644 --- a/plugins/Transitions/API.php +++ b/plugins/Transitions/API.php @@ -66,6 +66,10 @@ class API extends \Piwik\Plugin\API { Piwik::checkUserHasViewAccess($idSite); + if (!$this->isPeriodAllowed($idSite, $period, $date)) { + throw new Exception('PeriodNotAllowed'); + } + // get idaction of the requested action $idaction = $this->deriveIdAction($actionName, $actionType); if ($idaction < 0) { @@ -656,4 +660,53 @@ class API extends \Piwik\Plugin\API $this->totalTransitionsToFollowingPages += $actions; } } + + + /** + * Check if a period is allowed by config settings + * + * @param $idSite + * @param $period + * @param $date + * + * @return bool + */ + public function isPeriodAllowed($idSite, $period, $date) : bool + { + $maxPeriodAllowed = Transitions::getPeriodAllowedConfig($idSite); + if ($maxPeriodAllowed === 'all') { + return true; + } + + // If the period is a range then the number of days in the range must be less or equal to the max period allowed + if ($period === 'range') { + + $range = new Period\Range($period, $date); + $rangeDays = $range->getDayCount(); + + switch ($maxPeriodAllowed) { + case 'day': + return $rangeDays == 1; + case 'week': + return $rangeDays <= 7; + case 'month': + return $rangeDays <= 31; + case 'year': + return $rangeDays <= 365; + } + } + + switch ($maxPeriodAllowed) { + case 'day': + return $period === 'day'; + case 'week': + return in_array($period, ['day', 'week']); + case 'month': + return in_array($period, ['day', 'week', 'month']); + case 'year': + return in_array($period, ['day', 'week', 'month', 'year']); + } + + return false; + } } diff --git a/plugins/Transitions/Controller.php b/plugins/Transitions/Controller.php index 2cabbc62d2..a8a85e0115 100644 --- a/plugins/Transitions/Controller.php +++ b/plugins/Transitions/Controller.php @@ -60,6 +60,9 @@ class Controller extends \Piwik\Plugin\Controller 'NoDataForAction' => 'Transitions_NoDataForAction', 'NoDataForActionDetails' => 'Transitions_NoDataForActionDetails', 'NoDataForActionBack' => 'Transitions_ErrorBack', + 'PeriodNotAllowed' => 'Transitions_PeriodNotAllowed', + 'PeriodNotAllowedDetails'=> 'Transitions_PeriodNotAllowedDetails', + 'PeriodNotAllowedBack' => 'Transitions_ErrorBack', 'ShareOfAllPageviews' => 'Transitions_ShareOfAllPageviews', 'DateRange' => 'General_DateRange' ); diff --git a/plugins/Transitions/Transitions.php b/plugins/Transitions/Transitions.php index 67d5be7f25..afd5f3a2fc 100644 --- a/plugins/Transitions/Transitions.php +++ b/plugins/Transitions/Transitions.php @@ -9,6 +9,10 @@ namespace Piwik\Plugins\Transitions; +use Piwik\Common; +use Piwik\Plugins\Transitions\API; +use Piwik\Config; + /** */ class Transitions extends \Piwik\Plugin @@ -22,7 +26,8 @@ class Transitions extends \Piwik\Plugin 'AssetManager.getStylesheetFiles' => 'getStylesheetFiles', 'AssetManager.getJavaScriptFiles' => 'getJsFiles', 'Translate.getClientSideTranslationKeys' => 'getClientSideTranslationKeys', - 'API.getPagesComparisonsDisabledFor' => 'getPagesComparisonsDisabledFor', + 'API.getPagesComparisonsDisabledFor' => 'getPagesComparisonsDisabledFor', + 'Template.jsGlobalVariables' => 'addJsGlobalVariables', ); } @@ -55,4 +60,39 @@ class Transitions extends \Piwik\Plugin $translationKeys[] = 'CoreHome_ThereIsNoDataForThisReport'; $translationKeys[] = 'General_Others'; } + + public function addJsGlobalVariables(&$out) + { + $idSite = Common::getRequestVar('idSite', 1, 'int'); + $maxPeriodAllowed = self::getPeriodAllowedConfig($idSite); + + $out .= ' piwik.transitionsMaxPeriodAllowed = "'.($maxPeriodAllowed ? $maxPeriodAllowed : 'all').'"'."\n"; + } + + /** + * Retrieve the period allowed config setting for a site or all sites if null + * + * @param $idSite + * + * @return string + */ + public static function getPeriodAllowedConfig($idSite) : string + { + $transitionsGeneralConfig = Config::getInstance()->Transitions; + $generalMaxPeriodAllowed = ($transitionsGeneralConfig && !empty($transitionsGeneralConfig['max_period_allowed']) ? $transitionsGeneralConfig['max_period_allowed']: null); + + $siteMaxPeriodAllowed = null; + if ($idSite) { + $sectionName = 'Transitions_'.$idSite; + $transitionsSiteConfig = Config::getInstance()->$sectionName; + $siteMaxPeriodAllowed = ($transitionsSiteConfig && !empty($transitionsSiteConfig['max_period_allowed']) ? $transitionsSiteConfig['max_period_allowed'] : null); + } + + if (!$generalMaxPeriodAllowed && !$siteMaxPeriodAllowed) { + return 'all'; // No config setting, so all periods are valid + } + + // Site setting overrides general, if it exists + return $siteMaxPeriodAllowed ?? $generalMaxPeriodAllowed; + } } diff --git a/plugins/Transitions/javascripts/transitions.js b/plugins/Transitions/javascripts/transitions.js index 19bd467b14..caabaa0b69 100644 --- a/plugins/Transitions/javascripts/transitions.js +++ b/plugins/Transitions/javascripts/transitions.js @@ -123,6 +123,45 @@ DataTable_RowActions_Registry.register({ }, isAvailableOnReport: function (dataTableParams) { + + if (piwik.transitionsMaxPeriodAllowed && dataTableParams['period']) { + + if (dataTableParams['period'] === 'range') { + + var piwikPeriods = piwikHelper.getAngularDependency('piwikPeriods'); + if (piwikPeriods) { + var range = piwikPeriods.parse(dataTableParams['period'], dataTableParams['date']); + if (range) { + var rangeDays = range.getDayCount(); + if ((piwik.transitionsMaxPeriodAllowed === 'day' && rangeDays > 1) || + (piwik.transitionsMaxPeriodAllowed === 'week' && rangeDays > 7) || + (piwik.transitionsMaxPeriodAllowed === 'month' && rangeDays > 31) || + (piwik.transitionsMaxPeriodAllowed === 'year' && rangeDays > 365)) + { + return false; + } + } + } + } else { + if (piwik.transitionsMaxPeriodAllowed === 'day' && dataTableParams['period'] !== 'day') { + return false; + } + if (piwik.transitionsMaxPeriodAllowed === 'week' && dataTableParams['period'] !== 'day' + && dataTableParams['period'] !== 'week') { + return false; + } + if (piwik.transitionsMaxPeriodAllowed === 'month' && dataTableParams['period'] !== 'day' + && dataTableParams['period'] !== 'week' && dataTableParams['period'] !== 'month') { + return false; + } + if (piwik.transitionsMaxPeriodAllowed === 'year' && dataTableParams['period'] !== 'day' + && dataTableParams['period'] !== 'week' && dataTableParams['period'] !== 'month' + && dataTableParams['period'] !== 'year' + ) { + return false; + } + } + } var i = 0; for (i; i < DataTable_RowActions_Transitions.registeredReports.length; i++) { var report = DataTable_RowActions_Transitions.registeredReports[i]; @@ -1586,8 +1625,8 @@ Piwik_Transitions_Ajax.prototype.callApi = function (method, params, callback) { if (typeof Piwik_Transitions_Translations == 'undefined') { self.callApi('Transitions.getTranslations', {}, function (response) { - if (typeof response[0] == 'object') { - Piwik_Transitions_Translations = response[0]; + if (typeof response == 'object') { + Piwik_Transitions_Translations = response; } else { Piwik_Transitions_Translations = {}; } diff --git a/plugins/Transitions/lang/en.json b/plugins/Transitions/lang/en.json index 321557d613..71cdb25bb5 100644 --- a/plugins/Transitions/lang/en.json +++ b/plugins/Transitions/lang/en.json @@ -24,6 +24,8 @@ "LoopsInline": "%s page reloads", "NoDataForAction": "There's no data for %s", "NoDataForActionDetails": "Either the action had no pageviews during the period %s or it is invalid.", + "PeriodNotAllowed": "Time period not allowed", + "PeriodNotAllowedDetails": "This feature is not available for this period, try selecting a period with fewer days", "OutgoingTraffic": "Outgoing traffic", "PluginDescription": "Reports previous and following actions for each page URL in a new Transitions report, available in the Actions reports via a new icon.", "ShareOfAllPageviews": "This page had %1$s pageviews (%2$s of all pageviews)", diff --git a/plugins/Transitions/tests/Integration/TransitionsMaxAllowedPeriodTest.php b/plugins/Transitions/tests/Integration/TransitionsMaxAllowedPeriodTest.php new file mode 100644 index 0000000000..b074e7d3ab --- /dev/null +++ b/plugins/Transitions/tests/Integration/TransitionsMaxAllowedPeriodTest.php @@ -0,0 +1,133 @@ +<?php +/** + * Matomo - free/libre analytics platform + * + * @link https://matomo.org + * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later + */ +namespace Piwik\Plugins\Transitions\tests\Integration; + +use Piwik\Plugins\Transitions\Transitions; +use Piwik\Tests\Framework\TestCase\IntegrationTestCase; +use Piwik\Config; +use Piwik\Tests\Framework\Fixture; +use Piwik\Plugins\Transitions\API; + +/** + * Tests the transitions plugin max_period_allowed setting + * + * @group TransitionsMaxAllowedPeriodTest + * @group Plugins + */ +class TransitionsMaxAllowedPeriodTest extends IntegrationTestCase +{ + + public $api; + + protected static function configureFixture($fixture) + { + parent::configureFixture($fixture); + $fixture->createSuperUser = true; + } + + public function setUp(): void + { + parent::setUp(); + Fixture::createWebsite('2010-02-03 00:00:00'); + $this->api = API::getInstance(); + + $t = Fixture::getTracker(1, '2012-08-09 01:02:03', $defaultInit = true, $useLocalTracker = false); + + $t->setUrl('http://example.org/page/one.html'); + $t->doTrackPageView('incredible title '); + } + + public function test_ShouldThrowException_IfPeriodNotAllowed() + { + $invalidPeriods = [ + 'day' => ['week', 'month', 'year'], + 'week' => ['month', 'year'], + 'month' => ['year'], + ]; + foreach ($invalidPeriods as $period => $invalids) { + Config::setSetting('Transitions_1', 'max_period_allowed', $period); + foreach ($invalids as $ip) { + try { + $this->api->getTransitionsForAction('http://example.org/page/one.html', 'url', + 1, $ip, '2012-08-09'); + $this->fail("Failed asserting that exception 'PeriodNotAllowed' was thrown"); + } catch (\Exception $e) { + $this->assertEquals('PeriodNotAllowed', $e->getMessage()); + } + } + } + } + + public function test_ShouldReturnData_IfPeriodAllowed() + { + $validPeriods = [ + 'day' => ['day'], + 'week' => ['day', 'week'], + 'month' => ['day', 'week', 'month'], + 'year' => ['day', 'week', 'month', 'year'], + 'all' => ['day', 'week', 'month', 'year'], + ]; + foreach ($validPeriods as $period => $valids) { + Config::setSetting('Transitions_1', 'max_period_allowed', $period); + foreach ($valids as $vp) { + $r = $this->api->getTransitionsForAction('http://example.org/page/one.html', 'url', + 1, $vp, '2012-08-09'); + self::assertEquals(1, $r['pageMetrics']['pageviews']); + } + } + } + + public function test_ShouldThrowException_IfRangeDayCountIsLargerThanDayPeriod() + { + Config::setSetting('Transitions_1', 'max_period_allowed', 'day'); + $this->expectException(\Exception::class); + $this->expectExceptionMessage('PeriodNotAllowed'); + $this->api->getTransitionsForAction('http://example.org/page/one.html', 'url', 1, + 'range','2012-08-09,2012-08-10'); + } + + public function test_ShouldThrowException_IfRangeDayCountIsLargerThanWeekPeriod() + { + Config::setSetting('Transitions_1', 'max_period_allowed', 'day'); + $this->expectException(\Exception::class); + $this->expectExceptionMessage('PeriodNotAllowed'); + $this->api->getTransitionsForAction('http://example.org/page/one.html', 'url', 1, + 'range','2012-08-09,2012-08-17'); + } + + public function test_ShouldThrowException_IfRangeDayCountIsLargerThanMonthPeriod() + { + Config::setSetting('Transitions_1', 'max_period_allowed', 'day'); + $this->expectException(\Exception::class); + $this->expectExceptionMessage('PeriodNotAllowed'); + $this->api->getTransitionsForAction('http://example.org/page/one.html', 'url', 1, + 'range','2012-08-09,2012-09-10'); + } + + public function test_ShouldThrowException_IfRangeDayCountIsLargerThanYearPeriod() + { + Config::setSetting('Transitions_1', 'max_period_allowed', 'day'); + $this->expectException(\Exception::class); + $this->expectExceptionMessage('PeriodNotAllowed'); + $this->api->getTransitionsForAction('http://example.org/page/one.html', 'url', 1, + 'range','2012-08-09,2013-08-10'); + } + + public function test_ShouldUseSiteConfigInsteadOfGeneral_IfSiteConfigExists() + { + Config::setSetting('Transitions_1', 'max_period_allowed', null); + Config::setSetting('Transitions', 'max_period_allowed', 'month'); + $maxAllowedPeriod = Transitions::getPeriodAllowedConfig(1); + $this->assertEquals('month', $maxAllowedPeriod); + + Config::setSetting('Transitions_1', 'max_period_allowed', 'week'); + $maxAllowedPeriod = Transitions::getPeriodAllowedConfig(1); + $this->assertEquals('week', $maxAllowedPeriod); + } + +} diff --git a/plugins/Transitions/tests/UI/Transitions_spec.js b/plugins/Transitions/tests/UI/Transitions_spec.js index ed125f3078..4e0d716d09 100644 --- a/plugins/Transitions/tests/UI/Transitions_spec.js +++ b/plugins/Transitions/tests/UI/Transitions_spec.js @@ -84,4 +84,18 @@ describe("Transitions", function () { expect(await page.screenshotSelector('body')).to.matchImage('transitions_report_switch_type_title'); }); -});
\ No newline at end of file + it('should show period not allowed for disabled periods', async function () { + + testEnvironment.overrideConfig('Transitions_1', 'max_period_allowed', 'day'); + testEnvironment.save(); + + await page.goto("?" + urlBase + "#?" + generalParams + "&category=General_Actions&subcategory=Transitions_Transitions"); + await page.waitForNetworkIdle(); + expect(await page.screenshotSelector('.pageWrap')).to.matchImage('transitions_report_period_not_allowed'); + + testEnvironment.overrideConfig('Transitions_1', 'max_period_allowed', 'all'); + testEnvironment.save(); + }); + + +}); |