From 5d2dab75e3654126ed95ea72b58b4c225ac59492 Mon Sep 17 00:00:00 2001 From: Stefan Giehl Date: Tue, 11 Feb 2020 09:38:48 +0100 Subject: [PATCH] Merge branch 3.x-dev into 4.x-dev (#15543) * Updates search engine and social definitions (#15384) * updates device detector to latest release (#15388) * updates device detector to latest release * updates tests * translation update (#15389) * Fix Could not get the lock for ID, when creating a site (#15401) * Lock key start * do not empty key lock Co-authored-by: Thomas Steur * 3.13.1 * submodule updates * Use correct name in update available message (#15423) * Fix removing user capabilities (#15422) * Order of implode() args, avoid E_NOTICE in PHP7.4 (#15428) * Fixes possible php warning in visitor log (#15442) * silence is_executable call (#15446) * Make sure geolocation admin experience is consistent if user is not using GeoIp2 plugin. (#15447) * Fix referrers test. (#15448) * Ensure to close visitor popover correctly (#15443) * Fixes possible warning (#15453) * Forward instance_id from local config when reseting config during tests. (#15445) * Add event that allows plugins to disable archiving for certain periods/sites if they want. (#15457) * Add event that allows plugins to disable archiving for certain periods/sites if they want. * apply review feedback * Fix possible warning for columns without index (#15467) * Day range archiving issue (#15462) * Improve lock ID check for max length (#15407) Better patch for https://github.com/matomo-org/matomo/pull/15401 which was merged last minute... This way it always works even when someone calls `acquireLock` directly instead of `execute` Pushing this for now into 3.x-dev but can also put it into 4.x-dev directly but then there might be merge conflicts when merging 3.x-dev into 4.x-dev * Use SameSite none for session token when embedded into iframe (#15439) * Make sure tracking works in IE9 and lower (#15480) * Mention Joomla install FAQ (#15481) * Make sparklines work when mbstring extension is not installed (#15489) 1) Too few arguments to function mb_strtolower(), 1 passed in matomo/vendor/davaxi/sparkline/src/Sparkline/StyleTrait.php on line 129 and exactly 2 expected 2) mb_strlen is not defined * update screenshots (#15488) * 3.13.2-rc1 * Use safemode when running CLI commands (#15472) * update icons submodule (#15490) * update icons submodule * update UI tests * Fix possible undefined index notice (#15502) * Use latest davaxi/sparkline release (#15464) * translation update * submodule updates * Fix deprecation notice (#15530) see https://github.com/matomo-org/matomo/pull/15467#issuecomment-583283444 * 3.13.2-rc2 * update cache component (#15536) * fixes copy dashboard to user for more than 100 users (#15538) cherry picking #15424 to fix #15420 in 3.x-dev * Add missing return statement. (#15539) * 3.13.2 * update tests * update tests Co-authored-by: Matthieu Aubry Co-authored-by: Thomas Steur Co-authored-by: Peter Upfold Co-authored-by: diosmosis Co-authored-by: Lukas Winkler --- composer.json | 4 +- composer.lock | 22 +-- console | 5 + core/Archive.php | 5 +- core/ArchiveProcessor/PluginsArchiver.php | 6 +- core/ArchiveProcessor/Rules.php | 20 ++- core/Archiver/Request.php | 29 +++- core/CliMulti/CliPhp.php | 2 +- core/Concurrency/Lock.php | 14 +- core/Console.php | 15 ++ core/CronArchive.php | 21 ++- core/DataAccess/ArchiveSelector.php | 2 +- core/FrontController.php | 2 +- core/Plugin/Report.php | 8 +- core/Session.php | 11 ++ core/Session/SessionAuth.php | 2 +- core/Tracker/Model.php | 2 +- core/Tracker/Settings.php | 2 +- js/piwik.js | 4 +- js/piwik.min.js | 8 +- libs/Zend/Session.php | 4 +- libs/upgradephp/upgrade.php | 19 ++- matomo.js | 8 +- piwik.js | 8 +- ...Name__API.getSuggestedValuesForSegment.xml | 7 + ...Name__API.getSuggestedValuesForSegment.xml | 1 + plugins/CoreAdminHome/javascripts/optOut.js | 20 ++- .../CoreHome/templates/_headerMessage.twig | 2 +- .../Visualizations/HtmlTable.php | 5 +- .../Dashboard_loaded_token_auth.png | 4 +- .../Dashboard_removed.png | 4 +- plugins/Live/Visualizations/VisitorLog.php | 7 +- plugins/Live/javascripts/visitorProfile.js | 29 ++-- plugins/Morpheus/icons | 2 +- ...ager_gdpr_tools_delete_visit_cancelled.png | 4 +- ...er_gdpr_tools_delete_visit_unconfirmed.png | 4 +- ...anager_gdpr_tools_enrich_segment_by_ip.png | 4 +- ...cyManager_gdpr_tools_uncheck_one_visit.png | 4 +- plugins/Referrers/tests/System/ApiTest.php | 14 +- .../templates/_trackingCodeEmail.twig | 1 + .../templates/siteWithoutData.twig | 1 + plugins/UserCountry/Controller.php | 6 + plugins/UserCountry/lang/el.json | 3 +- plugins/UserCountry/lang/en.json | 3 +- plugins/UserCountry/lang/es-ar.json | 3 +- plugins/UserCountry/lang/pt-br.json | 3 +- plugins/UserCountry/lang/sq.json | 3 +- plugins/UserCountry/lang/tr.json | 3 +- plugins/UserCountry/templates/adminIndex.twig | 13 +- .../capabilities-edit.component.html | 2 +- tests/PHPUnit/Framework/Fixture.php | 15 ++ tests/PHPUnit/Framework/Mock/TestConfig.php | 11 +- tests/PHPUnit/System/ConsoleTest.php | 132 ++++++++++++++++++ ...eportMetadata__API.getSegmentsMetadata.xml | 2 +- tests/PHPUnit/Unit/Archiver/RequestTest.php | 28 ++++ .../Comparison_segmented_visitorlog.png | 4 +- .../EmptySite_emptySiteDashboard.png | 4 +- .../OneClickUpdate_login.png | 4 +- tests/UI/expected-screenshots/Theme_home.png | 4 +- .../UIIntegrationTest_dashboard1.png | 4 +- .../UIIntegrationTest_ecommerce_log.png | 4 +- ...ntegrationTest_ecommerce_log_segmented.png | 4 +- ...UIIntegrationTest_segmented_visitorlog.png | 4 +- ...IIntegrationTest_visitor_profile_popup.png | 4 +- ...IIntegrationTest_visitors_realtime_map.png | 4 +- .../UIIntegrationTest_visitors_software.png | 4 +- ...IntegrationTest_widgetize_ecommercelog.png | 4 +- tests/travis | 2 +- 68 files changed, 480 insertions(+), 133 deletions(-) diff --git a/composer.json b/composer.json index 77a6204cb3c..d6ca89fa3ec 100644 --- a/composer.json +++ b/composer.json @@ -37,8 +37,8 @@ "matomo/ini": "~2.0", "matomo/matomo-php-tracker": "~2.0", "matomo/network": "~2.0", - "matomo/referrer-spam-blacklist": "~1.0", - "matomo/searchengine-and-social-list": "~1.0", + "matomo/referrer-spam-blacklist": "~3.0", + "matomo/searchengine-and-social-list": "~3.0", "monolog/monolog": "~1.11", "mustangostang/spyc": "~0.6.0", "pear/pear_exception": "~1.0.0", diff --git a/composer.lock b/composer.lock index 41cefe7cda4..8e53fec2d27 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "6436d84b7a1cbf44a996b4795723ce68", + "content-hash": "ef319f0bec0c7988dd83727e05ac2b39", "packages": [ { "name": "composer/ca-bundle", @@ -626,16 +626,16 @@ }, { "name": "matomo/searchengine-and-social-list", - "version": "1.4.4", + "version": "3.11.0", "source": { "type": "git", "url": "https://github.com/matomo-org/searchengine-and-social-list.git", - "reference": "5c29a58c6cab8a78c3e625ffc615e759ef8466d3" + "reference": "80ab98ed17ea5b72730f4f4d96acc03847440103" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matomo-org/searchengine-and-social-list/zipball/5c29a58c6cab8a78c3e625ffc615e759ef8466d3", - "reference": "5c29a58c6cab8a78c3e625ffc615e759ef8466d3", + "url": "https://api.github.com/repos/matomo-org/searchengine-and-social-list/zipball/80ab98ed17ea5b72730f4f4d96acc03847440103", + "reference": "80ab98ed17ea5b72730f4f4d96acc03847440103", "shasum": "" }, "replace": { @@ -647,7 +647,7 @@ "CC0-1.0" ], "description": "Search engine and social network definitions used by Matomo (formerly Piwik)", - "time": "2018-05-25T11:09:26+00:00" + "time": "2020-01-13T09:01:25+00:00" }, { "name": "maxmind-db/reader", @@ -1236,16 +1236,16 @@ }, { "name": "piwik/device-detector", - "version": "3.12.2", + "version": "3.12.3", "source": { "type": "git", "url": "https://github.com/matomo-org/device-detector.git", - "reference": "c352144e2ab1aff81e659aa38224be987b87855b" + "reference": "22257883bd2c7c21d68112a907cdad7de4a2ba31" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/c352144e2ab1aff81e659aa38224be987b87855b", - "reference": "c352144e2ab1aff81e659aa38224be987b87855b", + "url": "https://api.github.com/repos/matomo-org/device-detector/zipball/22257883bd2c7c21d68112a907cdad7de4a2ba31", + "reference": "22257883bd2c7c21d68112a907cdad7de4a2ba31", "shasum": "" }, "require": { @@ -1287,7 +1287,7 @@ "parser", "useragent" ], - "time": "2019-12-22T21:23:31+00:00" + "time": "2020-01-13T16:15:20+00:00" }, { "name": "psr/container", diff --git a/console b/console index 47b8ba59f98..069c992dd7b 100755 --- a/console +++ b/console @@ -1,5 +1,8 @@ #!/usr/bin/env php run(); diff --git a/core/Archive.php b/core/Archive.php index 19b06db4a55..ad85d6242ec 100644 --- a/core/Archive.php +++ b/core/Archive.php @@ -649,10 +649,11 @@ private function cacheArchiveIdsAfterLaunching($archiveGroups, $plugins) foreach ($this->params->getIdSites() as $idSite) { $site = new Site($idSite); - if ($period->getLabel() === 'day' + if ($period->getLabel() === 'day' && !$this->params->getSegment()->isEmpty() && Common::getRequestVar('skipArchiveSegmentToday', 0, 'int') - && $period->getDateStart()->toString() == Date::factory('now', $site->getTimezone())->toString()) { + && $period->getDateStart()->toString() == Date::factory('now', $site->getTimezone())->toString() + ) { Log::debug("Skipping archive %s for %s as segment today is disabled", $period->getLabel(), $period->getPrettyString()); continue; diff --git a/core/ArchiveProcessor/PluginsArchiver.php b/core/ArchiveProcessor/PluginsArchiver.php index a5f828ee6e9..2ada786bd41 100644 --- a/core/ArchiveProcessor/PluginsArchiver.php +++ b/core/ArchiveProcessor/PluginsArchiver.php @@ -160,13 +160,15 @@ public function callAggregateAllPlugins($visits, $visitsConverted, $forceArchivi try { self::$currentPluginBeingArchived = $pluginName; + $period = $this->params->getPeriod()->getLabel(); + $timer = new Timer(); if ($this->shouldAggregateFromRawData) { - Log::debug("PluginsArchiver::%s: Archiving day reports for plugin '%s'.", __FUNCTION__, $pluginName); + Log::debug("PluginsArchiver::%s: Archiving $period reports for plugin '%s' from raw data.", __FUNCTION__, $pluginName); $archiver->callAggregateDayReport(); } else { - Log::debug("PluginsArchiver::%s: Archiving period reports for plugin '%s'.", __FUNCTION__, $pluginName); + Log::debug("PluginsArchiver::%s: Archiving $period reports for plugin '%s' using reports for smaller periods.", __FUNCTION__, $pluginName); $archiver->callAggregateMultipleReports(); } diff --git a/core/ArchiveProcessor/Rules.php b/core/ArchiveProcessor/Rules.php index bf0f73b836a..24f9cc2fe27 100644 --- a/core/ArchiveProcessor/Rules.php +++ b/core/ArchiveProcessor/Rules.php @@ -226,9 +226,21 @@ public static function isArchivingDisabledFor(array $idSites, Segment $segment, return !$isArchivingEnabled; } - public static function isRequestAuthorizedToArchive() + public static function isRequestAuthorizedToArchive(Parameters $params = null) { - return Rules::isBrowserTriggerEnabled() || SettingsServer::isArchivePhpTriggered(); + $isRequestAuthorizedToArchive = Rules::isBrowserTriggerEnabled() || SettingsServer::isArchivePhpTriggered(); + + if (!empty($params)) { + /** + * @ignore + * + * @params bool &$isRequestAuthorizedToArchive + * @params Parameters $params + */ + Piwik::postEvent('Archiving.isRequestAuthorizedToArchive', [&$isRequestAuthorizedToArchive, $params]); + } + + return $isRequestAuthorizedToArchive; } public static function isBrowserTriggerEnabled() @@ -293,11 +305,11 @@ public static function isSegmentPreProcessed(array $idSites, Segment $segment) * * @return string[] */ - public static function getSelectableDoneFlagValues($includeInvalidated = true) + public static function getSelectableDoneFlagValues($includeInvalidated = true, Parameters $params = null) { $possibleValues = array(ArchiveWriter::DONE_OK, ArchiveWriter::DONE_OK_TEMPORARY); - if (!Rules::isRequestAuthorizedToArchive() + if (!Rules::isRequestAuthorizedToArchive($params) && $includeInvalidated ) { //If request is not authorized to archive then fetch also invalidated archives diff --git a/core/Archiver/Request.php b/core/Archiver/Request.php index e08b23ac548..58389384a67 100644 --- a/core/Archiver/Request.php +++ b/core/Archiver/Request.php @@ -31,7 +31,7 @@ class Request */ public function __construct($url) { - $this->url = $url; + $this->setUrl($url); } public function before($callable) @@ -68,9 +68,34 @@ public function setUrl($url) } public function changeDate($newDate) + { + $this->changeParam('date', $newDate); + } + + public function makeSureDateIsNotSingleDayRange() + { + // TODO: revisit in matomo 4 + // period=range&date=last1/period=range&date=previous1 can cause problems during archiving due to Parameters::isDayArchive() + if (preg_match('/[&?]period=range/', $this->url)) { + if (preg_match('/[&?]date=last1/', $this->url)) { + $this->changeParam('period', 'day'); + $this->changeParam('date', 'today'); + } else if (preg_match('/[&?]date=previous1/', $this->url)) { + $this->changeParam('period', 'day'); + $this->changeParam('date', 'yesterday'); + } else if (preg_match('/[&?]date=([^,]+),([^,&]+)/', $this->url, $matches) + && $matches[1] == $matches[2] + ) { + $this->changeParam('period', 'day'); + $this->changeParam('date', $matches[1]); + } + } + } + + public function changeParam($name, $newValue) { $url = $this->getUrl(); - $url = preg_replace('/([&?])date=[^&]*/', '$1date=' . $newDate, $url); + $url = preg_replace('/([&?])' . preg_quote($name) . '=[^&]*/', '$1' . $name . '=' . $newValue, $url); $this->setUrl($url); } } diff --git a/core/CliMulti/CliPhp.php b/core/CliMulti/CliPhp.php index 0d254e2339a..3b1661510e4 100644 --- a/core/CliMulti/CliPhp.php +++ b/core/CliMulti/CliPhp.php @@ -86,7 +86,7 @@ private function isValidPhpType($path) private function getPhpCommandIfValid($path) { - if (!empty($path) && is_executable($path)) { + if (!empty($path) && @is_executable($path)) { if (0 === strpos($path, PHP_BINDIR) && $this->isValidPhpType($path)) { return $path; } diff --git a/core/Concurrency/Lock.php b/core/Concurrency/Lock.php index f63bec640a3..f26f5896992 100644 --- a/core/Concurrency/Lock.php +++ b/core/Concurrency/Lock.php @@ -50,13 +50,6 @@ public function getAllAcquiredLockKeys() public function execute($id, $callback) { - if (Common::mb_strlen($id) > self::MAX_KEY_LEN) { - // Lock key might be too long for DB column, so we hash it but leave the start of the original as well - // to make it more readable - $md5Len = 32; - $id = Common::mb_substr($id, 0, self::MAX_KEY_LEN - $md5Len - 1) . md5($id); - } - $i = 0; while (!$this->acquireLock($id)) { $i++; @@ -76,6 +69,13 @@ public function acquireLock($id, $ttlInSeconds = 60) { $this->lockKey = $this->lockKeyStart . $id; + if (Common::mb_strlen($this->lockKey) > self::MAX_KEY_LEN) { + // Lock key might be too long for DB column, so we hash it but leave the start of the original as well + // to make it more readable + $md5Len = 32; + $this->lockKey = Common::mb_substr($id, 0, self::MAX_KEY_LEN - $md5Len - 1) . md5($id); + } + $lockValue = substr(Common::generateUniqId(), 0, 12); $locked = $this->backend->setIfNotExists($this->lockKey, $lockValue, $ttlInSeconds); diff --git a/core/Console.php b/core/Console.php index 70cec3c740d..1bf61c0fd26 100644 --- a/core/Console.php +++ b/core/Console.php @@ -77,6 +77,21 @@ public function renderException($e, $output) } public function doRun(InputInterface $input, OutputInterface $output) + { + try { + return $this->doRunImpl($input, $output); + } catch (\Exception $ex) { + try { + FrontController::generateSafeModeOutputFromException($ex); + } catch (\Exception $ex) { + // ignore, we re-throw the original exception, not a wrapped one + } + + throw $ex; + } + } + + private function doRunImpl(InputInterface $input, OutputInterface $output) { if ($input->hasParameterOption('--xhprof')) { Profiler::setupProfilerXHProf(true, true); diff --git a/core/CronArchive.php b/core/CronArchive.php index fb17b960b6f..6e7d186db23 100644 --- a/core/CronArchive.php +++ b/core/CronArchive.php @@ -1104,7 +1104,16 @@ private function archiveReportsFor($idSite, $period, $date, $archiveSegments, Ti return Request::ABORT; } + $urlBefore = $request->getUrl(); $request->changeDate($newDate); + $request->makeSureDateIsNotSingleDayRange(); + + // check again if we are already archiving the URL since we just changed it + if ($request->getUrl() !== $urlBefore + && $self->isAlreadyArchivingSegment($request->getUrl(), $idSite, $period, $segment) + ) { + return Request::ABORT; + } $this->logArchiveWebsite($idSite, $period, $newDate); }); @@ -1972,9 +1981,17 @@ private function getUrlsWithSegment($idSite, $period, $date) return Request::ABORT; } - $url = $request->getUrl(); - $url = preg_replace('/([&?])date=[^&]*/', '$1date=' . $newDate, $url); + $urlBefore = $request->getUrl(); + $url = preg_replace('/([&?])date=[^&]*/', '$1date=' . $newDate, $urlBefore); $request->setUrl($url); + $request->makeSureDateIsNotSingleDayRange(); + + // check again if we are already archiving the URL since we just changed it + if ($request->getUrl() !== $urlBefore + && $self->isAlreadyArchivingSegment($request->getUrl(), $idSite, $period, $segment) + ) { + return Request::ABORT; + } $processedSegmentCount++; $logger->info(sprintf( diff --git a/core/DataAccess/ArchiveSelector.php b/core/DataAccess/ArchiveSelector.php index 21d7a9f6266..42324041418 100644 --- a/core/DataAccess/ArchiveSelector.php +++ b/core/DataAccess/ArchiveSelector.php @@ -71,7 +71,7 @@ public static function getArchiveIdAndVisits(ArchiveProcessor\Parameters $params $plugins = array("VisitsSummary", $requestedPlugin); $doneFlags = Rules::getDoneFlags($plugins, $segment); - $doneFlagValues = Rules::getSelectableDoneFlagValues($includeInvalidated); + $doneFlagValues = Rules::getSelectableDoneFlagValues($includeInvalidated, $params); $results = self::getModel()->getArchiveIdAndVisits($numericTable, $idSite, $period, $dateStartIso, $dateEndIso, $minDatetimeIsoArchiveProcessedUTC, $doneFlags, $doneFlagValues); diff --git a/core/FrontController.php b/core/FrontController.php index 8a81006e9ae..84ce6a19276 100644 --- a/core/FrontController.php +++ b/core/FrontController.php @@ -106,7 +106,7 @@ private static function generateSafeModeOutputFromError($lastError) * @param Exception $e * @return string */ - private static function generateSafeModeOutputFromException($e) + public static function generateSafeModeOutputFromException($e) { StaticContainer::get(LoggerInterface::class)->error('Uncaught exception: {exception}', [ 'exception' => $e, diff --git a/core/Plugin/Report.php b/core/Plugin/Report.php index 391ae994d53..740eed18531 100644 --- a/core/Plugin/Report.php +++ b/core/Plugin/Report.php @@ -496,8 +496,8 @@ protected function getMetricsDocumentation() } elseif ($metric instanceof Metric) { $name = $metric->getName(); $metricDocs = $metric->getDocumentation(); - if (empty($metricDocs)) { - $metricDocs = @$translations[$name]; + if (empty($metricDocs) && !empty($translations[$name])) { + $metricDocs = $translations[$name]; } if (!empty($metricDocs)) { @@ -513,8 +513,8 @@ protected function getMetricsDocumentation() } elseif ($processedMetric instanceof Metric) { $name = $processedMetric->getName(); $metricDocs = $processedMetric->getDocumentation(); - if (empty($metricDocs)) { - $metricDocs = @$translations[$name]; + if (empty($metricDocs) && !empty($translations[$name])) { + $metricDocs = $translations[$name]; } if (!empty($metricDocs)) { diff --git a/core/Session.php b/core/Session.php index 92857e9d3c5..d7ee14beb49 100644 --- a/core/Session.php +++ b/core/Session.php @@ -171,6 +171,17 @@ public static function isSessionStarted() return self::$sessionStarted; } + public static function getSameSiteCookieValue() + { + $config = Config::getInstance(); + $general = $config->General; + if (!empty($general['enable_framed_pages']) && ProxyHttp::isHttps()) { + return 'None'; + } + + return 'Lax'; + } + /** * Write cookie header. Similar to the native setcookie() function but also supports * the SameSite cookie property. diff --git a/core/Session/SessionAuth.php b/core/Session/SessionAuth.php index 2b803b686f5..001b3d2bb09 100644 --- a/core/Session/SessionAuth.php +++ b/core/Session/SessionAuth.php @@ -195,7 +195,7 @@ private function updateSessionExpireTime(SessionFingerprint $sessionFingerprint) $sessionParams['domain'], $sessionParams['secure'], $sessionParams['httponly'], - 'lax' + Session::getSameSiteCookieValue() ); // ...and we also update the expiration time stored server side so we can prevent expired sessions from being reused diff --git a/core/Tracker/Model.php b/core/Tracker/Model.php index 8e8b7cac9e5..c7bdc72a497 100644 --- a/core/Tracker/Model.php +++ b/core/Tracker/Model.php @@ -346,7 +346,7 @@ public function updateAction($idLinkVa, $valuesToUpdate) list($updateParts, $sqlBind) = $this->fieldsToQuery($valuesToUpdate); - $parts = implode($updateParts, ', '); + $parts = implode(', ', $updateParts); $table = Common::prefixTable('log_link_visit_action'); $sqlQuery = "UPDATE $table SET $parts WHERE idlink_va = ?"; diff --git a/core/Tracker/Settings.php b/core/Tracker/Settings.php index 78c889c40e6..0fd61612f97 100644 --- a/core/Tracker/Settings.php +++ b/core/Tracker/Settings.php @@ -40,7 +40,7 @@ public function getConfigId(Request $request, $ipAddress) $deviceDetector = StaticContainer::get(DeviceDetectorFactory::class)->makeInstance($userAgent); $aBrowserInfo = $deviceDetector->getClient(); - if ($aBrowserInfo['type'] != 'browser') { + if (empty($aBrowserInfo['type']) || 'browser' !== $aBrowserInfo['type']) { // for now only track browsers unset($aBrowserInfo); } diff --git a/js/piwik.js b/js/piwik.js index bee045d487f..3031f4d01cb 100644 --- a/js/piwik.js +++ b/js/piwik.js @@ -6690,7 +6690,7 @@ if (typeof window.Piwik !== 'object') { // initialize the Piwik singleton addEventListener(windowAlias, 'beforeunload', beforeUnloadHandler, false); - window.addEventListener('message', function(e) { + addEventListener(windowAlias,'message', function(e) { if (!e || !e.origin) { return; } @@ -6773,7 +6773,7 @@ if (typeof window.Piwik !== 'object') { maq_optout_by_default: tracker.isConsentRequired() }); } - }); + }, false); Date.prototype.getTimeAlias = Date.prototype.getTime; diff --git a/js/piwik.min.js b/js/piwik.min.js index 353c2150666..f4fda77e086 100644 --- a/js/piwik.min.js +++ b/js/piwik.min.js @@ -59,10 +59,10 @@ var dm=di+":"+dh;if(dj){dm+=":"+dj}at(dl,dm,dk)});if(df){return df(dk,di,dh,dj,d dg=a(dg);if(!dh||!di){return}df=df||"Unknown";ce(function(){var dj=aO(dh,di,df,dg);if(dj){bC(dj,bG)}})};this.trackContentInteractionNode=function(dh,dg){if(N(b3)||!dh){return}var df=null;ce(function(){df=c7(dh,dg);if(df){bC(df,bG)}});return df};this.logAllContentBlocksOnPage=function(){var dh=v.findContentNodes();var df=v.collectContent(dh);var dg=typeof console;if(dg!=="undefined"&&console&&console.log){console.log(df)}};this.trackEvent=function(dg,di,df,dh,dk,dj){ce(function(){at(dg,di,df,dh,dk,dj)})};this.trackSiteSearch=function(df,dh,dg,di){b7=[];ce(function(){b5(df,dh,dg,di)})};this.setEcommerceView=function(di,df,dh,dg){if(Y(dh)){dh=String(dh)}if(!J(dh)||dh===null||dh===false||!dh.length){dh=""}else{if(dh instanceof Array){dh=T.JSON.stringify(dh)}}bT[5]=["_pkc",dh];if(J(dg)&&dg!==null&&dg!==false&&String(dg).length){bT[2]=["_pkp",dg]}if(!Y(di)&&!Y(df)){return}if(Y(di)){bT[3]=["_pks",di]}if(!Y(df)){df=""}bT[4]=["_pkn",df]};this.getEcommerceItems=function(){return JSON.parse(JSON.stringify(cW)) };this.addEcommerceItem=function(dj,df,dh,dg,di){if(Y(dj)){cW[dj]=[String(dj),df,dh,dg,di]}};this.removeEcommerceItem=function(df){if(Y(df)){df=String(df);delete cW[df]}};this.clearEcommerceCart=function(){cW={}};this.trackEcommerceOrder=function(df,dj,di,dh,dg,dk){bW(df,dj,di,dh,dg,dk)};this.trackEcommerceCartUpdate=function(df){bq(df)};this.trackRequest=function(dg,di,dh,df){ce(function(){var dj=cq(dg,di,df);bC(dj,bG,dh)})};this.ping=function(){this.trackRequest("ping=1",null,null,"ping")};this.disableQueueRequest=function(){bA.enabled=false};this.setRequestQueueInterval=function(df){if(df<1000){throw new Error("Request queue interval needs to be at least 1000ms")}bA.interval=df};this.queueRequest=function(df){ce(function(){var dg=cq(df);bA.push(dg)})};this.isConsentRequired=function(){return cx};this.getRememberedConsent=function(){var df=aC(bc);if(aC(cH)){if(df){bV(bc,bn,cT)}return null}if(!df||df===0){return null}return df};this.hasRememberedConsent=function(){return !!this.getRememberedConsent() };this.requireConsent=function(){cx=true;bz=this.hasRememberedConsent();x++;b["CoreConsent"+x]={unload:function(){if(!bz){aE()}}}};this.setConsentGiven=function(){bz=true;bV(cH,bn,cT);var dg,df;for(dg=0;dg1&&ap!=="addTracker"){ak("The method "+ap+' is registered more than once in "_paq" variable. Only the last call has an effect. Please have a look at the multiple Piwik trackers documentation: https://developer.piwik.org/guides/tracking-javascript-guide#multiple-piwik-trackers')}av[ap]++}}}}return au}var C=["addTracker","disableCookies","setTrackerUrl","setAPIUrl","enableCrossDomainLinking","setCrossDomainLinkingTimeout","setSessionCookieTimeout","setVisitorCookieTimeout","setSecureCookie","setCookiePath","setCookieDomain","setDomains","setUserId","setSiteId","alwaysUseSendBeacon","enableLinkTracking","requireConsent","setConsentGiven"];function ad(ao,aq){var ap=new Q(ao,aq);I.push(ap);_paq=c(_paq,C);for(E=0;E<_paq.length;E++){if(_paq[E]){af(_paq[E])}}_paq=new H();e.trigger("TrackerAdded",[ap]);return ap}an(T,"beforeunload",ai,false);window.addEventListener("message",function(au){if(!au||!au.origin){return}var aw,ar,ap;var ax=d(au.origin);var at=e.getAsyncTrackers();for(ar=0;ar1&&ap!=="addTracker"){ak("The method "+ap+' is registered more than once in "_paq" variable. Only the last call has an effect. Please have a look at the multiple Piwik trackers documentation: https://developer.piwik.org/guides/tracking-javascript-guide#multiple-piwik-trackers')}av[ap]++}}}}return au}var C=["addTracker","disableCookies","setTrackerUrl","setAPIUrl","enableCrossDomainLinking","setCrossDomainLinkingTimeout","setSessionCookieTimeout","setVisitorCookieTimeout","setSecureCookie","setCookiePath","setCookieDomain","setDomains","setUserId","setSiteId","alwaysUseSendBeacon","enableLinkTracking","requireConsent","setConsentGiven"];function ad(ao,aq){var ap=new Q(ao,aq);I.push(ap);_paq=c(_paq,C);for(E=0;E<_paq.length;E++){if(_paq[E]){af(_paq[E])}}_paq=new H();e.trigger("TrackerAdded",[ap]);return ap}an(T,"beforeunload",ai,false);an(T,"message",function(au){if(!au||!au.origin){return}var aw,ar,ap;var ax=d(au.origin);var at=e.getAsyncTrackers();for(ar=0;ar1&&ap!=="addTracker"){ak("The method "+ap+' is registered more than once in "_paq" variable. Only the last call has an effect. Please have a look at the multiple Piwik trackers documentation: https://developer.piwik.org/guides/tracking-javascript-guide#multiple-piwik-trackers')}av[ap]++}}}}return au}var C=["addTracker","disableCookies","setTrackerUrl","setAPIUrl","enableCrossDomainLinking","setCrossDomainLinkingTimeout","setSessionCookieTimeout","setVisitorCookieTimeout","setSecureCookie","setCookiePath","setCookieDomain","setDomains","setUserId","setSiteId","alwaysUseSendBeacon","enableLinkTracking","requireConsent","setConsentGiven"];function ad(ao,aq){var ap=new Q(ao,aq);I.push(ap);_paq=c(_paq,C);for(E=0;E<_paq.length;E++){if(_paq[E]){af(_paq[E])}}_paq=new H();e.trigger("TrackerAdded",[ap]);return ap}an(T,"beforeunload",ai,false);window.addEventListener("message",function(au){if(!au||!au.origin){return}var aw,ar,ap;var ax=d(au.origin);var at=e.getAsyncTrackers();for(ar=0;ar1&&ap!=="addTracker"){ak("The method "+ap+' is registered more than once in "_paq" variable. Only the last call has an effect. Please have a look at the multiple Piwik trackers documentation: https://developer.piwik.org/guides/tracking-javascript-guide#multiple-piwik-trackers')}av[ap]++}}}}return au}var C=["addTracker","disableCookies","setTrackerUrl","setAPIUrl","enableCrossDomainLinking","setCrossDomainLinkingTimeout","setSessionCookieTimeout","setVisitorCookieTimeout","setSecureCookie","setCookiePath","setCookieDomain","setDomains","setUserId","setSiteId","alwaysUseSendBeacon","enableLinkTracking","requireConsent","setConsentGiven"];function ad(ao,aq){var ap=new Q(ao,aq);I.push(ap);_paq=c(_paq,C);for(E=0;E<_paq.length;E++){if(_paq[E]){af(_paq[E])}}_paq=new H();e.trigger("TrackerAdded",[ap]);return ap}an(T,"beforeunload",ai,false);an(T,"message",function(au){if(!au||!au.origin){return}var aw,ar,ap;var ax=d(au.origin);var at=e.getAsyncTrackers();for(ar=0;ar1&&ap!=="addTracker"){ak("The method "+ap+' is registered more than once in "_paq" variable. Only the last call has an effect. Please have a look at the multiple Piwik trackers documentation: https://developer.piwik.org/guides/tracking-javascript-guide#multiple-piwik-trackers')}av[ap]++}}}}return au}var C=["addTracker","disableCookies","setTrackerUrl","setAPIUrl","enableCrossDomainLinking","setCrossDomainLinkingTimeout","setSessionCookieTimeout","setVisitorCookieTimeout","setSecureCookie","setCookiePath","setCookieDomain","setDomains","setUserId","setSiteId","alwaysUseSendBeacon","enableLinkTracking","requireConsent","setConsentGiven"];function ad(ao,aq){var ap=new Q(ao,aq);I.push(ap);_paq=c(_paq,C);for(E=0;E<_paq.length;E++){if(_paq[E]){af(_paq[E])}}_paq=new H();e.trigger("TrackerAdded",[ap]);return ap}an(T,"beforeunload",ai,false);window.addEventListener("message",function(au){if(!au||!au.origin){return}var aw,ar,ap;var ax=d(au.origin);var at=e.getAsyncTrackers();for(ar=0;ar1&&ap!=="addTracker"){ak("The method "+ap+' is registered more than once in "_paq" variable. Only the last call has an effect. Please have a look at the multiple Piwik trackers documentation: https://developer.piwik.org/guides/tracking-javascript-guide#multiple-piwik-trackers')}av[ap]++}}}}return au}var C=["addTracker","disableCookies","setTrackerUrl","setAPIUrl","enableCrossDomainLinking","setCrossDomainLinkingTimeout","setSessionCookieTimeout","setVisitorCookieTimeout","setSecureCookie","setCookiePath","setCookieDomain","setDomains","setUserId","setSiteId","alwaysUseSendBeacon","enableLinkTracking","requireConsent","setConsentGiven"];function ad(ao,aq){var ap=new Q(ao,aq);I.push(ap);_paq=c(_paq,C);for(E=0;E<_paq.length;E++){if(_paq[E]){af(_paq[E])}}_paq=new H();e.trigger("TrackerAdded",[ap]);return ap}an(T,"beforeunload",ai,false);an(T,"message",function(au){if(!au||!au.origin){return}var aw,ar,ap;var ax=d(au.origin);var at=e.getAsyncTrackers();for(ar=0;arAmiga Aweb Atomic Web Browser Avast Secure Browser + AVG Secure Browser Beaker Browser Beamrise BlackBerry Browser @@ -56,6 +57,7 @@ Chrome Webview dbrowser Deepnet Explorer + Delta Browser Dolphin Dorado Dooble @@ -77,6 +79,7 @@ Fennec Firefox Firefox Focus + Firefox Reality Firefox Rocket Flock Firefox Mobile @@ -117,6 +120,7 @@ LieBaoFast LG Browser Links + Lovense Browser LuaKit Lunascape Lynx @@ -149,6 +153,7 @@ Odyssey Web Browser Off By One ONE Browser + Opera GX Opera Neon Opera Devices Opera Mini @@ -156,6 +161,7 @@ Opera Opera Next Opera Touch + Ordissimo Oregano Origyn Web Browser Openwave Mobile Browser @@ -199,6 +205,7 @@ Sunrise SuperBird Super Fast Browser + START Internet Browser Streamy Swiftfox Seznam Browser diff --git a/plugins/API/tests/System/expected/test_AutoSuggestAPITest_operatingSystemName__API.getSuggestedValuesForSegment.xml b/plugins/API/tests/System/expected/test_AutoSuggestAPITest_operatingSystemName__API.getSuggestedValuesForSegment.xml index cda5b1843bf..ca3ca7f06ba 100644 --- a/plugins/API/tests/System/expected/test_AutoSuggestAPITest_operatingSystemName__API.getSuggestedValuesForSegment.xml +++ b/plugins/API/tests/System/expected/test_AutoSuggestAPITest_operatingSystemName__API.getSuggestedValuesForSegment.xml @@ -47,6 +47,7 @@ OS/2 OSF1 OpenBSD + Ordissimo PlayStation Portable PlayStation Red Hat diff --git a/plugins/CoreAdminHome/javascripts/optOut.js b/plugins/CoreAdminHome/javascripts/optOut.js index cbca7a81811..03ba11d927a 100644 --- a/plugins/CoreAdminHome/javascripts/optOut.js +++ b/plugins/CoreAdminHome/javascripts/optOut.js @@ -4,6 +4,20 @@ function getDomain(url) return url.replace(/^http[s]?:\/\//, '').replace(/\/.*/, ''); } +function addEventListener(element, eventType, eventHandler) { + if (element.addEventListener) { + element.addEventListener(eventType, eventHandler, false); + + return true; + } + + if (element.attachEvent) { + return element.attachEvent('on' + eventType, eventHandler); + } + + element['on' + eventType] = eventHandler; +} + // Strips off protocol and trailing path and URL params function getHostName(url) { @@ -72,7 +86,7 @@ function submitForm(e, form) { // Send a message to the parent window so that it can set a first-party cookie (a fallback in case // third-party cookies are not permitted by the browser). if (typeof parent === 'object' && typeof parent.postMessage !== 'undefined') { - window.addEventListener('message', function(e) { + addEventListener(window, 'message', function(e) { var data = getDataIfMessageIsForThisFrame(e); if (!data || typeof data.maq_confirm_opted_in === 'undefined') { return; @@ -172,7 +186,7 @@ function showWarningIfCookiesDisabled() { var initializationTimer = null; -document.addEventListener('DOMContentLoaded', function() { +addEventListener(document, 'DOMContentLoaded', function() { showWarningIfCookiesDisabled(); var trackVisitsCheckbox = document.getElementById('trackVisits'); @@ -200,7 +214,7 @@ document.addEventListener('DOMContentLoaded', function() { // Listener for initialization message from parent window // This will tell us the initial state the form should be in // based on the first-party cookie value (which we can't access directly) -window.addEventListener('message', function(e) { +addEventListener(window, 'message', function(e) { var data = getDataIfMessageIsForThisFrame(e); if (!data) { return; diff --git a/plugins/CoreHome/templates/_headerMessage.twig b/plugins/CoreHome/templates/_headerMessage.twig index 5633fca3cbe..46ecd55c187 100644 --- a/plugins/CoreHome/templates/_headerMessage.twig +++ b/plugins/CoreHome/templates/_headerMessage.twig @@ -43,7 +43,7 @@
{% elseif latest_version_available and not isPiwikDemo and hasSomeViewAccess and not isUserIsAnonymous %} {% set updateSubject = 'General_NewUpdatePiwikX'|translate(latest_version_available)|e('url') %} - {{ 'General_PiwikXIsAvailablePleaseNotifyPiwikAdmin'|translate("Piwik " ~ latest_version_available ~ "", "", "")|raw }} + {{ 'General_PiwikXIsAvailablePleaseNotifyPiwikAdmin'|translate("Matomo " ~ latest_version_available ~ "", "", "")|raw }}
{% endif %} diff --git a/plugins/CoreVisualizations/Visualizations/HtmlTable.php b/plugins/CoreVisualizations/Visualizations/HtmlTable.php index 21116fefb92..42c0798fbfe 100644 --- a/plugins/CoreVisualizations/Visualizations/HtmlTable.php +++ b/plugins/CoreVisualizations/Visualizations/HtmlTable.php @@ -225,9 +225,10 @@ private function calculateTotalPercentages() foreach ($this->dataTable->getRows() as $row) { foreach ($this->report->getMetrics() as $column => $translation) { - $indexColumn = $columnNamesToIndices[$column]; // TODO: This might fail for goal specific columns... + // Try to check the column by it's index (not possible for all metrics, like custom columns) + $indexColumn = !empty($columnNamesToIndices[$column]) ? $columnNamesToIndices[$column] : null; - $value = $row->getColumn($indexColumn) ?: $row->getColumn($column) ?: 0; + $value = (($indexColumn && $row->getColumn($indexColumn)) ? $row->getColumn($indexColumn) : $row->getColumn($column)) ?: 0; if ($column == 'label') { continue; } diff --git a/plugins/Dashboard/tests/UI/expected-screenshots/Dashboard_loaded_token_auth.png b/plugins/Dashboard/tests/UI/expected-screenshots/Dashboard_loaded_token_auth.png index 53eccc51ba8..75623864d3f 100644 --- a/plugins/Dashboard/tests/UI/expected-screenshots/Dashboard_loaded_token_auth.png +++ b/plugins/Dashboard/tests/UI/expected-screenshots/Dashboard_loaded_token_auth.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea8954c9b69f59fe06edb66b9959f3b826786f58f84367bc6a0bab15f67715d2 -size 714817 +oid sha256:8135a587491cf93c53374854053cb54776d8666611b3e6869578edcbd29a4bb7 +size 714834 diff --git a/plugins/Dashboard/tests/UI/expected-screenshots/Dashboard_removed.png b/plugins/Dashboard/tests/UI/expected-screenshots/Dashboard_removed.png index 53eccc51ba8..75623864d3f 100644 --- a/plugins/Dashboard/tests/UI/expected-screenshots/Dashboard_removed.png +++ b/plugins/Dashboard/tests/UI/expected-screenshots/Dashboard_removed.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ea8954c9b69f59fe06edb66b9959f3b826786f58f84367bc6a0bab15f67715d2 -size 714817 +oid sha256:8135a587491cf93c53374854053cb54776d8666611b3e6869578edcbd29a4bb7 +size 714834 diff --git a/plugins/Live/Visualizations/VisitorLog.php b/plugins/Live/Visualizations/VisitorLog.php index d6c3cd08a22..937bfec893e 100644 --- a/plugins/Live/Visualizations/VisitorLog.php +++ b/plugins/Live/Visualizations/VisitorLog.php @@ -260,11 +260,14 @@ private static function mergeRefreshes(array $actionGroups) } $action = $group['pageviewAction']; + $actionUrl = !empty($action['url']) ? $action['url'] : ''; + $actionTitle = !empty($action['pageTitle']) ? $action['pageTitle'] : ''; $lastActionGroup = $actionGroups[$previousId]; + $lastGroupUrl = !empty($lastActionGroup['pageviewAction']['url']) ? $lastActionGroup['pageviewAction']['url'] : ''; + $lastGroupTitle = !empty($lastActionGroup['pageviewAction']['pageTitle']) ? $lastActionGroup['pageviewAction']['pageTitle'] : ''; $isLastGroupEmpty = empty($actionGroups[$previousId]['actionsOnPage']); - $isPageviewActionSame = $lastActionGroup['pageviewAction']['url'] == $action['url'] - && $lastActionGroup['pageviewAction']['pageTitle'] == $action['pageTitle']; + $isPageviewActionSame = $lastGroupUrl == $actionUrl && $lastGroupTitle == $actionTitle; // if the current action has the same url/action name as the last, merge w/ the last action group if ($isLastGroupEmpty diff --git a/plugins/Live/javascripts/visitorProfile.js b/plugins/Live/javascripts/visitorProfile.js index 021908f2e87..c5335618877 100644 --- a/plugins/Live/javascripts/visitorProfile.js +++ b/plugins/Live/javascripts/visitorProfile.js @@ -71,14 +71,27 @@ var self = this, $element = this.$element; - $element.on('click', '.visitor-profile-close', function (e) { - e.preventDefault(); - try { - $element.tooltip('destroy'); - } catch (e) {} - broadcast.propagateNewPopoverParameter(false); - return false; - }); + // if there are no popover params in stack, simply close the popover + if (!broadcast.popoverParamStack.length) { + $element.on('click', '.visitor-profile-close', function (e) { + e.preventDefault(); + try { + $element.tooltip('destroy'); + } catch (e) { + } + Piwik_Popover.close(); + }); + } else { + $element.on('click', '.visitor-profile-close', function (e) { + e.preventDefault(); + try { + $element.tooltip('destroy'); + } catch (e) { + } + broadcast.propagateNewPopoverParameter(false); + return false; + }); + } $element.on('click', '.visitor-profile-toggle-actions', function (e) { e.preventDefault(); diff --git a/plugins/Morpheus/icons b/plugins/Morpheus/icons index d22c22848b3..44add4357b4 160000 --- a/plugins/Morpheus/icons +++ b/plugins/Morpheus/icons @@ -1 +1 @@ -Subproject commit d22c22848b3b8f19a031f396745fcaeaefb1abcd +Subproject commit 44add4357b4394777e53ecea987205cb70eee28b diff --git a/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_delete_visit_cancelled.png b/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_delete_visit_cancelled.png index 2042ab5b233..d47260c242a 100644 --- a/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_delete_visit_cancelled.png +++ b/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_delete_visit_cancelled.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b65fb3d081c59a5d3925d2cf02e4ba233731e4bac89f77567362be0f31fb5603 -size 544457 +oid sha256:d84b46c2698d65715ea9030081117abc91fbbe8e82ebf8ae6fddf59812861574 +size 578891 diff --git a/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_delete_visit_unconfirmed.png b/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_delete_visit_unconfirmed.png index f86a2bb2907..4aff2f54ba2 100644 --- a/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_delete_visit_unconfirmed.png +++ b/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_delete_visit_unconfirmed.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:85f5a6e7f0bf43cad861da1fd9a1ae7ceccda110091b25b023ddc0408f065151 -size 9192 +oid sha256:e41e6690c96286c93a7c76fc81d2dedeb49e14391c7022701412bbd23a162087 +size 9193 diff --git a/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_enrich_segment_by_ip.png b/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_enrich_segment_by_ip.png index 2042ab5b233..d226aeba916 100644 --- a/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_enrich_segment_by_ip.png +++ b/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_enrich_segment_by_ip.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b65fb3d081c59a5d3925d2cf02e4ba233731e4bac89f77567362be0f31fb5603 -size 544457 +oid sha256:339c7870fa7f06734f81ecffd150be3d6f65ddfe9f9e81121c5ebecb24102c62 +size 579155 diff --git a/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_uncheck_one_visit.png b/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_uncheck_one_visit.png index a04da828f74..d47260c242a 100644 --- a/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_uncheck_one_visit.png +++ b/plugins/PrivacyManager/tests/UI/expected-screenshots/PrivacyManager_gdpr_tools_uncheck_one_visit.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5bcb002145fd55f0987253acd06ca8d494174c3820ef91812c2d04fb760ba1db -size 544528 +oid sha256:d84b46c2698d65715ea9030081117abc91fbbe8e82ebf8ae6fddf59812861574 +size 578891 diff --git a/plugins/Referrers/tests/System/ApiTest.php b/plugins/Referrers/tests/System/ApiTest.php index be8ad2c2e64..ffcd06a46a4 100644 --- a/plugins/Referrers/tests/System/ApiTest.php +++ b/plugins/Referrers/tests/System/ApiTest.php @@ -220,24 +220,24 @@ public function test_referrersReport_sameUrlButDifferentProtocol_flat() $t = Fixture::getTracker($idSite, $dateTime . ' 00:01:02', $defaultInit = true); // track an HTTPS request - $t->setUrlReferrer('https://t.umblr.com/'); + $t->setUrlReferrer('https://somewebsite.com/'); $t->setUrl('http://piwik.net/'); $t->doTrackPageView('My Title'); // track an HTTP request $t->setForceNewVisit(true); - $t->setUrlReferrer('http://t.umblr.com/'); + $t->setUrlReferrer('http://somewebsite.com/'); $t->setUrl('http://piwik.net/'); $t->doTrackPageView('My Title'); /** @var DataTable $visits */ $visits = Request::processRequest( - 'Referrers.getWebsites', + 'Referrers.getWebsites', array('idSite' => $idSite, 'period' => 'day', 'date' => $dateTime, 'flat' => 1) ); $firstRow = $visits->getFirstRow(); - $this->assertEquals('t.umblr.com/index', $firstRow->getColumn('label')); + $this->assertEquals('somewebsite.com/index', $firstRow->getColumn('label')); $this->assertEquals(2, $firstRow->getColumn('nb_visits')); } @@ -248,19 +248,19 @@ public function test_referrersReport_sameUrlButDifferentProtocol_hierarchical() $t = Fixture::getTracker($idSite, $dateTime . ' 00:01:02', $defaultInit = true); // track an HTTPS request - $t->setUrlReferrer('https://t.umblr.com/'); + $t->setUrlReferrer('https://somewebsite.com/'); $t->setUrl('http://piwik.net/'); $t->doTrackPageView('My Title'); // track an HTTP request $t->setForceNewVisit(true); - $t->setUrlReferrer('http://t.umblr.com/'); + $t->setUrlReferrer('http://somewebsite.com/'); $t->setUrl('http://piwik.net/'); $t->doTrackPageView('My Title'); /** @var DataTable $visits */ $visits = Request::processRequest( - 'Referrers.getWebsites', + 'Referrers.getWebsites', array('idSite' => $idSite, 'period' => 'day', 'date' => $dateTime) ); diff --git a/plugins/SitesManager/templates/_trackingCodeEmail.twig b/plugins/SitesManager/templates/_trackingCodeEmail.twig index 156eef55307..be2a0e23629 100644 --- a/plugins/SitesManager/templates/_trackingCodeEmail.twig +++ b/plugins/SitesManager/templates/_trackingCodeEmail.twig @@ -14,6 +14,7 @@ WordPress: https://matomo.org/faq/new-to-piwik/how-do-i-install-the-matomo-track Squarespace: https://matomo.org/faq/new-to-piwik/how-do-i-integrate-matomo-with-squarespace-website/ Wix: https://matomo.org/faq/new-to-piwik/how-do-i-install-the-matomo-analytics-tracking-code-on-wix/ SharePoint: https://matomo.org/faq/how-to-install/faq_19424/ +Joomla: https://matomo.org/faq/new-to-piwik/how-do-i-install-the-matomo-analytics-tracking-code-on-joomla/ ** {{ 'SitesManager_Integrations'|translate }} {{ 'CoreAdminHome_JSTrackingIntro3a'|translate('', '') }} diff --git a/plugins/SitesManager/templates/siteWithoutData.twig b/plugins/SitesManager/templates/siteWithoutData.twig index f4e13772e49..19e831c00e9 100644 --- a/plugins/SitesManager/templates/siteWithoutData.twig +++ b/plugins/SitesManager/templates/siteWithoutData.twig @@ -48,6 +48,7 @@ | Squarespace | Wix | SharePoint + | Joomla

{{ 'SitesManager_ExtraInformationNeeded'|translate }} diff --git a/plugins/UserCountry/Controller.php b/plugins/UserCountry/Controller.php index 84e7fd2376d..97b5eadf924 100644 --- a/plugins/UserCountry/Controller.php +++ b/plugins/UserCountry/Controller.php @@ -70,6 +70,9 @@ public function adminIndex() } $view->isThereWorkingProvider = $isThereWorkingProvider; + $view->notUsingGeoIpPlugin = !Manager::getInstance()->isPluginActivated('GeoIp2') + && !Manager::getInstance()->isPluginActivated('GeoIp'); + // if using either the Apache, Nginx or PECL module, they are working and there are no databases // in misc, then the databases are located outside of Piwik, so we cannot update them $view->showGeoIPUpdateSection = true; @@ -80,6 +83,9 @@ public function adminIndex() ) { $view->showGeoIPUpdateSection = false; } + if ($view->notUsingGeoIpPlugin) { + $view->showGeoIPUpdateSection = false; + } $view->isInternetEnabled = SettingsPiwik::isInternetEnabled(); diff --git a/plugins/UserCountry/lang/el.json b/plugins/UserCountry/lang/el.json index b282ebbdd75..e23f0f9a9da 100644 --- a/plugins/UserCountry/lang/el.json +++ b/plugins/UserCountry/lang/el.json @@ -98,6 +98,7 @@ "UpdaterScheduledForNextRun": "Είναι προγραμματισμένο για εκτέλεση κατά την εκτέλεση του επόμενου archive.php από το cron.", "UpdaterWasLastRun": "Το πρόγραμμα ενημέρωσης εκτελέστηκε τελευταία στις %s.", "UpdaterWillRunNext": "Είναι προγραμματισμένο για εκτέλεση στις %s.", - "WidgetLocation": "Τοποθεσία Επισκέπτη" + "WidgetLocation": "Τοποθεσία Επισκέπτη", + "InstallGeoIp2": "Το Matomo προτείνει τη χρήση των βάσεων %1$sdbip%2$s, αλλά αυτό απαιτεί τη χρήση του πρόσθετου GeoIp2. Αν το εγκαταστήσετε και το ενεργοποιήσετε (που ενδεχομένως να χρειαστεί μια μακρόχρονη διαδικασία), θα μπορέσετε να ξεκινήσετε τη χρήση των βάσεων %1$sdbip%2$s. (Αγνοήστε το παρόν αν χρησιμοποιείτε ήδη τρίτο πρόσθετο που παρέχει τη δική του λειτουργικότητα για γεωτοποθεσία.)" } } \ No newline at end of file diff --git a/plugins/UserCountry/lang/en.json b/plugins/UserCountry/lang/en.json index a707f363e8f..852293b84d1 100644 --- a/plugins/UserCountry/lang/en.json +++ b/plugins/UserCountry/lang/en.json @@ -98,6 +98,7 @@ "UpdaterScheduledForNextRun": "It is scheduled to run during the next cron core:archive command execution.", "UpdaterWasLastRun": "The updater was last run on %s.", "UpdaterWillRunNext": "It is next scheduled to run on %s.", - "WidgetLocation": "Visitor Location" + "WidgetLocation": "Visitor Location", + "InstallGeoIp2": "Matomo recommends using the %1$sdbip%2$s databases, but this requires using the GeoIp2 plugin. If you install and activate it (which will require a possibly long running update), you will be able to get started using %1$sdbip%2$s databases. (Ignore this if you are using a third party plugin that provides it's own geolocation functionality.)" } } \ No newline at end of file diff --git a/plugins/UserCountry/lang/es-ar.json b/plugins/UserCountry/lang/es-ar.json index 40cc3a2f781..d2f268ea3b3 100644 --- a/plugins/UserCountry/lang/es-ar.json +++ b/plugins/UserCountry/lang/es-ar.json @@ -98,6 +98,7 @@ "UpdaterScheduledForNextRun": "Está programado para ejecutarse durante la próxima ejecución de comando cron \"core:archive\".", "UpdaterWasLastRun": "El actualizador se ejecutó por última vez: %s.", "UpdaterWillRunNext": "Está programado para ejecutarse: %s.", - "WidgetLocation": "Ubicación del visitante" + "WidgetLocation": "Ubicación del visitante", + "InstallGeoIp2": "Matomo recomienda usar las bases de datos de %1$sdbip%2$s, pero requiere usar el plugin GeoIP2. Si lo instalás y activás (el cual probablemente requiera una larga actualización), vas a poder usar las bases de datos de %1$sdbip%2$s (ignorá esto si ya estás usando un plugin de terceros que ofrece su propia función de geolocalización)." } } \ No newline at end of file diff --git a/plugins/UserCountry/lang/pt-br.json b/plugins/UserCountry/lang/pt-br.json index 5f44beee1b5..3927a686291 100644 --- a/plugins/UserCountry/lang/pt-br.json +++ b/plugins/UserCountry/lang/pt-br.json @@ -98,6 +98,7 @@ "UpdaterScheduledForNextRun": "Está programado para ser executado durante a próxima execução do cron job archive.php", "UpdaterWasLastRun": "O atualizador foi executado pela última vez em %s.", "UpdaterWillRunNext": "A próxima execução está programada para ser executada em %s.", - "WidgetLocation": "Localização dos visitantes" + "WidgetLocation": "Localização dos visitantes", + "InstallGeoIp2": "O Matomo recomenda usar as bases de dados %1$sdbip%2$s, mas isto requer usar o plugin GeoIp2. Se você instalá-lo e ativá-lo (o que deve possivelmente exigir uma atualização de longa duração), você poderá começar a usar bases de dados %1$sdbip%2$s. (Ignore isto se você estiver usando um plugin de terceiro que fornece sua própria funcionalidade de geolocalização.)" } } \ No newline at end of file diff --git a/plugins/UserCountry/lang/sq.json b/plugins/UserCountry/lang/sq.json index 779a1d6bd90..80ea3839f4f 100644 --- a/plugins/UserCountry/lang/sq.json +++ b/plugins/UserCountry/lang/sq.json @@ -98,6 +98,7 @@ "UpdaterScheduledForNextRun": "Është vënë në plan të xhirojë gjatë përmbushjes së ardhshme të urdhrit cron core:archive.", "UpdaterWasLastRun": "Përditësuesi u xhirua së fundi më %s.", "UpdaterWillRunNext": "Është planifikuar të xhirojë sërish më %s.", - "WidgetLocation": "Vend Vizitori" + "WidgetLocation": "Vend Vizitori", + "InstallGeoIp2": "Matomo rekomandon përdorimin e bazave të të dhënave %1$sdbip%2$s, por kjo lyp përdorimin e shtojcës GeoIp2. Nëse e instaloni dhe e aktivizoni (çka ka shumë mundësi se do të kërkojë një përditësim që zgjat ca), do të jeni në gjendje të filloni të përdorni baza të dhënash %1$sdbip%2$s. (Shpërfilleni këtë , nëse përdorni një shtojcë pale të tretë që për gjeovendëzim sjell funksione të vetat.)" } } \ No newline at end of file diff --git a/plugins/UserCountry/lang/tr.json b/plugins/UserCountry/lang/tr.json index 5c5e6fb0cf7..ef27d981dca 100644 --- a/plugins/UserCountry/lang/tr.json +++ b/plugins/UserCountry/lang/tr.json @@ -98,6 +98,7 @@ "UpdaterScheduledForNextRun": "core:archive komutunun yürütüleceği zamanlanmış görevin bir sonraki çalışmasında güncellenecek.", "UpdaterWasLastRun": "Güncelleyici en son %s zamanında çalıştı.", "UpdaterWillRunNext": "Zamanlanmış görev %s zamanında çalışacak.", - "WidgetLocation": "Ziyaretçi Konumu" + "WidgetLocation": "Ziyaretçi Konumu", + "InstallGeoIp2": "Matomo %1$sdbip%2$s veritabanlarının kullanılmasını önerir. Ancak bunun için GeoIp2 uygulama eki gereklidir. Bu uygulama ekini kurup etkinleştirdiyseniz (büyük olasılıkla uzun sürecek bir güncelleme yapılır), %1$sdbip%2$s veritabanlarını kullanmaya başlayabilirsiniz (kendi coğrafi konum özelliğini sunan bir üçüncü taraf uygulama eki kullanıyorsanız bunu yok sayabilirsiniz)." } } \ No newline at end of file diff --git a/plugins/UserCountry/templates/adminIndex.twig b/plugins/UserCountry/templates/adminIndex.twig index ac9e2c1f593..f0a32da5887 100644 --- a/plugins/UserCountry/templates/adminIndex.twig +++ b/plugins/UserCountry/templates/adminIndex.twig @@ -16,6 +16,7 @@ {% if not isThereWorkingProvider %}

{{ 'UserCountry_HowToSetupGeoIP'|translate }}

+ {% if dbipLiteUrl|default is not empty %}

{{ 'UserCountry_HowToSetupGeoIPIntro'|translate }}

  • {{ 'UserCountry_HowToSetupGeoIP_Step1'|translate('','','','')|raw }}
  • @@ -23,6 +24,9 @@
  • {{ 'UserCountry_HowToSetupGeoIP_Step3'|translate('','','','')|raw }}
  • {{ 'UserCountry_HowToSetupGeoIP_Step4'|translate }}
+ {% else %} +

{{ 'UserCountry_InstallGeoIp2'|translate('','')|raw }}

+ {% endif %}

 

{% endif %} @@ -127,7 +131,7 @@ {% endif %} -{% if isInternetEnabled %} +{% if isInternetEnabled and not notUsingGeoIpPlugin %}
@@ -161,9 +165,14 @@
+ {% if dbipLiteUrl|default is not empty %} + {% set downloadingDbLink %}{{ dbipLiteFilename }}{% endset %} + {% else %} + {% set downloadingDbLink = '' %} + {% endif %}
'~dbipLiteFilename~'') ~ '...')|json_encode }}" + label="{{ ('UserCountry_DownloadingDb'|translate(downloadingDbLink) ~ '...')|json_encode }}" progress="locationUpdater.progressFreeDownload">
diff --git a/plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.html b/plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.html index acb0b5cf792..4eee7fe20e0 100644 --- a/plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.html +++ b/plugins/UsersManager/angularjs/capabilities-edit/capabilities-edit.component.html @@ -13,7 +13,7 @@ diff --git a/tests/PHPUnit/Framework/Fixture.php b/tests/PHPUnit/Framework/Fixture.php index 88b057f4e16..1150444db31 100644 --- a/tests/PHPUnit/Framework/Fixture.php +++ b/tests/PHPUnit/Framework/Fixture.php @@ -15,6 +15,7 @@ use Piwik\Auth\Password; use Matomo\Cache\Backend\File; use Piwik\Cache as PiwikCache; +use Piwik\CliMulti\CliPhp; use Piwik\Common; use Piwik\Config; use Piwik\Container\StaticContainer; @@ -145,6 +146,20 @@ protected static function getPythonBinary() return 'python'; } + public static function getCliCommandBase() + { + $cliPhp = new CliPhp(); + $php = $cliPhp->findPhpBinary(); + + $command = $php . ' ' . PIWIK_INCLUDE_PATH .'/tests/PHPUnit/proxy/console '; + + if (!empty($_SERVER['HTTP_HOST'])) { + $command .= '--matomo-domain=' . $_SERVER['HTTP_HOST']; + } + + return $command; + } + public static function getTestRootUrl() { return self::getRootUrl() . 'tests/PHPUnit/proxy/'; diff --git a/tests/PHPUnit/Framework/Mock/TestConfig.php b/tests/PHPUnit/Framework/Mock/TestConfig.php index 3676163e0d3..7fe0302e11a 100644 --- a/tests/PHPUnit/Framework/Mock/TestConfig.php +++ b/tests/PHPUnit/Framework/Mock/TestConfig.php @@ -58,9 +58,18 @@ public function setTestEnvironment() // Ensure local mods do not affect tests if (empty($pathGlobal)) { + $general = $chain->getFrom($this->getLocalPath(), 'General'); + $instanceId = isset($general['instance_id']) ? $general['instance_id'] : null; + $chain->set('Debug', $chain->getFrom($this->getGlobalPath(), 'Debug')); $chain->set('mail', $chain->getFrom($this->getGlobalPath(), 'mail')); - $chain->set('General', $chain->getFrom($this->getGlobalPath(), 'General')); + + $globalGeneral = $chain->getFrom($this->getGlobalPath(), 'General'); + if ($instanceId) { + $globalGeneral['instance_id'] = $instanceId; + } + $chain->set('General', $globalGeneral); + $chain->set('Segments', $chain->getFrom($this->getGlobalPath(), 'Segments')); $chain->set('Tracker', $chain->getFrom($this->getGlobalPath(), 'Tracker')); $chain->set('Deletelogs', $chain->getFrom($this->getGlobalPath(), 'Deletelogs')); diff --git a/tests/PHPUnit/System/ConsoleTest.php b/tests/PHPUnit/System/ConsoleTest.php index 939cfee6acc..9221fa8530a 100644 --- a/tests/PHPUnit/System/ConsoleTest.php +++ b/tests/PHPUnit/System/ConsoleTest.php @@ -8,9 +8,13 @@ namespace Piwik\Tests\System; +use Piwik\CliMulti\CliPhp; +use Piwik\Config; use Piwik\Container\StaticContainer; +use Piwik\Development; use Piwik\Plugin\ConsoleCommand; use Piwik\Plugins\Monolog\Handler\FailureLogMessageDetector; +use Piwik\Tests\Framework\Fixture; use Psr\Log\LoggerInterface; use Monolog\Logger; use Symfony\Component\Console\Input\InputInterface; @@ -51,6 +55,56 @@ public function execute(InputInterface $input, OutputInterface $output) } } +class TestCommandWithFatalError extends ConsoleCommand +{ + public function configure() + { + parent::configure(); + + $this->setName('test-command-with-fatal-error'); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + try { + \Piwik\ErrorHandler::pushFatalErrorBreadcrumb(static::class); + + $this->executeImpl($input, $output); + } finally { + \Piwik\ErrorHandler::popFatalErrorBreadcrumb(); + } + } + + public function executeImpl(InputInterface $input, OutputInterface $output) + { + try { + \Piwik\ErrorHandler::pushFatalErrorBreadcrumb(static::class, []); + + $val = ""; + while (true) { + $val .= str_repeat("*", 1024 * 1024 * 1024); + } + } finally { + \Piwik\ErrorHandler::popFatalErrorBreadcrumb(); + } + } +} + +class TestCommandWithException extends ConsoleCommand +{ + public function configure() + { + parent::configure(); + + $this->setName('test-command-with-exception'); + } + + public function execute(InputInterface $input, OutputInterface $output) + { + throw new \Exception('test error'); + } +} + class ConsoleTest extends ConsoleCommandTestCase { public function setUp() @@ -89,12 +143,90 @@ public function test_Console_ReturnsCorrectExitCode_IfCommandDoesNotEmitAnything $this->assertEquals(0, $exitCode); } + public function test_Console_handlesFatalErrorsCorrectly() + { + $command = Fixture::getCliCommandBase(); + $command .= ' test-command-with-fatal-error'; + $command .= ' 2>&1'; + + $output = shell_exec($command); + $output = $this->normalizeOutput($output); + + $expected = << 1, + 'message' => 'Allowed memory size of X bytes exhausted (tried to allocate X bytes)', + 'file' => '/tests/PHPUnit/System/ConsoleTest.php', + 'line' => 85, + 'backtrace' => ' on /tests/PHPUnit/System/ConsoleTest.php(85) +#0 /tests/PHPUnit/System/ConsoleTest.php(72): Piwik\\\\Tests\\\\System\\\\TestCommandWithFatalError->executeImpl() +#1 /vendor/symfony/console/Symfony/Component/Console/Command/Command.php(257): Piwik\\\\Tests\\\\System\\\\TestCommandWithFatalError->execute() +', +)) +END; + + $this->assertEquals($expected, $output); + } + + public function test_Console_handlesExceptionsCorrectly() + { + $command = Fixture::getCliCommandBase(); + $command .= ' test-command-with-exception'; + $command .= ' 2>&1'; + + $output = shell_exec($command); + $output = $this->normalizeOutput($output); + + $expected = <<assertEquals($expected, $output); + } + public static function provideContainerConfigBeforeClass() { return [ 'log.handlers' => [\DI\get(FailureLogMessageDetector::class)], LoggerInterface::class => \DI\object(Logger::class) ->constructor('piwik', \DI\get('log.handlers'), \DI\get('log.processors')), + + 'observers.global' => \DI\add([ + ['Console.filterCommands', function (&$commands) { + $commands[] = TestCommandWithFatalError::class; + $commands[] = TestCommandWithException::class; + }], + + ['Request.dispatch', function ($module, $action) { + if ($module === 'CorePluginsAdmin' && $action === 'safemode') { + print "*** IN SAFEMODE ***\n"; // will appear in output + } + }], + ]), ]; } + + private function normalizeOutput($output) + { + $output = str_replace(PIWIK_INCLUDE_PATH, '', $output); + $output = preg_replace('/[0-9]+ bytes/', 'X bytes', $output); + return $output; + } } \ No newline at end of file diff --git a/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getSegmentsMetadata.xml b/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getSegmentsMetadata.xml index effff1c3821..d3d5264cab3 100644 --- a/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getSegmentsMetadata.xml +++ b/tests/PHPUnit/System/expected/test_apiGetReportMetadata__API.getSegmentsMetadata.xml @@ -106,7 +106,7 @@ Visitors Device brand deviceBrand - 3Q, 4Good, Acer, Advan, Advance, AGM, Ainol, Airness, Airties, AIS, Aiwa, Akai, Alba, Alcatel, AllCall, Allview, Allwinner, Altech UEC, altron, Amazon, AMGOO, Amoi, ANS, Apple, Archos, Arian Space, Ark, Arnova, ARRIS, Ask, Assistant, Asus, Audiovox, AVH, Avvio, Axxion, Azumi Mobile, BangOlufsen, Barnes & Noble, BBK, BDF, Becker, Beeline, Beetel, BenQ, BenQ-Siemens, BGH, Bird, Bitel, Black Fox, Blackview, Blaupunkt, Blu, Bluboo, Bluegood, Bmobile, bogo, Boway, bq, Bravis, Brondi, Bush, CAGI, Capitel, Captiva, Carrefour, Casio, Casper, Cat, Celkon, Changhong, Cherry Mobile, China Mobile, Clarmin, CnM, Coby Kyros, Comio, Compal, Compaq, ComTrade Tesla, Concord, ConCorde, Condor, Coolpad, Cowon, CreNova, Crescent, Cricket, Crius Mea, Crosscall, Cube, CUBOT, CVTE, Cyrus, Danew, Datang, Datsun, Dbtel, Dell, Denver, Desay, DEXP, Dialog, Dicam, Digi, Digicel, Digiland, Digma, DMM, DNS, DoCoMo, Doogee, Doov, Dopod, Doro, Dune HD, E-Boda, E-tel, Easypix, EBEST, Echo Mobiles, ECS, EE, EKO, Eks Mobility, Elenberg, Elephone, Energizer, Energy Sistem, Ergo, Ericsson, Ericy, Essential, Essentielb, Eton, eTouch, Etuline, Eurostar, Evercoss, Evertek, Evolio, Evolveo, EvroMedia, Explay, Extrem, Ezio, Ezze, Fairphone, Famoco, Fengxiang, FiGO, FinePower, Fly, FNB, Fondi, FORME, Forstar, Foxconn, Freetel, Fujitsu, G-TiDE, Garmin-Asus, Gateway, Gemini, General Mobile, Geotel, Ghia, Gigabyte, Gigaset, Ginzzu, Gionee, GOCLEVER, Goly, GoMobile, Google, Gradiente, Grape, Grundig, Hafury, Haier, HannSpree, Hasee, Hi-Level, Highscreen, Hisense, Hoffmann, Homtom, Hoozo, Hosin, HP, HTC, Huawei, Humax, Hyrican, Hyundai, i-Joy, i-mate, i-mobile, iBall, iBerry, IconBIT, iHunt, Ikea, iKoMo, iLA, IMO Mobile, Impression, iNew, Infinix, InFocus, Inkti, InnJoo, Innostream, Inoi, INQ, Insignia, Intek, Intex, Inverto, iOcean, iPro, Irbis, iRola, iTel, iView, iZotron, JAY-Tech, Jiayu, Jolla, Just5, K-Touch, Kaan, Kalley, Karbonn, Kazam, KDDI, Kempler & Strauss, Keneksi, Kiano, Kingsun, Kocaso, Kodak, Kogan, Komu, Konka, Konrow, Koobee, KOPO, Koridy, KRONO, Krüger&Matz, KT-Tech, Kumai, Kyocera, LAIQ, Land Rover, Landvo, Lanix, Lark, Lava, LCT, Leagoo, Ledstar, LeEco, Lemhoov, Lenco, Lenovo, Leotec, Le Pan, Lephone, Lexand, Lexibook, LG, Lingwin, Loewe, Logicom, Lumus, LYF, M.T.T., M4tel, Majestic, Manta Multimedia, Masstel, Maxwest, Maze, Mecer, Mecool, Mediacom, MediaTek, Medion, MEEG, MegaFon, Meitu, Meizu, Memup, Metz, MEU, MicroMax, Microsoft, Mio, Miray, Mitsubishi, MIXC, MLLED, Mobicel, Mobiistar, Mobiola, Mobistel, Modecom, Mofut, Motorola, Movic, Mpman, MSI, MTC, MTN, MYFON, MyPhone, Myria, MyWigo, Navon, NEC, Neffos, Netgear, NeuImage, Newgen, NEXBOX, Nexian, Nextbit, NextBook, NGM, Nikon, Nintendo, NOA, Noain, Nobby, Noblex, Nokia, Nomi, Nous, NUU Mobile, Nvidia, NYX Mobile, O+, O2, Obi, Odys, Onda, OnePlus, OPPO, Opsson, Orange, Ouki, OUYA, Overmax, Oysters, Palm, Panacom, Panasonic, Pantech, PCBOX, PCD, PCD Argentina, PEAQ, Pentagram, Philips, phoneOne, Pioneer, Pixus, Ployer, Plum, Point of View, Polaroid, PolyPad, Polytron, Pomp, Positivo, PPTV, Prestigio, Primepad, ProScan, PULID, Q-Touch, Qilive, QMobile, Qtek, Quantum, Quechua, R-TV, Ramos, RCA Tablets, Readboy, Rikomagic, RIM, Rinno, Ritmix, Riviera, Roadrover, Rokit, Roku, Rombica, Ross&Moor, Rover, RoverPad, RT Project, Safaricom, Sagem, Samsung, Sanei, Santin BiTBiZ, Sanyo, Savio, Sega, Selevision, Selfix, Sencor, Sendo, Senseit, Senwa, SFR, Sharp, Shuttle, Siemens, Sigma, Silent Circle, Simbans, Sky, Skyworth, Smart, Smartfren, Smartisan, Softbank, Sonim, Sony, Sony Ericsson, Spice, Star, Starway, STF Mobile, STK, Stonex, Storex, Sumvision, SunVan, SuperSonic, Supra, SWISSMOBILITY, Symphony, Syrox, T-Mobile, TB Touch, TCL, TechniSat, TechnoTrend, TechPad, Teclast, Tecno Mobile, Telefunken, Telego, Telenor, Telit, Tesco, Tesla, teXet, ThL, Thomson, TIANYU, Timovi, TiPhone, Tolino, Tooky, Top House, Toplux, Toshiba, Touchmate, TrekStor, Trevi, True, Tunisie Telecom, Turbo, Turbo-X, TVC, U.S. Cellular, Uhappy, Ulefone, UMIDIGI, Unimax, Uniscope, Unknown, Unnecto, Unonu, Unowhy, UTOK, UTStarcom, Vastking, Venso, Verizon, Vernee, Vertex, Vertu, Verykool, Vestel, VGO TEL, Videocon, Videoweb, ViewSonic, Vinsoc, Vitelcom, Vivax, Vivo, Vizio, VK Mobile, Vodafone, Vonino, Vorago, Voto, Voxtel, Vulcan, Walton, Web TV, Weimei, WellcoM, Wexler, Wiko, Wileyfox, Wink, Wolder, Wolfgang, Wonu, Woo, Woxter, X-TIGI, X-View, Xiaolajiao, Xiaomi, Xion, Xolo, Yandex, Yarvik, Yes, Yezz, Ytone, Yu, Yuandao, Yusun, Zeemi, Zen, Zenek, Zonda, Zopo, ZTE, Zuum, Zync, ZYQ, öwn + 3Q, 4Good, Acer, Advan, Advance, AGM, Ainol, Airness, Airties, AIS, Aiwa, Akai, Alba, Alcatel, AllCall, Allview, Allwinner, Altech UEC, altron, Amazon, AMGOO, Amoi, ANS, Apple, Archos, Arian Space, Ark, Arnova, ARRIS, Ask, Assistant, Asus, Audiovox, AVH, Avvio, Axxion, Azumi Mobile, BangOlufsen, Barnes & Noble, BBK, BDF, Becker, Beeline, Beetel, BenQ, BenQ-Siemens, BGH, Bird, Bitel, Black Fox, Blackview, Blaupunkt, Blu, Bluboo, Bluegood, Bmobile, bogo, Boway, bq, Bravis, Brondi, Bush, CAGI, Capitel, Captiva, Carrefour, Casio, Casper, Cat, Celkon, Changhong, Cherry Mobile, China Mobile, Clarmin, CnM, Coby Kyros, Comio, Compal, Compaq, ComTrade Tesla, Concord, ConCorde, Condor, Coolpad, Cowon, CreNova, Crescent, Cricket, Crius Mea, Crosscall, Cube, CUBOT, CVTE, Cyrus, Danew, Datang, Datsun, Dbtel, Dell, Denver, Desay, DEXP, Dialog, Dicam, Digi, Digicel, Digiland, Digma, DMM, DNS, DoCoMo, Doogee, Doov, Dopod, Doro, Dune HD, E-Boda, E-tel, Easypix, EBEST, Echo Mobiles, ECS, EE, EKO, Eks Mobility, Elenberg, Elephone, Energizer, Energy Sistem, Ergo, Ericsson, Ericy, Essential, Essentielb, Eton, eTouch, Etuline, Eurostar, Evercoss, Evertek, Evolio, Evolveo, EvroMedia, Explay, Extrem, Ezio, Ezze, Fairphone, Famoco, Fengxiang, FiGO, FinePower, Fly, FNB, Fondi, FORME, Forstar, Foxconn, Freetel, Fujitsu, G-TiDE, Garmin-Asus, Gateway, Gemini, General Mobile, Geotel, Ghia, Gigabyte, Gigaset, Ginzzu, Gionee, GOCLEVER, Goly, GoMobile, Google, Gradiente, Grape, Grundig, Hafury, Haier, HannSpree, Hasee, Hi-Level, Highscreen, Hisense, Hoffmann, Homtom, Hoozo, Hosin, HP, HTC, Huawei, Humax, Hyrican, Hyundai, i-Joy, i-mate, i-mobile, iBall, iBerry, IconBIT, iHunt, Ikea, iKoMo, iLA, IMO Mobile, Impression, iNew, Infinix, InFocus, Inkti, InnJoo, Innostream, Inoi, INQ, Insignia, Intek, Intex, Inverto, iOcean, iPro, Irbis, iRola, iTel, iView, iZotron, JAY-Tech, Jiayu, Jolla, Just5, K-Touch, Kaan, Kalley, Karbonn, Kazam, KDDI, Kempler & Strauss, Keneksi, Kiano, Kingsun, Kocaso, Kodak, Kogan, Komu, Konka, Konrow, Koobee, KOPO, Koridy, KRONO, Krüger&Matz, KT-Tech, Kumai, Kyocera, LAIQ, Land Rover, Landvo, Lanix, Lark, Lava, LCT, Leagoo, Ledstar, LeEco, Lemhoov, Lenco, Lenovo, Leotec, Le Pan, Lephone, Lexand, Lexibook, LG, Lingwin, Loewe, Logicom, Lumus, LYF, M.T.T., M4tel, Majestic, Manta Multimedia, Masstel, Maxwest, Maze, Mecer, Mecool, Mediacom, MediaTek, Medion, MEEG, MegaFon, Meitu, Meizu, Memup, Metz, MEU, MicroMax, Microsoft, Mio, Miray, Mitsubishi, MIXC, MLLED, Mobicel, Mobiistar, Mobiola, Mobistel, Modecom, Mofut, Motorola, Movic, Mpman, MSI, MTC, MTN, MYFON, MyPhone, Myria, MyWigo, Navon, NEC, Neffos, Netgear, NeuImage, Newgen, NEXBOX, Nexian, Nextbit, NextBook, NGM, Nikon, Nintendo, NOA, Noain, Nobby, Noblex, Nokia, Nomi, Nous, NUU Mobile, Nvidia, NYX Mobile, O+, O2, Obi, Odys, Onda, OnePlus, OPPO, Opsson, Orange, Ordissimo, Ouki, OUYA, Overmax, Oysters, Palm, Panacom, Panasonic, Pantech, PCBOX, PCD, PCD Argentina, PEAQ, Pentagram, Philips, phoneOne, Pioneer, Pixus, Ployer, Plum, Point of View, Polaroid, PolyPad, Polytron, Pomp, Positivo, PPTV, Prestigio, Primepad, ProScan, PULID, Q-Touch, Qilive, QMobile, Qtek, Quantum, Quechua, R-TV, Ramos, RCA Tablets, Readboy, Rikomagic, RIM, Rinno, Ritmix, Riviera, Roadrover, Rokit, Roku, Rombica, Ross&Moor, Rover, RoverPad, RT Project, Safaricom, Sagem, Samsung, Sanei, Santin BiTBiZ, Sanyo, Savio, Sega, Selevision, Selfix, Sencor, Sendo, Senseit, Senwa, SFR, Sharp, Shuttle, Siemens, Sigma, Silent Circle, Simbans, Sky, Skyworth, Smart, Smartfren, Smartisan, Softbank, Sonim, Sony, Sony Ericsson, Spice, Star, Starway, STF Mobile, STK, Stonex, Storex, Sumvision, SunVan, SuperSonic, Supra, SWISSMOBILITY, Symphony, Syrox, T-Mobile, TB Touch, TCL, TechniSat, TechnoTrend, TechPad, Teclast, Tecno Mobile, Telefunken, Telego, Telenor, Telit, Tesco, Tesla, teXet, ThL, Thomson, TIANYU, Timovi, TiPhone, Tolino, Tooky, Top House, Toplux, Toshiba, Touchmate, TrekStor, Trevi, True, Tunisie Telecom, Turbo, Turbo-X, TVC, U.S. Cellular, Uhappy, Ulefone, UMIDIGI, Unimax, Uniscope, Unknown, Unnecto, Unonu, Unowhy, UTOK, UTStarcom, Vastking, Venso, Verizon, Vernee, Vertex, Vertu, Verykool, Vestel, VGO TEL, Videocon, Videoweb, ViewSonic, Vinsoc, Vitelcom, Vivax, Vivo, Vizio, VK Mobile, Vodafone, Vonino, Vorago, Voto, Voxtel, Vulcan, Walton, Web TV, Weimei, WellcoM, Wexler, Wiko, Wileyfox, Wink, Wolder, Wolfgang, Wonu, Woo, Woxter, X-TIGI, X-View, Xiaolajiao, Xiaomi, Xion, Xolo, Yandex, Yarvik, Yes, Yezz, Ytone, Yu, Yuandao, Yusun, Zeemi, Zen, Zenek, Zonda, Zopo, ZTE, Zuum, Zync, ZYQ, öwn dimension diff --git a/tests/PHPUnit/Unit/Archiver/RequestTest.php b/tests/PHPUnit/Unit/Archiver/RequestTest.php index ae168023c2e..6ae658e10b7 100644 --- a/tests/PHPUnit/Unit/Archiver/RequestTest.php +++ b/tests/PHPUnit/Unit/Archiver/RequestTest.php @@ -11,9 +11,16 @@ use Piwik\Archiver\Request; +use Piwik\Date; class RequestTest extends \PHPUnit_Framework_TestCase { + protected function tearDown() + { + parent::tearDown(); + Date::$now = null; + } + /** * @dataProvider getTestDataForChangeDate */ @@ -44,4 +51,25 @@ public function getTestDataForChangeDate() ], ]; } + + /** + * @dataProvider getTestDataForMakeSureDateIsNotSingleDayRange + */ + public function test_makeSureDateIsNotSingleDayRange($url, $expectedResult) + { + $request = new Request($url); + $request->makeSureDateIsNotSingleDayRange(); + $this->assertEquals($expectedResult, $request->getUrl()); + } + + public function getTestDataForMakeSureDateIsNotSingleDayRange() + { + return [ + ['?idSite=1&date=2012-03-04&period=day', '?idSite=1&date=2012-03-04&period=day'], + ['?idSite=1&date=2012-03-04,2012-03-06&period=range', '?idSite=1&date=2012-03-04,2012-03-06&period=range'], + ['?idSite=1&date=2012-03-04,2012-03-04&period=range', '?idSite=1&date=2012-03-04&period=day'], + ['?idSite=1&date=last1&period=range', '?idSite=1&date=today&period=day'], + ['?idSite=1&date=previous1&period=range', '?idSite=1&date=yesterday&period=day'], + ]; + } } \ No newline at end of file diff --git a/tests/UI/expected-screenshots/Comparison_segmented_visitorlog.png b/tests/UI/expected-screenshots/Comparison_segmented_visitorlog.png index 70a7be1660c..0143bbd3e64 100644 --- a/tests/UI/expected-screenshots/Comparison_segmented_visitorlog.png +++ b/tests/UI/expected-screenshots/Comparison_segmented_visitorlog.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9b42b527f2c040b7d8a799f2911d4106ea7d45c4445492ba01c5612e96e1d1a5 -size 402405 +oid sha256:a2c444a6346d473478d736bf795daa423f63c8b4b117d24143b295bb5b7433e6 +size 402422 diff --git a/tests/UI/expected-screenshots/EmptySite_emptySiteDashboard.png b/tests/UI/expected-screenshots/EmptySite_emptySiteDashboard.png index 398f1992d87..364c635978f 100644 --- a/tests/UI/expected-screenshots/EmptySite_emptySiteDashboard.png +++ b/tests/UI/expected-screenshots/EmptySite_emptySiteDashboard.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5659a10d7a765d14695f644d0f261ec48e3837b4e2d76cf4adc35cf201a47b48 -size 299416 +oid sha256:955f729afa61f6602b09e45da4535de8e64608cc7a4f14229a1fd4992f88e88f +size 300129 diff --git a/tests/UI/expected-screenshots/OneClickUpdate_login.png b/tests/UI/expected-screenshots/OneClickUpdate_login.png index 8ffded54d44..c0f41534c30 100644 --- a/tests/UI/expected-screenshots/OneClickUpdate_login.png +++ b/tests/UI/expected-screenshots/OneClickUpdate_login.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:63cfae7c2afcafca1d96340384b829f817219e36dbd6d89fca81a0079f71610f -size 244652 +oid sha256:1053964b638aff9107e69cd0d465a0a72799f3ea9db8884df3117c6d42efc830 +size 268010 diff --git a/tests/UI/expected-screenshots/Theme_home.png b/tests/UI/expected-screenshots/Theme_home.png index cbb3613d0c0..548efd60929 100644 --- a/tests/UI/expected-screenshots/Theme_home.png +++ b/tests/UI/expected-screenshots/Theme_home.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:78d41258eee99c5fe3afeecada66a2bd6c6b386684aaefa87ed6dc03e21cf643 -size 708602 +oid sha256:07a3d8e06179049407d8089499fce1e6c45c7622755bf411dba01680774486ef +size 708620 diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_dashboard1.png b/tests/UI/expected-screenshots/UIIntegrationTest_dashboard1.png index ccfa9ab4e7d..5e2f22458d7 100644 --- a/tests/UI/expected-screenshots/UIIntegrationTest_dashboard1.png +++ b/tests/UI/expected-screenshots/UIIntegrationTest_dashboard1.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4060bac4f42231b58dce665c64998e9886cd6d5175ee9c4692080b8cdd23ddae -size 632336 +oid sha256:c2490d9349b38b65962458e6344b767ae32c3adbf3e7f040a367035d82c845fd +size 632381 diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_ecommerce_log.png b/tests/UI/expected-screenshots/UIIntegrationTest_ecommerce_log.png index f565793aaf1..43297579546 100644 --- a/tests/UI/expected-screenshots/UIIntegrationTest_ecommerce_log.png +++ b/tests/UI/expected-screenshots/UIIntegrationTest_ecommerce_log.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7bed358956b83d163cd6b6a50add25d343479caecfc63f1752f45bce31af0a2f -size 499249 +oid sha256:4bb7d263038ade7d53af8cda07d482efef3dc741626380832f112de561bab741 +size 499294 diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_ecommerce_log_segmented.png b/tests/UI/expected-screenshots/UIIntegrationTest_ecommerce_log_segmented.png index 779c8f836f8..e2b9cf62638 100644 --- a/tests/UI/expected-screenshots/UIIntegrationTest_ecommerce_log_segmented.png +++ b/tests/UI/expected-screenshots/UIIntegrationTest_ecommerce_log_segmented.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c1f826eac0237f8447bbea06cb8b0fb092adaf6007eddcb4c39bd477de4ee581 -size 61880 +oid sha256:84a67bdeb17c8b0fdad09f9170bdebb5f3325c2d459ebfcd35fcc648fc5e5552 +size 61896 diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_segmented_visitorlog.png b/tests/UI/expected-screenshots/UIIntegrationTest_segmented_visitorlog.png index b13791984c2..f3d5270ff64 100644 --- a/tests/UI/expected-screenshots/UIIntegrationTest_segmented_visitorlog.png +++ b/tests/UI/expected-screenshots/UIIntegrationTest_segmented_visitorlog.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:292a885028edf409c1e20af41e3e54bed24c21a6cbf0118885e083a8fb63a7b7 -size 379446 +oid sha256:1b7ca48581626674bef127e465760e2fe5d22a85801ff7d96bdaeddaf3d33ee1 +size 379471 diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_visitor_profile_popup.png b/tests/UI/expected-screenshots/UIIntegrationTest_visitor_profile_popup.png index 2672fb78e18..41a8af6fb63 100644 --- a/tests/UI/expected-screenshots/UIIntegrationTest_visitor_profile_popup.png +++ b/tests/UI/expected-screenshots/UIIntegrationTest_visitor_profile_popup.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b8d15df1c59ece6e63a11886d934de599a6625fca9a0edc3c0ba55e6675e65e8 -size 184786 +oid sha256:bd66aa14cc29d4917ac5bbcda1ae99aaeac188d485b22d944c8eca55666cb0c5 +size 184802 diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_visitors_realtime_map.png b/tests/UI/expected-screenshots/UIIntegrationTest_visitors_realtime_map.png index 8c1a283cf5a..d79dd14d585 100644 --- a/tests/UI/expected-screenshots/UIIntegrationTest_visitors_realtime_map.png +++ b/tests/UI/expected-screenshots/UIIntegrationTest_visitors_realtime_map.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e152f24cce664e5919939e0e1433a32ac7a54274c66d51d6f448f31af91007cb -size 117081 +oid sha256:03ee5b90fbcda06971f51a13115882df782af7a5dda0a74ab0824f3d897bb75d +size 117095 diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_visitors_software.png b/tests/UI/expected-screenshots/UIIntegrationTest_visitors_software.png index ec35942247a..595620a5a6d 100644 --- a/tests/UI/expected-screenshots/UIIntegrationTest_visitors_software.png +++ b/tests/UI/expected-screenshots/UIIntegrationTest_visitors_software.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d48a483dec59934bbc464b46e6e9d32a7bfed6ecfdefe9e5a85c868b331211a8 -size 152916 +oid sha256:44eaebc5b4514b58019679140201ec2f1ea34295ae0a994164de98096a94723b +size 152925 diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_widgetize_ecommercelog.png b/tests/UI/expected-screenshots/UIIntegrationTest_widgetize_ecommercelog.png index 8c0c0cd66f2..d17add09340 100644 --- a/tests/UI/expected-screenshots/UIIntegrationTest_widgetize_ecommercelog.png +++ b/tests/UI/expected-screenshots/UIIntegrationTest_widgetize_ecommercelog.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:96dcb392d7faef30bad0c5a48f13b4eea7529e887af3d9fe136a83c1acd5f0c0 -size 485504 +oid sha256:64cd903c8e7c86e364bc239022d2cf0a669ba8d69f87ebf92d38849b4b7745be +size 485536 diff --git a/tests/travis b/tests/travis index 74e0a7b6902..f215e0066c4 160000 --- a/tests/travis +++ b/tests/travis @@ -1 +1 @@ -Subproject commit 74e0a7b6902f6799f3647b0f29638158d3b1116b +Subproject commit f215e0066c4ea0c45cceaee3ed6a06fc623ebaff