From cef2d69f76320d8f02cea2418a4bf5d506aee513 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Sat, 24 May 2014 18:37:04 +0200 Subject: [PATCH 01/78] starting to implement new DeviceDetector structure --- composer.json | 2 +- core/Tracker/Visit.php | 8 ++- libs/UserAgentParser/UserAgentParser.php | 10 ++-- piwik.php | 2 - plugins/API/API.php | 4 +- plugins/DevicesDetection/Controller.php | 55 ++++++++++--------- plugins/DevicesDetection/DevicesDetection.php | 13 +++-- plugins/DevicesDetection/functions.php | 54 +++++++++--------- 8 files changed, 77 insertions(+), 71 deletions(-) diff --git a/composer.json b/composer.json index 0cfa4c9f062..eef9ed3d8e8 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "symfony/console": ">=v2.3.5", "tedivm/jshrink": "v0.5.1", "mustangostang/spyc": "0.5.*", - "piwik/device-detector": "1.0" + "piwik/device-detector": "dev-master" }, "require-dev": { "phpunit/phpunit": "4.*" diff --git a/core/Tracker/Visit.php b/core/Tracker/Visit.php index b2a65cf39f3..7411b3a4a1f 100644 --- a/core/Tracker/Visit.php +++ b/core/Tracker/Visit.php @@ -9,7 +9,7 @@ namespace Piwik\Tracker; -use DeviceDetector; +use DeviceDetector\DeviceDetector; use Piwik\Common; use Piwik\Config; use Piwik\IP; @@ -602,7 +602,11 @@ protected function getUserSettingsInformation() $deviceDetector = new DeviceDetector($userAgent); $deviceDetector->parse(); - $aBrowserInfo = $deviceDetector->getBrowser(); + $aBrowserInfo = $deviceDetector->getClient(); + if ($aBrowserInfo['type'] != 'browser') { + // for now only track browsers + unset($aBrowserInfo); + } $browserName = !empty($aBrowserInfo['short_name']) ? $aBrowserInfo['short_name'] : 'UNK'; $browserVersion = !empty($aBrowserInfo['version']) ? $aBrowserInfo['version'] : ''; diff --git a/libs/UserAgentParser/UserAgentParser.php b/libs/UserAgentParser/UserAgentParser.php index a57554e4dae..4f85951c930 100644 --- a/libs/UserAgentParser/UserAgentParser.php +++ b/libs/UserAgentParser/UserAgentParser.php @@ -655,9 +655,9 @@ static public function getBrowserNameFromId($browserId) if (isset(self::$browserIdToName[$browserId])) { return self::$browserIdToName[$browserId]; } - if(class_exists('DeviceDetector')) { - if( !empty(DeviceDetector::$browsers[$browserId])) { - return DeviceDetector::$browsers[$browserId]; + if(class_exists('DeviceDetector\\Parser\\Client\\Browser')) { + if( array_key_exists($browserId, DeviceDetector\Parser\Client\Browser::getAvailableBrowsers())) { + return DeviceDetector\Parser\Client\Browser::getAvailableBrowsers()[$browserId]; } } return false; @@ -692,8 +692,8 @@ static public function getOperatingSystemNameFromId($osId) return self::$operatingSystemsIdToName[$osId]; } - if(class_exists('DeviceDetector')) { - return DeviceDetector::getOsNameFromId($osId); + if(class_exists('DeviceDetector\\Parser\\OperatingSystem')) { + return DeviceDetector\Parser\OperatingSystem::getNameFromId($osId); } return false; } diff --git a/piwik.php b/piwik.php index 18f5b22a542..00c2041a52e 100644 --- a/piwik.php +++ b/piwik.php @@ -91,8 +91,6 @@ $vendorDirectory = PIWIK_INCLUDE_PATH . '/../..'; } require_once $vendorDirectory . '/autoload.php'; -require_once $vendorDirectory . '/mustangostang/spyc/Spyc.php'; -require_once $vendorDirectory . '/piwik/device-detector/DeviceDetector.php'; session_cache_limiter('nocache'); @date_default_timezone_set('UTC'); diff --git a/plugins/API/API.php b/plugins/API/API.php index 6d2b0e4e461..94a39e0186c 100644 --- a/plugins/API/API.php +++ b/plugins/API/API.php @@ -714,11 +714,11 @@ protected function addTopMenuMobileApp() if (empty($_SERVER['HTTP_USER_AGENT'])) { return; } - if (!class_exists("DeviceDetector")) { + if (!class_exists("DeviceDetector\\DeviceDetector")) { throw new \Exception("DeviceDetector could not be found, maybe you are using Piwik from git and need to have update Composer.
php composer.phar update"); } - $ua = new \DeviceDetector($_SERVER['HTTP_USER_AGENT']); + $ua = new \DeviceDetector\DeviceDetector($_SERVER['HTTP_USER_AGENT']); $ua->parse(); $os = $ua->getOs('short_name'); if ($os && in_array($os, array('AND', 'IOS'))) { diff --git a/plugins/DevicesDetection/Controller.php b/plugins/DevicesDetection/Controller.php index 12b5750dcf7..2f50ca79f9a 100644 --- a/plugins/DevicesDetection/Controller.php +++ b/plugins/DevicesDetection/Controller.php @@ -8,7 +8,7 @@ */ namespace Piwik\Plugins\DevicesDetection; -use DeviceDetector; +use DeviceDetector\DeviceDetector; use Piwik\Common; use Piwik\Db; use Piwik\Piwik; @@ -74,26 +74,27 @@ public function deviceDetection() $userAgent = Common::getRequestVar('ua', $_SERVER['HTTP_USER_AGENT'], 'string'); - $parsedUA = DeviceDetector::getInfoFromUserAgent($userAgent); + $uaParser = new DeviceDetector($userAgent); + $uaParser->parse(); $view->userAgent = $userAgent; - $view->browser_name = $parsedUA['browser']['name']; - $view->browser_short_name = $parsedUA['browser']['short_name']; - $view->browser_version = $parsedUA['browser']['version']; - $view->browser_logo = getBrowserLogoExtended($parsedUA['browser']['short_name']); - $view->browser_family = $parsedUA['browser_family']; - $view->browser_family_logo = getBrowserFamilyLogoExtended($parsedUA['browser_family']); - $view->os_name = $parsedUA['os']['name']; - $view->os_logo = getOsLogoExtended($parsedUA['os']['short_name']); - $view->os_short_name = $parsedUA['os']['short_name']; - $view->os_family = $parsedUA['os_family']; - $view->os_family_logo = getOsFamilyLogoExtended($parsedUA['os_family']); - $view->os_version = $parsedUA['os']['version']; - $view->device_type = getDeviceTypeLabel($parsedUA['device']['type']); - $view->device_type_logo = getDeviceTypeLogo($parsedUA['device']['type']); - $view->device_model = $parsedUA['device']['model']; - $view->device_brand = getDeviceBrandLabel($parsedUA['device']['brand']); - $view->device_brand_logo = getBrandLogo($view->device_brand); + $view->browser_name = $uaParser->getClient('name'); + $view->browser_short_name = $uaParser->getClient('short_name'); + $view->browser_version = $uaParser->getClient('version'); + $view->browser_logo = getBrowserLogoExtended($uaParser->getClient('short_name')); + $view->browser_family = \DeviceDetector\Parser\Client\Browser::getBrowserFamily($uaParser->getClient('short_name')); + $view->browser_family_logo = getBrowserFamilyLogoExtended($view->browser_family); + $view->os_name = $uaParser->getOs('name'); + $view->os_logo = getOsLogoExtended($uaParser->getOs('short_name')); + $view->os_short_name = $uaParser->getOs('short_name'); + $view->os_family = \DeviceDetector\Parser\OperatingSystem::getOsFamily($uaParser->getOs('short_name')); + $view->os_family_logo = getOsFamilyLogoExtended($view->os_family); + $view->os_version = $uaParser->getOs('version'); + $view->device_type = getDeviceTypeLabel($uaParser->getDeviceName()); + $view->device_type_logo = getDeviceTypeLogo($uaParser->getDeviceName()); + $view->device_model = $uaParser->getModel(); + $view->device_brand = getDeviceBrandLabel($uaParser->getBrand()); + $view->device_brand_logo = getBrandLogo($uaParser->getBrand()); return $view->render(); } @@ -110,7 +111,7 @@ public function showList() switch ($type) { case 'brands': - $availableBrands = DeviceDetector::$deviceBrands; + $availableBrands = \DeviceDetector\Parser\Device\DeviceParserAbstract::$deviceBrands; foreach ($availableBrands AS $short => $name) { if ($name != 'Unknown') { @@ -120,7 +121,7 @@ public function showList() break; case 'browsers': - $availableBrowsers = DeviceDetector::$browsers; + $availableBrowsers = \DeviceDetector\Parser\Client\Browser::getAvailableBrowsers(); foreach ($availableBrowsers AS $short => $name) { $list[$name] = getBrowserLogoExtended($short); @@ -128,7 +129,7 @@ public function showList() break; case 'browserfamilies': - $availableBrowserFamilies = DeviceDetector::$browserFamilies; + $availableBrowserFamilies = \DeviceDetector\Parser\Client\Browser::getAvailableBrowserFamilies(); foreach ($availableBrowserFamilies AS $name => $browsers) { $list[$name] = getBrowserFamilyLogoExtended($name); @@ -136,9 +137,9 @@ public function showList() break; case 'os': - $availableOSs = DeviceDetector::$osShorts; + $availableOSs = \DeviceDetector\Parser\OperatingSystem::getAvailableOperatingSystems(); - foreach ($availableOSs AS $name => $short) { + foreach ($availableOSs AS $short => $name) { if ($name != 'Bot') { $list[$name] = getOsLogoExtended($short); } @@ -146,7 +147,7 @@ public function showList() break; case 'osfamilies': - $osFamilies = DeviceDetector::$osFamilies; + $osFamilies = \DeviceDetector\Parser\OperatingSystem::getAvailableOperatingSystemFamilies(); foreach ($osFamilies AS $name => $oss) { if ($name != 'Bot') { @@ -156,9 +157,9 @@ public function showList() break; case 'devicetypes': - $deviceTypes = DeviceDetector::$deviceTypes; + $deviceTypes = \DeviceDetector\Parser\Device\DeviceParserAbstract::getAvailableDeviceTypes(); - foreach ($deviceTypes AS $name) { + foreach ($deviceTypes AS $name => $id) { $list[$name] = getDeviceTypeLogo($name); } break; diff --git a/plugins/DevicesDetection/DevicesDetection.php b/plugins/DevicesDetection/DevicesDetection.php index a6b8b451496..65e805a8a52 100644 --- a/plugins/DevicesDetection/DevicesDetection.php +++ b/plugins/DevicesDetection/DevicesDetection.php @@ -9,7 +9,8 @@ namespace Piwik\Plugins\DevicesDetection; -use DeviceDetector; +use DeviceDetector\Parser\Device\DeviceParserAbstract AS DeviceParser; +use DeviceDetector\DeviceDetector; use Exception; use Piwik\ArchiveProcessor; use Piwik\CacheFile; @@ -58,10 +59,10 @@ public function __construct() protected function getRawMetadataDeviceType() { - $deviceTypeList = implode(", ", DeviceDetector::$deviceTypes); + $deviceTypeList = implode(", ", DeviceParser::getAvailableDeviceTypeNames()); $deviceTypeLabelToCode = function ($type) use ($deviceTypeList) { - $index = array_search(strtolower(trim(urldecode($type))), DeviceDetector::$deviceTypes); + $index = array_search(strtolower(trim(urldecode($type))), DeviceParser::getAvailableDeviceTypeNames()); if ($index === false) { throw new Exception("deviceType segment must be one of: $deviceTypeList"); } @@ -257,10 +258,10 @@ public function parseMobileVisitData(&$visitorInfo, \Piwik\Tracker\Request $requ $userAgent = $request->getUserAgent(); $UAParser = new DeviceDetector($userAgent); - $UAParser->setCache(new CacheFile('tracker', 86400)); + #$UAParser->setCache(new CacheFile('tracker', 86400)); $UAParser->parse(); - $deviceInfo['config_browser_name'] = $UAParser->getBrowser("short_name"); - $deviceInfo['config_browser_version'] = $UAParser->getBrowser("version"); + $deviceInfo['config_browser_name'] = $UAParser->getClient("type") == 'browser' ? $UAParser->getClient("short_name") : 'UNK'; + $deviceInfo['config_browser_version'] = $UAParser->getClient("type") == 'browser' ? $UAParser->getClient("version") : 'UNK'; $deviceInfo['config_os'] = $UAParser->getOs("short_name"); $deviceInfo['config_os_version'] = $UAParser->getOs("version"); $deviceInfo['config_device_type'] = $UAParser->getDevice(); diff --git a/plugins/DevicesDetection/functions.php b/plugins/DevicesDetection/functions.php index 895b0ed33ca..7858b439703 100644 --- a/plugins/DevicesDetection/functions.php +++ b/plugins/DevicesDetection/functions.php @@ -9,8 +9,10 @@ namespace Piwik\Plugins\DevicesDetection; -use DeviceDetector; use Piwik\Piwik; +use DeviceDetector\Parser\OperatingSystem AS OperatingSystemParser; +use DeviceDetector\Parser\Device\DeviceParserAbstract AS DeviceParser; +use DeviceDetector\Parser\Client\Browser AS BrowserParser; function getBrandLogo($label) { @@ -25,7 +27,7 @@ function getBrandLogo($label) function getBrowserFamilyFullNameExtended($label) { - foreach (DeviceDetector::$browserFamilies as $name => $family) { + foreach (BrowserParser::getAvailableBrowserFamilies() as $name => $family) { if (in_array($label, $family)) { return $name; } @@ -35,8 +37,8 @@ function getBrowserFamilyFullNameExtended($label) function getBrowserFamilyLogoExtended($label) { - if (array_key_exists($label, DeviceDetector::$browserFamilies)) { - return getBrowserLogoExtended(DeviceDetector::$browserFamilies[$label][0]); + if (!empty($label) && array_key_exists($label, BrowserParser::getAvailableBrowserFamilies())) { + return getBrowserLogoExtended(BrowserParser::getAvailableBrowserFamilies()[$label][0]); } return getBrowserLogoExtended($label); } @@ -45,8 +47,8 @@ function getBrowserNameExtended($label) { $short = substr($label, 0, 2); $ver = substr($label, 3, 10); - if (array_key_exists($short, DeviceDetector::$browsers)) { - return trim(ucfirst(DeviceDetector::$browsers[$short]) . ' ' . $ver); + if (array_key_exists($short, BrowserParser::getAvailableBrowsers())) { + return trim(ucfirst(BrowserParser::getAvailableBrowsers()[$short]) . ' ' . $ver); } else { return Piwik::translate('General_Unknown'); } @@ -70,8 +72,8 @@ function getBrowserLogoExtended($short) // If name is given instead of short code, try to find matching shortcode if (strlen($short) > 2) { - if (in_array($short, DeviceDetector::$browsers)) { - $flippedBrowsers = array_flip(DeviceDetector::$browsers); + if (in_array($short, BrowserParser::getAvailableBrowsers())) { + $flippedBrowsers = array_flip(BrowserParser::getAvailableBrowsers()); $short = $flippedBrowsers[$short]; } else { $short = substr($short, 0, 2); @@ -80,18 +82,18 @@ function getBrowserLogoExtended($short) $family = getBrowserFamilyFullNameExtended($short); - if (array_key_exists($short, DeviceDetector::$browsers) && file_exists(PIWIK_INCLUDE_PATH.'/'.sprintf($path, $short))) { + if (!empty($short) && array_key_exists($short, BrowserParser::getAvailableBrowsers()) && file_exists(PIWIK_INCLUDE_PATH.'/'.sprintf($path, $short))) { return sprintf($path, $short); - } elseif (array_key_exists($family, DeviceDetector::$browserFamilies) && file_exists(PIWIK_INCLUDE_PATH.'/'.sprintf($path, DeviceDetector::$browserFamilies[$family][0]))) { - return sprintf($path, DeviceDetector::$browserFamilies[$family][0]); + } elseif (!empty($short) && array_key_exists($family, BrowserParser::getAvailableBrowserFamilies()) && file_exists(PIWIK_INCLUDE_PATH.'/'.sprintf($path, BrowserParser::getAvailableBrowserFamilies()[$family][0]))) { + return sprintf($path, BrowserParser::getAvailableBrowserFamilies()[$family][0]); } return sprintf($path, 'UNK'); } function getDeviceBrandLabel($label) { - if (array_key_exists($label, DeviceDetector::$deviceBrands)) { - return ucfirst(DeviceDetector::$deviceBrands[$label]); + if (array_key_exists($label, DeviceParser::$deviceBrands)) { + return ucfirst(DeviceParser::$deviceBrands[$label]); } else { return Piwik::translate('General_Unknown'); } @@ -110,8 +112,8 @@ function getDeviceTypeLabel($label) 'smart display' => 'DevicesDetection_SmartDisplay', 'camera' => 'DevicesDetection_Camera' ); - if (isset(DeviceDetector::$deviceTypes[$label]) && isset($translations[DeviceDetector::$deviceTypes[$label]])) { - return Piwik::translate($translations[DeviceDetector::$deviceTypes[$label]]); + if (in_array($label, DeviceParser::getAvailableDeviceTypes()) && isset($translations[array_search($label, DeviceParser::getAvailableDeviceTypes())])) { + return Piwik::translate($translations[array_search($label, DeviceParser::getAvailableDeviceTypes())]); } else if (isset($translations[$label])) { return Piwik::translate($translations[$label]); } else { @@ -121,8 +123,8 @@ function getDeviceTypeLabel($label) function getDeviceTypeLogo($label) { - if (is_numeric($label) && isset(DeviceDetector::$deviceTypes[$label])) { - $label = DeviceDetector::$deviceTypes[$label]; + if (is_numeric($label) && in_array($label, DeviceParser::getAvailableDeviceTypes())) { + $label = array_search($label, DeviceParser::getAvailableDeviceTypes()); } $label = strtolower($label); @@ -156,7 +158,7 @@ function getModelName($label) function getOSFamilyFullNameExtended($label) { - $label = DeviceDetector::getOsFamily($label); + $label = OperatingSystemParser::getOsFamily($label); if($label !== false) { return $label; } @@ -165,8 +167,8 @@ function getOSFamilyFullNameExtended($label) function getOsFamilyLogoExtended($label) { - if (array_key_exists($label, DeviceDetector::$osFamilies)) { - return getOsLogoExtended(DeviceDetector::$osFamilies[$label][0]); + if (!empty($label) && array_key_exists($label, OperatingSystemParser::getAvailableOperatingSystemFamilies())) { + return getOsLogoExtended(OperatingSystemParser::getAvailableOperatingSystemFamilies()[$label][0]); } return getOsLogoExtended($label); } @@ -176,7 +178,7 @@ function getOsFullNameExtended($label) if (!empty($label) && $label != ";") { $os = substr($label, 0, 3); $ver = substr($label, 4, 15); - $name = DeviceDetector::getOsNameFromId($os, $ver); + $name = OperatingSystemParser::getNameFromId($os, $ver); if (!empty($name)) { return $name; } @@ -202,8 +204,8 @@ function getOsLogoExtended($short) // If name is given instead of short code, try to find matching shortcode if (strlen($short) > 3) { - if (array_key_exists($short, DeviceDetector::$osShorts)) { - $short = DeviceDetector::$osShorts[$short]; + if (in_array($short, OperatingSystemParser::getAvailableOperatingSystems())) { + $short = array_search($short, OperatingSystemParser::getAvailableOperatingSystems()); } else { $short = substr($short, 0, 3); } @@ -211,10 +213,10 @@ function getOsLogoExtended($short) $family = getOsFamilyFullNameExtended($short); - if (in_array($short, DeviceDetector::$osShorts) && file_exists(PIWIK_INCLUDE_PATH.'/'.sprintf($path, $short))) { + if (!empty($short) && array_key_exists($short, OperatingSystemParser::getAvailableOperatingSystems()) && file_exists(PIWIK_INCLUDE_PATH.'/'.sprintf($path, $short))) { return sprintf($path, $short); - } elseif (array_key_exists($family, DeviceDetector::$osFamilies) && file_exists(PIWIK_INCLUDE_PATH.'/'.sprintf($path, DeviceDetector::$osFamilies[$family][0]))) { - return sprintf($path, DeviceDetector::$osFamilies[$family][0]); + } elseif (!empty($family) && array_key_exists($family, OperatingSystemParser::getAvailableOperatingSystemFamilies()) && file_exists(PIWIK_INCLUDE_PATH.'/'.sprintf($path, OperatingSystemParser::getAvailableOperatingSystemFamilies()[$family][0]))) { + return sprintf($path, OperatingSystemParser::getAvailableOperatingSystemFamilies()[$family][0]); } return sprintf($path, 'UNK'); } From 0b5aba1a651755cf3a65db7ba1bafe5870547118 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Sun, 25 May 2014 14:04:26 +0200 Subject: [PATCH 02/78] updating composer lock file --- composer.lock | 57 +++++++++++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/composer.lock b/composer.lock index e6d9aecfb62..0a88b2a36b8 100644 --- a/composer.lock +++ b/composer.lock @@ -3,7 +3,7 @@ "This file locks the dependencies of your project to a known state", "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "6d358fe10eaef73ee1323cb06cd0e5c8", + "hash": "8432cff50123bf1d2eaf0c1a56b0b72f", "packages": [ { "name": "leafo/lessphp", @@ -95,27 +95,30 @@ }, { "name": "piwik/device-detector", - "version": "1.0", + "version": "dev-master", "source": { "type": "git", "url": "https://github.com/piwik/device-detector.git", - "reference": "ea7c5d8b76def0d8345a4eba59c5f98ec0109de6" + "reference": "46ade5240edb89efac85b5ec05b73a84b6a37fec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/piwik/device-detector/zipball/ea7c5d8b76def0d8345a4eba59c5f98ec0109de6", - "reference": "ea7c5d8b76def0d8345a4eba59c5f98ec0109de6", + "url": "https://api.github.com/repos/piwik/device-detector/zipball/46ade5240edb89efac85b5ec05b73a84b6a37fec", + "reference": "46ade5240edb89efac85b5ec05b73a84b6a37fec", "shasum": "" }, "require": { "mustangostang/spyc": "*", "php": ">=5.3.1" }, + "require-dev": { + "phpunit/phpunit": "4.0.*" + }, "type": "library", "autoload": { - "files": [ - "DeviceDetector.php" - ] + "psr-4": { + "DeviceDetector\\": "" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -135,21 +138,21 @@ "parser", "useragent" ], - "time": "2014-04-03 08:59:48" + "time": "2014-05-23 20:49:45" }, { "name": "symfony/console", - "version": "v2.4.4", + "version": "v2.4.5", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "2e452005b1e1d003d23702d227e23614679eb5ca" + "reference": "24f723436e62598c9dddee2a8573d6992504dc5d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/2e452005b1e1d003d23702d227e23614679eb5ca", - "reference": "2e452005b1e1d003d23702d227e23614679eb5ca", + "url": "https://api.github.com/repos/symfony/Console/zipball/24f723436e62598c9dddee2a8573d6992504dc5d", + "reference": "24f723436e62598c9dddee2a8573d6992504dc5d", "shasum": "" }, "require": { @@ -190,7 +193,7 @@ ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2014-04-27 13:34:57" + "time": "2014-05-14 21:48:29" }, { "name": "tedivm/jshrink", @@ -542,16 +545,16 @@ }, { "name": "phpunit/phpunit", - "version": "4.1.0", + "version": "4.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "efb1b1334605594417a3bd466477772d06d460a8" + "reference": "1d6b554732382879045e11c56decd4be76130720" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/efb1b1334605594417a3bd466477772d06d460a8", - "reference": "efb1b1334605594417a3bd466477772d06d460a8", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1d6b554732382879045e11c56decd4be76130720", + "reference": "1d6b554732382879045e11c56decd4be76130720", "shasum": "" }, "require": { @@ -612,7 +615,7 @@ "testing", "xunit" ], - "time": "2014-05-02 07:13:40" + "time": "2014-05-24 10:48:51" }, { "name": "phpunit/phpunit-mock-objects", @@ -940,17 +943,17 @@ }, { "name": "symfony/yaml", - "version": "v2.4.4", + "version": "v2.4.5", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "65539ecde838f9c0d18b006b2101e3deb4b5c9ff" + "reference": "fd22bb88c3a6f73c898b39bec185a9e211b06265" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/65539ecde838f9c0d18b006b2101e3deb4b5c9ff", - "reference": "65539ecde838f9c0d18b006b2101e3deb4b5c9ff", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/fd22bb88c3a6f73c898b39bec185a9e211b06265", + "reference": "fd22bb88c3a6f73c898b39bec185a9e211b06265", "shasum": "" }, "require": { @@ -985,16 +988,16 @@ ], "description": "Symfony Yaml Component", "homepage": "http://symfony.com", - "time": "2014-04-18 20:37:09" + "time": "2014-05-12 09:27:48" } ], "aliases": [ ], "minimum-stability": "stable", - "stability-flags": [ - - ], + "stability-flags": { + "piwik/device-detector": 20 + }, "platform": { "php": ">=5.3.2" }, From a0819c5f5670ccdcddc281aff1e7b54bebc33b14 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Sun, 25 May 2014 14:15:04 +0200 Subject: [PATCH 03/78] php compatibility fixes --- plugins/DevicesDetection/functions.php | 33 ++++++++++++++++---------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/plugins/DevicesDetection/functions.php b/plugins/DevicesDetection/functions.php index 7858b439703..b8ff3a8854c 100644 --- a/plugins/DevicesDetection/functions.php +++ b/plugins/DevicesDetection/functions.php @@ -37,8 +37,9 @@ function getBrowserFamilyFullNameExtended($label) function getBrowserFamilyLogoExtended($label) { - if (!empty($label) && array_key_exists($label, BrowserParser::getAvailableBrowserFamilies())) { - return getBrowserLogoExtended(BrowserParser::getAvailableBrowserFamilies()[$label][0]); + $browserFamilies = BrowserParser::getAvailableBrowserFamilies(); + if (!empty($label) && array_key_exists($label, $browserFamilies)) { + return getBrowserLogoExtended($browserFamilies[$label][0]); } return getBrowserLogoExtended($label); } @@ -47,8 +48,9 @@ function getBrowserNameExtended($label) { $short = substr($label, 0, 2); $ver = substr($label, 3, 10); - if (array_key_exists($short, BrowserParser::getAvailableBrowsers())) { - return trim(ucfirst(BrowserParser::getAvailableBrowsers()[$short]) . ' ' . $ver); + $browsers = BrowserParser::getAvailableBrowsers(); + if (array_key_exists($short, $browsers)) { + return trim(ucfirst($browsers[$short]) . ' ' . $ver); } else { return Piwik::translate('General_Unknown'); } @@ -82,10 +84,12 @@ function getBrowserLogoExtended($short) $family = getBrowserFamilyFullNameExtended($short); + $browserFamilies = BrowserParser::getAvailableBrowserFamilies(); + if (!empty($short) && array_key_exists($short, BrowserParser::getAvailableBrowsers()) && file_exists(PIWIK_INCLUDE_PATH.'/'.sprintf($path, $short))) { return sprintf($path, $short); - } elseif (!empty($short) && array_key_exists($family, BrowserParser::getAvailableBrowserFamilies()) && file_exists(PIWIK_INCLUDE_PATH.'/'.sprintf($path, BrowserParser::getAvailableBrowserFamilies()[$family][0]))) { - return sprintf($path, BrowserParser::getAvailableBrowserFamilies()[$family][0]); + } elseif (!empty($short) && array_key_exists($family, $browserFamilies) && file_exists(PIWIK_INCLUDE_PATH.'/'.sprintf($path, $browserFamilies[$family][0]))) { + return sprintf($path, $browserFamilies[$family][0]); } return sprintf($path, 'UNK'); } @@ -112,8 +116,11 @@ function getDeviceTypeLabel($label) 'smart display' => 'DevicesDetection_SmartDisplay', 'camera' => 'DevicesDetection_Camera' ); - if (in_array($label, DeviceParser::getAvailableDeviceTypes()) && isset($translations[array_search($label, DeviceParser::getAvailableDeviceTypes())])) { - return Piwik::translate($translations[array_search($label, DeviceParser::getAvailableDeviceTypes())]); + + $deviceTypes = DeviceParser::getAvailableDeviceTypes(); + + if (in_array($label, $deviceTypes) && isset($translations[array_search($label, $deviceTypes)])) { + return Piwik::translate($translations[array_search($label, $deviceTypes)]); } else if (isset($translations[$label])) { return Piwik::translate($translations[$label]); } else { @@ -167,8 +174,9 @@ function getOSFamilyFullNameExtended($label) function getOsFamilyLogoExtended($label) { - if (!empty($label) && array_key_exists($label, OperatingSystemParser::getAvailableOperatingSystemFamilies())) { - return getOsLogoExtended(OperatingSystemParser::getAvailableOperatingSystemFamilies()[$label][0]); + $osFamilies = OperatingSystemParser::getAvailableOperatingSystemFamilies(); + if (!empty($label) && array_key_exists($label, $osFamilies)) { + return getOsLogoExtended($osFamilies[$label][0]); } return getOsLogoExtended($label); } @@ -212,11 +220,12 @@ function getOsLogoExtended($short) } $family = getOsFamilyFullNameExtended($short); + $osFamilies = OperatingSystemParser::getAvailableOperatingSystemFamilies(); if (!empty($short) && array_key_exists($short, OperatingSystemParser::getAvailableOperatingSystems()) && file_exists(PIWIK_INCLUDE_PATH.'/'.sprintf($path, $short))) { return sprintf($path, $short); - } elseif (!empty($family) && array_key_exists($family, OperatingSystemParser::getAvailableOperatingSystemFamilies()) && file_exists(PIWIK_INCLUDE_PATH.'/'.sprintf($path, OperatingSystemParser::getAvailableOperatingSystemFamilies()[$family][0]))) { - return sprintf($path, OperatingSystemParser::getAvailableOperatingSystemFamilies()[$family][0]); + } elseif (!empty($family) && array_key_exists($family, $osFamilies) && file_exists(PIWIK_INCLUDE_PATH.'/'.sprintf($path, $osFamilies[$family][0]))) { + return sprintf($path, $osFamilies[$family][0]); } return sprintf($path, 'UNK'); } From 7900025598b4901c12ad45bde2b97b471073b5c9 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Sun, 25 May 2014 14:20:22 +0200 Subject: [PATCH 04/78] php compatibility fixes --- libs/UserAgentParser/UserAgentParser.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libs/UserAgentParser/UserAgentParser.php b/libs/UserAgentParser/UserAgentParser.php index 4f85951c930..c0c8fea1ce1 100644 --- a/libs/UserAgentParser/UserAgentParser.php +++ b/libs/UserAgentParser/UserAgentParser.php @@ -656,8 +656,9 @@ static public function getBrowserNameFromId($browserId) return self::$browserIdToName[$browserId]; } if(class_exists('DeviceDetector\\Parser\\Client\\Browser')) { - if( array_key_exists($browserId, DeviceDetector\Parser\Client\Browser::getAvailableBrowsers())) { - return DeviceDetector\Parser\Client\Browser::getAvailableBrowsers()[$browserId]; + $browsers = DeviceDetector\Parser\Client\Browser::getAvailableBrowsers(); + if( array_key_exists($browserId, $browsers)) { + return $browsers[$browserId]; } } return false; From a38322c2aa47a67e0abf9823504f5fe11c821bef Mon Sep 17 00:00:00 2001 From: sgiehl Date: Tue, 27 May 2014 11:21:00 +0200 Subject: [PATCH 05/78] disable cache for now, as it needs a new implementation --- core/Tracker/Settings.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/Tracker/Settings.php b/core/Tracker/Settings.php index 877e1e89f8d..3eed338f3ba 100644 --- a/core/Tracker/Settings.php +++ b/core/Tracker/Settings.php @@ -38,7 +38,7 @@ protected function loadInfo() $userAgent = $this->request->getUserAgent(); $deviceDetector = new DeviceDetector($userAgent); - $deviceDetector->setCache(new CacheFile('tracker', 86400)); + #$deviceDetector->setCache(new CacheFile('tracker', 86400)); $deviceDetector->parse(); $aBrowserInfo = $deviceDetector->getClient(); if ($aBrowserInfo['type'] != 'browser') { @@ -115,4 +115,4 @@ protected function getConfigHash($os, $browserName, $browserVersion, $plugin_Fla $hash = md5($os . $browserName . $browserVersion . $plugin_Flash . $plugin_Java . $plugin_Director . $plugin_Quicktime . $plugin_RealPlayer . $plugin_PDF . $plugin_WindowsMedia . $plugin_Gears . $plugin_Silverlight . $plugin_Cookie . $ip . $browserLang, $raw_output = true); return substr($hash, 0, Tracker::LENGTH_BINARY_ID); } -} \ No newline at end of file +} From e1abcdd54e60f69fd52303d9faf0ada734178b9e Mon Sep 17 00:00:00 2001 From: sgiehl Date: Thu, 29 May 2014 13:01:46 +0200 Subject: [PATCH 06/78] updated composer.lock --- composer.lock | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/composer.lock b/composer.lock index 0a88b2a36b8..a9822dc62a1 100644 --- a/composer.lock +++ b/composer.lock @@ -1,7 +1,8 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "This file is @generated automatically" ], "hash": "8432cff50123bf1d2eaf0c1a56b0b72f", "packages": [ @@ -99,12 +100,12 @@ "source": { "type": "git", "url": "https://github.com/piwik/device-detector.git", - "reference": "46ade5240edb89efac85b5ec05b73a84b6a37fec" + "reference": "d3ccb7938fa272a857c279850ffbb3d8fe04c0b7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/piwik/device-detector/zipball/46ade5240edb89efac85b5ec05b73a84b6a37fec", - "reference": "46ade5240edb89efac85b5ec05b73a84b6a37fec", + "url": "https://api.github.com/repos/piwik/device-detector/zipball/d3ccb7938fa272a857c279850ffbb3d8fe04c0b7", + "reference": "d3ccb7938fa272a857c279850ffbb3d8fe04c0b7", "shasum": "" }, "require": { @@ -138,7 +139,7 @@ "parser", "useragent" ], - "time": "2014-05-23 20:49:45" + "time": "2014-05-25 17:45:14" }, { "name": "symfony/console", @@ -297,16 +298,16 @@ "packages-dev": [ { "name": "phpunit/php-code-coverage", - "version": "2.0.6", + "version": "2.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "bccecf50645068b44f49a84009e2a0499a500b99" + "reference": "58401826c8cfc8fd689b60026e91c337df374bca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/bccecf50645068b44f49a84009e2a0499a500b99", - "reference": "bccecf50645068b44f49a84009e2a0499a500b99", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/58401826c8cfc8fd689b60026e91c337df374bca", + "reference": "58401826c8cfc8fd689b60026e91c337df374bca", "shasum": "" }, "require": { @@ -358,7 +359,7 @@ "testing", "xunit" ], - "time": "2014-04-30 09:01:21" + "time": "2014-05-26 14:55:24" }, { "name": "phpunit/php-file-iterator", From 69892f5a7f450bf4a0d79f17c2e10a9607272a66 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Thu, 29 May 2014 17:56:04 +0200 Subject: [PATCH 07/78] use DeviceDetector's bot parser to look for bots --- core/Tracker/VisitExcluded.php | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/core/Tracker/VisitExcluded.php b/core/Tracker/VisitExcluded.php index 00b01aaf637..8bfb4e31ada 100644 --- a/core/Tracker/VisitExcluded.php +++ b/core/Tracker/VisitExcluded.php @@ -8,6 +8,7 @@ */ namespace Piwik\Tracker; +use DeviceDetector\Parser\Bot; use Piwik\Common; use Piwik\Config; use Piwik\IP; @@ -73,9 +74,9 @@ public function isExcluded() /** * Triggered on every tracking request. - * + * * This event can be used to tell the Tracker not to record this particular action or visit. - * + * * @param bool &$excluded Whether the request should be excluded or not. Initialized * to `false`. Event subscribers should set it to `true` in * order to exclude the request. @@ -147,32 +148,19 @@ protected function isPrefetchDetected() * As a result, these sophisticated bots exhibit characteristics of * browsers (cookies enabled, executing JavaScript, etc). * + * @see \DeviceDetector\Parser\Bot + * * @return boolean */ protected function isNonHumanBot() { $allowBots = $this->request->getParam('bots'); - return !$allowBots - // Seen in the wild - && (strpos($this->userAgent, 'Googlebot') !== false // Googlebot - || strpos($this->userAgent, 'Google Web Preview') !== false // Google Instant - || strpos($this->userAgent, 'AdsBot-Google') !== false // Google Adwords landing pages - || strpos($this->userAgent, 'Google Page Speed Insights') !== false // #4049 - || strpos($this->userAgent, 'Google (+https://developers.google.com') !== false // Google Snippet https://developers.google.com/+/web/snippet/ - || strpos($this->userAgent, 'facebookexternalhit') !== false // http://www.facebook.com/externalhit_uatext.php - || strpos($this->userAgent, 'baidu') !== false // Baidu - || strpos($this->userAgent, 'bingbot') !== false // Bingbot - || strpos($this->userAgent, 'BingPreview') !== false // BingPreview - || strpos($this->userAgent, 'YottaaMonitor') !== false // Yottaa - || strpos($this->userAgent, 'CloudFlare') !== false // CloudFlare-AlwaysOnline + $botParser = new Bot($this->userAgent); + $botParser->discardDetails(); - // Added as they are popular bots - || strpos($this->userAgent, 'pingdom') !== false // pingdom - || strpos($this->userAgent, 'yandex') !== false // yandex - || strpos($this->userAgent, 'exabot') !== false // Exabot - || strpos($this->userAgent, 'sogou') !== false // Sogou - || strpos($this->userAgent, 'soso') !== false // Soso + return !$allowBots + && ($botParser->parse() === true || IP::isIpInRange($this->ip, $this->getBotIpRanges())); } From b826190f10c4cad57b542e8634f3bce0607aba42 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Thu, 29 May 2014 23:37:04 +0200 Subject: [PATCH 08/78] fixed test --- ...VisitsDetails_sortAsc__Live.getLastVisitsDetails_month.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/PHPUnit/Integration/expected/test_ManyVisitorsOneWebsiteTest_Live.getLastVisitsDetails_sortAsc__Live.getLastVisitsDetails_month.xml b/tests/PHPUnit/Integration/expected/test_ManyVisitorsOneWebsiteTest_Live.getLastVisitsDetails_sortAsc__Live.getLastVisitsDetails_month.xml index 86ae52a0733..7cebbfae049 100644 --- a/tests/PHPUnit/Integration/expected/test_ManyVisitorsOneWebsiteTest_Live.getLastVisitsDetails_sortAsc__Live.getLastVisitsDetails_month.xml +++ b/tests/PHPUnit/Integration/expected/test_ManyVisitorsOneWebsiteTest_Live.getLastVisitsDetails_sortAsc__Live.getLastVisitsDetails_month.xml @@ -104,7 +104,7 @@ FF 3.6 normal - Unknown + Desktop 1024x768 plugins/UserSettings/images/screens/normal.gif flash, java @@ -476,7 +476,7 @@ FF 3.6 normal - Unknown + Desktop 1024x768 plugins/UserSettings/images/screens/normal.gif flash, java From f85f7d61d9a398b812920c6121461d518349e21a Mon Sep 17 00:00:00 2001 From: sgiehl Date: Thu, 29 May 2014 23:48:56 +0200 Subject: [PATCH 09/78] reimplemented caching; fixed detection of BOT 'os' --- composer.lock | 8 ++++---- core/CacheFile.php | 2 +- core/Tracker/Settings.php | 12 ++++++++--- libs/UserAgentParser/UserAgentParser.php | 3 +++ piwik.php | 20 +++++++++---------- plugins/DevicesDetection/DevicesDetection.php | 2 +- plugins/DevicesDetection/functions.php | 6 ++++++ tests/PHPUnit/bootstrap.php | 6 +++--- tests/PHPUnit/proxy/includes.php | 4 ++++ 9 files changed, 41 insertions(+), 22 deletions(-) diff --git a/composer.lock b/composer.lock index a9822dc62a1..a440208ae18 100644 --- a/composer.lock +++ b/composer.lock @@ -100,12 +100,12 @@ "source": { "type": "git", "url": "https://github.com/piwik/device-detector.git", - "reference": "d3ccb7938fa272a857c279850ffbb3d8fe04c0b7" + "reference": "863ae43f5c68c15ce110516a0f7b11477e2a01c0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/piwik/device-detector/zipball/d3ccb7938fa272a857c279850ffbb3d8fe04c0b7", - "reference": "d3ccb7938fa272a857c279850ffbb3d8fe04c0b7", + "url": "https://api.github.com/repos/piwik/device-detector/zipball/863ae43f5c68c15ce110516a0f7b11477e2a01c0", + "reference": "863ae43f5c68c15ce110516a0f7b11477e2a01c0", "shasum": "" }, "require": { @@ -139,7 +139,7 @@ "parser", "useragent" ], - "time": "2014-05-25 17:45:14" + "time": "2014-05-29 20:51:28" }, { "name": "symfony/console", diff --git a/core/CacheFile.php b/core/CacheFile.php index 5d9000332f7..f75657f1762 100644 --- a/core/CacheFile.php +++ b/core/CacheFile.php @@ -16,7 +16,7 @@ * It is for example used by the Tracker process to cache various settings and websites attributes in tmp/cache/tracker/* * */ -class CacheFile +class CacheFile implements \DeviceDetector\Cache\CacheInterface { // for testing purposes since tests run on both CLI/FPM (changes in CLI can't invalidate // opcache in FPM, so we have to invalidate before reading) diff --git a/core/Tracker/Settings.php b/core/Tracker/Settings.php index 3eed338f3ba..251046ca298 100644 --- a/core/Tracker/Settings.php +++ b/core/Tracker/Settings.php @@ -38,8 +38,10 @@ protected function loadInfo() $userAgent = $this->request->getUserAgent(); $deviceDetector = new DeviceDetector($userAgent); - #$deviceDetector->setCache(new CacheFile('tracker', 86400)); + $deviceDetector->discardBotInformation(); + $deviceDetector->setCache(new CacheFile('tracker', 86400)); $deviceDetector->parse(); + $aBrowserInfo = $deviceDetector->getClient(); if ($aBrowserInfo['type'] != 'browser') { // for now only track browsers @@ -49,8 +51,12 @@ protected function loadInfo() $browserName = !empty($aBrowserInfo['short_name']) ? $aBrowserInfo['short_name'] : 'UNK'; $browserVersion = !empty($aBrowserInfo['version']) ? $aBrowserInfo['version'] : ''; - $os = $deviceDetector->getOS(); - $os = empty($os['short_name']) ? 'UNK' : $os['short_name']; + if ($deviceDetector->isBot()) { + $os = 'BOT'; + } else { + $os = $deviceDetector->getOS(); + $os = empty($os['short_name']) ? 'UNK' : $os['short_name']; + } $browserLang = substr($this->request->getBrowserLanguage(), 0, 20); // limit the length of this string to match db $configurationHash = $this->getConfigHash( diff --git a/libs/UserAgentParser/UserAgentParser.php b/libs/UserAgentParser/UserAgentParser.php index c0c8fea1ce1..009bc5a7853 100644 --- a/libs/UserAgentParser/UserAgentParser.php +++ b/libs/UserAgentParser/UserAgentParser.php @@ -694,6 +694,9 @@ static public function getOperatingSystemNameFromId($osId) } if(class_exists('DeviceDetector\\Parser\\OperatingSystem')) { + if ($osId == 'BOT') { + return 'Bot'; + } return DeviceDetector\Parser\OperatingSystem::getNameFromId($osId); } return false; diff --git a/piwik.php b/piwik.php index 00c2041a52e..03e405cdd94 100644 --- a/piwik.php +++ b/piwik.php @@ -40,6 +40,16 @@ @ignore_user_abort(true); +/* + * Manually require needed vendor libraries, as composers autorequire would do too much + */ +if (file_exists(PIWIK_INCLUDE_PATH . '/vendor/autoload.php')) { + $vendorDirectory = PIWIK_INCLUDE_PATH . '/vendor'; +} else { + $vendorDirectory = PIWIK_INCLUDE_PATH . '/../..'; +} +require_once $vendorDirectory . '/autoload.php'; + require_once PIWIK_INCLUDE_PATH . '/core/Plugin/Controller.php'; require_once PIWIK_INCLUDE_PATH . '/core/Plugin/ControllerAdmin.php'; @@ -82,16 +92,6 @@ require_once PIWIK_INCLUDE_PATH . '/core/Cookie.php'; require_once PIWIK_INCLUDE_PATH . '/core/Loader.php'; -/* - * Manually require needed vendor libraries, as composers autorequire would do too much - */ -if (file_exists(PIWIK_INCLUDE_PATH . '/vendor/autoload.php')) { - $vendorDirectory = PIWIK_INCLUDE_PATH . '/vendor'; -} else { - $vendorDirectory = PIWIK_INCLUDE_PATH . '/../..'; -} -require_once $vendorDirectory . '/autoload.php'; - session_cache_limiter('nocache'); @date_default_timezone_set('UTC'); diff --git a/plugins/DevicesDetection/DevicesDetection.php b/plugins/DevicesDetection/DevicesDetection.php index 5d6312e8f0a..9b8cf601d18 100644 --- a/plugins/DevicesDetection/DevicesDetection.php +++ b/plugins/DevicesDetection/DevicesDetection.php @@ -244,7 +244,7 @@ public function parseMobileVisitData(&$visitorInfo, \Piwik\Tracker\Request $requ $userAgent = $request->getUserAgent(); $UAParser = new DeviceDetector($userAgent); - #$UAParser->setCache(new CacheFile('tracker', 86400)); + $UAParser->setCache(new CacheFile('tracker', 86400)); $UAParser->parse(); $deviceInfo['config_browser_name'] = $UAParser->getClient("type") == 'browser' ? $UAParser->getClient("short_name") : 'UNK'; $deviceInfo['config_browser_version'] = $UAParser->getClient("type") == 'browser' ? $UAParser->getClient("version") : 'UNK'; diff --git a/plugins/DevicesDetection/functions.php b/plugins/DevicesDetection/functions.php index b8ff3a8854c..085a35814c9 100644 --- a/plugins/DevicesDetection/functions.php +++ b/plugins/DevicesDetection/functions.php @@ -165,6 +165,9 @@ function getModelName($label) function getOSFamilyFullNameExtended($label) { + if ($label == 'BOT') { + return 'Bot'; + } $label = OperatingSystemParser::getOsFamily($label); if($label !== false) { return $label; @@ -183,6 +186,9 @@ function getOsFamilyLogoExtended($label) function getOsFullNameExtended($label) { + if ($label == 'BOT') { + return 'Bot'; + } if (!empty($label) && $label != ";") { $os = substr($label, 0, 3); $ver = substr($label, 4, 15); diff --git a/tests/PHPUnit/bootstrap.php b/tests/PHPUnit/bootstrap.php index 1dcb995b0ea..c951e4a3c62 100644 --- a/tests/PHPUnit/bootstrap.php +++ b/tests/PHPUnit/bootstrap.php @@ -27,6 +27,9 @@ error_reporting(E_ALL | E_NOTICE); @date_default_timezone_set('UTC'); +require_once file_exists(PIWIK_INCLUDE_PATH . '/vendor/autoload.php') + ? PIWIK_INCLUDE_PATH . '/vendor/autoload.php' // Piwik is the main project + : PIWIK_INCLUDE_PATH . '/../../autoload.php'; // Piwik is installed as a dependency require_once PIWIK_INCLUDE_PATH . '/libs/upgradephp/upgrade.php'; require_once PIWIK_INCLUDE_PATH . '/core/testMinimumPhpVersion.php'; @@ -37,9 +40,6 @@ require_once PIWIK_INCLUDE_PATH . '/tests/PHPUnit/FakeAccess.php'; require_once PIWIK_INCLUDE_PATH . '/tests/PHPUnit/MockPiwikOption.php'; require_once PIWIK_INCLUDE_PATH . '/tests/PHPUnit/TestingEnvironment.php'; -require_once file_exists(PIWIK_INCLUDE_PATH . '/vendor/autoload.php') - ? PIWIK_INCLUDE_PATH . '/vendor/autoload.php' // Piwik is the main project - : PIWIK_INCLUDE_PATH . '/../../autoload.php'; // Piwik is installed as a dependency \Piwik\Profiler::setupProfilerXHProf( $mainRun = true ); diff --git a/tests/PHPUnit/proxy/includes.php b/tests/PHPUnit/proxy/includes.php index 0ffce4642b2..2ecb204244a 100644 --- a/tests/PHPUnit/proxy/includes.php +++ b/tests/PHPUnit/proxy/includes.php @@ -9,6 +9,10 @@ define('PIWIK_USER_PATH', PIWIK_INCLUDE_PATH); } +require_once file_exists(PIWIK_INCLUDE_PATH . '/vendor/autoload.php') + ? PIWIK_INCLUDE_PATH . '/vendor/autoload.php' // Piwik is the main project + : PIWIK_INCLUDE_PATH . '/../../autoload.php'; // Piwik is installed as a dependency + require_once PIWIK_INCLUDE_PATH . '/core/Loader.php'; require_once PIWIK_INCLUDE_PATH . '/core/EventDispatcher.php'; require_once PIWIK_INCLUDE_PATH . '/core/Piwik.php'; From 0c4d1442225cad7fd224c2f274a90ec6c9a0bbea Mon Sep 17 00:00:00 2001 From: sgiehl Date: Fri, 30 May 2014 00:47:59 +0200 Subject: [PATCH 10/78] fixed detection of legacy BOT os --- plugins/DevicesDetection/DevicesDetection.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/DevicesDetection/DevicesDetection.php b/plugins/DevicesDetection/DevicesDetection.php index 9b8cf601d18..dc915e359f5 100644 --- a/plugins/DevicesDetection/DevicesDetection.php +++ b/plugins/DevicesDetection/DevicesDetection.php @@ -244,11 +244,12 @@ public function parseMobileVisitData(&$visitorInfo, \Piwik\Tracker\Request $requ $userAgent = $request->getUserAgent(); $UAParser = new DeviceDetector($userAgent); + $UAParser->discardBotInformation(); $UAParser->setCache(new CacheFile('tracker', 86400)); $UAParser->parse(); $deviceInfo['config_browser_name'] = $UAParser->getClient("type") == 'browser' ? $UAParser->getClient("short_name") : 'UNK'; $deviceInfo['config_browser_version'] = $UAParser->getClient("type") == 'browser' ? $UAParser->getClient("version") : 'UNK'; - $deviceInfo['config_os'] = $UAParser->getOs("short_name"); + $deviceInfo['config_os'] = $UAParser->isBot() ? 'BOT' : $UAParser->getOs("short_name"); $deviceInfo['config_os_version'] = $UAParser->getOs("version"); $deviceInfo['config_device_type'] = $UAParser->getDevice(); $deviceInfo['config_device_model'] = $UAParser->getModel(); From fc03712e98c2a437b74284cc6d86a8589aca71e6 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Fri, 30 May 2014 11:27:41 +0200 Subject: [PATCH 11/78] fixed detection for 'unknown' device types; fixed tests --- plugins/DevicesDetection/functions.php | 2 +- ...rtLogs__DevicesDetection.getType_month.xml | 21 ++++++++++++++----- ...tLogs__Live.getLastVisitsDetails_range.xml | 8 +++---- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/plugins/DevicesDetection/functions.php b/plugins/DevicesDetection/functions.php index 085a35814c9..c28882b4bd6 100644 --- a/plugins/DevicesDetection/functions.php +++ b/plugins/DevicesDetection/functions.php @@ -119,7 +119,7 @@ function getDeviceTypeLabel($label) $deviceTypes = DeviceParser::getAvailableDeviceTypes(); - if (in_array($label, $deviceTypes) && isset($translations[array_search($label, $deviceTypes)])) { + if (is_numeric($label) && in_array($label, $deviceTypes) && isset($translations[array_search($label, $deviceTypes)])) { return Piwik::translate($translations[array_search($label, $deviceTypes)]); } else if (isset($translations[$label])) { return Piwik::translate($translations[$label]); diff --git a/tests/PHPUnit/Integration/expected/test_ImportLogs__DevicesDetection.getType_month.xml b/tests/PHPUnit/Integration/expected/test_ImportLogs__DevicesDetection.getType_month.xml index bc13cbdb128..524f43508d0 100644 --- a/tests/PHPUnit/Integration/expected/test_ImportLogs__DevicesDetection.getType_month.xml +++ b/tests/PHPUnit/Integration/expected/test_ImportLogs__DevicesDetection.getType_month.xml @@ -2,15 +2,26 @@ - 25 - 28 + 23 + 26 3 305 - 23 - 23 - 25 + 21 + 22 + 23 plugins/DevicesDetection/images/screens/normal.gif + + + 2 + 2 + 1 + 0 + 2 + 1 + 2 + plugins/DevicesDetection/images/screens/unknown.gif + 2 diff --git a/tests/PHPUnit/Integration/expected/test_ImportLogs__Live.getLastVisitsDetails_range.xml b/tests/PHPUnit/Integration/expected/test_ImportLogs__Live.getLastVisitsDetails_range.xml index 923b92e3f28..f4228a61cc8 100644 --- a/tests/PHPUnit/Integration/expected/test_ImportLogs__Live.getLastVisitsDetails_range.xml +++ b/tests/PHPUnit/Integration/expected/test_ImportLogs__Live.getLastVisitsDetails_range.xml @@ -983,7 +983,7 @@ FF 27.0 mobile - Desktop + Unknown 360x640 plugins/UserSettings/images/screens/mobile.gif flash @@ -1789,7 +1789,7 @@ UNK UNK unknown - Desktop + Unknown unknown plugins/UserSettings/images/screens/unknown.gif @@ -2514,7 +2514,7 @@ UNK UNK unknown - Desktop + Unknown unknown plugins/UserSettings/images/screens/unknown.gif @@ -2718,7 +2718,7 @@ UNK UNK unknown - Desktop + Unknown unknown plugins/UserSettings/images/screens/unknown.gif From 771f5f390645b22e05c4ec84ae46085c76e90172 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Fri, 30 May 2014 15:23:57 +0200 Subject: [PATCH 12/78] bots never contain a version --- plugins/DevicesDetection/functions.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/DevicesDetection/functions.php b/plugins/DevicesDetection/functions.php index c28882b4bd6..c61cf85c850 100644 --- a/plugins/DevicesDetection/functions.php +++ b/plugins/DevicesDetection/functions.php @@ -186,7 +186,7 @@ function getOsFamilyLogoExtended($label) function getOsFullNameExtended($label) { - if ($label == 'BOT') { + if (substr($label, 0, 3) == 'BOT') { return 'Bot'; } if (!empty($label) && $label != ";") { From 55f53dadc058bc0592df9ca812b72d7d885fd21e Mon Sep 17 00:00:00 2001 From: sgiehl Date: Fri, 30 May 2014 22:30:47 +0200 Subject: [PATCH 13/78] fixed test --- ...VisitsDetails_sortAsc__Live.getLastVisitsDetails_month.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/PHPUnit/Integration/expected/test_ManyVisitorsOneWebsiteTest_Live.getLastVisitsDetails_sortAsc__Live.getLastVisitsDetails_month.xml b/tests/PHPUnit/Integration/expected/test_ManyVisitorsOneWebsiteTest_Live.getLastVisitsDetails_sortAsc__Live.getLastVisitsDetails_month.xml index 7cebbfae049..86ae52a0733 100644 --- a/tests/PHPUnit/Integration/expected/test_ManyVisitorsOneWebsiteTest_Live.getLastVisitsDetails_sortAsc__Live.getLastVisitsDetails_month.xml +++ b/tests/PHPUnit/Integration/expected/test_ManyVisitorsOneWebsiteTest_Live.getLastVisitsDetails_sortAsc__Live.getLastVisitsDetails_month.xml @@ -104,7 +104,7 @@ FF 3.6 normal - Desktop + Unknown 1024x768 plugins/UserSettings/images/screens/normal.gif flash, java @@ -476,7 +476,7 @@ FF 3.6 normal - Desktop + Unknown 1024x768 plugins/UserSettings/images/screens/normal.gif flash, java From eaf1036670082fcedeae42d03624c9312a5db271 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Sat, 31 May 2014 00:02:48 +0200 Subject: [PATCH 14/78] use latest DeviceDetector release (2.0) --- composer.json | 2 +- composer.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index eef9ed3d8e8..3015cb736b5 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "symfony/console": ">=v2.3.5", "tedivm/jshrink": "v0.5.1", "mustangostang/spyc": "0.5.*", - "piwik/device-detector": "dev-master" + "piwik/device-detector": "2.*" }, "require-dev": { "phpunit/phpunit": "4.*" diff --git a/composer.lock b/composer.lock index a440208ae18..90002e86c01 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "8432cff50123bf1d2eaf0c1a56b0b72f", + "hash": "4608e7a637e41e4ba55deba353d4765d", "packages": [ { "name": "leafo/lessphp", @@ -96,7 +96,7 @@ }, { "name": "piwik/device-detector", - "version": "dev-master", + "version": "2.0", "source": { "type": "git", "url": "https://github.com/piwik/device-detector.git", @@ -996,9 +996,9 @@ ], "minimum-stability": "stable", - "stability-flags": { - "piwik/device-detector": 20 - }, + "stability-flags": [ + + ], "platform": { "php": ">=5.3.2" }, From 0d7b51944e9b1c18859dcb99ed6397859ca17e07 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Sat, 31 May 2014 20:50:25 +0200 Subject: [PATCH 15/78] added special DeviceDetectorCache class used for caching DeviceDetector. This cache combines file and static caching to speed up detections as much as possible --- core/CacheFile.php | 2 +- core/DeviceDetectorCache.php | 65 +++++++++++++++++++ core/Tracker/Settings.php | 4 +- core/Tracker/Visit.php | 1 - piwik.php | 3 - plugins/DevicesDetection/DevicesDetection.php | 4 +- 6 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 core/DeviceDetectorCache.php diff --git a/core/CacheFile.php b/core/CacheFile.php index f75657f1762..5d9000332f7 100644 --- a/core/CacheFile.php +++ b/core/CacheFile.php @@ -16,7 +16,7 @@ * It is for example used by the Tracker process to cache various settings and websites attributes in tmp/cache/tracker/* * */ -class CacheFile implements \DeviceDetector\Cache\CacheInterface +class CacheFile { // for testing purposes since tests run on both CLI/FPM (changes in CLI can't invalidate // opcache in FPM, so we have to invalidate before reading) diff --git a/core/DeviceDetectorCache.php b/core/DeviceDetectorCache.php new file mode 100644 index 00000000000..744560df92b --- /dev/null +++ b/core/DeviceDetectorCache.php @@ -0,0 +1,65 @@ +cleanupId($id); + + if (array_key_exists($id, self::$staticCache)) { + return self::$staticCache[$id]; + } + + return parent::get($id); + } + + + /** + * A function to store content a cache entry. + * + * @param string $id The cache entry ID + * @param array $content The cache content + * @throws \Exception + * @return bool True if the entry was succesfully stored + */ + public function set($id, $content) + { + if (empty($id)) { + return false; + } + + $id = $this->cleanupId($id); + + self::$staticCache[$id] = $content; + + return parent::set($id, $content); + } +} diff --git a/core/Tracker/Settings.php b/core/Tracker/Settings.php index 251046ca298..8aa5b9a0df3 100644 --- a/core/Tracker/Settings.php +++ b/core/Tracker/Settings.php @@ -8,7 +8,7 @@ */ namespace Piwik\Tracker; -use Piwik\CacheFile; +use Piwik\DeviceDetectorCache; use Piwik\Tracker; use DeviceDetector\DeviceDetector; @@ -39,7 +39,7 @@ protected function loadInfo() $deviceDetector = new DeviceDetector($userAgent); $deviceDetector->discardBotInformation(); - $deviceDetector->setCache(new CacheFile('tracker', 86400)); + $deviceDetector->setCache(new DeviceDetectorCache('tracker', 86400)); $deviceDetector->parse(); $aBrowserInfo = $deviceDetector->getClient(); diff --git a/core/Tracker/Visit.php b/core/Tracker/Visit.php index 75a11e128a3..643c6bf31bb 100644 --- a/core/Tracker/Visit.php +++ b/core/Tracker/Visit.php @@ -9,7 +9,6 @@ namespace Piwik\Tracker; -use DeviceDetector\DeviceDetector; use Piwik\Common; use Piwik\Config; use Piwik\IP; diff --git a/piwik.php b/piwik.php index 03e405cdd94..25528679363 100644 --- a/piwik.php +++ b/piwik.php @@ -40,9 +40,6 @@ @ignore_user_abort(true); -/* - * Manually require needed vendor libraries, as composers autorequire would do too much - */ if (file_exists(PIWIK_INCLUDE_PATH . '/vendor/autoload.php')) { $vendorDirectory = PIWIK_INCLUDE_PATH . '/vendor'; } else { diff --git a/plugins/DevicesDetection/DevicesDetection.php b/plugins/DevicesDetection/DevicesDetection.php index dc915e359f5..c6c9262f05b 100644 --- a/plugins/DevicesDetection/DevicesDetection.php +++ b/plugins/DevicesDetection/DevicesDetection.php @@ -13,9 +13,9 @@ use DeviceDetector\DeviceDetector; use Exception; use Piwik\ArchiveProcessor; -use Piwik\CacheFile; use Piwik\Common; use Piwik\Db; +use Piwik\DeviceDetectorCache; use Piwik\Piwik; use Piwik\Plugin\ViewDataTable; use Piwik\WidgetsList; @@ -245,7 +245,7 @@ public function parseMobileVisitData(&$visitorInfo, \Piwik\Tracker\Request $requ $UAParser = new DeviceDetector($userAgent); $UAParser->discardBotInformation(); - $UAParser->setCache(new CacheFile('tracker', 86400)); + $UAParser->setCache(new DeviceDetectorCache('tracker', 86400)); $UAParser->parse(); $deviceInfo['config_browser_name'] = $UAParser->getClient("type") == 'browser' ? $UAParser->getClient("short_name") : 'UNK'; $deviceInfo['config_browser_version'] = $UAParser->getClient("type") == 'browser' ? $UAParser->getClient("version") : 'UNK'; From 2ceaab4b595bf667abf9b4edb6705a04dce0402b Mon Sep 17 00:00:00 2001 From: sgiehl Date: Tue, 3 Jun 2014 18:39:30 +0200 Subject: [PATCH 16/78] do detection only once --- core/Tracker/Settings.php | 4 ++++ plugins/DevicesDetection/DevicesDetection.php | 22 ------------------- 2 files changed, 4 insertions(+), 22 deletions(-) diff --git a/core/Tracker/Settings.php b/core/Tracker/Settings.php index 8aa5b9a0df3..3e2a289e0a0 100644 --- a/core/Tracker/Settings.php +++ b/core/Tracker/Settings.php @@ -79,8 +79,12 @@ protected function loadInfo() $this->params = array( 'config_id' => $configurationHash, 'config_os' => $os, + 'config_os_version' => $deviceDetector->getOs('version'), 'config_browser_name' => $browserName, 'config_browser_version' => $browserVersion, + 'config_device_type' => $deviceDetector->getDevice(), + 'config_device_model' => $deviceDetector->getModel(), + 'config_device_brand' => $deviceDetector->getBrand(), 'config_resolution' => $resolution, 'config_pdf' => $plugin_PDF, 'config_flash' => $plugin_Flash, diff --git a/plugins/DevicesDetection/DevicesDetection.php b/plugins/DevicesDetection/DevicesDetection.php index c6c9262f05b..87f1a54064d 100644 --- a/plugins/DevicesDetection/DevicesDetection.php +++ b/plugins/DevicesDetection/DevicesDetection.php @@ -88,7 +88,6 @@ protected function getRawMetadataDeviceType() public function getListHooksRegistered() { return array( - 'Tracker.newVisitorInformation' => 'parseMobileVisitData', 'WidgetsList.addWidgets' => 'addWidgets', 'API.getReportMetadata' => 'getReportMetadata', 'API.getSegmentDimensionMetadata' => 'getSegmentsMetadata', @@ -239,27 +238,6 @@ public function install() } } - public function parseMobileVisitData(&$visitorInfo, \Piwik\Tracker\Request $request) - { - $userAgent = $request->getUserAgent(); - - $UAParser = new DeviceDetector($userAgent); - $UAParser->discardBotInformation(); - $UAParser->setCache(new DeviceDetectorCache('tracker', 86400)); - $UAParser->parse(); - $deviceInfo['config_browser_name'] = $UAParser->getClient("type") == 'browser' ? $UAParser->getClient("short_name") : 'UNK'; - $deviceInfo['config_browser_version'] = $UAParser->getClient("type") == 'browser' ? $UAParser->getClient("version") : 'UNK'; - $deviceInfo['config_os'] = $UAParser->isBot() ? 'BOT' : $UAParser->getOs("short_name"); - $deviceInfo['config_os_version'] = $UAParser->getOs("version"); - $deviceInfo['config_device_type'] = $UAParser->getDevice(); - $deviceInfo['config_device_model'] = $UAParser->getModel(); - $deviceInfo['config_device_brand'] = $UAParser->getBrand(); - - $visitorInfo = array_merge($visitorInfo, $deviceInfo); - Common::printDebug("Device Detection:"); - Common::printDebug($deviceInfo); - } - public function configureViewDataTable(ViewDataTable $view) { switch ($view->requestConfig->apiMethodToRequestDataTable) { From f85934195e6a078592e0a2de8c3f990864653655 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Sat, 7 Jun 2014 21:32:48 +0200 Subject: [PATCH 17/78] also set additional visitor data by default --- core/Tracker/Visit.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/Tracker/Visit.php b/core/Tracker/Visit.php index 2a2395ae4a4..a0f7be03eee 100644 --- a/core/Tracker/Visit.php +++ b/core/Tracker/Visit.php @@ -568,9 +568,13 @@ protected function getNewVisitorInformation($action) 'referer_keyword' => $referrerInfo['referer_keyword'], 'config_id' => $userInfo['config_id'], 'config_os' => $userInfo['config_os'], + 'config_os_version' => $userInfo['config_os_version'], 'config_browser_name' => $userInfo['config_browser_name'], 'config_browser_version' => $userInfo['config_browser_version'], 'config_resolution' => $userInfo['config_resolution'], + 'config_device_type' => $userInfo['config_device_type'], + 'config_device_model' => $userInfo['config_device_model'], + 'config_device_brand' => $userInfo['config_device_brand'], 'config_pdf' => $userInfo['config_pdf'], 'config_flash' => $userInfo['config_flash'], 'config_java' => $userInfo['config_java'], From 6e9d1c76e065c7c2cc031cede76d3c037124152e Mon Sep 17 00:00:00 2001 From: sgiehl Date: Sat, 7 Jun 2014 21:58:20 +0200 Subject: [PATCH 18/78] set version to UNK if there is none detected --- core/Tracker/Settings.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/Tracker/Settings.php b/core/Tracker/Settings.php index 3e2a289e0a0..8c7b43b5965 100644 --- a/core/Tracker/Settings.php +++ b/core/Tracker/Settings.php @@ -49,7 +49,7 @@ protected function loadInfo() } $browserName = !empty($aBrowserInfo['short_name']) ? $aBrowserInfo['short_name'] : 'UNK'; - $browserVersion = !empty($aBrowserInfo['version']) ? $aBrowserInfo['version'] : ''; + $browserVersion = !empty($aBrowserInfo['version']) ? $aBrowserInfo['version'] : 'UNK'; if ($deviceDetector->isBot()) { $os = 'BOT'; From 70ab6597a3ecf26f565c29161b796e37fe985a03 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Sat, 7 Jun 2014 22:33:47 +0200 Subject: [PATCH 19/78] revert last commit; fixed failing test --- core/Tracker/Settings.php | 2 +- .../test_ImportLogs__Live.getLastVisitsDetails_range.xml | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/Tracker/Settings.php b/core/Tracker/Settings.php index 8c7b43b5965..3e2a289e0a0 100644 --- a/core/Tracker/Settings.php +++ b/core/Tracker/Settings.php @@ -49,7 +49,7 @@ protected function loadInfo() } $browserName = !empty($aBrowserInfo['short_name']) ? $aBrowserInfo['short_name'] : 'UNK'; - $browserVersion = !empty($aBrowserInfo['version']) ? $aBrowserInfo['version'] : 'UNK'; + $browserVersion = !empty($aBrowserInfo['version']) ? $aBrowserInfo['version'] : ''; if ($deviceDetector->isBot()) { $os = 'BOT'; diff --git a/tests/PHPUnit/Integration/expected/test_ImportLogs__Live.getLastVisitsDetails_range.xml b/tests/PHPUnit/Integration/expected/test_ImportLogs__Live.getLastVisitsDetails_range.xml index f4228a61cc8..14213e25adf 100644 --- a/tests/PHPUnit/Integration/expected/test_ImportLogs__Live.getLastVisitsDetails_range.xml +++ b/tests/PHPUnit/Integration/expected/test_ImportLogs__Live.getLastVisitsDetails_range.xml @@ -1787,7 +1787,7 @@ Unknown plugins/UserSettings/images/browsers/UNK.gif UNK - UNK + unknown Unknown unknown @@ -2512,7 +2512,7 @@ Unknown plugins/UserSettings/images/browsers/UNK.gif UNK - UNK + unknown Unknown unknown @@ -2716,7 +2716,7 @@ Unknown plugins/UserSettings/images/browsers/UNK.gif UNK - UNK + unknown Unknown unknown From c65f56d740a56de624e83ffe32d0ce82aeb08f7f Mon Sep 17 00:00:00 2001 From: sgiehl Date: Sat, 7 Jun 2014 23:08:25 +0200 Subject: [PATCH 20/78] improved doc --- core/DeviceDetectorCache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/DeviceDetectorCache.php b/core/DeviceDetectorCache.php index 744560df92b..eab44a92977 100644 --- a/core/DeviceDetectorCache.php +++ b/core/DeviceDetectorCache.php @@ -15,7 +15,7 @@ * * Combines Piwik\CacheFile with an additional caching in static property * - * Static caching speeds up multiple detections in one request, which is mostly the case when importing logs + * Static caching speeds up multiple detections in one request, which is the case when sending bulk requests */ class DeviceDetectorCache extends CacheFile implements \DeviceDetector\Cache\CacheInterface { From 12b27e8701b2895b0daa87dbb4bacab5cc60147d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyril=20Bont=C3=A9?= Date: Sun, 8 Jun 2014 01:00:43 +0200 Subject: [PATCH 21/78] cache parsed DeviceDetector instances for bulk requests By caching parsed DeviceDetectors, we reduce the number of regexes to process. It allows to process more requests per second when the same user agent is met. --- core/Tracker/Settings.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/core/Tracker/Settings.php b/core/Tracker/Settings.php index 3e2a289e0a0..8c8ff1a773b 100644 --- a/core/Tracker/Settings.php +++ b/core/Tracker/Settings.php @@ -11,6 +11,7 @@ use Piwik\DeviceDetectorCache; use Piwik\Tracker; use DeviceDetector\DeviceDetector; +use DeviceDetector\Cache\CacheStatic; class Settings { @@ -37,10 +38,17 @@ protected function loadInfo() $resolution = $this->request->getParam('res'); $userAgent = $this->request->getUserAgent(); - $deviceDetector = new DeviceDetector($userAgent); - $deviceDetector->discardBotInformation(); - $deviceDetector->setCache(new DeviceDetectorCache('tracker', 86400)); - $deviceDetector->parse(); + static $deviceDetectorsCache; + $deviceDetectorsCache = new CacheStatic(); + $deviceDetector = $deviceDetectorsCache->get($userAgent); + if (! $deviceDetector) { + $deviceDetector = new DeviceDetector($userAgent); + $deviceDetector->discardBotInformation(); + $deviceDetector->setCache(new DeviceDetectorCache('tracker', 86400)); + $deviceDetector->parse(); + + $deviceDetectorsCache->set($userAgent, $deviceDetector); + } $aBrowserInfo = $deviceDetector->getClient(); if ($aBrowserInfo['type'] != 'browser') { From 9c861a929cfd4a7eca14e1ce6aa9e993a8213e7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cyril=20Bont=C3=A9?= Date: Sun, 8 Jun 2014 01:50:04 +0200 Subject: [PATCH 22/78] Use its own static array to store DeviceDetector instances The previous commit had at least 2 issues : one identified by sgiehl, who reported that the static variable was useless if we always create a new cache instance, and indeed, he's absolutely right ! Another one can be classified as a potential security issue, where a request can forge a user agent as a key to an object which is not meant to be accessed (CacheStatic instances share their data). --- core/Tracker/Settings.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/Tracker/Settings.php b/core/Tracker/Settings.php index 8c8ff1a773b..65bb17fb948 100644 --- a/core/Tracker/Settings.php +++ b/core/Tracker/Settings.php @@ -11,7 +11,6 @@ use Piwik\DeviceDetectorCache; use Piwik\Tracker; use DeviceDetector\DeviceDetector; -use DeviceDetector\Cache\CacheStatic; class Settings { @@ -38,16 +37,17 @@ protected function loadInfo() $resolution = $this->request->getParam('res'); $userAgent = $this->request->getUserAgent(); - static $deviceDetectorsCache; - $deviceDetectorsCache = new CacheStatic(); - $deviceDetector = $deviceDetectorsCache->get($userAgent); - if (! $deviceDetector) { + static $deviceDetectorsCache = array(); + if (array_key_exists($userAgent, $deviceDetectorsCache)) { + $deviceDetector = $deviceDetectorsCache[$userAgent]; + } + else { $deviceDetector = new DeviceDetector($userAgent); $deviceDetector->discardBotInformation(); $deviceDetector->setCache(new DeviceDetectorCache('tracker', 86400)); $deviceDetector->parse(); - $deviceDetectorsCache->set($userAgent, $deviceDetector); + $deviceDetectorsCache[$userAgent] = $deviceDetector; } $aBrowserInfo = $deviceDetector->getClient(); From 08537777dacbc8888b2ff4b2bde29480d89a83a6 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Sun, 8 Jun 2014 13:12:08 +0200 Subject: [PATCH 23/78] removed unused use statements --- plugins/DevicesDetection/DevicesDetection.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugins/DevicesDetection/DevicesDetection.php b/plugins/DevicesDetection/DevicesDetection.php index 87f1a54064d..94f5bb3ced0 100644 --- a/plugins/DevicesDetection/DevicesDetection.php +++ b/plugins/DevicesDetection/DevicesDetection.php @@ -10,12 +10,10 @@ namespace Piwik\Plugins\DevicesDetection; use DeviceDetector\Parser\Device\DeviceParserAbstract AS DeviceParser; -use DeviceDetector\DeviceDetector; use Exception; use Piwik\ArchiveProcessor; use Piwik\Common; use Piwik\Db; -use Piwik\DeviceDetectorCache; use Piwik\Piwik; use Piwik\Plugin\ViewDataTable; use Piwik\WidgetsList; From 6229e8ff5403b004e5994cf02d6721367474d17e Mon Sep 17 00:00:00 2001 From: sgiehl Date: Sun, 8 Jun 2014 19:51:46 +0200 Subject: [PATCH 24/78] introduce devicedetector factory to get singleton instances of devicedetector based on the given user agent. That provides the possibility to reuse DeviceDetector for bot and visitor data detection. --- core/Tracker/Settings.php | 14 ++------------ core/Tracker/VisitExcluded.php | 6 +++--- 2 files changed, 5 insertions(+), 15 deletions(-) diff --git a/core/Tracker/Settings.php b/core/Tracker/Settings.php index 65bb17fb948..08d4341d200 100644 --- a/core/Tracker/Settings.php +++ b/core/Tracker/Settings.php @@ -9,6 +9,7 @@ namespace Piwik\Tracker; use Piwik\DeviceDetectorCache; +use Piwik\DeviceDetectorFactory; use Piwik\Tracker; use DeviceDetector\DeviceDetector; @@ -37,18 +38,7 @@ protected function loadInfo() $resolution = $this->request->getParam('res'); $userAgent = $this->request->getUserAgent(); - static $deviceDetectorsCache = array(); - if (array_key_exists($userAgent, $deviceDetectorsCache)) { - $deviceDetector = $deviceDetectorsCache[$userAgent]; - } - else { - $deviceDetector = new DeviceDetector($userAgent); - $deviceDetector->discardBotInformation(); - $deviceDetector->setCache(new DeviceDetectorCache('tracker', 86400)); - $deviceDetector->parse(); - - $deviceDetectorsCache[$userAgent] = $deviceDetector; - } + $deviceDetector = DeviceDetectorFactory::getInstance($userAgent); $aBrowserInfo = $deviceDetector->getClient(); if ($aBrowserInfo['type'] != 'browser') { diff --git a/core/Tracker/VisitExcluded.php b/core/Tracker/VisitExcluded.php index 60b26a88671..d7af157b4a2 100644 --- a/core/Tracker/VisitExcluded.php +++ b/core/Tracker/VisitExcluded.php @@ -11,6 +11,7 @@ use DeviceDetector\Parser\Bot; use Piwik\Common; use Piwik\Config; +use Piwik\DeviceDetectorFactory; use Piwik\IP; use Piwik\Piwik; @@ -156,11 +157,10 @@ protected function isNonHumanBot() { $allowBots = $this->request->getParam('bots'); - $botParser = new Bot($this->userAgent); - $botParser->discardDetails(); + $deviceDetector = DeviceDetectorFactory::getInstance($this->userAgent); return !$allowBots - && ($botParser->parse() === true + && ($deviceDetector->isBot() || IP::isIpInRange($this->ip, $this->getBotIpRanges())); } From 18f9b8c4ed39df73b540c91168c56e615e441975 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Sun, 8 Jun 2014 19:53:31 +0200 Subject: [PATCH 25/78] added missing class DeviceDetectorFactory --- core/DeviceDetectorFactory.php | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 core/DeviceDetectorFactory.php diff --git a/core/DeviceDetectorFactory.php b/core/DeviceDetectorFactory.php new file mode 100644 index 00000000000..f8bd1ad5ac0 --- /dev/null +++ b/core/DeviceDetectorFactory.php @@ -0,0 +1,39 @@ +discardBotInformation(); + $deviceDetector->setCache(new DeviceDetectorCache('tracker', 86400)); + $deviceDetector->parse(); + + self::$deviceDetectorInstances[$userAgent] = $deviceDetector; + + return $deviceDetector; + } + +} From 428bfff8b48a1f0f1919ce6d07fad805f93993d5 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Wed, 11 Jun 2014 18:17:03 +0200 Subject: [PATCH 26/78] fixing some integration tests --- ...ITest__Live.getLastVisitsDetails_range.xml | 28 +++++++++---------- ...sion__API.getSuggestedValuesForSegment.xml | 1 - 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/tests/PHPUnit/Integration/expected/test_AutoSuggestAPITest__Live.getLastVisitsDetails_range.xml b/tests/PHPUnit/Integration/expected/test_AutoSuggestAPITest__Live.getLastVisitsDetails_range.xml index 84105464083..247d5fbf7ab 100644 --- a/tests/PHPUnit/Integration/expected/test_AutoSuggestAPITest__Live.getLastVisitsDetails_range.xml +++ b/tests/PHPUnit/Integration/expected/test_AutoSuggestAPITest__Live.getLastVisitsDetails_range.xml @@ -1713,9 +1713,9 @@ Unknown plugins/UserSettings/images/browsers/UNK.gif UNK - UNK + normal - Desktop + Unknown 1024x768 plugins/UserSettings/images/screens/normal.gif flash, java @@ -1961,9 +1961,9 @@ Unknown plugins/UserSettings/images/browsers/UNK.gif UNK - UNK + normal - Desktop + Unknown 1024x768 plugins/UserSettings/images/screens/normal.gif flash, java @@ -2263,9 +2263,9 @@ Unknown plugins/UserSettings/images/browsers/UNK.gif UNK - UNK + normal - Desktop + Unknown 1024x768 plugins/UserSettings/images/screens/normal.gif flash, java @@ -2511,9 +2511,9 @@ Unknown plugins/UserSettings/images/browsers/UNK.gif UNK - UNK + normal - Desktop + Unknown 1024x768 plugins/UserSettings/images/screens/normal.gif flash, java @@ -2917,9 +2917,9 @@ Unknown plugins/UserSettings/images/browsers/UNK.gif UNK - UNK + normal - Desktop + Unknown 1024x768 plugins/UserSettings/images/screens/normal.gif flash, java @@ -3427,9 +3427,9 @@ Unknown plugins/UserSettings/images/browsers/UNK.gif UNK - UNK + normal - Desktop + Unknown 1024x768 plugins/UserSettings/images/screens/normal.gif flash, java @@ -4008,9 +4008,9 @@ Unknown plugins/UserSettings/images/browsers/UNK.gif UNK - UNK + normal - Desktop + Unknown 1024x768 plugins/UserSettings/images/screens/normal.gif flash, java diff --git a/tests/PHPUnit/Integration/expected/test_AutoSuggestAPITest_browserVersion__API.getSuggestedValuesForSegment.xml b/tests/PHPUnit/Integration/expected/test_AutoSuggestAPITest_browserVersion__API.getSuggestedValuesForSegment.xml index 08963463013..abcc43c819b 100644 --- a/tests/PHPUnit/Integration/expected/test_AutoSuggestAPITest_browserVersion__API.getSuggestedValuesForSegment.xml +++ b/tests/PHPUnit/Integration/expected/test_AutoSuggestAPITest_browserVersion__API.getSuggestedValuesForSegment.xml @@ -1,5 +1,4 @@ 3.6 - UNK \ No newline at end of file From 32f996a30f3b9ea4b794059c7bfd08d81ab072ea Mon Sep 17 00:00:00 2001 From: sgiehl Date: Wed, 11 Jun 2014 23:49:27 +0200 Subject: [PATCH 27/78] fixing more integration tests --- ...ecified__Live.getLastVisitsDetails_day.xml | 8 ++-- ...dReports.generateReport_month.original.csv | 3 +- ...Reports.generateReport_month.original.html | 37 ++++++++++++++++--- ...Reports.generateReport_month.original.html | 35 +++++++++++++++--- 4 files changed, 67 insertions(+), 16 deletions(-) diff --git a/tests/PHPUnit/Integration/expected/test_OneVisitor_NoKeywordSpecified__Live.getLastVisitsDetails_day.xml b/tests/PHPUnit/Integration/expected/test_OneVisitor_NoKeywordSpecified__Live.getLastVisitsDetails_day.xml index a9ba35c127c..0e713de68a3 100644 --- a/tests/PHPUnit/Integration/expected/test_OneVisitor_NoKeywordSpecified__Live.getLastVisitsDetails_day.xml +++ b/tests/PHPUnit/Integration/expected/test_OneVisitor_NoKeywordSpecified__Live.getLastVisitsDetails_day.xml @@ -74,9 +74,9 @@ Inconnu plugins/UserSettings/images/browsers/UNK.gif UNK - UNK + normal - Bureau + Inconnu 1024x768 plugins/UserSettings/images/screens/normal.gif flash, java @@ -180,9 +180,9 @@ Inconnu plugins/UserSettings/images/browsers/UNK.gif UNK - UNK + normal - Bureau + Inconnu 1024x768 plugins/UserSettings/images/screens/normal.gif flash, java diff --git a/tests/PHPUnit/Integration/expected/test_TwoVisitors_twoWebsites_differentDays_scheduled_report_in_csv__ScheduledReports.generateReport_month.original.csv b/tests/PHPUnit/Integration/expected/test_TwoVisitors_twoWebsites_differentDays_scheduled_report_in_csv__ScheduledReports.generateReport_month.original.csv index 7df9d36979a..ba5dafe7221 100644 --- a/tests/PHPUnit/Integration/expected/test_TwoVisitors_twoWebsites_differentDays_scheduled_report_in_csv__ScheduledReports.generateReport_month.original.csv +++ b/tests/PHPUnit/Integration/expected/test_TwoVisitors_twoWebsites_differentDays_scheduled_report_in_csv__ScheduledReports.generateReport_month.original.csv @@ -319,7 +319,8 @@ Unknown,10,43,0%,4.3,00:12:37,10% Device type label,nb_visits,nb_actions,conversion_rate,nb_actions_per_visit,avg_time_on_site,bounce_rate -Desktop,10,43,0%,4.3,00:12:37,10% +Unknown,8,40,0%,5,00:15:01,0% +Desktop,2,3,0%,1.5,00:03:01,50% Device brand label,nb_visits,nb_actions,conversion_rate,nb_actions_per_visit,avg_time_on_site,bounce_rate diff --git a/tests/PHPUnit/Integration/expected/test_TwoVisitors_twoWebsites_differentDays_scheduled_report_in_html_tables_and_graph__ScheduledReports.generateReport_month.original.html b/tests/PHPUnit/Integration/expected/test_TwoVisitors_twoWebsites_differentDays_scheduled_report_in_html_tables_and_graph__ScheduledReports.generateReport_month.original.html index 656a1dfc645..91152824286 100644 --- a/tests/PHPUnit/Integration/expected/test_TwoVisitors_twoWebsites_differentDays_scheduled_report_in_html_tables_and_graph__ScheduledReports.generateReport_month.original.html +++ b/tests/PHPUnit/Integration/expected/test_TwoVisitors_twoWebsites_differentDays_scheduled_report_in_html_tables_and_graph__ScheduledReports.generateReport_month.original.html @@ -5063,7 +5063,7 @@

@@ -5097,24 +5097,49 @@

+ + +   + Unknown + + 8 + + + 40 + + + 5 + + + 00:15:01 + + + 0% + + + 0% + + + +   Desktop - 10 + 2 - 43 + 3 - 4.3 + 1.5 - 00:12:37 + 00:03:01 - 10% + 50% 0% diff --git a/tests/PHPUnit/Integration/expected/test_TwoVisitors_twoWebsites_differentDays_scheduled_report_in_html_tables_only__ScheduledReports.generateReport_month.original.html b/tests/PHPUnit/Integration/expected/test_TwoVisitors_twoWebsites_differentDays_scheduled_report_in_html_tables_only__ScheduledReports.generateReport_month.original.html index e1906cdab3a..6b1e064fde3 100644 --- a/tests/PHPUnit/Integration/expected/test_TwoVisitors_twoWebsites_differentDays_scheduled_report_in_html_tables_only__ScheduledReports.generateReport_month.original.html +++ b/tests/PHPUnit/Integration/expected/test_TwoVisitors_twoWebsites_differentDays_scheduled_report_in_html_tables_only__ScheduledReports.generateReport_month.original.html @@ -4869,24 +4869,49 @@

+ + +   + Unknown + + 8 + + + 40 + + + 5 + + + 00:15:01 + + + 0% + + + 0% + + + +   Desktop - 10 + 2 - 43 + 3 - 4.3 + 1.5 - 00:12:37 + 00:03:01 - 10% + 50% 0% From 3c2525aed078da74d8afba1cd05bc128afbaf282 Mon Sep 17 00:00:00 2001 From: mattab Date: Fri, 13 Jun 2014 10:14:01 +1200 Subject: [PATCH 28/78] Display chmod when test fails --- tests/PHPUnit/Core/ReleaseCheckListTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPUnit/Core/ReleaseCheckListTest.php b/tests/PHPUnit/Core/ReleaseCheckListTest.php index cb53dde0dc3..630327ab54f 100644 --- a/tests/PHPUnit/Core/ReleaseCheckListTest.php +++ b/tests/PHPUnit/Core/ReleaseCheckListTest.php @@ -214,7 +214,7 @@ public function test_directoriesShouldBeChmod755() $valid = array('775', '755'); $command = "find $pluginsPath -type d -exec chmod 755 {} +"; $this->assertTrue(in_array($chmod, $valid), - "Some directories within plugins/ are not chmod 755. \n For example: $pathToTest \n\n". + "Some directories within plugins/ are not chmod 755 \n\nGot: $chmod for : $pathToTest \n\n". "Run this command to set all directories to 755: \n$command\n");; } } From ae2441f24e613a47c7711582a3ad00072f157578 Mon Sep 17 00:00:00 2001 From: mattab Date: Fri, 13 Jun 2014 12:32:30 +1200 Subject: [PATCH 29/78] Also allow 777 --- tests/PHPUnit/Core/ReleaseCheckListTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPUnit/Core/ReleaseCheckListTest.php b/tests/PHPUnit/Core/ReleaseCheckListTest.php index 630327ab54f..67dc9efe289 100644 --- a/tests/PHPUnit/Core/ReleaseCheckListTest.php +++ b/tests/PHPUnit/Core/ReleaseCheckListTest.php @@ -211,7 +211,7 @@ public function test_directoriesShouldBeChmod755() foreach($paths as $pathToTest) { $chmod = substr(decoct(fileperms($pathToTest)), -3); - $valid = array('775', '755'); + $valid = array('777', '775', '755'); $command = "find $pluginsPath -type d -exec chmod 755 {} +"; $this->assertTrue(in_array($chmod, $valid), "Some directories within plugins/ are not chmod 755 \n\nGot: $chmod for : $pathToTest \n\n". From e27243355ecae1ec449995a2c86ab0f836df1822 Mon Sep 17 00:00:00 2001 From: mattab Date: Fri, 13 Jun 2014 15:09:33 +1200 Subject: [PATCH 30/78] Fixes #5343 Cron core:archive: make sure the PHP cli binary is at least 5.3.2 --- core/CliMulti.php | 57 +++--------------- core/CliMulti/CliPhp.php | 87 ++++++++++++++++++++++++++++ plugins/Installation/SystemCheck.php | 18 +++++- 3 files changed, 112 insertions(+), 50 deletions(-) create mode 100644 core/CliMulti/CliPhp.php diff --git a/core/CliMulti.php b/core/CliMulti.php index af576f685db..8085631feb9 100644 --- a/core/CliMulti.php +++ b/core/CliMulti.php @@ -7,6 +7,7 @@ */ namespace Piwik; +use Piwik\CliMulti\CliPhp; use Piwik\CliMulti\Output; use Piwik\CliMulti\Process; @@ -157,11 +158,17 @@ private function generateCommandId($command) * What is missing under windows? Detection whether a process is still running in Process::isProcessStillRunning * and how to send a process into background in start() */ - private function supportsAsync() + public function supportsAsync() { return Process::isSupported() && $this->findPhpBinary(); } + private function findPhpBinary() + { + $cliPhp = new CliPhp(); + return $cliPhp->findPhpBinary(); + } + private function cleanup() { foreach ($this->processes as $pid) { @@ -204,36 +211,6 @@ public static function getTmpPath() return SettingsPiwik::rewriteTmpPathWithInstanceId($dir); } - private function findPhpBinary() - { - if (defined('PHP_BINARY') && $this->isValidPhpType(PHP_BINARY)) { - return PHP_BINARY; - } - - $bin = ''; - - if (!empty($_SERVER['_']) && Common::isPhpCliMode()) { - $bin = $this->getPhpCommandIfValid($_SERVER['_']); - } - - if (empty($bin) && !empty($_SERVER['argv'][0]) && Common::isPhpCliMode()) { - $bin = $this->getPhpCommandIfValid($_SERVER['argv'][0]); - } - - if (!$this->isValidPhpType($bin)) { - $bin = shell_exec('which php'); - } - - if (!$this->isValidPhpType($bin)) { - $bin = shell_exec('which php5'); - } - - if ($this->isValidPhpType($bin)) { - return trim($bin); - } - - return false; - } private function executeAsyncCli($url, Output $output, $cmdId) { @@ -280,23 +257,6 @@ private function appendTestmodeParamToUrlIfNeeded($url) return $url; } - private function isValidPhpType($path) - { - return !empty($path) - && false === strpos($path, 'fpm') - && false === strpos($path, 'cgi') - && false === strpos($path, 'phpunit'); - } - - private function getPhpCommandIfValid($path) - { - if (!empty($path) && is_executable($path)) { - if (0 === strpos($path, PHP_BINDIR) && $this->isValidPhpType($path)) { - return $path; - } - } - } - /** * @param array $piwikUrls * @return array @@ -316,4 +276,5 @@ private function requestUrls(array $piwikUrls) return $results; } + } diff --git a/core/CliMulti/CliPhp.php b/core/CliMulti/CliPhp.php new file mode 100644 index 00000000000..bac7b4bc4fc --- /dev/null +++ b/core/CliMulti/CliPhp.php @@ -0,0 +1,87 @@ +isValidPhpType(PHP_BINARY)) { + return PHP_BINARY; + } + + $bin = ''; + + if (!empty($_SERVER['_']) && Common::isPhpCliMode()) { + $bin = $this->getPhpCommandIfValid($_SERVER['_']); + } + + if (empty($bin) && !empty($_SERVER['argv'][0]) && Common::isPhpCliMode()) { + $bin = $this->getPhpCommandIfValid($_SERVER['argv'][0]); + } + + if (!$this->isValidPhpType($bin)) { + $bin = shell_exec('which php'); + } + + if (!$this->isValidPhpType($bin)) { + $bin = shell_exec('which php5'); + } + + if (!$this->isValidPhpType($bin)) { + return false; + } + + $bin = trim($bin); + + if (!$this->isValidPhpVersion($bin)) { + return false; + } + return $bin; + } + + private function isValidPhpVersion($bin) + { + $cliVersion = $this->getPhpVersion($bin); + $isCliVersionValid = SystemCheck::isPhpVersionValid($cliVersion); + return $isCliVersionValid; + } + + private function isValidPhpType($path) + { + return !empty($path) + && false === strpos($path, 'fpm') + && false === strpos($path, 'cgi') + && false === strpos($path, 'phpunit'); + } + + private function getPhpCommandIfValid($path) + { + if (!empty($path) && is_executable($path)) { + if (0 === strpos($path, PHP_BINDIR) && $this->isValidPhpType($path)) { + return $path; + } + } + } + + /** + * @param $bin PHP binary + * @return string + */ + private function getPhpVersion($bin) + { + $command = sprintf("%s -r 'echo phpversion();'", $bin); + $version = shell_exec($command); + return $version; + } +} diff --git a/plugins/Installation/SystemCheck.php b/plugins/Installation/SystemCheck.php index 60585cf80ad..17ee93fedaf 100644 --- a/plugins/Installation/SystemCheck.php +++ b/plugins/Installation/SystemCheck.php @@ -8,6 +8,7 @@ */ namespace Piwik\Plugins\Installation; +use Piwik\CliMulti; use Piwik\CliMulti\Process; use Piwik\Common; use Piwik\Config; @@ -59,7 +60,7 @@ public static function getSystemInformation() $infos['phpVersion_minimum'] = $piwik_minimumPHPVersion; $infos['phpVersion'] = PHP_VERSION; - $infos['phpVersion_ok'] = version_compare($piwik_minimumPHPVersion, $infos['phpVersion']) === -1; + $infos['phpVersion_ok'] = self::isPhpVersionValid($infos['phpVersion']); // critical errors $extensions = @get_loaded_extensions(); @@ -174,7 +175,9 @@ public static function getSystemInformation() } $infos['timezone'] = SettingsServer::isTimezoneSupportEnabled(); - $infos['cli_process_ok'] = Process::isSupported(); + + $process = new CliMulti(); + $infos['cli_process_ok'] = $process->supportsAsync(); $infos['tracker_status'] = Common::getRequestVar('trackerStatus', 0, 'int'); @@ -315,4 +318,15 @@ protected static function initServerFilesForSecurity() ServerFilesGenerator::createWebRootFiles(); } + /** + * @param $piwik_minimumPHPVersion + * @param $infos + * @return bool + */ + public static function isPhpVersionValid($phpVersion) + { + global $piwik_minimumPHPVersion; + return version_compare($piwik_minimumPHPVersion, $phpVersion) === -1; + } + } \ No newline at end of file From 26578caa243c3d441a144a947d6741822c91098d Mon Sep 17 00:00:00 2001 From: mattab Date: Fri, 13 Jun 2014 15:12:56 +1200 Subject: [PATCH 31/78] Ignore DoNotTrack for all IE browsers since it is enabled by default. --- plugins/PrivacyManager/DoNotTrackHeaderChecker.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/PrivacyManager/DoNotTrackHeaderChecker.php b/plugins/PrivacyManager/DoNotTrackHeaderChecker.php index 93c0e79fcaa..5ee5642fdd6 100644 --- a/plugins/PrivacyManager/DoNotTrackHeaderChecker.php +++ b/plugins/PrivacyManager/DoNotTrackHeaderChecker.php @@ -37,9 +37,9 @@ public function checkHeaderInTracker(&$exclude) ) { $request = new Request($_REQUEST); $ua = $request->getUserAgent(); - if (strpos($ua, 'MSIE 10') !== false - || strpos($ua, 'Trident/7') !== false) { - Common::printDebug("INTERNET EXPLORER 10 and 11 enable DoNotTrack by default; so Piwik ignores DNT for all IE10 + IE11 browsers..."); + if (strpos($ua, 'MSIE') !== false + || strpos($ua, 'Trident') !== false) { + Common::printDebug("INTERNET EXPLORER enable DoNotTrack by default; so Piwik ignores DNT IE browsers..."); return; } From f09625bff8e941655c96dce94ba833ac38f2f7c6 Mon Sep 17 00:00:00 2001 From: mattab Date: Fri, 13 Jun 2014 15:35:48 +1200 Subject: [PATCH 32/78] Fixes #5344 add new system check to alert user when session.auto_start = 1 --- lang/en.json | 1 + plugins/Installation/Controller.php | 1 + plugins/Installation/SystemCheck.php | 13 +++++++++++-- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lang/en.json b/lang/en.json index 55b3e6872b6..c4f3cc2a199 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1153,6 +1153,7 @@ "SystemCheckZlibHelp": "You need to configure and rebuild PHP with \"zlib\" support enabled, --with-zlib.", "SystemCheckCronArchiveProcess": "Archive Cron", "SystemCheckCronArchiveProcessCLI": "Managing processes via CLI", + "SystemCheckSessionAutostart": "To prevent some issues please set the following in your php.ini file: session.auto_start=0", "NotSupported": "not supported", "Tables": "Creating the Tables", "TablesCreatedSuccess": "Tables created with success!", diff --git a/plugins/Installation/Controller.php b/plugins/Installation/Controller.php index 377783f6049..b04ddd2afbe 100644 --- a/plugins/Installation/Controller.php +++ b/plugins/Installation/Controller.php @@ -625,6 +625,7 @@ private function setupSystemCheckView($view) 'gzuncompress' => 'Installation_SystemCheckGzuncompressHelp', 'pack' => 'Installation_SystemCheckPackHelp', 'php5-json' => 'Installation_SystemCheckJsonHelp', + 'session.auto_start' => 'Installation_SystemCheckSessionAutostart', ); $view->problemWithSomeDirectories = (false !== array_search(false, $view->infos['directories'])); diff --git a/plugins/Installation/SystemCheck.php b/plugins/Installation/SystemCheck.php index 17ee93fedaf..c017a19d418 100644 --- a/plugins/Installation/SystemCheck.php +++ b/plugins/Installation/SystemCheck.php @@ -132,7 +132,6 @@ public static function getSystemInformation() 'parse_ini_file', 'glob', ); - $infos['desired_functions'] = $desired_functions; $infos['missing_desired_functions'] = array(); foreach ($desired_functions as $desired_function) { if (!self::functionExists($desired_function)) { @@ -140,11 +139,20 @@ public static function getSystemInformation() } } + $sessionAutoStarted = (int)ini_get('session.auto_start'); + if($sessionAutoStarted) { + $infos['missing_desired_functions'][] = 'session.auto_start'; + } + + $desired_settings = array( + 'session.auto_start', + ); + $infos['desired_functions'] = array_merge($desired_functions, $desired_settings); + $infos['openurl'] = Http::getTransportMethod(); $infos['gd_ok'] = SettingsServer::isGdExtensionEnabled(); - $serverSoftware = isset($_SERVER['SERVER_SOFTWARE']) ? $_SERVER['SERVER_SOFTWARE'] : ''; $infos['serverVersion'] = addslashes($serverSoftware); $infos['serverOs'] = @php_uname(); @@ -185,6 +193,7 @@ public static function getSystemInformation() $infos['is_nfs'] = Filesystem::checkIfFileSystemIsNFS(); $infos = self::enrichSystemChecks($infos); + return $infos; } From 50dece7f4c45a89dcd8253e2c151b49b707f48c0 Mon Sep 17 00:00:00 2001 From: mattab Date: Fri, 13 Jun 2014 15:45:32 +1200 Subject: [PATCH 33/78] Use HTTPS for youtube video link --- plugins/CoreHome/Controller.php | 2 +- plugins/CoreHome/templates/getPromoVideo.twig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/CoreHome/Controller.php b/plugins/CoreHome/Controller.php index 302f1181a29..1e01e1dc150 100644 --- a/plugins/CoreHome/Controller.php +++ b/plugins/CoreHome/Controller.php @@ -204,7 +204,7 @@ public function getPromoVideo() $view = new View('@CoreHome/getPromoVideo'); $view->shareText = Piwik::translate('CoreHome_SharePiwikShort'); $view->shareTextLong = Piwik::translate('CoreHome_SharePiwikLong'); - $view->promoVideoUrl = 'http://www.youtube.com/watch?v=OslfF_EH81g'; + $view->promoVideoUrl = 'https://www.youtube.com/watch?v=OslfF_EH81g'; return $view->render(); } diff --git a/plugins/CoreHome/templates/getPromoVideo.twig b/plugins/CoreHome/templates/getPromoVideo.twig index 0fa24bc5cb3..84ffbe63fd6 100755 --- a/plugins/CoreHome/templates/getPromoVideo.twig +++ b/plugins/CoreHome/templates/getPromoVideo.twig @@ -42,7 +42,7 @@ var promoEmbed = $('#piwik-promo-embed'), widgetWidth = $(this).closest('.widgetContent').width(), height = (266 * widgetWidth) / 421, - embedHtml = ''; + embedHtml = ''; $(this).hide(); promoEmbed.height(height).html(embedHtml); From 74a3341e02a629e835961f3019b26d2b19ffbff4 Mon Sep 17 00:00:00 2001 From: mattab Date: Fri, 13 Jun 2014 16:06:51 +1200 Subject: [PATCH 34/78] Throw exception for better error reporting --- plugins/CoreHome/DataTableRowAction/RowEvolution.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugins/CoreHome/DataTableRowAction/RowEvolution.php b/plugins/CoreHome/DataTableRowAction/RowEvolution.php index 2fb65b40b4a..915139d3000 100644 --- a/plugins/CoreHome/DataTableRowAction/RowEvolution.php +++ b/plugins/CoreHome/DataTableRowAction/RowEvolution.php @@ -86,6 +86,9 @@ public function __construct($idSite, $date, $graphType = null) if (empty($this->apiMethod)) throw new Exception("Parameter apiMethod not set."); $this->label = ResponseBuilder::getLabelFromRequest($_GET); + if(!is_array($this->label)) { + throw new Exception("Expected label to be an array, got instead: " . $this->label); + } $this->label = $this->label[0]; if ($this->label === '') throw new Exception("Parameter label not set."); From 39dc7f04b9a0b62f26615560dfb665947f1b0927 Mon Sep 17 00:00:00 2001 From: mattab Date: Fri, 13 Jun 2014 16:08:49 +1200 Subject: [PATCH 35/78] Always link "Dashboard" top menu link to the default website being set as a user preference. --- plugins/Dashboard/Menu.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/plugins/Dashboard/Menu.php b/plugins/Dashboard/Menu.php index 95d5a618d46..e972ae7dfd9 100644 --- a/plugins/Dashboard/Menu.php +++ b/plugins/Dashboard/Menu.php @@ -15,6 +15,7 @@ use Piwik\Menu\MenuReporting; use Piwik\Menu\MenuTop; use Piwik\Piwik; +use Piwik\Plugins\UsersManager\UserPreferences; use Piwik\Site; /** @@ -41,16 +42,18 @@ public function configureReportingMenu(MenuReporting $menu) public function configureTopMenu(MenuTop $menu) { - $tooltip = false; - try { - $idSite = Common::getRequestVar('idSite'); - $tooltip = Piwik::translate('Dashboard_TopLinkTooltip', Site::getNameFor($idSite)); - } catch (Exception $ex) { - // if no idSite parameter, show no tooltip - } + $userPreferences = new UserPreferences(); + $idSite = $userPreferences->getDefaultWebsiteId(); + + $tooltip = Piwik::translate('Dashboard_TopLinkTooltip', Site::getNameFor($idSite)); - $urlParams = array('module' => 'CoreHome', 'action' => 'index'); + $urlParams = array( + 'module' => 'CoreHome', + 'action' => 'index', + 'idSite' => $idSite, + ); $menu->add('Dashboard_Dashboard', null, $urlParams, true, 1, $tooltip); } } + From 662c8c44a3fa2eccad602c51838e3f0d7690451e Mon Sep 17 00:00:00 2001 From: mattab Date: Fri, 13 Jun 2014 16:19:37 +1200 Subject: [PATCH 36/78] Fixes #5263 use HHVM binary with --php. Archive may now be compatible with HHVM. If you still have any issue please comment in the ticket! --- core/CliMulti/CliPhp.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/core/CliMulti/CliPhp.php b/core/CliMulti/CliPhp.php index bac7b4bc4fc..c7dd2884ec2 100644 --- a/core/CliMulti/CliPhp.php +++ b/core/CliMulti/CliPhp.php @@ -16,8 +16,15 @@ class CliPhp public function findPhpBinary() { - if (defined('PHP_BINARY') && $this->isValidPhpType(PHP_BINARY)) { - return PHP_BINARY; + if (defined('PHP_BINARY')) { + + if($this->isValidPhpType(PHP_BINARY)) { + return PHP_BINARY; + } + + if($this->isHhvmBinary(PHP_BINARY)) { + return PHP_BINARY . ' --php'; + } } $bin = ''; @@ -50,6 +57,11 @@ public function findPhpBinary() return $bin; } + private function isHhvmBinary($bin) + { + return false !== strpos($bin, 'hhvm'); + } + private function isValidPhpVersion($bin) { $cliVersion = $this->getPhpVersion($bin); From e1015de8204642c33da6cd1a175b3c8764ebb4be Mon Sep 17 00:00:00 2001 From: mattab Date: Fri, 13 Jun 2014 16:42:54 +1200 Subject: [PATCH 37/78] Fixes #5339: do not hardcode user and group in error messages --- core/Filechecks.php | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/core/Filechecks.php b/core/Filechecks.php index ddfade4e6e3..ab25ae7d9d6 100644 --- a/core/Filechecks.php +++ b/core/Filechecks.php @@ -84,11 +84,11 @@ public static function dieIfDirectoriesNotWritable($directoriesToCheck = null) // Also give the chown since the chmod is only 755 if (!SettingsServer::isWindows()) { $realpath = Filesystem::realpath(PIWIK_INCLUDE_PATH . '/'); - $directoryList = "chown -R www-data:www-data " . $realpath . "
" . $directoryList; + $directoryList = "chown -R ". self::getUserAndGroup() ." " . $realpath . "
" . $directoryList; } if(function_exists('shell_exec')) { - $currentUser = trim(shell_exec('whoami')); + $currentUser = self::getUser(); if(!empty($currentUser)) { $optionalUserInfo = " (running as user '" . $currentUser . "')"; } @@ -178,7 +178,7 @@ public static function getAutoUpdateMakeWritableMessage() { $realpath = Filesystem::realpath(PIWIK_INCLUDE_PATH . '/'); $message = ''; - $message .= "chown -R www-data:www-data " . $realpath . "
"; + $message .= "chown -R ". self::getUserAndGroup() ." " . $realpath . "
"; $message .= "chmod -R 0755 " . $realpath . "
"; $message .= 'After you execute these commands (or change permissions via your FTP software), refresh the page and you should be able to use the "Automatic Update" feature.'; return $message; @@ -198,9 +198,10 @@ public static function getErrorMessageMissingPermissions($path) $message .= "On Windows, check that the folder is not read only and is writable.\n You can try to execute:
"; } else { - $message .= "For example, on a GNU/Linux server if your Apache httpd user - is www-data, you can try to execute:
\n" - . "chown -R www-data:www-data " . $path . "
"; + $message .= "For example, on a GNU/Linux server if your Apache httpd user is " + . self::getUser() + . ", you can try to execute:
\n" + . "chown -R ". self::getUserAndGroup() ." " . $path . "
"; } $message .= self::getMakeWritableCommand($path); @@ -208,6 +209,29 @@ public static function getErrorMessageMissingPermissions($path) return $message; } + private static function getUserAndGroup() + { + $user = self::getUser(); + if(!function_exists('shell_exec')) { + return $user . ':' . $user; + } + + $group = trim(shell_exec('groups '. $user .' | cut -f3 -d" "')); + + if(empty($group)) { + $group = 'www-data'; + } + return $user . ':' . $group; + } + + private static function getUser() + { + if(!function_exists('shell_exec')) { + return 'www-data'; + } + return trim(shell_exec('whoami')); + } + /** * Returns the help text displayed to suggest which command to run to give writable access to a file or directory * From 0e127134ae1875bea54015bd73f304d89026c9af Mon Sep 17 00:00:00 2001 From: mattab Date: Fri, 13 Jun 2014 17:43:42 +1200 Subject: [PATCH 38/78] added new syscheck --- tests/PHPUnit/UI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPUnit/UI b/tests/PHPUnit/UI index a29aec44747..6192dce4a09 160000 --- a/tests/PHPUnit/UI +++ b/tests/PHPUnit/UI @@ -1 +1 @@ -Subproject commit a29aec44747e85fd2e95aeefb5236db6561f01bf +Subproject commit 6192dce4a09b2e3414c5af7c867f13f8902e62c5 From d2cb6ea5c0a2ee3b0b14b14369cc5ccff3b33cf3 Mon Sep 17 00:00:00 2001 From: pebosi Date: Fri, 13 Jun 2014 09:38:14 +0200 Subject: [PATCH 39/78] Even better use -nocookie Domain --- plugins/CoreHome/templates/getPromoVideo.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/CoreHome/templates/getPromoVideo.twig b/plugins/CoreHome/templates/getPromoVideo.twig index 84ffbe63fd6..36d94381a9d 100755 --- a/plugins/CoreHome/templates/getPromoVideo.twig +++ b/plugins/CoreHome/templates/getPromoVideo.twig @@ -42,7 +42,7 @@ var promoEmbed = $('#piwik-promo-embed'), widgetWidth = $(this).closest('.widgetContent').width(), height = (266 * widgetWidth) / 421, - embedHtml = ''; + embedHtml = ''; $(this).hide(); promoEmbed.height(height).html(embedHtml); From 27ce498b05d2b96c3a4c2e8e085bf388d334a9cc Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 13 Jun 2014 14:00:53 -0700 Subject: [PATCH 40/78] Allow UI tests to overwrite Option data. --- tests/PHPUnit/TestingEnvironment.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/PHPUnit/TestingEnvironment.php b/tests/PHPUnit/TestingEnvironment.php index df7538c63ac..28e1a70d60b 100644 --- a/tests/PHPUnit/TestingEnvironment.php +++ b/tests/PHPUnit/TestingEnvironment.php @@ -3,6 +3,7 @@ use Piwik\Common; use Piwik\Config; use Piwik\Piwik; +use Piwik\Option; require_once PIWIK_INCLUDE_PATH . "/core/Config.php"; @@ -151,7 +152,13 @@ public static function addHooks() } }); } - Piwik::addAction('Request.dispatch', function() { + Piwik::addAction('Request.dispatch', function() use ($testingEnvironment) { + if ($testingEnvironment->optionsOverride) { + foreach ($testingEnvironment->optionsOverride as $name => $value) { + Option::set($name, $value); + } + } + \Piwik\Plugins\CoreVisualizations\Visualizations\Cloud::$debugDisableShuffle = true; \Piwik\Visualization\Sparkline::$enableSparklineImages = false; \Piwik\Plugins\ExampleUI\API::$disableRandomness = true; From a44743b22440e419b5251b2e747344f435a5ba1c Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 13 Jun 2014 14:02:33 -0700 Subject: [PATCH 41/78] Attempt to fix issue on plugin travis where nginx fails to start. --- tests/travis/piwik_nginx.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/travis/piwik_nginx.conf b/tests/travis/piwik_nginx.conf index 7483693f573..3095c63a0a7 100644 --- a/tests/travis/piwik_nginx.conf +++ b/tests/travis/piwik_nginx.conf @@ -1,3 +1,5 @@ +user root root; + server { listen 80; root @PIWIK_ROOT@/; From 7ca83d509bf993ec8b27696ce9926110d38d4716 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 13 Jun 2014 14:06:09 -0700 Subject: [PATCH 42/78] Revert last commit. --- tests/travis/piwik_nginx.conf | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/travis/piwik_nginx.conf b/tests/travis/piwik_nginx.conf index 3095c63a0a7..7483693f573 100644 --- a/tests/travis/piwik_nginx.conf +++ b/tests/travis/piwik_nginx.conf @@ -1,5 +1,3 @@ -user root root; - server { listen 80; root @PIWIK_ROOT@/; From 5a5d41b67ce14a904b5b81cefc0fe6e2e5ff7d1a Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 13 Jun 2014 14:13:18 -0700 Subject: [PATCH 43/78] Output php-fpm user on travis for debug purposes. --- tests/travis/setup_webserver.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/travis/setup_webserver.sh b/tests/travis/setup_webserver.sh index 6ab7767d806..4ffe375c6a4 100755 --- a/tests/travis/setup_webserver.sh +++ b/tests/travis/setup_webserver.sh @@ -27,6 +27,8 @@ fi USER=$(whoami) +echo "php-fpm user = $USER" + touch "$PHP_FPM_LOG" # Adjust php-fpm.ini From c6f3c3b7d434c46db8d0189665f3764636bbfe5d Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 13 Jun 2014 14:25:39 -0700 Subject: [PATCH 44/78] Try using 'www-data' as user in setting up webserver instead of 'travis'. --- tests/travis/setup_webserver.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/travis/setup_webserver.sh b/tests/travis/setup_webserver.sh index 4ffe375c6a4..a881d11c24e 100755 --- a/tests/travis/setup_webserver.sh +++ b/tests/travis/setup_webserver.sh @@ -25,7 +25,7 @@ else PHP_FPM_LOG="$HOME/php-fpm.log" fi -USER=$(whoami) +USER=www-data echo "php-fpm user = $USER" From dae24f708c6a904cbf33065c134a1633a830f52d Mon Sep 17 00:00:00 2001 From: mattab Date: Sat, 14 Jun 2014 09:30:26 +1200 Subject: [PATCH 45/78] When checking if Piwik server works, fail the check if the Piwik shows an error message --- core/SettingsPiwik.php | 9 ++++++++- core/testMinimumPhpVersion.php | 4 +++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/core/SettingsPiwik.php b/core/SettingsPiwik.php index f2b8d147b33..f6201128057 100644 --- a/core/SettingsPiwik.php +++ b/core/SettingsPiwik.php @@ -292,6 +292,10 @@ public static function rewriteMiscUserPathWithInstanceId($path) /** * Returns true if the Piwik server appears to be working. * + * If the Piwik server is in an error state (eg. some directories are not writable and Piwik displays error message), + * or if the Piwik server is "offline", + * this will return false.. + * * @param $piwikServerUrl * @return bool */ @@ -319,7 +323,10 @@ static public function checkPiwikServerWorking($piwikServerUrl, $acceptInvalidSS $expectedString = 'misc/user/'; $expectedStringNotFound = strpos($fetched, $expectedString) === false && strpos($fetched, $expectedStringAlt) === false; - if ($expectedStringNotFound) { + + $hasError = false !== strpos($fetched, PAGE_TITLE_WHEN_ERROR); + + if ($hasError || $expectedStringNotFound) { throw new Exception("\nPiwik should be running at: " . $piwikServerUrl . " but this URL returned an unexpected response: '" diff --git a/core/testMinimumPhpVersion.php b/core/testMinimumPhpVersion.php index 206ebd08c08..589ffbaaa6a 100644 --- a/core/testMinimumPhpVersion.php +++ b/core/testMinimumPhpVersion.php @@ -66,6 +66,8 @@ } } +define('PAGE_TITLE_WHEN_ERROR', 'Piwik › Error'); + if (!function_exists('Piwik_ExitWithMessage')) { /** * Returns true if Piwik should print the backtrace with error messages. @@ -111,7 +113,7 @@ function Piwik_ExitWithMessage($message, $optionalTrace = false, $optionalLinks $headerPage = file_get_contents(PIWIK_INCLUDE_PATH . '/plugins/Morpheus/templates/simpleLayoutHeader.tpl'); $footerPage = file_get_contents(PIWIK_INCLUDE_PATH . '/plugins/Morpheus/templates/simpleLayoutFooter.tpl'); - $headerPage = str_replace('{$HTML_TITLE}', 'Piwik › Error', $headerPage); + $headerPage = str_replace('{$HTML_TITLE}', PAGE_TITLE_WHEN_ERROR, $headerPage); $content = '

' . $message . '

' From d21922be2705b2d48511b5dfb022a55dab6cb43d Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 13 Jun 2014 14:42:43 -0700 Subject: [PATCH 46/78] Revert last commit. --- tests/travis/setup_webserver.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/travis/setup_webserver.sh b/tests/travis/setup_webserver.sh index a881d11c24e..4ffe375c6a4 100755 --- a/tests/travis/setup_webserver.sh +++ b/tests/travis/setup_webserver.sh @@ -25,7 +25,7 @@ else PHP_FPM_LOG="$HOME/php-fpm.log" fi -USER=www-data +USER=$(whoami) echo "php-fpm user = $USER" From 18ac0057c55137aa63923783f6c0a7dc7d618216 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 13 Jun 2014 15:44:06 -0700 Subject: [PATCH 47/78] Make sure original database is never dropped in tests. --- tests/PHPUnit/Fixture.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPUnit/Fixture.php b/tests/PHPUnit/Fixture.php index 3c1651757b7..ecaf93ec7cd 100644 --- a/tests/PHPUnit/Fixture.php +++ b/tests/PHPUnit/Fixture.php @@ -722,7 +722,7 @@ public static function createAccessInstance() public function dropDatabase($dbName = null) { - $dbName = $dbName ?: $this->dbName; + $dbName = $dbName ?: $this->dbName ?: Config::getInstance()->database_tests['dbname']; $this->log("Dropping database '$dbName'..."); From 77b8faca2597e22ac703506aa1e6632373d2eeb2 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 13 Jun 2014 15:45:06 -0700 Subject: [PATCH 48/78] Adding debug output to travis.sh. --- tests/PHPUnit/travis.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/PHPUnit/travis.sh b/tests/PHPUnit/travis.sh index 2ba14958d5e..90eff649058 100755 --- a/tests/PHPUnit/travis.sh +++ b/tests/PHPUnit/travis.sh @@ -16,6 +16,9 @@ fi if [ -n "$TEST_SUITE" ] then + echo "Executing tests in test suite $TEST_SUITE..." + echo " [ plugin name = $PLUGIN_NAME ]" + if [ "$TEST_SUITE" = "AngularJSTests" ] then sh ./../angularjs/scripts/travis.sh From 592b7659e218b7b2ceaa7b59bc9f77455a2de3ab Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 13 Jun 2014 15:58:06 -0700 Subject: [PATCH 49/78] Modify travis setup_webserver.sh script to chown php-fpm socket to www-data user (to avoid strange travis errors). --- tests/travis/setup_webserver.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/travis/setup_webserver.sh b/tests/travis/setup_webserver.sh index 4ffe375c6a4..66916f6f301 100755 --- a/tests/travis/setup_webserver.sh +++ b/tests/travis/setup_webserver.sh @@ -48,5 +48,6 @@ sudo cp "$DIR/piwik_nginx.conf" $NGINX_CONF # Start daemons echo "Starting php-fpm" sudo $PHP_FPM_BIN --fpm-config "$DIR/php-fpm.ini" +sudo chown www-data:www-data ./tests/travis/php-fpm.sock echo "Starting nginx" sudo service nginx start From b12ac135fdf309649eb03cc6103a255f4228b136 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 13 Jun 2014 16:34:01 -0700 Subject: [PATCH 50/78] Handle tests plugin subdirectory in artifacts upload script. --- tests/travis/upload_artifacts.sh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/travis/upload_artifacts.sh b/tests/travis/upload_artifacts.sh index 991b18b515d..98a3f4fffa0 100755 --- a/tests/travis/upload_artifacts.sh +++ b/tests/travis/upload_artifacts.sh @@ -30,7 +30,11 @@ else base_dir=`pwd` if [ -n "$PLUGIN_NAME" ]; then - cd "./plugins/$PLUGIN_NAME/Test/UI" + if [ -d "./plugins/$PLUGIN_NAME/Test/UI" ]; then + cd "./plugins/$PLUGIN_NAME/Test/UI" + else + cd "./plugins/$PLUGIN_NAME/tests/UI" + fi else cd ./tests/PHPUnit/UI fi From 9f63778afb5c517e567c573ec6ed090bdc66c6ec Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 13 Jun 2014 16:53:30 -0700 Subject: [PATCH 51/78] Debugging plugin travis failure. --- core/Console.php | 1 + 1 file changed, 1 insertion(+) diff --git a/core/Console.php b/core/Console.php index a33a72d3b94..83b3a8f8720 100644 --- a/core/Console.php +++ b/core/Console.php @@ -74,6 +74,7 @@ private function getAvailableCommands() $commands = $this->getDefaultPiwikCommands(); $pluginNames = PluginManager::getInstance()->getLoadedPluginsName(); + \Piwik\Log::info("loaded plugins in Console::getAvailableCommands(): " . print_r($pluginNames, true)); foreach ($pluginNames as $pluginName) { $commands = array_merge($commands, $this->findCommandsInPlugin($pluginName)); } From aa751f987d846d2dc6f22474cc05289ed2214e6c Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 13 Jun 2014 16:56:27 -0700 Subject: [PATCH 52/78] Remove debugging code in last commit. --- core/Console.php | 1 - 1 file changed, 1 deletion(-) diff --git a/core/Console.php b/core/Console.php index 83b3a8f8720..a33a72d3b94 100644 --- a/core/Console.php +++ b/core/Console.php @@ -74,7 +74,6 @@ private function getAvailableCommands() $commands = $this->getDefaultPiwikCommands(); $pluginNames = PluginManager::getInstance()->getLoadedPluginsName(); - \Piwik\Log::info("loaded plugins in Console::getAvailableCommands(): " . print_r($pluginNames, true)); foreach ($pluginNames as $pluginName) { $commands = array_merge($commands, $this->findCommandsInPlugin($pluginName)); } From 58ab1d9bef62ec1cb874f8df0c96d24538572539 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 13 Jun 2014 17:01:10 -0700 Subject: [PATCH 53/78] Output debug infor regarding plugins loaded during tests. --- tests/PHPUnit/Fixture.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/PHPUnit/Fixture.php b/tests/PHPUnit/Fixture.php index ecaf93ec7cd..367a744bc98 100644 --- a/tests/PHPUnit/Fixture.php +++ b/tests/PHPUnit/Fixture.php @@ -269,7 +269,10 @@ public static function loadAllPlugins() { DbHelper::createTables(); $pluginsManager = \Piwik\Plugin\Manager::getInstance(); + $plugins = $pluginsManager->getPluginsToLoadDuringTests(); + Log::info("Plugins to load during tests: " . implode(', ', $plugins)); + $pluginsManager->loadPlugins($plugins); // Install plugins From b1f7cc1e227e83ac8467525160d85422b67eea92 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Fri, 13 Jun 2014 17:04:20 -0700 Subject: [PATCH 54/78] Make sure plugins get loaded in travis for plugins. --- tests/PHPUnit/config.ini.travis.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/PHPUnit/config.ini.travis.php b/tests/PHPUnit/config.ini.travis.php index c82be7b22b1..0cd03c4197e 100644 --- a/tests/PHPUnit/config.ini.travis.php +++ b/tests/PHPUnit/config.ini.travis.php @@ -25,3 +25,6 @@ ; leave this empty here [General] + +[DebugTests] +enable_load_standalone_plugins_during_tests = 1 From 7d515ce1a3f4f3fae5fd004d8a05519018656ae0 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sat, 14 Jun 2014 13:52:18 -0700 Subject: [PATCH 55/78] Use diff in comparison of images in UI screenshot tests to hopefully get past any random differences in rendering on travis. --- tests/lib/screenshot-testing/run-tests.js | 14 +++++++++++ .../screenshot-testing/support/chai-extras.js | 24 ++++++++++++++----- .../lib/screenshot-testing/support/globals.js | 2 ++ 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/tests/lib/screenshot-testing/run-tests.js b/tests/lib/screenshot-testing/run-tests.js index 62d7a56012b..b9073395771 100644 --- a/tests/lib/screenshot-testing/run-tests.js +++ b/tests/lib/screenshot-testing/run-tests.js @@ -27,6 +27,20 @@ require('./support/mocha-loader'); phantom.injectJs(chaiPath); require('./support/chai-extras'); +// load & configure resemble (for comparison) +phantom.injectJs(resemblePath); + +resemble.outputSettings({ + errorColor: { + red: 255, + green: 0, + blue: 0, + alpha: 125 + }, + errorType: 'movement', + transparency: 0.3 +}); + // run script if (options['help']) { app.printHelpAndExit(); diff --git a/tests/lib/screenshot-testing/support/chai-extras.js b/tests/lib/screenshot-testing/support/chai-extras.js index 1253f8fb13b..f2c7f0544d8 100644 --- a/tests/lib/screenshot-testing/support/chai-extras.js +++ b/tests/lib/screenshot-testing/support/chai-extras.js @@ -108,6 +108,14 @@ function capture(screenName, compareAgainst, selector, pageSetupFn, done) { done(error); }; + var pass = function () { + if (options['print-logs']) { + console.log(getPageLogsString(pageRenderer.pageLogs, " ")); + } + + done(); + }; + if (!testInfo.processed) { fail("Failed to generate screenshot to " + screenshotFileName + "."); return; @@ -121,16 +129,20 @@ function capture(screenName, compareAgainst, selector, pageSetupFn, done) { var expected = fs.read(expectedScreenshotPath), processed = fs.read(processedScreenshotPath); - if (expected != processed) { - fail("Processed screenshot does not match expected for " + screenshotFileName + "."); + if (processed == expected) { + pass(); return; } - if (options['print-logs']) { - console.log(getPageLogsString(pageRenderer.pageLogs, " ")); - } + // if the files are not exact, perform a diff to check if they are truly different + resemble("file://" + processedScreenshotPath).compareTo("file://" + expectedScreenshotPath).onComplete(function(data) { + if (data.misMatchPercentage != 0) { + fail("Processed screenshot does not match expected for " + screenshotFileName + "."); + return; + } - done(); + pass(); + }); }, selector); } catch (ex) { var err = new Error(ex.message); diff --git a/tests/lib/screenshot-testing/support/globals.js b/tests/lib/screenshot-testing/support/globals.js index 1cd9b782fd8..53d8d050e5d 100644 --- a/tests/lib/screenshot-testing/support/globals.js +++ b/tests/lib/screenshot-testing/support/globals.js @@ -21,6 +21,8 @@ var mochaPath = path.join(testsLibDir, config.mocha, "mocha.js"); var chaiPath = path.join(testsLibDir, config.chai, "chai.js"); +var resemblePath = path.join(testsLibDir, 'resemblejs', 'resemble.js'); + var expect = function () { return chai.expect.apply(chai.expect, arguments); }; From 669b43662308677ad5713f381503c7a831948046 Mon Sep 17 00:00:00 2001 From: Petr Soukup Date: Sun, 15 Jun 2014 19:55:30 +0200 Subject: [PATCH 56/78] MySQL port should be always integer (HHVM compatibility) --- core/Tracker/Db/Mysqli.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/Tracker/Db/Mysqli.php b/core/Tracker/Db/Mysqli.php index 737719e51f4..66521b120b2 100644 --- a/core/Tracker/Db/Mysqli.php +++ b/core/Tracker/Db/Mysqli.php @@ -46,7 +46,7 @@ public function __construct($dbInfo, $driverName = 'mysql') $this->socket = $dbInfo['port']; } else { $this->host = $dbInfo['host']; - $this->port = $dbInfo['port']; + $this->port = (int)$dbInfo['port']; $this->socket = null; } $this->dbname = $dbInfo['dbname']; From 4e17f95f2edf06ddf532d5e212c5eeca11efd80b Mon Sep 17 00:00:00 2001 From: mattab Date: Mon, 16 Jun 2014 10:30:13 +1200 Subject: [PATCH 57/78] Refs #5348 Set geo location based on GeoIP values detected from IPv6 Refs https://github.com/piwik/piwik/pull/316/files --- .../LocationProvider/GeoIp/ServerBased.php | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/plugins/UserCountry/LocationProvider/GeoIp/ServerBased.php b/plugins/UserCountry/LocationProvider/GeoIp/ServerBased.php index 3e9b51488b0..b7df9966377 100755 --- a/plugins/UserCountry/LocationProvider/GeoIp/ServerBased.php +++ b/plugins/UserCountry/LocationProvider/GeoIp/ServerBased.php @@ -28,6 +28,7 @@ class ServerBased extends GeoIp const TITLE = 'GeoIP (%s)'; const TEST_SERVER_VAR = 'GEOIP_ADDR'; const TEST_SERVER_VAR_ALT = 'GEOIP_COUNTRY_CODE'; + const TEST_SERVER_VAR_ALT_IPV6 = 'GEOIP_COUNTRY_CODE_V6'; private static $geoIpServerVars = array( parent::COUNTRY_CODE_KEY => 'GEOIP_COUNTRY_CODE', @@ -96,6 +97,11 @@ public function getLocation($info) if (!empty($_SERVER[$geoipVarName])) { $result[$resultKey] = $_SERVER[$geoipVarName]; } + + $geoipVarNameV6 = $geoipVarName . '_V6'; + if (!empty($_SERVER[$geoipVarNameV6])) { + $result[$resultKey] = $_SERVER[$geoipVarNameV6]; + } } foreach (self::$geoIpUtfServerVars as $resultKey => $geoipVarName) { if (!empty($_SERVER[$geoipVarName])) { @@ -150,25 +156,27 @@ public function isAvailable() } $available = !empty($_SERVER[self::TEST_SERVER_VAR]) - || !empty($_SERVER[self::TEST_SERVER_VAR_ALT]); + || !empty($_SERVER[self::TEST_SERVER_VAR_ALT]) + || !empty($_SERVER[self::TEST_SERVER_VAR_ALT_IPV6]) + ; if ($available) { return true; - } else // if not available return message w/ extra info - { - if (!function_exists('apache_get_modules')) { - return Piwik::translate('General_Note') . ': ' . Piwik::translate('UserCountry_AssumingNonApache'); - } + } - $message = "" . Piwik::translate('General_Note') . ': ' - . Piwik::translate('UserCountry_FoundApacheModules') - . ":

\n

    \n"; - foreach (apache_get_modules() as $name) { - $message .= "
  • $name
  • \n"; - } - $message .= "
"; - return $message; + // if not available return message w/ extra info + if (!function_exists('apache_get_modules')) { + return Piwik::translate('General_Note') . ': ' . Piwik::translate('UserCountry_AssumingNonApache'); + } + + $message = "" . Piwik::translate('General_Note') . ': ' + . Piwik::translate('UserCountry_FoundApacheModules') + . ":

\n
    \n"; + foreach (apache_get_modules() as $name) { + $message .= "
  • $name
  • \n"; } + $message .= "
"; + return $message; } /** @@ -180,6 +188,7 @@ public function isWorking() { if (empty($_SERVER[self::TEST_SERVER_VAR]) && empty($_SERVER[self::TEST_SERVER_VAR_ALT]) + && empty($_SERVER[self::TEST_SERVER_VAR_ALT_IPV6]) ) { return Piwik::translate("UserCountry_CannotFindGeoIPServerVar", self::TEST_SERVER_VAR . ' $_SERVER'); } From b7c3f39647a2c3cbb83465d42f84d9e7636f3f18 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sun, 15 Jun 2014 15:40:05 -0700 Subject: [PATCH 58/78] When executing tests, check for non-core plugin that should be loaded by looking at test case class & current backtrace. (Removing need for enable_load_standalone_plugins_during_tests config option). --- core/Plugin.php | 27 +++++++++++++++---- tests/PHPUnit/Fixture.php | 23 ++++++++++++++-- tests/PHPUnit/IntegrationTestCase.php | 2 ++ tests/PHPUnit/TestingEnvironment.php | 9 +++++++ .../support/test-environment.js | 8 ++++++ 5 files changed, 62 insertions(+), 7 deletions(-) diff --git a/core/Plugin.php b/core/Plugin.php index aeb687398e0..2ddd07aa26a 100644 --- a/core/Plugin.php +++ b/core/Plugin.php @@ -353,12 +353,29 @@ public static function getPluginNameFromBacktrace($backtrace) { foreach ($backtrace as $tracepoint) { // try and discern the plugin name - if (isset($tracepoint['class']) - && preg_match("/Piwik\\\\Plugins\\\\([a-zA-Z_0-9]+)\\\\/", $tracepoint['class'], $matches) - ) { - return $matches[1]; + if (isset($tracepoint['class'])) { + $className = self::getPluginNameFromNamespace($tracepoint['class']); + if ($className) { + return $className; + } } } return false; } -} + + /** + * Extracts the plugin name from a namespace name or a fully qualified class name. Returns `false` + * if we can't find one. + * + * @param string $namespaceOrClassName The namespace or class string. + * @return string|false + */ + public static function getPluginNameFromNamespace($namespaceOrClassName) + { + if (preg_match("/Piwik\\\\Plugins\\\\([a-zA-Z_0-9]+)\\\\/", $namespaceOrClassName, $matches)) { + return $matches[1]; + } else { + return false; + } + } +} \ No newline at end of file diff --git a/tests/PHPUnit/Fixture.php b/tests/PHPUnit/Fixture.php index 367a744bc98..f651dd1d757 100644 --- a/tests/PHPUnit/Fixture.php +++ b/tests/PHPUnit/Fixture.php @@ -67,6 +67,8 @@ class Fixture extends PHPUnit_Framework_Assert public $resetPersistedFixture = false; public $printToScreen = false; + public $testCaseClass = false; + public $testEnvironment = null; /** @@ -173,7 +175,7 @@ public function performSetUp($setupEnvironmentOnly = false) Cache::deleteTrackerCache(); - static::loadAllPlugins(); + static::loadAllPlugins($this->getTestEnvironment(), $this->testCaseClass); $_GET = $_REQUEST = array(); $_SERVER['HTTP_REFERER'] = ''; @@ -265,12 +267,29 @@ public function performTearDown() Translate::unloadEnglishTranslation(); } - public static function loadAllPlugins() + public static function loadAllPlugins($testEnvironment = null, $testCaseClass = false) { DbHelper::createTables(); $pluginsManager = \Piwik\Plugin\Manager::getInstance(); $plugins = $pluginsManager->getPluginsToLoadDuringTests(); + + // make sure the plugin that executed this method is included in the plugins to load + $extraPlugins = array( + \Piwik\Plugin::getPluginNameFromBacktrace(debug_backtrace()), + \Piwik\Plugin::getPluginNameFromNamespace($testCaseClass) + ); + foreach ($extraPlugins as $pluginName) { + if (empty($pluginName)) { + continue; + } + + $plugins[] = $pluginName; + if ($testEnvironment) { + $testEnvironment->pluginsToLoad = array_merge($testEnvironment->pluginsToLoad ?: array(), array($pluginName)); + } + } + Log::info("Plugins to load during tests: " . implode(', ', $plugins)); $pluginsManager->loadPlugins($plugins); diff --git a/tests/PHPUnit/IntegrationTestCase.php b/tests/PHPUnit/IntegrationTestCase.php index f51bc3e35f0..8ca26efcff2 100755 --- a/tests/PHPUnit/IntegrationTestCase.php +++ b/tests/PHPUnit/IntegrationTestCase.php @@ -78,6 +78,8 @@ public static function setUpBeforeClass() $fixture = static::$fixture; } + $fixture->testCaseClass = get_called_class(); + try { $fixture->performSetUp(); } catch (Exception $e) { diff --git a/tests/PHPUnit/TestingEnvironment.php b/tests/PHPUnit/TestingEnvironment.php index 28e1a70d60b..c9ea3a2be82 100644 --- a/tests/PHPUnit/TestingEnvironment.php +++ b/tests/PHPUnit/TestingEnvironment.php @@ -62,6 +62,11 @@ public function __set($key, $value) $this->behaviorOverrideProperties[$key] = $value; } + public function __isset($name) + { + return isset($this->behaviorOverrideProperties[$name]); + } + public function save() { $overridePath = PIWIK_INCLUDE_PATH . '/tmp/testingPathOverride.json'; @@ -124,6 +129,10 @@ public static function addHooks() $manager = \Piwik\Plugin\Manager::getInstance(); $pluginsToLoad = $manager->getPluginsToLoadDuringTests(); + if (!empty($testingEnvironment->pluginsToLoad)) { + $pluginsToLoad = array_unique(array_merge($pluginsToLoad, $testingEnvironment->pluginsToLoad)); + } + $config->Plugins = array('Plugins' => $pluginsToLoad); $trackerPluginsToLoad = array_filter($pluginsToLoad, function ($plugin) use ($manager) { diff --git a/tests/lib/screenshot-testing/support/test-environment.js b/tests/lib/screenshot-testing/support/test-environment.js index e7a0f1f44eb..375408e562f 100644 --- a/tests/lib/screenshot-testing/support/test-environment.js +++ b/tests/lib/screenshot-testing/support/test-environment.js @@ -118,6 +118,13 @@ TestingEnvironment.prototype.executeConsoleCommand = function (command, args, ca child.on("exit", callback); }; +TestingEnvironment.prototype.addPluginOnCmdLineToTestEnv = function () { + if (options.plugin) { + this.pluginsToLoad = [options.plugin]; + this.save(); + } +}; + var droppedOnce = false; TestingEnvironment.prototype.setupFixture = function (fixtureClass, done) { console.log(" Setting up fixture " + fixtureClass + "..."); @@ -140,6 +147,7 @@ TestingEnvironment.prototype.setupFixture = function (fixtureClass, done) { var self = this; this.executeConsoleCommand('tests:setup-fixture', args, function (code) { self.reload(); + self.addPluginOnCmdLineToTestEnv(); console.log(); From 5719d8f460a2a63afdb9771abb99a6b83618beb4 Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sun, 15 Jun 2014 15:42:11 -0700 Subject: [PATCH 59/78] Remove enable_load_standalone_plugins_during_tests option from travis config.ini.php file. --- tests/PHPUnit/config.ini.travis.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/PHPUnit/config.ini.travis.php b/tests/PHPUnit/config.ini.travis.php index 0cd03c4197e..c82be7b22b1 100644 --- a/tests/PHPUnit/config.ini.travis.php +++ b/tests/PHPUnit/config.ini.travis.php @@ -25,6 +25,3 @@ ; leave this empty here [General] - -[DebugTests] -enable_load_standalone_plugins_during_tests = 1 From a97aa1f660c47626d6dd393e9460cc06ea3245c1 Mon Sep 17 00:00:00 2001 From: mattab Date: Mon, 16 Jun 2014 10:50:00 +1200 Subject: [PATCH 60/78] fixing tests the lazy way --- tests/PHPUnit/Core/DeprecatedMethodsTest.php | 2 +- tests/PHPUnit/UI | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/PHPUnit/Core/DeprecatedMethodsTest.php b/tests/PHPUnit/Core/DeprecatedMethodsTest.php index 1e170bd814f..ce496684ba0 100644 --- a/tests/PHPUnit/Core/DeprecatedMethodsTest.php +++ b/tests/PHPUnit/Core/DeprecatedMethodsTest.php @@ -17,7 +17,7 @@ class DeprecatedMethodsTest extends PHPUnit_Framework_TestCase public function test_version2_0_4() { - $validTill = '2014-06-15'; + $validTill = '2014-09-15'; $this->assertDeprecatedMethodIsRemoved('\Piwik\Period', 'factory', $validTill); $validTill = '2014-10-01'; diff --git a/tests/PHPUnit/UI b/tests/PHPUnit/UI index 6192dce4a09..ea045c36cdd 160000 --- a/tests/PHPUnit/UI +++ b/tests/PHPUnit/UI @@ -1 +1 @@ -Subproject commit 6192dce4a09b2e3414c5af7c867f13f8902e62c5 +Subproject commit ea045c36cdd1d258a9ca68f0704b21fef1120b3e From 3109ad3ff87ca2d5153ca396c79bcb82470c022f Mon Sep 17 00:00:00 2001 From: diosmosis Date: Sun, 15 Jun 2014 15:50:33 -0700 Subject: [PATCH 61/78] Sort plugins to load in test environment class before overriding config to keep screenshot output predictable. --- tests/PHPUnit/TestingEnvironment.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/PHPUnit/TestingEnvironment.php b/tests/PHPUnit/TestingEnvironment.php index c9ea3a2be82..363c8a89b96 100644 --- a/tests/PHPUnit/TestingEnvironment.php +++ b/tests/PHPUnit/TestingEnvironment.php @@ -133,6 +133,8 @@ public static function addHooks() $pluginsToLoad = array_unique(array_merge($pluginsToLoad, $testingEnvironment->pluginsToLoad)); } + sort($pluginsToLoad); + $config->Plugins = array('Plugins' => $pluginsToLoad); $trackerPluginsToLoad = array_filter($pluginsToLoad, function ($plugin) use ($manager) { From 66b5355e5935ab05e50ba57e58a708de737746d9 Mon Sep 17 00:00:00 2001 From: mattab Date: Mon, 16 Jun 2014 12:04:36 +1200 Subject: [PATCH 62/78] Throw exception when site Ids array is empty, to prevent error: Error: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ') GROUP BY idsite, date1, date2' at line 5 Payload: /index.php?date=last10&format=rss&idSite=12345%27%22\%27\%22%29;|]*{%0d%0a%3C%00%3E%bf%27%27&method=Actions.getPageUrl&module=API&pageUrl=http://forum.piwik.org/&period=day&token_auth=anonymous&translateColumnNames=1 --- core/DataAccess/ArchiveSelector.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/DataAccess/ArchiveSelector.php b/core/DataAccess/ArchiveSelector.php index cd7d0a044c2..72fb0faeb3e 100644 --- a/core/DataAccess/ArchiveSelector.php +++ b/core/DataAccess/ArchiveSelector.php @@ -146,9 +146,14 @@ protected static function getMostRecentIdArchiveFromResults(Segment $segment, $r * '2010-01-01' => array(1,2,3) * ) * ) + * @throws */ static public function getArchiveIds($siteIds, $periods, $segment, $plugins, $isSkipAggregationOfSubTables = false) { + if(empty($siteIds)) { + throw new \Exception("Website IDs could not be read from the request, ie. idSite="); + } + $getArchiveIdsSql = "SELECT idsite, name, date1, date2, MAX(idarchive) as idarchive FROM %s WHERE %s From a73266bfd702777bd94b59b91dc2974ba6306c10 Mon Sep 17 00:00:00 2001 From: mattab Date: Mon, 16 Jun 2014 12:30:44 +1200 Subject: [PATCH 63/78] Refs #5349 adding failing to showcase bug --- tests/resources/Config/common.config.ini.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/resources/Config/common.config.ini.php b/tests/resources/Config/common.config.ini.php index 572f1a937a4..db8cb53d41a 100644 --- a/tests/resources/Config/common.config.ini.php +++ b/tests/resources/Config/common.config.ini.php @@ -1,6 +1,9 @@ [Category] key2 = valueCommon +; This should not trigger an error if INI_SCANNER_RAW is used +key3 = "${@piwik(crash))}" + [GeneralSection] password = passwordCommonShouldNotBeOverriden From 5a19012cc33b2b7eec7c28bb660be5280090adf1 Mon Sep 17 00:00:00 2001 From: mattab Date: Mon, 16 Jun 2014 12:33:05 +1200 Subject: [PATCH 64/78] Fixes #5349 Adding flag INI_SCANNER_RAW to prevent error This should fix the build --- libs/upgradephp/upgrade.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libs/upgradephp/upgrade.php b/libs/upgradephp/upgrade.php index c45ee1ca956..5ab68078a83 100644 --- a/libs/upgradephp/upgrade.php +++ b/libs/upgradephp/upgrade.php @@ -127,7 +127,11 @@ function mysqli_set_charset($link, $charset) if(function_exists('parse_ini_file')) { // provide a wrapper function _parse_ini_file($filename, $process_sections = false) { - return file_exists($filename) ? parse_ini_file($filename, $process_sections) : false; + if(!file_exists($filename)) { + return false; + } + // Note: INI_SCANNER_RAW is important here! + return parse_ini_file($filename, $process_sections, INI_SCANNER_RAW); } } else { // we can't redefine parse_ini_file() if it has been disabled From c764c5e1c3c57e1fa3255f285cd23e2e1744bb7a Mon Sep 17 00:00:00 2001 From: mattab Date: Tue, 17 Jun 2014 13:43:33 +1200 Subject: [PATCH 65/78] Submoduel --- tests/PHPUnit/UI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPUnit/UI b/tests/PHPUnit/UI index ea045c36cdd..f3dbd4c324a 160000 --- a/tests/PHPUnit/UI +++ b/tests/PHPUnit/UI @@ -1 +1 @@ -Subproject commit ea045c36cdd1d258a9ca68f0704b21fef1120b3e +Subproject commit f3dbd4c324aa8b73e9091f274a1a670f5d869b5c From c87a1209d51b344032628e512db3f9fb3331d74f Mon Sep 17 00:00:00 2001 From: mattab Date: Tue, 17 Jun 2014 14:57:43 +1200 Subject: [PATCH 66/78] Do not show version number to anonymous user. --- plugins/API/API.php | 1 + plugins/ExampleAPI/API.php | 1 + 2 files changed, 2 insertions(+) diff --git a/plugins/API/API.php b/plugins/API/API.php index 66313b0a15d..4f254931036 100644 --- a/plugins/API/API.php +++ b/plugins/API/API.php @@ -54,6 +54,7 @@ class API extends \Piwik\Plugin\API public function getPiwikVersion() { Piwik::checkUserHasSomeViewAccess(); + Piwik::checkUserIsNotAnonymous(); return Version::VERSION; } diff --git a/plugins/ExampleAPI/API.php b/plugins/ExampleAPI/API.php index 27dc2f59aaf..f7cb0424cea 100644 --- a/plugins/ExampleAPI/API.php +++ b/plugins/ExampleAPI/API.php @@ -28,6 +28,7 @@ class API extends \Piwik\Plugin\API public function getPiwikVersion() { Piwik::checkUserHasSomeViewAccess(); + Piwik::checkUserIsNotAnonymous(); return Version::VERSION; } From 4f1f5894969031e2d9eacada1bd5e47bafbe8e86 Mon Sep 17 00:00:00 2001 From: mattab Date: Tue, 17 Jun 2014 15:58:42 +1200 Subject: [PATCH 67/78] Installer: remove one of the opted-in newsletter entry, replace it with opt-in only Piwik PRO updates --- lang/en.json | 4 ++-- plugins/Installation/Controller.php | 28 +++++++++++++------------- plugins/Installation/FormSuperUser.php | 22 +++++++++++--------- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/lang/en.json b/lang/en.json index c4f3cc2a199..2266afbb86f 100644 --- a/lang/en.json +++ b/lang/en.json @@ -1045,7 +1045,6 @@ }, "Installation": { "CollaborativeProject": "Piwik is a collaborative project, built with love by people from all over the world.", - "CommunityNewsletter": "email me with community updates (new plugins, new features, etc.)", "ConfigurationHelp": "Your Piwik configuration file appears to be misconfigured. You can either remove config\/config.ini.php and resume installation, or correct the database connection settings.", "ConfirmDeleteExistingTables": "Are you sure you want to delete the tables: %s from your database? WARNING: DATA FROM THESE TABLES CANNOT BE RECOVERED!", "Congratulations": "Congratulations", @@ -1091,7 +1090,8 @@ "Requirements": "Piwik Requirements", "RestartWebServer": "After making this change, restart your web server.", "ReusingTables": "Reusing the Tables", - "SecurityNewsletter": "email me with major Piwik upgrades and security alerts", + "PiwikOrgNewsletter": "email me with major Piwik community updates", + "PiwikProNewsletter": "email me with %sPiwik PRO%s updates", "SeeBelowForMoreInfo": "See below for more information.", "SetupWebsite": "Setup a Website", "SetupWebsiteError": "There was an error when adding the website", diff --git a/plugins/Installation/Controller.php b/plugins/Installation/Controller.php index b04ddd2afbe..c0e7fd2be15 100644 --- a/plugins/Installation/Controller.php +++ b/plugins/Installation/Controller.php @@ -279,9 +279,9 @@ function setupSuperUser() $form->getSubmitValue('email')); $email = $form->getSubmitValue('email'); - $newsletterSecurity = $form->getSubmitValue('subscribe_newsletter_security'); - $newsletterCommunity = $form->getSubmitValue('subscribe_newsletter_community'); - $this->registerNewsletter($email, $newsletterSecurity, $newsletterCommunity); + $newsletterPiwikORG = $form->getSubmitValue('subscribe_newsletter_piwikorg'); + $newsletterPiwikPRO = $form->getSubmitValue('subscribe_newsletter_piwikpro'); + $this->registerNewsletter($email, $newsletterPiwikORG, $newsletterPiwikPRO); $this->redirectToNextStep(__FUNCTION__); } catch (Exception $e) { @@ -666,27 +666,27 @@ private function deleteConfigFileIfNeeded() /** * @param $email - * @param $newsletterSecurity - * @param $newsletterCommunity + * @param $newsletterPiwikORG + * @param $newsletterPiwikPRO */ - protected function registerNewsletter($email, $newsletterSecurity, $newsletterCommunity) + protected function registerNewsletter($email, $newsletterPiwikORG, $newsletterPiwikPRO) { $url = Config::getInstance()->General['api_service_url']; $url .= '/1.0/subscribeNewsletter/'; $params = array( 'email' => $email, - 'security' => $newsletterSecurity, - 'community' => $newsletterCommunity, + 'piwikorg' => $newsletterPiwikORG, + 'piwikpro' => $newsletterPiwikPRO, 'url' => Url::getCurrentUrlWithoutQueryString(), ); - if ($params['security'] == '1' - || $params['community'] == '1' + if ($params['piwikorg'] == '1' + || $params['piwikpro'] == '1' ) { - if (!isset($params['security'])) { - $params['security'] = '0'; + if (!isset($params['piwikorg'])) { + $params['piwikorg'] = '0'; } - if (!isset($params['community'])) { - $params['community'] = '0'; + if (!isset($params['piwikpro'])) { + $params['piwikpro'] = '0'; } $url .= '?' . http_build_query($params, '', '&'); try { diff --git a/plugins/Installation/FormSuperUser.php b/plugins/Installation/FormSuperUser.php index 68d9dcad14d..aef40d6a405 100644 --- a/plugins/Installation/FormSuperUser.php +++ b/plugins/Installation/FormSuperUser.php @@ -53,21 +53,25 @@ function init() $email->addRule('required', Piwik::translate('General_Required', Piwik::translate('Installation_Email'))); $email->addRule('checkEmail', Piwik::translate('UsersManager_ExceptionInvalidEmail')); - $this->addElement('checkbox', 'subscribe_newsletter_security', null, array( - 'content' => '  ' . Piwik::translate('Installation_SecurityNewsletter'), - )); + $this->addElement('checkbox', 'subscribe_newsletter_piwikorg', null, + array( + 'content' => '  ' . Piwik::translate('Installation_PiwikOrgNewsletter'), + )); - $this->addElement('checkbox', 'subscribe_newsletter_community', null, array( - 'content' => '  ' . Piwik::translate('Installation_CommunityNewsletter'), - )); + $this->addElement('checkbox', 'subscribe_newsletter_piwikpro', null, + array( + 'content' => '  ' . Piwik::translate('Installation_PiwikProNewsletter', + array("", "") + ), + )); $this->addElement('submit', 'submit', array('value' => Piwik::translate('General_Next') . ' »', 'class' => 'submit')); // default values $this->addDataSource(new HTML_QuickForm2_DataSource_Array(array( - 'subscribe_newsletter_community' => 1, - 'subscribe_newsletter_security' => 1, - ))); + 'subscribe_newsletter_piwikorg' => 1, + 'subscribe_newsletter_piwikpro' => 0, + ))); } } From 56cf3539e3a20f3f86028e459a91292a27ce91b9 Mon Sep 17 00:00:00 2001 From: mattab Date: Tue, 17 Jun 2014 16:51:00 +1200 Subject: [PATCH 68/78] newsletter installer --- tests/PHPUnit/UI | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/PHPUnit/UI b/tests/PHPUnit/UI index f3dbd4c324a..fb641188b26 160000 --- a/tests/PHPUnit/UI +++ b/tests/PHPUnit/UI @@ -1 +1 @@ -Subproject commit f3dbd4c324aa8b73e9091f274a1a670f5d869b5c +Subproject commit fb641188b26d371972604e93c2d9de8f52f93373 From 3f82b4ab7b8fc82eed0303936e869f78adcf4fb3 Mon Sep 17 00:00:00 2001 From: mattab Date: Tue, 17 Jun 2014 17:12:12 +1200 Subject: [PATCH 69/78] we must use operator === when comparing token strings because of the following php magic: $ php -r "var_dump('0e12345678909876543212345678901' == '0');" bool(true) --- core/CronArchive.php | 2 +- core/Plugin/Controller.php | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/core/CronArchive.php b/core/CronArchive.php index 0a2903ac576..e9392298dc8 100644 --- a/core/CronArchive.php +++ b/core/CronArchive.php @@ -731,7 +731,7 @@ private function initCheckCli() return; } $token_auth = Common::getRequestVar('token_auth', '', 'string'); - if ($token_auth != $this->token_auth + if ($token_auth !== $this->token_auth || strlen($token_auth) != 32 ) { die('You must specify the Super User token_auth as a parameter to this script, eg. ?token_auth=XYZ if you wish to run this script through the browser.
diff --git a/core/Plugin/Controller.php b/core/Plugin/Controller.php index 43e385f2639..b65823be58d 100644 --- a/core/Plugin/Controller.php +++ b/core/Plugin/Controller.php @@ -828,7 +828,9 @@ public function redirectToIndex($moduleToRedirect, $actionToRedirect, $websiteId */ protected function checkTokenInUrl() { - if (Common::getRequestVar('token_auth', false) != Piwik::getCurrentUserTokenAuth()) { + $requestTokenAuth = Common::getRequestVar('token_auth', false); + $currentUserTokenAuth = Piwik::getCurrentUserTokenAuth(); + if ($requestTokenAuth !== $currentUserTokenAuth) { throw new NoAccessException(Piwik::translate('General_ExceptionInvalidToken')); } } From 138e65868f6ae7b544677e4172ad0eb27831dae3 Mon Sep 17 00:00:00 2001 From: mattab Date: Tue, 17 Jun 2014 18:12:17 +1200 Subject: [PATCH 70/78] Add missing line break in notification message --- core/Plugin/ControllerAdmin.php | 1 + 1 file changed, 1 insertion(+) diff --git a/core/Plugin/ControllerAdmin.php b/core/Plugin/ControllerAdmin.php index 4254cdbb2c3..0212a3769c7 100644 --- a/core/Plugin/ControllerAdmin.php +++ b/core/Plugin/ControllerAdmin.php @@ -56,6 +56,7 @@ private static function notifyAnyInvalidPlugin() $invalidPluginsWarning = Piwik::translate('CoreAdminHome_InvalidPluginsWarning', array( self::getPiwikVersion(), '' . implode('', $missingPlugins) . '')) + . "
" . Piwik::translate('CoreAdminHome_InvalidPluginsYouCanUninstall', array( '', '' From 5f5f7fd1fa39ed664ba6d84001b6085037b5e70c Mon Sep 17 00:00:00 2001 From: mattab Date: Tue, 17 Jun 2014 18:14:10 +1200 Subject: [PATCH 71/78] updating composer.lock --- composer.lock | 51 ++++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/composer.lock b/composer.lock index 90002e86c01..d4813ca0996 100644 --- a/composer.lock +++ b/composer.lock @@ -1,10 +1,9 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", - "This file is @generated automatically" + "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file" ], - "hash": "4608e7a637e41e4ba55deba353d4765d", + "hash": "016b7b6646d1d3ec6d8b574b5a6c5561", "packages": [ { "name": "leafo/lessphp", @@ -143,32 +142,34 @@ }, { "name": "symfony/console", - "version": "v2.4.5", + "version": "v2.5.0", "target-dir": "Symfony/Component/Console", "source": { "type": "git", "url": "https://github.com/symfony/Console.git", - "reference": "24f723436e62598c9dddee2a8573d6992504dc5d" + "reference": "ef4ca73b0b3a10cbac653d3ca482d0cdd4502b2c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Console/zipball/24f723436e62598c9dddee2a8573d6992504dc5d", - "reference": "24f723436e62598c9dddee2a8573d6992504dc5d", + "url": "https://api.github.com/repos/symfony/Console/zipball/ef4ca73b0b3a10cbac653d3ca482d0cdd4502b2c", + "reference": "ef4ca73b0b3a10cbac653d3ca482d0cdd4502b2c", "shasum": "" }, "require": { "php": ">=5.3.3" }, "require-dev": { + "psr/log": "~1.0", "symfony/event-dispatcher": "~2.1" }, "suggest": { + "psr/log": "For using the console logger", "symfony/event-dispatcher": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -194,7 +195,7 @@ ], "description": "Symfony Console Component", "homepage": "http://symfony.com", - "time": "2014-05-14 21:48:29" + "time": "2014-05-22 08:54:24" }, { "name": "tedivm/jshrink", @@ -546,16 +547,16 @@ }, { "name": "phpunit/phpunit", - "version": "4.1.1", + "version": "4.1.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "1d6b554732382879045e11c56decd4be76130720" + "reference": "939cb801b3b2aa253aedd0b279f40bb8f35cec91" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/1d6b554732382879045e11c56decd4be76130720", - "reference": "1d6b554732382879045e11c56decd4be76130720", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/939cb801b3b2aa253aedd0b279f40bb8f35cec91", + "reference": "939cb801b3b2aa253aedd0b279f40bb8f35cec91", "shasum": "" }, "require": { @@ -616,20 +617,20 @@ "testing", "xunit" ], - "time": "2014-05-24 10:48:51" + "time": "2014-06-11 14:15:47" }, { "name": "phpunit/phpunit-mock-objects", - "version": "2.1.0", + "version": "2.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit-mock-objects.git", - "reference": "da0eb04d8ee95ec2898187e407e519c118d3d27c" + "reference": "1a894a16b6c15fcdc5ef2b110f0e6233952c9b0f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/da0eb04d8ee95ec2898187e407e519c118d3d27c", - "reference": "da0eb04d8ee95ec2898187e407e519c118d3d27c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit-mock-objects/zipball/1a894a16b6c15fcdc5ef2b110f0e6233952c9b0f", + "reference": "1a894a16b6c15fcdc5ef2b110f0e6233952c9b0f", "shasum": "" }, "require": { @@ -673,7 +674,7 @@ "mock", "xunit" ], - "time": "2014-05-02 07:04:11" + "time": "2014-06-07 16:22:57" }, { "name": "sebastian/comparator", @@ -944,17 +945,17 @@ }, { "name": "symfony/yaml", - "version": "v2.4.5", + "version": "v2.5.0", "target-dir": "Symfony/Component/Yaml", "source": { "type": "git", "url": "https://github.com/symfony/Yaml.git", - "reference": "fd22bb88c3a6f73c898b39bec185a9e211b06265" + "reference": "b4b09c68ec2f2727574544ef0173684281a5033c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/Yaml/zipball/fd22bb88c3a6f73c898b39bec185a9e211b06265", - "reference": "fd22bb88c3a6f73c898b39bec185a9e211b06265", + "url": "https://api.github.com/repos/symfony/Yaml/zipball/b4b09c68ec2f2727574544ef0173684281a5033c", + "reference": "b4b09c68ec2f2727574544ef0173684281a5033c", "shasum": "" }, "require": { @@ -963,7 +964,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "2.4-dev" + "dev-master": "2.5-dev" } }, "autoload": { @@ -989,7 +990,7 @@ ], "description": "Symfony Yaml Component", "homepage": "http://symfony.com", - "time": "2014-05-12 09:27:48" + "time": "2014-05-16 14:25:18" } ], "aliases": [ From 8de766cac28fef6e885f8c3eff3133688675a4a1 Mon Sep 17 00:00:00 2001 From: sgiehl Date: Tue, 17 Jun 2014 08:53:04 +0200 Subject: [PATCH 72/78] language update refs #3430 --- lang/am.json | 2 -- lang/ar.json | 2 -- lang/be.json | 2 -- lang/bg.json | 18 ++++++++++-- lang/ca.json | 2 -- lang/cs.json | 2 -- lang/da.json | 54 +++++++++++++++++++++++++++++------ lang/de.json | 6 ++-- lang/el.json | 9 ++++-- lang/es.json | 2 -- lang/et.json | 2 -- lang/eu.json | 2 -- lang/fa.json | 2 -- lang/fi.json | 4 +-- lang/fr.json | 2 -- lang/hi.json | 2 -- lang/hu.json | 2 -- lang/id.json | 2 -- lang/it.json | 11 +++++-- lang/ja.json | 49 ++++++++++++++++++++++++------- lang/ka.json | 2 -- lang/ko.json | 2 -- lang/lt.json | 2 -- lang/lv.json | 2 -- lang/nb.json | 2 -- lang/nl.json | 21 +++++++++++--- lang/nn.json | 2 -- lang/pl.json | 2 -- lang/pt-br.json | 2 -- lang/pt.json | 2 -- lang/ro.json | 12 +++++--- lang/ru.json | 2 -- lang/sk.json | 2 -- lang/sl.json | 1 - lang/sq.json | 2 -- lang/sr.json | 2 -- lang/sv.json | 2 -- lang/th.json | 2 -- lang/tr.json | 2 -- lang/uk.json | 2 -- lang/vi.json | 2 -- lang/zh-cn.json | 6 ++-- lang/zh-tw.json | 2 -- plugins/Events/lang/bg.json | 3 ++ plugins/Events/lang/da.json | 23 ++++++++++++++- plugins/Events/lang/nl.json | 1 + plugins/LeftMenu/lang/bg.json | 5 ++++ plugins/LeftMenu/lang/da.json | 10 +++++++ plugins/LeftMenu/lang/el.json | 10 +++++++ plugins/LeftMenu/lang/it.json | 10 +++++++ plugins/LeftMenu/lang/nl.json | 6 ++++ 51 files changed, 216 insertions(+), 107 deletions(-) create mode 100644 plugins/LeftMenu/lang/bg.json create mode 100644 plugins/LeftMenu/lang/da.json create mode 100644 plugins/LeftMenu/lang/el.json create mode 100644 plugins/LeftMenu/lang/it.json create mode 100644 plugins/LeftMenu/lang/nl.json diff --git a/lang/am.json b/lang/am.json index 20666521684..45e288cc74d 100644 --- a/lang/am.json +++ b/lang/am.json @@ -196,7 +196,6 @@ "ColumnConversions": "ልወጣዎች" }, "Installation": { - "CommunityNewsletter": "ከማህበረሰብ አልቅ ጋር ኢ-ሜይል አድርግልኝ(አዲስ ተሰኪዎች, አዲስ ባህርይዎች, ወዘተ.)", "ConfirmDeleteExistingTables": "እርግጠኛ ነህ ይህንን ሰንጠረዥ ከውሂብ ጎታህ ውስጥ : %s መሰረዝ ትፈልጋለህ? ማስጠንቀቂያ: ከዚህ ሰንጠረዥ ውስጥ የጠፉ ውሂቦች ተመልሰው ሊገኙ አይችሉም!", "Congratulations": "እንኳን ደስያለዎ", "CongratulationsHelp": "

እንኳን ደስያለዎ! የፒዊክ መጫንዎ ተሳክቷል።<\/p>

የጃቫ ስክሪፕትዎ ቾድ በሁሉ ገፆች ላይ መግባቱን ያረጋግጡና የመጀመሪያ ጎበኚዎችዎን ይጠብቁ!<\/p>", @@ -209,7 +208,6 @@ "PasswordDoNotMatch": "የይለፍ ቃሉ አቻ አይደለም", "PasswordRepeat": "የይለፍ ቃል (ድገም)", "PercentDone": "%s %% አልቋል", - "SecurityNewsletter": "ከዋነኛ የፒዊክ ማላቂያዎች እና የጥበቃ ማስጠንቀቂያዎች ጋር ኢ-ሜይል አድርግልኝ", "SetupWebsite": "ድር ጣቢያ ጫን", "SetupWebsiteError": "ድር ጣቢያውን በመጫን ጊዜ ስህተት አጋጥሟል", "SuperUserLogin": "ሊቀ ተገልጋይ ግባ", diff --git a/lang/ar.json b/lang/ar.json index 230701c33f0..826e89c6bfb 100644 --- a/lang/ar.json +++ b/lang/ar.json @@ -683,7 +683,6 @@ "WhereVisitedPageManuallyCallsJavascriptTrackerLearnMore": "حيث تكون الصفحة تحتوي على استدعاء لجافاسكريبت piwikTracker.trackGoal() (%sتعرف على المزيد%s)" }, "Installation": { - "CommunityNewsletter": "راسلني عند وجود تحديثات (إضافات جديدة، خصائص جديدة، وغيرها)", "ConfigurationHelp": "يبدو أن ملف الإعدادات الخاص بك به خطأ. يمكنك إما حذف config\/config.ini.php ومتابعة التثبيت أو تصحيح إعدادات الاتصال بقاعدة البيانات.", "ConfirmDeleteExistingTables": "هل ترغب حقاً في حذف الجداول: %s من قاعدة بياناتك؟ تنبيه: لن يمكن إستعادة البيانات من هذه الجداول!", "Congratulations": "مبروك", @@ -713,7 +712,6 @@ "PleaseFixTheFollowingErrors": "الرجاء إصلاح الأخطاء التالية", "PluginDescription": "عملية تثبيت Piwik. عملية التثبيت تتم مرة واحدة عادة. إذا تم حذف ملف الإعدادات config\/config.inc.php فستبدأ عملية التثبيت مرة أخرى.", "Requirements": "متطلبات Piwik", - "SecurityNewsletter": "راسلني عند وجود ترقيات وتنبيهات أمنية في Piwik", "SetupWebsite": "إعداد موقع ويب", "SetupWebsiteError": "حدث خطأ ما أثناء إضافة الموقع", "SetupWebSiteName": "اسم موقع ويب", diff --git a/lang/be.json b/lang/be.json index 89aa18d13d0..d0f450385a4 100644 --- a/lang/be.json +++ b/lang/be.json @@ -583,7 +583,6 @@ "YouCanEnableEcommerceReports": "Вы можаце ўключыць %s для гэтага вэб-сайта ў %s старонкі." }, "Installation": { - "CommunityNewsletter": "паведамляць мне пра абнаўленні супольнасці (новыя ўбудовы, новыя функцыі і г.д.) па email", "ConfigurationHelp": "Ваш Piwik канфігурацыйны файл, няправільна зканфігураваны. Вы можаце альбо выдаліць config\/config.ini.php і працягнуць усталёўку або правільна наладзіць злучэнне з базай дадзеных.", "ConfirmDeleteExistingTables": "Вы сапраўды жадаеце выдаліць табліцы: %s з базы дадзеных? УВАГА: ВЫДАЛЕНЫЯ ДАДЗЕНЫЯ НЕМАГЧЫМА АДНАВІЦЬ!", "Congratulations": "Віншуем", @@ -613,7 +612,6 @@ "PleaseFixTheFollowingErrors": "Калі ласка, выпраўце наступныя памылкі", "PluginDescription": "Працэс усталёўкі Piwik. Усталёўка звычайна адбывацца толькі адзін раз. Калі канфігурацыйны файл config\/config.inc.php выдалены, ўстаноўка пачнецца зноў.", "Requirements": "Патрабаванні Piwik", - "SecurityNewsletter": "паведамляць мяне пра значныя абнаўленні Piwik і памылках бяспекі па email", "SetupWebsite": "Дадаць сайт", "SetupWebsiteError": "Паўстала памылка пры даданні сайта", "SetupWebSiteName": "імя вэб-сайта", diff --git a/lang/bg.json b/lang/bg.json index 0239c7e0d67..98e95f17574 100644 --- a/lang/bg.json +++ b/lang/bg.json @@ -103,6 +103,7 @@ "CustomLogoFeedbackInfo": "Ако модифицирате Piwik логото, може също да пожелаете да скриете %s връзката в главното меню. За да направите това, можете да изключите добавката за обратна връзка в страницата %sУправление на добавки%s.", "CustomLogoHelpText": "Можете да модифицирате логото на Piwik, което да се показва в интерфейса на потребителя и имейлите с отчети.", "EmailServerSettings": "Настройки сървър на е-поща", + "FaviconUpload": "Изберете Favicon за качване", "ForBetaTestersOnly": "Само за бета тестери", "ImageTracking": "Проследяване на изображенията", "ImageTrackingIntro1": "Когато посетителят е изключил JavaScript или когато JavaScript не може да бъде използван, може да се използва проследяващата връзка към изображение, за да бъдат проследени посетителите.", @@ -190,6 +191,8 @@ "InjectedHostSuperUserWarning": "Възможно е конфигурацията на Piwik да е неправилна (това се случва когато Piwik е бил изместен на нов сървър или друг адрес). Вие можете или %1$sда щракнете тук и да добавите %2$s като валиден Piwik адрес (ако сте сигурни в достоверността му)%3$s, или %4$sда щракнете тук и да посетите %5$s, за да достъпите Piwik безпасно%6$s.", "InjectedHostWarningIntro": "В момента достъпвате Piwik от %1$s, но Piwik е настроен да работи чрез този адрес: %2$s.", "JavascriptDisabled": "JavaScript трябва да бъде разрешен за да използвате Piwik в стандартен изглед.
Същото е ако JavaScript не е разрешен или браузъра не го поддържа.
За да използвате стандартен изглед разрешете JavaScript от настройките на Вашия браузър и %1$sопитайте отново%2$s.
", + "LongMonthFormat": "%longYear%, %longMonth%", + "LongWeekFormat": "%dayFrom% %longMonthFrom% - %dayTo% %longMonthTo% %longYearTo%", "MakeADifference": "Открийте разликата: %1$sДарете%2$s за фонд Piwik 2.0!", "MakeOneTimeDonation": "Направете еднократно дарение", "NoPrivilegesAskPiwikAdmin": "Вие се логнахте в като '%s' но изглежда че нямате разрешение от Piwik. %s Попитайте Вашият Piwik администратор (клик на email)%s да Ви даде \"поглед\" достъп до сайта.", @@ -209,6 +212,10 @@ "SharePiwikLong": "Здравейте! Туко-що открих прекрасен софтуер с отворен код: Piwik! Piwik позволява проследяването на посетителите на даден сайт безплатно. Задължително трябва да го пробвате!", "SharePiwikShort": "Piwik! Софтуер с отворен код за уеб анализ. Притежавайте вашите собствени данни.", "ShareThis": "Сподели това", + "ShortDateFormat": "%shortDay% %day% %shortMonth%", + "ShortDateFormatWithYear": "%day% %shortMonth% %shortYear%", + "ShortMonthFormat": "%shortMonth% %longYear%", + "ShortWeekFormat": "%dayFrom% %shortMonthFrom% - %dayTo% %shortMonthTo% %shortYearTo%", "ShowJSCode": "Покажи JavaScript кода за вмъкване в сайта", "SubscribeAndBecomePiwikSupporter": "Пристъпете към сигурната страница за плащане (PayPal) за да станете Piwik Supporter!", "SupportPiwik": "Подкрепи Piwik!", @@ -246,6 +253,7 @@ "Developer": "Разработчик", "DoMoreContactPiwikAdmins": "За да се инсталира нова добавка или нова тема, трябва да се свържете с вашия администратор, който отговаря за Piwik.", "DownloadAndInstallPluginsFromMarketplace": "Можете автоматично да свалите и инсталирате нови добавки от %sмагазина за приложения%s.", + "EmailToEnquireUpdatedVersion": "Моля, пишете до %1$s и изискайте актуална версия на %2$s.", "EnjoyAnotherLookAndFeelOfThemes": "Насладете се на друг изглед и усещане", "FeaturedPlugin": "Препоръчана добавка", "GetEarlyAccessForPaidPlugins": "Забележка: всички от наличните добавки са безплатни за използване; в бъдеще ще има платена секция в магазина за приложения (%sсвържете се с нас%s за предварителен достъп).", @@ -435,7 +443,8 @@ "SpecialRequest": "Имате ли специална молба към екипа на Piwik?", "ThankYou": "Благодаря, че помогнахте да направим Piwik по-добър!", "TopLinkTooltip": "Може да ни кажете какво мислите, както и да изискате професионална помощ.", - "VisitTheForums": "Посетете нашият %sФорум%s" + "VisitTheForums": "Посетете нашият %sФорум%s", + "WantToThankConsiderDonating": "Смятате, че Piwik е страхотен и искате да ни благодарите?" }, "General": { "AbandonedCarts": "Отказани колички", @@ -969,15 +978,16 @@ "PluginDescription": "Генерирайте красиви статични PNG графични изображения за всеки Piwik доклад." }, "Insights": { + "ControlComparedToDescription": "Ръст спрямо", "DayComparedToPreviousDay": "предишен ден", "Filter": "Филтър", "FilterOnlyNew": "Само нови", + "TitleRowDisappearedDetails": "'%1$s' намалял с %2$s и изчезна в %3$s сравнено с %4$s.", "WeekComparedToPreviousWeek": "предишна седмица", "YearComparedToPreviousYear": "предишна година" }, "Installation": { "CollaborativeProject": "Piwik е съвместен проект, изграден с много любов от хора от всички краища на света.", - "CommunityNewsletter": "изпращай по пощата информация за нови добавки, функции и др.", "ConfigurationHelp": "Вашият Piwik конфигурационен файл изглежда не добре конфигуриран. Можете да премахнете config\/config.ini.php и да започнете инсталирането, или да поправите настройките за връзка към БД-то.", "ConfirmDeleteExistingTables": "Наистина ли искате да изтриете следните таблици: %s от базата от данни (БД)? ПРЕДУПРЕЖДЕНИЕ: ДАННИТЕ ОТ ТАЗИ ТАБЛИЦА НЕ МОГАТ ДА БЪДАТ ВЪЗСТАНОВЕНИ!!!", "Congratulations": "Поздравления", @@ -1009,6 +1019,7 @@ "NfsFilesystemWarning": "Вашият сървър ползва NFS файлова система.", "NfsFilesystemWarningSuffixAdmin": "Това означава, че Piwik ще бъде изключително бавен, когато използвате файлови базирани сесии.", "NoConfigFound": "Piwik конфигурационният файл не е открит.
  » Можете да инсталирате Piwik сега<\/a><\/b>
Ако преди това сте инсталирали Piwik и имате в базата от данни (БД) таблици - можете да запазите Вашите данни!<\/small>", + "NotSupported": "не се поддържа", "Optional": "По избор", "Password": "парола", "PasswordDoNotMatch": "паролата не съвпада", @@ -1018,7 +1029,6 @@ "PluginDescription": "Инсталационния процес на Piwik. Инсталацията обикновено се прави само веднъж. Ако конфигурационния файл config\/ config.inc.php е изтрит, инсталацията ще започне отново.", "Requirements": "Piwik Изисквания", "RestartWebServer": "След като направите промените, рестартирайте уеб сървара.", - "SecurityNewsletter": "изпращай на имейл информация за обновленията и сигнали относно сигурността", "SeeBelowForMoreInfo": "Вижте по-долу за повече информация.", "SetupWebsite": "Настройки на сайт", "SetupWebsiteError": "Възникнала е грешка при добавянето на сайт", @@ -1170,6 +1180,7 @@ "HowtoDeleteAnAccount": "Натиснете продължително, за да изтриете профил.", "HowtoDeleteAnAccountOniOS": "Плъзнете от ляво на дясно за да изтриете акаунта", "HowtoLoginAnonymous": "Оставете потребителско име и парола празно за анонимен вход", + "HttpTimeout": "HTTP сесията изтече", "IncompatiblePiwikVersion": "Piwik версията, която използвате не е съвместима с Piwik Mobile 2. Обновете вашата инсталация на Piwik и пробвайте отново или инсталирайте Piwik Mobile 1.", "LastUpdated": "Последна актуализация: %s", "LoadingReport": "Зарежда се %s", @@ -1244,6 +1255,7 @@ "MultiSites": { "Evolution": "Развитие", "LoadingWebsites": "Зарежда сайтовете", + "Pagination": "%s - %s като %s", "PluginDescription": "Показва обобщена статистика\/резюме. В момента се поддържа като основна добавка в Piwik.", "TopLinkTooltip": "Сравнете статистиката за всички ваши уебсайтове." }, diff --git a/lang/ca.json b/lang/ca.json index ff8fad2447f..cc3ac28576b 100644 --- a/lang/ca.json +++ b/lang/ca.json @@ -777,7 +777,6 @@ "PluginDescription": "Generar belles imatges estàtiques en gràfic PNG per qualsevol informe del Piwik." }, "Installation": { - "CommunityNewsletter": "Envieu-me correus-e amb les actualitzacions de la comunitat (nous connectors, funcionalitats, etc.)", "ConfigurationHelp": "Sembla que el vostre fitxer de configuració del Piwik no està definit correctament. Podeu eliminar el fitxer confi\/config.ini.php i torna a començar la instal·lació o corregir les preferències de connexió a la Base de dades.", "ConfirmDeleteExistingTables": "Realment voleu esborrar les taules %s de la base de dades? AVÍS: NO ES PODRAN RECUPERAR LES DADES!", "Congratulations": "Felicitats", @@ -816,7 +815,6 @@ "PluginDescription": "Procès d'instal·lació del Piwik. El procès d'instal·lació només es dur a temre una vegada. Si el fitxer de configuració config\/config.inc.php s'esborrà es tornarà a iniciar la instal·lació.", "Requirements": "Requeriments del Piwik", "RestartWebServer": "Desprès de fer aquest canvi, reinicieu el vostre servidor web.", - "SecurityNewsletter": "Envieu-me correus-e sobre les actualitzacions grans del Piwik i les alertes de seguretat", "SeeBelowForMoreInfo": "Llegiu a continuació per més informació.", "SetupWebsite": "Configura un lloc", "SetupWebsiteError": "Hi ha hagut un problema en el moment d'afegir el lloc.", diff --git a/lang/cs.json b/lang/cs.json index 8b259f7ef90..3e5612f1117 100644 --- a/lang/cs.json +++ b/lang/cs.json @@ -718,7 +718,6 @@ "PluginDescription": "Generuje nádherné statické PNG grafy pro jakékoli Piwik hlášení." }, "Installation": { - "CommunityNewsletter": "pošli mi e mail s komunitními aktualizacem (nové zásuvné moduly, nové funkce, atd.)", "ConfigurationHelp": "Váš konfigurační soubor Piwiku je špatně nastavený. Můžete buď odstranit soubor config\/config.ini a znovu začít instalaci, nebo opravit nastavení databáze.", "ConfirmDeleteExistingTables": "Jste si jistí, že chcete vymazat tabulky: %s z vaší databáze? UPOZORNĚNÍ: DATA Z TĚCHTO TABULEK NEPŮJDOU OBNOVIT!", "Congratulations": "Gratulujeme", @@ -752,7 +751,6 @@ "PluginDescription": "Instalační proces Piwiku. Instalace se obvykle používá jednou. V případě vymazání konfiguračního souboru config\/config.inc.php se instalace zahájí znovu", "Requirements": "Požadavky Piwiku", "RestartWebServer": "Po uložení změn restartujte Vás web server.", - "SecurityNewsletter": "pošli mi e-mail při hlavních aktualizacích a bezpečnostních oznámeních Piwiku", "SetupWebsite": "Nastavit Web", "SetupWebsiteError": "Při přidávání Webu se vyskytla chyba", "SetupWebSiteName": "jméno webu", diff --git a/lang/da.json b/lang/da.json index dc3f57fe5c3..0bec0dcb26b 100644 --- a/lang/da.json +++ b/lang/da.json @@ -104,6 +104,7 @@ "CustomLogoHelpText": "Du kan tilpasse Piwik logo, der bliver vist i brugergrænsefladen og e-mail rapporter.", "DevelopmentProcess": "Mens vores%s udviklingsproces%s omfatter tusindvis af automatiske tests, spiller betatestere en nøglerolle i at opnå \"ingen fejl politikken\" i Piwik.", "EmailServerSettings": "E-mail-server indstillinger", + "FaviconUpload": "Vælg Favicon til overførelse", "ForBetaTestersOnly": "Kun for beta testere", "ImageTracking": "Sporing vha. et billede", "ImageTrackingIntro1": "Når en besøgende har deaktiveret JavaScript, eller når JavaScript kan ikke bruges, kan sporing vha. et billede bruges til at spore besøgende.", @@ -154,11 +155,12 @@ "PiwikIsInstalledAt": "Piwik er installeret på", "PluginDescription": "Piwik administration.", "PluginSettingChangeNotAllowed": "Du må ikke ændre værdien \"%s\" i udvidelse \"%s\"", + "PluginSettingReadNotAllowed": "Du har ikke tilladelse til at læse værdien af ​​indstillingen \"%s\" i udvidelsen \"%s\"", "PluginSettings": "Programudvidelses indstilinger", "PluginSettingsIntro": "Her kan du ændre indstillingerne for følgende 3. parts udvidelsesmoduler:", "PluginSettingsValueNotAllowed": "Værdien for feltet \"%s\" i udvidelsen \"%s\" er ikke tilladt", - "SendPluginUpdateCommunication": "Send mig en e-mail når der er en ny opdatering af denne plugin.", - "SendPluginUpdateCommunicationHelp": "En e-mail vil blive sendt til Superbrugere, når der er en ny version tilgængelig for dette plugin.", + "SendPluginUpdateCommunication": "Send mig en e-mail når der er en ny opdatering af denne programudvidelse.", + "SendPluginUpdateCommunicationHelp": "En e-mail vil blive sendt til Superbrugere, når der er en ny version tilgængelig for denne programudvidelse.", "StableReleases": "Hvis Piwik er en kritisk del af virksomheden, anbefaler vi at man bruger den nyeste stabile udgave. Hvis man bruger den nyeste beta, og finder en fejl eller har et forslag, %sse her%s.", "TrackAGoal": "Spor et mål", "TrackingCode": "Sporingskode", @@ -188,6 +190,7 @@ "DonateCall3": "Synes du, at Piwik har tilføjet væsentlig merværdi til dig eller din virksomhed, %1$s overvej at donere!%2$s", "DonateFormInstructions": "Klik på skyderen for at vælge et beløb, og klik derefter på vælg at donere.", "ExcludeRowsWithLowPopulation": "Alle rækker vises %s Udeluk lav population", + "ExternalHelp": "Hjælp (åbnes i en ny fane)", "FlattenDataTable": "Rapporten er hierarkisk %s lav den ikke hierakisk", "HowMuchIsPiwikWorth": "Hvor meget er Piwik værd for dig?", "IncludeRowsWithLowPopulation": "Rækker med lav population er skjult %s Vis alle rækker", @@ -260,6 +263,7 @@ "Developer": "Udvikler", "DoMoreContactPiwikAdmins": "For at installere en ny programudvidelse eller et nyt tema, kontakt Piwik administratoren.", "DownloadAndInstallPluginsFromMarketplace": "Du kan automatisk hente og installere nye programudvidelser fra %smarkedspladsen%s.", + "EmailToEnquireUpdatedVersion": "Send e-mail til %1$s og forespørg om en opdateret version af %2$s.", "EnjoyAnotherLookAndFeelOfThemes": "Nyd et andet udseende", "FeaturedPlugin": "Udvalgte programudvidelser", "GetEarlyAccessForPaidPlugins": "Bemærk: alle programudvidelser er tilgængelige gratis på nuværende tidspunkt; i fremtiden vil vi sætte betalte programudvidelser på markedspladsen (%skontakt os%s for tidlig adgang).", @@ -297,6 +301,7 @@ "PluginKeywords": "Nøgleord", "PluginNotCompatibleWith": "%1$s udvidelsesmodul er ikke kompatibelt med %2$s.", "PluginNotWorkingAlternative": "Hvis du har brugt programudvidelsen,kan du måske finde en nyere version på markedspladen. Hvis ikke, kan du afinstallere den.", + "PluginRequirement": "%1$s kræver %2$s", "PluginsManagement": "Udvidelsesmodul administration", "PluginUpdateAvailable": "Du bruger version %s en ny version %s er tilgængelig.", "PluginVersionInfo": "%1$s fra %2$s", @@ -339,6 +344,7 @@ "CreatingBackupOfConfigurationFile": "Opretter sikkerhedskopi af konfigurationsfiler i %s", "CriticalErrorDuringTheUpgradeProcess": "Kritisk fejl under opdateringen:", "DatabaseUpgradeRequired": "Database opdatering er nødvendig", + "DisablingIncompatiblePlugins": "Deaktivere inkompatible programudvidelsen: %s", "DownloadingUpdateFromX": "Henter opdatering fra %s", "DownloadX": "Hent %s", "EmptyDatabaseError": "Databasen %s er tom. Redigere eller fjern Piwiks konfigurationsfil.", @@ -358,22 +364,23 @@ "HelpMessageIntroductionWhenError": "Ovenstående vises fejlmeddelelsen. Den bør hjælpe med at forklare årsagen, men hvis der behøves mere hjælp:", "HelpMessageIntroductionWhenWarning": "Opdateringen er fuldført, men det var nogle småproblemer under processen. Læs detaljerne ovenfor. For yderligere hjælp:", "HighTrafficPiwikServerEnableMaintenance": "Hvis du administrerer en Piwik server med høj trafik, anbefaler vi at du %s midlertidigt deaktivere sporing af besøgende og sætte Piwik brugergrænseflade i vedligeholdelsestilstand%s", + "IncompatbilePluginsWillBeDisabledInfo": "Bemærk: Nogle udvidelsesmoduler er ikke kompatible med Piwik %s. De vil blive deaktiveret, når du opgraderer:", "InstallingTheLatestVersion": "Installerer den seneste version", "MajorUpdateWarning1": "Dette er en stor opdatering! Den vil tage længere tid end normalt.", "MajorUpdateWarning2": "Det følgende råd er især vigtigt for store installationer.", "NoteForLargePiwikInstances": "Vigtig bemærkning til store Piwik installationer", "NoteItIsExpectedThatQueriesFail": "Bemærk: Hvis du manuelt udfører disse forespørgsler, forventes det, at nogle af dem mislykkes. I så fald ignoreres fejlene blot, og køre den næste forespørgsel på listen.", - "NotificationClickToUpdatePlugins": "Klik her for at opdatere dit plugins nu:", + "NotificationClickToUpdatePlugins": "Klik her for at opdatere dit programudvidelser nu:", "NotificationClickToUpdateThemes": "Klik her for at opdatere dine temaer nu:", "NotificationSubjectAvailableCoreUpdate": "Ny Piwik %s er nu tilgængelig", - "NotificationSubjectAvailablePluginUpdate": "En opdatering til tilgængelig for dine Piwik plugins", + "NotificationSubjectAvailablePluginUpdate": "En opdatering til tilgængelig for dine Piwik programudvidelser", "PiwikHasBeenSuccessfullyUpgraded": "Piwik blev opdateret!", "PiwikUpdatedSuccessfully": "Piwik er opdateret!", "PiwikWillBeUpgradedFromVersionXToVersionY": "Piwik vil blive opgraderet fra version %1$s til den nye version %2$s.", "PluginDescription": "Piwik ajourføringsmekanisme", "ReadyToGo": "Klar, parat, start?", "TheFollowingPluginsWillBeUpgradedX": "Følgende udvidelsesmoduler vil blive opgraderet: %s.", - "ThereIsNewPluginVersionAvailableForUpdate": "Nogle plugins du bruger er blevet opdateret på markedspladsen:", + "ThereIsNewPluginVersionAvailableForUpdate": "Nogle programudvidelser du bruger er blevet opdateret på markedspladsen:", "ThereIsNewVersionAvailableForUpdate": "Ny version af Piwik er tilgængelig", "TheUpgradeProcessMayFailExecuteCommand": "Hvis du har en stor Piwik database, kan opdateringer tage for lang tid at køre i browseren. I denne situation, kan du udføre opdateringen fra kommandolinjen: %s", "TheUpgradeProcessMayTakeAWhilePleaseBePatient": "Database opgraderingen kan tage lidt tid, vær tålmodig.", @@ -442,6 +449,7 @@ "ContactThePiwikTeam": "Kontakt Piwik holdet", "DoYouHaveBugReportOrFeatureRequest": "Har du en fejlrapport eller en anmodning om en funktion?", "GetInTouch": "Vi værdsætter din feedback og læser altid alle meddelelser uanset om du har en forretningsidé, ønsker at finde en Piwik konsulent, fortæl os en succeshistorie eller blot sige hej!", + "HowToCreateIssue": "Læs anbefalingerne om at skrive en god %1$sfejlrapport%2$s eller %3$sfunktionsforslag%4$s. Derefter %5$sregister%6$s eller %7$slogind%8$s på vores emne tracker og opret en %9$snyt emne%10$s.", "IWantTo": "Jeg ønsker at:", "LearnWaysToParticipate": "Lær om alle de måder, du kan %s bidrage%s", "ManuallySendEmailTo": "Send din besked manuelt til", @@ -451,10 +459,13 @@ "RateFeatureLeaveMessageLike": "Vi er glad for du kan lide det! Fortæl os hvad du kan lide mest eller hvis du har forslag til en ny funktion.", "RateFeatureSendFeedbackInformation": "Piwik vil sende Piwik holdet en e-mail (med din e-mail-adresse), så vi kan komme i kontakt med dig, hvis du har nogen spørgsmål.", "RateFeatureThankYouTitle": "Tak for din bedømmelse '%s'!", + "RateFeatureTitle": "Kan du lide '%s' funktionen? Bedøm og efterlade en kommentar", "SendFeedback": "Send tilbagemelding", "SpecialRequest": "Har du en speciel anmodning til Piwik holdet?", "ThankYou": "Tak, fordi du hjælper med at gøre Piwik bedre!", "TopLinkTooltip": "Fortæl os hvad du mener eller anmod om professionel support", + "ViewAnswersToFAQ": "Se svarene på %sOfte stillede spørgsmål%s", + "ViewUserGuides": "Lær at konfigurere Piwik og hvordan man effektivt analyserer data med vores %1$sbrugervejledninger%2$s", "VisitTheForums": "Besøg %s Forum%s", "WantToThankConsiderDonating": "Synes du at Piwik er fantastisk og ønsker du at takke os?" }, @@ -624,6 +635,7 @@ "ExceptionUnableToStartSession": "Kan ikke starte sessionen.", "ExceptionUndeletableFile": "Kunne ikke slette %s", "ExceptionUnreadableFileDisabledMethod": "Konfigurationsfilen (%s) kunne ikke læses. Udbyderen kan have deaktiveret %s.", + "ExpandDataTableFooter": "Ændre visualiseringen eller konfigurer rapporten", "Export": "Eksporter", "ExportAsImage": "Eksporter som billede", "ExportThisReport": "Eksporter datasættet i andre formater", @@ -757,6 +769,7 @@ "Password": "Adgangskode", "Period": "Periode", "Piechart": "Cirkeldiagram", + "PiwikIsACollaborativeProjectYouCanContributeAndDonate": "%1$sPiwik%2$s er et samarbejdsprojekt af %7$sPiwik holdets%8$s medlemmer samt mange andre bidragydere i hele verden. Hvis du er en fan af Piwik, kan du hjælpe med: at finde ud af %3$shvordan du hjælper Piwik%4$s eller %5$sdoner nu%6$s til at hjælpe med at finansiere Piwik 3.0!", "PiwikXIsAvailablePleaseNotifyPiwikAdmin": "%1$s er tilængelig. Kontakt venligst %2$sPiwik administrator%3$s.", "PiwikXIsAvailablePleaseUpdateNow": "Piwik %1$s er tilgængelig. %2$sOpdater nu!%3$s (se %4$sændringer%5$s).", "PleaseSpecifyValue": "Angiv værdi for '%s'.", @@ -840,6 +853,7 @@ "Table": "Tabel", "TagCloud": "Emne sky", "Tax": "Moms", + "TimeAgo": "%s siden", "TimeOnPage": "Tid på siden", "Today": "I dag", "Total": "Total", @@ -998,6 +1012,7 @@ "PluginDescription": "Generere flotte statiske PNG diagrammer til Piwik rapporter." }, "Insights": { + "ControlComparedToDescription": "Vækst i forhold til", "ControlFilterByDescription": "Vis alle, kun ændringer, kun nye eller kun forsvundne", "DatePeriodCombinationNotSupported": "Det er ikke muligt at generere rapporter til disse datoer og kombination af perioder.", "DayComparedToPreviousDay": "Foregående dag", @@ -1012,11 +1027,24 @@ "FilterOnlyNew": "Kun nye", "IgnoredChanges": "Ændringer, der påvirker mindre end %s besøgende bliver ignoreret", "MonthComparedToPreviousMonth": "forrige måned", - "MonthComparedToPreviousYear": "samme måned forrige år" + "MonthComparedToPreviousYear": "samme måned forrige år", + "MoversAndShakersWidgetTitle": "Op- og Nedgang", + "NoResultMatchesCriteria": "Ingen rækker svarer til kriteriet", + "OverviewWidgetTitle": "Indsigtsoversigt", + "TitleConsideredInsightsChanges": "Rækkerne steget eller faldet med mindst %1$s besøg (%2$s%% af %3$s samlede antal besøg).", + "TitleConsideredInsightsGrowth": "Følgende rækker har en vækst på mindst %1$s%% i forhold til %2$s.", + "TitleConsideredMoversAndShakersChanges": "Betragtes kun ændringer, hvis de voksede med mere end %1$s%% besøg eller faldt med mindre end %2$s%% besøg, nye poster hvis de er steget med mere end %3$s%% besøg (%4$s), og er forsvundne rækker, hvis de faldt med mindre end %5$s%% besøg (%6$s).", + "TitleConsideredMoversAndShakersGrowth": "%1$s ændret fra %2$s til %3$s i forhold til %4$s. Baseret på dette forventes en videreudvikling for hver række på %5$s%%.", + "TitleRowChangeDetails": "'%1$s' ændres fra %2$s (%3$s) til %4$s (%5$s) %6$s.", + "TitleRowDisappearedDetails": "'%1$s' faldt med %2$s og er forsvand i %3$s i forhold til %4$s.", + "TitleRowMoverAndShaker": "Denne række havde en større effekt end gennemsnittet.", + "TitleRowNewDetails": "'%1$s' øget med %2$s og er ny i forhold til %3$s.", + "WeekComparedToPreviousWeek": "forrige uge", + "WidgetCategory": "Indsigt", + "YearComparedToPreviousYear": "forrige år" }, "Installation": { "CollaborativeProject": "Piwik er et samarbejdsprojekt, bygget med kærlighed af folk fra hele verden.", - "CommunityNewsletter": "send e-mail med opdateringer (nye udvidelsesmoduler, nye muligheder m.m.)", "ConfigurationHelp": "Piwik konfigurationsfil synes at være konfigureret forkert. Fjern enten config\/config.ini.php og genoptage installation eller ret database forbindelsesindstillinger.", "ConfirmDeleteExistingTables": "Bekræft sletning af tabellerne: %s fra databasen? ADVARSEL: DATA FRA DISSE TABELLER KAN IKKE GENSKABES!", "Congratulations": "Tillykke", @@ -1052,6 +1080,7 @@ "NfsFilesystemWarningSuffixAdmin": "Det betyder at Piwik vil være ekstremt langsom når der benyttes filbaserede sessioner.", "NfsFilesystemWarningSuffixInstall": "Brug af filbaserede sessioner på et NFS filsystem er ekstrem langsomt, så Piwik vil benytte database sessioner. Hvis du har mange samtidige kontrolpanelsbrugere, vil du muligvis være nødt til at hæve det maksimale antal af klient forbindelser til database serveren.", "NoConfigFound": "Piwik-konfigurationsfil blev ikke fundet og du prøver at få adgang til Piwik.