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

github.com/matomo-org/matomo.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthieu Aubry <mattab@users.noreply.github.com>2016-09-29 05:03:02 +0300
committerGitHub <noreply@github.com>2016-09-29 05:03:02 +0300
commitbd5217287e84d8a2fdc457dd07ce63d78c5835b4 (patch)
treeb0c4121eda233d3bfeeae29a482dc8f5a3d6304b
parenta8f682a6039e9b765e248c6be531cce54a7903d1 (diff)
2.16.3-rc1 (#10590)2.16.3-rc1
* Fix depraction test: use assertDeprecatedMethodIsRemovedInPiwik3 * Fix Scheduled Reports sent one hour late in daylight saving timezones (#10443) * convert hour to send report to/from UTC, to ensure it isn't affected by daylight savings * adds update script to change existing scheduled reports to use utc time * code improvement * adds missing param * Added new event Archiving.makeNewArchiverObject to allow customising plugin archiving (#10366) * added hook to alllow plugin archiving prevention * cr code style notes * reworked PR to fit CR suggestions * added PHPDoc for hook * Event description more consistent * UI tests: minor changes * Comment out Visitor Log UI tests refs #10536 * Adds test checking if all screenshots are stored in lfs * removed screenshots not stored in lfs * readds screenshots to lfs * 2.16.3-b4 * Issue translation updates against 2.x-dev * language update * Fix bug in widget list remove where the JSON object becomes array * 2.16.3-rc1 * console command custom-piwik-js:update should work when directory is writable and file does not exist yet (#10576) * followup #10449 * Fix test (cherry picked from commit fac3d63) * Prevent chmod(): No such file or directory * Automatically update all marketplace plugins when updating Piwik (#10527) * update plugins and piwik at the same time * make sure plugins are updated with piwik * use only one try/catch * reload plugin information once it has been installed * make sure to clear caches after an update * fix ui tests * make sure to use correct php version without any extras * Additional informations passed in the hook "isExcludedVisit" (issue #10415) (#10564) * Additional informations passed in the hook "isExcludedVisit" (issue #10415) * Added better description to the new parameters * Update VisitExcluded.php * Remove two parameters not needed as better to use the Request object * Update VisitExcluded.php * remove extra two parameters in VisitExcluded constructor to prevent confusion (#10593) * Update our libs to latest https://github.com/piwik/piwik/issues/10526 * Update composer libraries to latest https://github.com/piwik/piwik/issues/10526 * Update log analytics to latest * When updating the config file failed (or when any other file is not writable...), the Updater (for core or plugins) will now automatically throw an error and cancel the update (#10423) * When updating the config file failed (or when any other file is not writable...), the Updater (for core or plugins) will now automatically throw an error and cancel the update * add integration test to check the correct exception is thrown when config not writabel * New integration test for updater * Make test better * When opening the visitor profile, do not apply the segment (#10533) * When opening the visitor profile, do not apply the segment * added ui test for profile but does work for me * next try to make ui test work * add expected screenshot * added missing doc
-rw-r--r--composer.lock99
-rw-r--r--core/Config.php16
-rw-r--r--core/Plugin.php17
-rw-r--r--core/Tracker/VisitExcluded.php21
-rw-r--r--core/Updater.php7
-rw-r--r--core/Version.php2
-rw-r--r--core/WidgetsList.php2
-rw-r--r--lang/es.json1
-rw-r--r--lang/it.json2
-rw-r--r--libs/bower_components/jquery.scrollTo/README.md142
-rw-r--r--libs/bower_components/jquery.scrollTo/jquery.scrollTo.min.js12
-rw-r--r--libs/bower_components/jquery.scrollTo/scrollTo.jquery.json56
m---------misc/log-analytics0
-rw-r--r--plugins/API/lang/es.json3
-rw-r--r--plugins/API/lang/tr.json14
-rw-r--r--plugins/Actions/lang/es.json4
-rw-r--r--plugins/Annotations/lang/tr.json6
-rw-r--r--plugins/Contents/lang/es.json5
-rw-r--r--plugins/CoreAdminHome/lang/es.json1
-rw-r--r--plugins/CoreAdminHome/tests/Integration/SetConfigTest.php41
-rw-r--r--plugins/CoreHome/Tracker/VisitRequestProcessor.php3
-rw-r--r--plugins/CoreHome/javascripts/popover.js10
-rw-r--r--plugins/CorePluginsAdmin/MarketplaceApiClient.php10
-rw-r--r--plugins/CorePluginsAdmin/PluginInstaller.php9
-rw-r--r--plugins/CorePluginsAdmin/config/config.php7
-rw-r--r--plugins/CorePluginsAdmin/lang/es.json4
-rw-r--r--plugins/CoreUpdater/Controller.php2
-rw-r--r--plugins/CoreUpdater/Updater.php54
-rw-r--r--plugins/CoreUpdater/lang/en.json4
-rw-r--r--plugins/CoreUpdater/lang/tr.json23
-rw-r--r--plugins/CustomPiwikJs/File.php9
-rw-r--r--plugins/CustomPiwikJs/lang/cs.json7
-rw-r--r--plugins/CustomPiwikJs/lang/de.json5
-rw-r--r--plugins/CustomPiwikJs/lang/el.json7
-rw-r--r--plugins/CustomPiwikJs/lang/es.json7
-rw-r--r--plugins/CustomPiwikJs/lang/fr.json7
-rw-r--r--plugins/CustomPiwikJs/lang/nb.json7
-rw-r--r--plugins/CustomPiwikJs/tests/Integration/FileTest.php70
-rw-r--r--plugins/CustomPiwikJs/tests/Integration/TrackerUpdaterTest.php8
-rw-r--r--plugins/CustomVariables/lang/es.json14
-rw-r--r--plugins/DevicePlugins/lang/es.json1
-rw-r--r--plugins/DevicePlugins/lang/tr.json7
-rw-r--r--plugins/Diagnostics/lang/es.json8
-rw-r--r--plugins/Feedback/lang/cs.json4
-rw-r--r--plugins/Feedback/lang/es.json1
-rw-r--r--plugins/Feedback/lang/nb.json3
-rw-r--r--plugins/Goals/lang/es.json1
-rw-r--r--plugins/Installation/lang/cs.json3
-rw-r--r--plugins/Installation/lang/de.json2
-rw-r--r--plugins/LanguagesManager/Commands/CreatePull.php18
-rw-r--r--plugins/Live/javascripts/visitorProfile.js5
-rw-r--r--plugins/Live/lang/es.json3
-rw-r--r--plugins/Login/lang/es.json2
-rw-r--r--plugins/Login/lang/tr.json22
-rw-r--r--plugins/Morpheus/javascripts/ajaxHelper.js42
-rw-r--r--plugins/ScheduledReports/lang/cs.json1
-rw-r--r--plugins/ScheduledReports/lang/el.json1
-rw-r--r--plugins/ScheduledReports/lang/es.json1
-rw-r--r--plugins/SitesManager/lang/es.json6
-rw-r--r--plugins/Transitions/lang/tr.json38
-rw-r--r--plugins/UserId/lang/es.json4
-rw-r--r--plugins/UsersManager/lang/es.json5
-rw-r--r--plugins/VisitFrequency/lang/tr.json26
-rw-r--r--tests/PHPUnit/Framework/Mock/Tracker/RequestAuthenticated.php10
-rw-r--r--tests/PHPUnit/Integration/Tracker/VisitTest.php24
-rw-r--r--tests/PHPUnit/Integration/UpdaterTest.php15
-rw-r--r--tests/UI/expected-screenshots/CoreUpdaterCode_newVersion.png4
-rw-r--r--tests/UI/expected-screenshots/UIIntegrationTest_visitor_profile_not_segmented.png3
-rw-r--r--tests/UI/specs/UIIntegration_spec.js26
-rw-r--r--tests/javascript/index.php2
-rw-r--r--tests/resources/Updater/testpluginUpdates/0.5.php12
71 files changed, 731 insertions, 287 deletions
diff --git a/composer.lock b/composer.lock
index f93891fd4c..056e4a4e19 100644
--- a/composer.lock
+++ b/composer.lock
@@ -305,16 +305,16 @@
},
{
"name": "monolog/monolog",
- "version": "1.20.0",
+ "version": "1.21.0",
"source": {
"type": "git",
"url": "https://github.com/Seldaek/monolog.git",
- "reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037"
+ "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Seldaek/monolog/zipball/55841909e2bcde01b5318c35f2b74f8ecc86e037",
- "reference": "55841909e2bcde01b5318c35f2b74f8ecc86e037",
+ "url": "https://api.github.com/repos/Seldaek/monolog/zipball/f42fbdfd53e306bda545845e4dbfd3e72edb4952",
+ "reference": "f42fbdfd53e306bda545845e4dbfd3e72edb4952",
"shasum": ""
},
"require": {
@@ -379,7 +379,7 @@
"logging",
"psr-3"
],
- "time": "2016-07-02 14:02:10"
+ "time": "2016-07-29 03:23:52"
},
{
"name": "mustangostang/spyc",
@@ -742,16 +742,16 @@
},
{
"name": "piwik/cache",
- "version": "0.2.7",
+ "version": "0.2.8",
"source": {
"type": "git",
"url": "https://github.com/piwik/component-cache.git",
- "reference": "7343e8b32da72f6ed50161c9c3b43ef8f5577cd6"
+ "reference": "254db008633ac86d06e5c250c7cf270fd721a7b6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/piwik/component-cache/zipball/7343e8b32da72f6ed50161c9c3b43ef8f5577cd6",
- "reference": "7343e8b32da72f6ed50161c9c3b43ef8f5577cd6",
+ "url": "https://api.github.com/repos/piwik/component-cache/zipball/254db008633ac86d06e5c250c7cf270fd721a7b6",
+ "reference": "254db008633ac86d06e5c250c7cf270fd721a7b6",
"shasum": ""
},
"require": {
@@ -785,7 +785,7 @@
"file",
"redis"
],
- "time": "2016-07-20 23:26:18"
+ "time": "2016-08-09 02:16:11"
},
{
"name": "piwik/decompress",
@@ -981,16 +981,16 @@
},
{
"name": "piwik/referrer-spam-blacklist",
- "version": "1.0.9",
+ "version": "1.0.10",
"source": {
"type": "git",
"url": "https://github.com/piwik/referrer-spam-blacklist.git",
- "reference": "7cce0bed292d148822ebad0eb9a286b04d27f340"
+ "reference": "58ecaaf7aced82ddbcc9339e1fc9e7fe9e996eb8"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/piwik/referrer-spam-blacklist/zipball/7cce0bed292d148822ebad0eb9a286b04d27f340",
- "reference": "7cce0bed292d148822ebad0eb9a286b04d27f340",
+ "url": "https://api.github.com/repos/piwik/referrer-spam-blacklist/zipball/58ecaaf7aced82ddbcc9339e1fc9e7fe9e996eb8",
+ "reference": "58ecaaf7aced82ddbcc9339e1fc9e7fe9e996eb8",
"shasum": ""
},
"type": "library",
@@ -999,20 +999,20 @@
"Public Domain"
],
"description": "Community-contributed list of referrer spammers",
- "time": "2016-07-20 19:55:33"
+ "time": "2016-09-28 16:10:53"
},
{
"name": "piwik/searchengine-and-social-list",
- "version": "1.3.3",
+ "version": "1.3.4",
"source": {
"type": "git",
"url": "https://github.com/piwik/searchengine-and-social-list.git",
- "reference": "07046e6c6472f3cf7751f45f7b1f1657dcf920e7"
+ "reference": "ef1547e4e3e64d5eb174e75a3bfa3906f33e3108"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/piwik/searchengine-and-social-list/zipball/07046e6c6472f3cf7751f45f7b1f1657dcf920e7",
- "reference": "07046e6c6472f3cf7751f45f7b1f1657dcf920e7",
+ "url": "https://api.github.com/repos/piwik/searchengine-and-social-list/zipball/ef1547e4e3e64d5eb174e75a3bfa3906f33e3108",
+ "reference": "ef1547e4e3e64d5eb174e75a3bfa3906f33e3108",
"shasum": ""
},
"type": "library",
@@ -1021,26 +1021,34 @@
"Public Domain"
],
"description": "Search engine and social network definitions used by Piwik",
- "time": "2016-09-18 14:28:00"
+ "time": "2016-09-22 08:52:36"
},
{
"name": "psr/log",
- "version": "1.0.0",
+ "version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/log.git",
- "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b"
+ "reference": "5277094ed527a1c4477177d102fe4c53551953e0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/php-fig/log/zipball/fe0936ee26643249e916849d48e3a51d5f5e278b",
- "reference": "fe0936ee26643249e916849d48e3a51d5f5e278b",
+ "url": "https://api.github.com/repos/php-fig/log/zipball/5277094ed527a1c4477177d102fe4c53551953e0",
+ "reference": "5277094ed527a1c4477177d102fe4c53551953e0",
"shasum": ""
},
+ "require": {
+ "php": ">=5.3.0"
+ },
"type": "library",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "1.0.x-dev"
+ }
+ },
"autoload": {
- "psr-0": {
- "Psr\\Log\\": ""
+ "psr-4": {
+ "Psr\\Log\\": "Psr/Log/"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -1054,12 +1062,13 @@
}
],
"description": "Common interface for logging libraries",
+ "homepage": "https://github.com/php-fig/log",
"keywords": [
"log",
"psr",
"psr-3"
],
- "time": "2012-12-21 11:40:51"
+ "time": "2016-09-19 16:02:08"
},
{
"name": "symfony/console",
@@ -1343,16 +1352,16 @@
},
{
"name": "twig/twig",
- "version": "v1.24.1",
+ "version": "v1.25.0",
"source": {
"type": "git",
"url": "https://github.com/twigphp/Twig.git",
- "reference": "3566d311a92aae4deec6e48682dc5a4528c4a512"
+ "reference": "f16a634ab08d87e520da5671ec52153d627f10f6"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/twigphp/Twig/zipball/3566d311a92aae4deec6e48682dc5a4528c4a512",
- "reference": "3566d311a92aae4deec6e48682dc5a4528c4a512",
+ "url": "https://api.github.com/repos/twigphp/Twig/zipball/f16a634ab08d87e520da5671ec52153d627f10f6",
+ "reference": "f16a634ab08d87e520da5671ec52153d627f10f6",
"shasum": ""
},
"require": {
@@ -1365,7 +1374,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.24-dev"
+ "dev-master": "1.25-dev"
}
},
"autoload": {
@@ -1400,7 +1409,7 @@
"keywords": [
"templating"
],
- "time": "2016-05-30 09:11:59"
+ "time": "2016-09-21 23:05:12"
}
],
"packages-dev": [
@@ -2104,16 +2113,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "4.8.26",
+ "version": "4.8.27",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74"
+ "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fc1d8cd5b5de11625979125c5639347896ac2c74",
- "reference": "fc1d8cd5b5de11625979125c5639347896ac2c74",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c062dddcb68e44b563f66ee319ddae2b5a322a90",
+ "reference": "c062dddcb68e44b563f66ee319ddae2b5a322a90",
"shasum": ""
},
"require": {
@@ -2172,7 +2181,7 @@
"testing",
"xunit"
],
- "time": "2016-05-17 03:09:28"
+ "time": "2016-07-21 06:48:14"
},
{
"name": "phpunit/phpunit-mock-objects",
@@ -2348,23 +2357,23 @@
},
{
"name": "sebastian/environment",
- "version": "1.3.7",
+ "version": "1.3.8",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716"
+ "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716",
- "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/be2c607e43ce4c89ecd60e75c6a85c126e754aea",
+ "reference": "be2c607e43ce4c89ecd60e75c6a85c126e754aea",
"shasum": ""
},
"require": {
- "php": ">=5.3.3"
+ "php": "^5.3.3 || ^7.0"
},
"require-dev": {
- "phpunit/phpunit": "~4.4"
+ "phpunit/phpunit": "^4.8 || ^5.0"
},
"type": "library",
"extra": {
@@ -2394,7 +2403,7 @@
"environment",
"hhvm"
],
- "time": "2016-05-17 03:18:57"
+ "time": "2016-08-18 05:49:44"
},
{
"name": "sebastian/exporter",
diff --git a/core/Config.php b/core/Config.php
index 01fa144a5c..f9a95feed0 100644
--- a/core/Config.php
+++ b/core/Config.php
@@ -12,6 +12,7 @@ namespace Piwik;
use Exception;
use Piwik\Application\Kernel\GlobalSettingsProvider;
use Piwik\Container\StaticContainer;
+use Piwik\Exception\MissingFilePermissionException;
use Piwik\ProfessionalServices\Advertising;
/**
@@ -375,15 +376,18 @@ class Config
*/
protected function writeConfig($clear = true)
{
- if ($this->doNotWriteConfigInTests) {
- return;
- }
-
$output = $this->dumpConfig();
if ($output !== null
&& $output !== false
) {
- $success = @file_put_contents($this->getLocalPath(), $output);
+
+ if ($this->doNotWriteConfigInTests) {
+ // simulate whether it would be successful
+ $success = is_writable($this->getLocalPath());
+ } else {
+ $success = @file_put_contents($this->getLocalPath(), $output);
+ }
+
if ($success === false) {
throw $this->getConfigNotWritableException();
}
@@ -411,6 +415,6 @@ class Config
public function getConfigNotWritableException()
{
$path = "config/" . basename($this->getLocalPath());
- return new Exception(Piwik::translate('General_ConfigFileIsNotWritable', array("(" . $path . ")", "")));
+ return new MissingFilePermissionException(Piwik::translate('General_ConfigFileIsNotWritable', array("(" . $path . ")", "")));
}
}
diff --git a/core/Plugin.php b/core/Plugin.php
index ff938a659f..f5a2854d4f 100644
--- a/core/Plugin.php
+++ b/core/Plugin.php
@@ -137,17 +137,22 @@ class Plugin
if ($cache->contains($cacheId)) {
$this->pluginInformation = $cache->fetch($cacheId);
} else {
- $metadataLoader = new MetadataLoader($pluginName);
- $this->pluginInformation = $metadataLoader->load();
-
- if ($this->hasDefinedPluginInformationInPluginClass() && $metadataLoader->hasPluginJson()) {
- throw new \Exception('Plugin ' . $pluginName . ' has defined the method getInformation() and as well as having a plugin.json file. Please delete the getInformation() method from the plugin class. Alternatively, you may delete the plugin directory from plugins/' . $pluginName);
- }
+ $this->reloadPluginInformation();
$cache->save($cacheId, $this->pluginInformation);
}
}
+ public function reloadPluginInformation()
+ {
+ $metadataLoader = new MetadataLoader($this->pluginName);
+ $this->pluginInformation = $metadataLoader->load();
+
+ if ($this->hasDefinedPluginInformationInPluginClass() && $metadataLoader->hasPluginJson()) {
+ throw new \Exception('Plugin ' . $this->pluginName . ' has defined the method getInformation() and as well as having a plugin.json file. Please delete the getInformation() method from the plugin class. Alternatively, you may delete the plugin directory from plugins/' . $this->pluginName);
+ }
+ }
+
private function createCacheIfNeeded()
{
if (is_null($this->cache)) {
diff --git a/core/Tracker/VisitExcluded.php b/core/Tracker/VisitExcluded.php
index a644d4479f..303d45c23b 100644
--- a/core/Tracker/VisitExcluded.php
+++ b/core/Tracker/VisitExcluded.php
@@ -28,25 +28,16 @@ class VisitExcluded
/**
* @param Request $request
- * @param bool|string $ip
- * @param bool|string $userAgent
*/
- public function __construct(Request $request, $ip = false, $userAgent = false)
+ public function __construct(Request $request)
{
$this->spamFilter = new ReferrerSpamFilter();
- if (false === $ip) {
- $ip = $request->getIp();
- }
-
- if (false === $userAgent) {
- $userAgent = $request->getUserAgent();
- }
-
$this->request = $request;
$this->idSite = $request->getIdSite();
- $this->userAgent = $userAgent;
- $this->ip = $ip;
+ $userAgent = $request->getUserAgent();
+ $this->userAgent = Common::unsanitizeInputValue($userAgent);
+ $this->ip = $request->getIp();
}
/**
@@ -89,8 +80,10 @@ class VisitExcluded
* @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.
+ * @param Request $request The request object which contains all of the request's information
+ *
*/
- Piwik::postEvent('Tracker.isExcludedVisit', array(&$excluded));
+ Piwik::postEvent('Tracker.isExcludedVisit', array(&$excluded, $this->request));
/*
* Following exclude operations happen after the hook.
diff --git a/core/Updater.php b/core/Updater.php
index 00cba745b2..8a67c0bd00 100644
--- a/core/Updater.php
+++ b/core/Updater.php
@@ -10,6 +10,7 @@ namespace Piwik;
use Piwik\Columns\Updater as ColumnUpdater;
use Piwik\Container\StaticContainer;
+use Piwik\Exception\MissingFilePermissionException;
use Piwik\Updater\UpdateObserver;
use Zend_Db_Exception;
@@ -257,8 +258,8 @@ class Updater
$this->markComponentSuccessfullyUpdated($componentName, $fileVersion);
} catch (UpdaterErrorException $e) {
$this->executeListenerHook('onError', array($componentName, $fileVersion, $e));
-
throw $e;
+
} catch (\Exception $e) {
$warningMessages[] = $e->getMessage();
@@ -581,7 +582,9 @@ class Updater
// make sure to check for them here
if ($e instanceof Zend_Db_Exception) {
throw new UpdaterErrorException($e->getMessage(), $e->getCode(), $e);
- } else {
+ } else if ($e instanceof MissingFilePermissionException) {
+ throw new UpdaterErrorException($e->getMessage(), $e->getCode(), $e);
+ }{
throw $e;
}
}
diff --git a/core/Version.php b/core/Version.php
index 2cf7565c10..9206f9e905 100644
--- a/core/Version.php
+++ b/core/Version.php
@@ -20,7 +20,7 @@ final class Version
* The current Piwik version.
* @var string
*/
- const VERSION = '2.16.3-b4';
+ const VERSION = '2.16.3-rc1';
public function isStableVersion($version)
{
diff --git a/core/WidgetsList.php b/core/WidgetsList.php
index bafc94323d..150b133dd3 100644
--- a/core/WidgetsList.php
+++ b/core/WidgetsList.php
@@ -81,7 +81,7 @@ class WidgetsList extends Singleton
$v = array_merge($widgets[$category], $v);
}
- $widgets[$category] = $v;
+ $widgets[$category] = array_values($v);
}
$cache->save($cacheId, $widgets);
diff --git a/lang/es.json b/lang/es.json
index 8dc19b7a06..7de9883818 100644
--- a/lang/es.json
+++ b/lang/es.json
@@ -286,6 +286,7 @@
"Password": "Contraseña",
"Period": "Periodo",
"Piechart": "Gráfica circular",
+ "PiwikIsACollaborativeProjectYouCanContributeAndDonate": "%1$sPiwik%2$s es un proyecto de colaboración traído para ti por los miembros del %7$sequipo de Piwik%8$s así como muchos otros colaboradores alrededor del mundo. <br\/> Si eres un fan de Piwik, puedes ayudar: descubrir %3$sCómo participar en Piwik%4$s, o %5$sdona ahora%6$s para ayudar a financiar Piwik 3.0!",
"PiwikXIsAvailablePleaseNotifyPiwikAdmin": "%1$s está disponible. Por favor alerte al %2$s administrador Piwik%3$s.",
"PiwikXIsAvailablePleaseUpdateNow": "Piwik %1$s está disponible. %2$s ¡Por favor, actualice ahora!%3$s (ver %4$scambios%5$s).",
"PleaseSpecifyValue": "Por favor especifique un valor para '%s'.",
diff --git a/lang/it.json b/lang/it.json
index 7612c7c81e..b6ca374ee9 100644
--- a/lang/it.json
+++ b/lang/it.json
@@ -367,7 +367,7 @@
"TrackingScopeVisit": "Visita",
"TransitionsRowActionTooltip": "Guarda cosa hanno fatto i visitatori prima e dopo aver visto questa pagina",
"TransitionsRowActionTooltipTitle": "Apri Transizioni",
- "TranslatorName": "Alessandro Coscia, Giovdi, Yusef Maali, Andrea Marchitelli (CILEA), Fabrizio Rocca, Ted Mosby, Alfio E. Fresta, Giovanni Matina, Blau",
+ "TranslatorName": "Alessandro Coscia, Giovdi, Yusef Maali, Andrea Marchitelli (CILEA), <a href=\"https:\/\/www.fabriziorocca.it\/\">Fabrizio Rocca<\/a>, Ted Mosby, Alfio E. Fresta, Giovanni Matina, Blau",
"UniquePurchases": "Acquisti unici",
"Unknown": "Sconosciuto",
"Upload": "Carica",
diff --git a/libs/bower_components/jquery.scrollTo/README.md b/libs/bower_components/jquery.scrollTo/README.md
index 844314ca0a..85911aecc5 100644
--- a/libs/bower_components/jquery.scrollTo/README.md
+++ b/libs/bower_components/jquery.scrollTo/README.md
@@ -1,71 +1,71 @@
-# jQuery.ScrollTo
-
-### Installation and usage
-
-Using [bower](https://github.com/twitter/bower):
-```bash
-bower install jquery.scrollTo
-```
-Using npm:
-```bash
-npm install jquery.scrollto
-```
-Using [composer](http://getcomposer.org/download/):
-
-Either run
-
-```
-php composer.phar require --prefer-dist flesler/jquery.scrollto "*"
-```
-
-or add
-
-```
-"flesler/jquery.scrollto": "*"
-```
-
-to the require section of your composer.json.
-
-### Downloading Manually
-
-If you want the latest stable version, get the latest release from the [releases page](https://github.com/flesler/jquery.scrollTo/releases).
-
-### Notes
-
-* Apart from the target and duration, the plugin can receive a hash of settings. Documentation and examples are included in the source file.
-
-* If you are interested in animated "same-page-scrolling" using anchors(href="#some_id"), check http://github.com/flesler/jquery.localScroll
-
-* For a slideshow-like behavior using scrolling, check http://github.com/flesler/jquery.serialScroll
-
-* The target can be specified as:
- * A Number/String specifying a position using px or just the number.
- * A string selector that will be relative, to the element that is going to be scrolled, and must match at least one child.
- * A DOM element, logically child of the element to scroll.
- * A hash { top:x, left:y }, x and y can be any kind of number/string like described above.
-
-* The plugin supports relative animations
-
-* 'em' and '%' are not supported as part of the target, because they won't work with jQuery.fn.animate.
-
-* The plugin might fail to scroll an element, to an inner node that is nested in more scrollable elements. This seems like an odd situation anyway.
-
-* Both axes ( x, y -> left, top ) can be scrolled, you can send 'x', 'y', 'xy' or 'yx' as 'axis' inside the settings.
-
-* If 2 axis are scrolled, there's an option to queue the animations, so that the second will start once the first ended ('xy' and 'yx' will have different effects)
-
-* The option 'margin' can be set to true, then the margin of the target element, will be taken into account and will be deducted.
-
-* 'margin' will only be valid, if the target is a selector, a DOM element, or a jQuery Object.
-
-* The option 'offset' allows to scroll less or more than the actual target by a defined amount of pixels. Can be a number(both axes), { top:x, left:y } or a function that returns an object with top & left.
-
-* The option 'over' lets you add or deduct a fraction of the element's height and width from the final position. so over:0.5 will scroll to the middle of the object. can be specified with {top:x, left:y}
-
-* Don't forget the callback event is now called 'onAfter', and if queuing is activated, then 'onAfterFirst' can be used.
-
-* If the first axis to be scrolled, is already positioned, that animation will be skipped, to avoid a delay in the animation.
-
-* The call to the plugin can be made in 2 different ways: $(...).scrollTo( target, duration, settings ) or $(...).scrollTo( target, settings ). Where one of the settings is 'duration'.
-
-* If you find any bug, or you have any advice, don't hesitate to open an issue.
+# jQuery.ScrollTo
+
+### Installation and usage
+
+Using [bower](https://github.com/twitter/bower):
+```bash
+bower install jquery.scrollTo
+```
+Using npm:
+```bash
+npm install jquery.scrollto
+```
+Using [composer](http://getcomposer.org/download/):
+
+Either run
+
+```
+php composer.phar require --prefer-dist flesler/jquery.scrollto "*"
+```
+
+or add
+
+```
+"flesler/jquery.scrollto": "*"
+```
+
+to the require section of your composer.json.
+
+### Downloading Manually
+
+If you want the latest stable version, get the latest release from the [releases page](https://github.com/flesler/jquery.scrollTo/releases).
+
+### Notes
+
+* Apart from the target and duration, the plugin can receive a hash of settings. Documentation and examples are included in the source file.
+
+* If you are interested in animated "same-page-scrolling" using anchors(href="#some_id"), check http://github.com/flesler/jquery.localScroll
+
+* For a slideshow-like behavior using scrolling, check http://github.com/flesler/jquery.serialScroll
+
+* The target can be specified as:
+ * A Number/String specifying a position using px or just the number.
+ * A string selector that will be relative, to the element that is going to be scrolled, and must match at least one child.
+ * A DOM element, logically child of the element to scroll.
+ * A hash { top:x, left:y }, x and y can be any kind of number/string like described above.
+
+* The plugin supports relative animations
+
+* 'em' and '%' are not supported as part of the target, because they won't work with jQuery.fn.animate.
+
+* The plugin might fail to scroll an element, to an inner node that is nested in more scrollable elements. This seems like an odd situation anyway.
+
+* Both axes ( x, y -> left, top ) can be scrolled, you can send 'x', 'y', 'xy' or 'yx' as 'axis' inside the settings.
+
+* If 2 axis are scrolled, there's an option to queue the animations, so that the second will start once the first ended ('xy' and 'yx' will have different effects)
+
+* The option 'margin' can be set to true, then the margin of the target element, will be taken into account and will be deducted.
+
+* 'margin' will only be valid, if the target is a selector, a DOM element, or a jQuery Object.
+
+* The option 'offset' allows to scroll less or more than the actual target by a defined amount of pixels. Can be a number(both axes), { top:x, left:y } or a function that returns an object with top & left.
+
+* The option 'over' lets you add or deduct a fraction of the element's height and width from the final position. so over:0.5 will scroll to the middle of the object. can be specified with {top:x, left:y}
+
+* Don't forget the callback event is now called 'onAfter', and if queuing is activated, then 'onAfterFirst' can be used.
+
+* If the first axis to be scrolled, is already positioned, that animation will be skipped, to avoid a delay in the animation.
+
+* The call to the plugin can be made in 2 different ways: $(...).scrollTo( target, duration, settings ) or $(...).scrollTo( target, settings ). Where one of the settings is 'duration'.
+
+* If you find any bug, or you have any advice, don't hesitate to open an issue.
diff --git a/libs/bower_components/jquery.scrollTo/jquery.scrollTo.min.js b/libs/bower_components/jquery.scrollTo/jquery.scrollTo.min.js
index 78ef4230d3..9364ebaf1e 100644
--- a/libs/bower_components/jquery.scrollTo/jquery.scrollTo.min.js
+++ b/libs/bower_components/jquery.scrollTo/jquery.scrollTo.min.js
@@ -1,7 +1,7 @@
-/**
- * Copyright (c) 2007-2014 Ariel Flesler - aflesler<a>gmail<d>com | http://flesler.blogspot.com
- * Licensed under MIT
- * @author Ariel Flesler
- * @version 1.4.13
- */
+/**
+ * Copyright (c) 2007-2014 Ariel Flesler - aflesler<a>gmail<d>com | http://flesler.blogspot.com
+ * Licensed under MIT
+ * @author Ariel Flesler
+ * @version 1.4.13
+ */
;(function(k){'use strict';k(['jquery'],function($){var j=$.scrollTo=function(a,b,c){return $(window).scrollTo(a,b,c)};j.defaults={axis:'xy',duration:parseFloat($.fn.jquery)>=1.3?0:1,limit:!0};j.window=function(a){return $(window)._scrollable()};$.fn._scrollable=function(){return this.map(function(){var a=this,isWin=!a.nodeName||$.inArray(a.nodeName.toLowerCase(),['iframe','#document','html','body'])!=-1;if(!isWin)return a;var b=(a.contentWindow||a).document||a.ownerDocument||a;return/webkit/i.test(navigator.userAgent)||b.compatMode=='BackCompat'?b.body:b.documentElement})};$.fn.scrollTo=function(f,g,h){if(typeof g=='object'){h=g;g=0}if(typeof h=='function')h={onAfter:h};if(f=='max')f=9e9;h=$.extend({},j.defaults,h);g=g||h.duration;h.queue=h.queue&&h.axis.length>1;if(h.queue)g/=2;h.offset=both(h.offset);h.over=both(h.over);return this._scrollable().each(function(){if(f==null)return;var d=this,$elem=$(d),targ=f,toff,attr={},win=$elem.is('html,body');switch(typeof targ){case'number':case'string':if(/^([+-]=?)?\d+(\.\d+)?(px|%)?$/.test(targ)){targ=both(targ);break}targ=win?$(targ):$(targ,this);if(!targ.length)return;case'object':if(targ.is||targ.style)toff=(targ=$(targ)).offset()}var e=$.isFunction(h.offset)&&h.offset(d,targ)||h.offset;$.each(h.axis.split(''),function(i,a){var b=a=='x'?'Left':'Top',pos=b.toLowerCase(),key='scroll'+b,old=d[key],max=j.max(d,a);if(toff){attr[key]=toff[pos]+(win?0:old-$elem.offset()[pos]);if(h.margin){attr[key]-=parseInt(targ.css('margin'+b))||0;attr[key]-=parseInt(targ.css('border'+b+'Width'))||0}attr[key]+=e[pos]||0;if(h.over[pos])attr[key]+=targ[a=='x'?'width':'height']()*h.over[pos]}else{var c=targ[pos];attr[key]=c.slice&&c.slice(-1)=='%'?parseFloat(c)/100*max:c}if(h.limit&&/^\d+$/.test(attr[key]))attr[key]=attr[key]<=0?0:Math.min(attr[key],max);if(!i&&h.queue){if(old!=attr[key])animate(h.onAfterFirst);delete attr[key]}});animate(h.onAfter);function animate(a){$elem.animate(attr,g,h.easing,a&&function(){a.call(this,targ,h)})}}).end()};j.max=function(a,b){var c=b=='x'?'Width':'Height',scroll='scroll'+c;if(!$(a).is('html,body'))return a[scroll]-$(a)[c.toLowerCase()]();var d='client'+c,html=a.ownerDocument.documentElement,body=a.ownerDocument.body;return Math.max(html[scroll],body[scroll])-Math.min(html[d],body[d])};function both(a){return $.isFunction(a)||typeof a=='object'?a:{top:a,left:a}}return j})}(typeof define==='function'&&define.amd?define:function(a,b){if(typeof module!=='undefined'&&module.exports){module.exports=b(require('jquery'))}else{b(jQuery)}})); \ No newline at end of file
diff --git a/libs/bower_components/jquery.scrollTo/scrollTo.jquery.json b/libs/bower_components/jquery.scrollTo/scrollTo.jquery.json
index f1f6d312f4..291c43edaa 100644
--- a/libs/bower_components/jquery.scrollTo/scrollTo.jquery.json
+++ b/libs/bower_components/jquery.scrollTo/scrollTo.jquery.json
@@ -1,29 +1,29 @@
-{
- "name": "scrollTo",
- "title": "Ariel Flesler's jQuery scrollTo",
- "description": "Easy element scrolling using jQuery.",
- "keywords": ["browser", "animated", "animation", "scrolling", "scroll", "links", "anchors"],
- "version": "1.4.13",
- "author": {
- "name": "Ariel Flesler",
- "email": "aflesler@gmail.com",
- "url": "http://flesler.blogspot.com"
- },
- "maintainers": [{
- "name": "Ariel Flesler",
- "email": "aflesler@gmail.com",
- "url": "http://flesler.blogspot.com"
- }],
- "licenses": [{
- "type": "MIT",
- "url": "https://github.com/flesler/jquery.scrollTo/blob/master/LICENSE"
- }],
- "homepage": "https://github.com/flesler/jquery.scrollTo",
- "docs": "http://flesler.blogspot.com/2007/10/jqueryscrollto.html",
- "bugs": "https://github.com/flesler/jquery.scrollTo/issues",
- "download": "https://github.com/flesler/jquery.scrollTo/releases",
- "demo": "http://demos.flesler.com/jquery/scrollTo",
- "dependencies": {
- "jquery": ">=1.8"
- }
+{
+ "name": "scrollTo",
+ "title": "Ariel Flesler's jQuery scrollTo",
+ "description": "Easy element scrolling using jQuery.",
+ "keywords": ["browser", "animated", "animation", "scrolling", "scroll", "links", "anchors"],
+ "version": "1.4.13",
+ "author": {
+ "name": "Ariel Flesler",
+ "email": "aflesler@gmail.com",
+ "url": "http://flesler.blogspot.com"
+ },
+ "maintainers": [{
+ "name": "Ariel Flesler",
+ "email": "aflesler@gmail.com",
+ "url": "http://flesler.blogspot.com"
+ }],
+ "licenses": [{
+ "type": "MIT",
+ "url": "https://github.com/flesler/jquery.scrollTo/blob/master/LICENSE"
+ }],
+ "homepage": "https://github.com/flesler/jquery.scrollTo",
+ "docs": "http://flesler.blogspot.com/2007/10/jqueryscrollto.html",
+ "bugs": "https://github.com/flesler/jquery.scrollTo/issues",
+ "download": "https://github.com/flesler/jquery.scrollTo/releases",
+ "demo": "http://demos.flesler.com/jquery/scrollTo",
+ "dependencies": {
+ "jquery": ">=1.8"
+ }
} \ No newline at end of file
diff --git a/misc/log-analytics b/misc/log-analytics
-Subproject 2878508f66c10d998c9e4e0bc276988b3755cde
+Subproject 9c4f36e66fc9b82a13643aae7d3310bfbfc731f
diff --git a/plugins/API/lang/es.json b/plugins/API/lang/es.json
index e35219972b..ced03941ee 100644
--- a/plugins/API/lang/es.json
+++ b/plugins/API/lang/es.json
@@ -9,6 +9,7 @@
"TopLinkTooltip": "Acceda a sus datos de análisis de internet programáticamente, a través de una sencilla API en json, xml, etc.",
"UserAuthentication": "Autenticación de usuario",
"UsingTokenAuth": "Si quieres %1$s solicitar datos dentro de un script, un crontab, etc. %2$s tiene que agregar el parámetro %3$s a las llamadas a la URL de la API que requieren autenticación.",
- "Glossary": "Glosario"
+ "Glossary": "Glosario",
+ "LearnAboutCommonlyUsedTerms": "Obtenga más información de los términos que se utilizan más frecuentemente para aprovechar al máximo de las analíticas de Piwik. %1$s y %2$s."
}
} \ No newline at end of file
diff --git a/plugins/API/lang/tr.json b/plugins/API/lang/tr.json
index 8e9e616b91..dd681977f2 100644
--- a/plugins/API/lang/tr.json
+++ b/plugins/API/lang/tr.json
@@ -1,12 +1,12 @@
{
"API": {
- "GenerateVisits": "Eğer bugün için bir veri yoksa öncelikle %1$s eklentisiyle biraz veri oluşturabilirsiniz. %2$s eklentisini aktifleştirin, sonrasında Piwik Yönetim alanından 'Ziyaretçi Oluşturucu' menüsüne tıklayınız.",
- "KeepTokenSecret": "token_auth kullanıcı adı ve şifreniz kadar gizlidir, %1$s kimseyle paylaşmayınız%2$s!",
- "LoadedAPIs": "%s API başarılı şekilde yüklendi",
- "MoreInformation": "Piwik APIsi hakkında daha fazla bilgi için lütfen %1$s Piwik API Kullanımı %2$s ve %3$s Piwik API Referansına %4$s bakınız.",
- "PluginDescription": "Piwik'teki tüm veri basit API tarafından ulaşılabilir. Bu plugin xml,json,php,csv ve benzeri şekildeki Web Analatik verisini çağırmak için web servis giriş noktasıdır.",
- "ReportingApiReference": "API Referanslarını Raporlamak",
- "TopLinkTooltip": "Json, xml veya diğerleri ile Api kullanarak erişin.",
+ "GenerateVisits": "Bugün için bir veri yoksa %1$s uygulama ekini kullanarak biraz veri oluşturabilirsiniz. %2$s uygulama ekini etkinleştirin. Ardından Piwik Yönetim bölümünden 'Ziyaretçi Üreteci' menüsüne tıklayın.",
+ "KeepTokenSecret": "Bu token_auth kodu kullanıcı adı ve parolanız kadar gizlidir. %1$s kimseyle paylaşmayın%2$s!",
+ "LoadedAPIs": "%s API yazılımı yüklendi",
+ "MoreInformation": "Piwik API yazılımı hakkında ayrıntılı bilgi almak için lütfen %1$s Piwik API Kullanımı %2$s ve %3$s Piwik API Referansı %4$s belgelerine bakın.",
+ "PluginDescription": "Tüm Piwik verilerine temel API kullanılarak erişilebilir. Bu uygulama eki web istatistiği verilerini xml, json, php, csv ve benzer şekillerde çağırabilen web hizmetinin başlangıç noktasıdır.",
+ "ReportingApiReference": "Rapor API Referansı",
+ "TopLinkTooltip": "Web istatistiği verilerine json, xml ve benzer yöntemlerle Temel API üzerinden erişilmesini sağlar.",
"UserAuthentication": "Kullanıcı kimlik doğrulaması",
"UsingTokenAuth": "Bir script, cron vb içerisinden %1$s verisi çağırmak isterseniz, %2$s kimlik doğrulama gerektiren API bağlantılarına %3$s parametresini eklemelisiniz.",
"Glossary": "Sözlük",
diff --git a/plugins/Actions/lang/es.json b/plugins/Actions/lang/es.json
index 739ec1ba1d..93759eddff 100644
--- a/plugins/Actions/lang/es.json
+++ b/plugins/Actions/lang/es.json
@@ -2,6 +2,7 @@
"Actions": {
"AvgGenerationTimeTooltip": "Promedio basado en %1$s acceso(s) %2$s entre %3$s y %4$s",
"ColumnClickedURL": "URL elegida",
+ "ColumnActionURL": "URL de acción",
"ColumnClicks": "Clics",
"ColumnClicksDocumentation": "El número de veces que se ha hecho clic en este enlace.",
"ColumnDownloadURL": "URL de descarga",
@@ -60,6 +61,7 @@
"WidgetPageUrlsFollowingSearch": "Páginas siguientes a una búsqueda interna",
"WidgetSearchCategories": "Categorías de búsqueda",
"WidgetSearchKeywords": "Palabras claves de las búsquedas internas del sitio",
- "WidgetSearchNoResultKeywords": "Búsquedas por palabras clave sin resultados"
+ "WidgetSearchNoResultKeywords": "Búsquedas por palabras clave sin resultados",
+ "ActionType": "Tipo de acción"
}
} \ No newline at end of file
diff --git a/plugins/Annotations/lang/tr.json b/plugins/Annotations/lang/tr.json
index 9c29b5e23b..14531eb745 100644
--- a/plugins/Annotations/lang/tr.json
+++ b/plugins/Annotations/lang/tr.json
@@ -15,8 +15,8 @@
"InlineQuickHelp": "Önemli etkinlikleri (yeni blog iletileri ya da web sitesi tasarım değişiklikleri gibi), veri incelemelerinizi ya da önemli olduğunu düşündüğünüz konuları kaydetmek için notlar oluşturabilirsiniz.",
"LoginToAnnotate": "Not eklemek için oturum açın.",
"NoAnnotations": "Bu tarih aralığında bir not yok.",
- "PluginDescription": "Websiteniz de yaptığınız değişiklikleri farklı günlerde belirtmek için not eklemeye izin verir, veriniz ile ilgili analizleri saklar ve bunları meslektaşlarınız ile birlikte paylaşmanıza izn verir. Neden o veriye baktığınızı hatırlamanızdan emin olmak için veriye dipnot koyar.",
- "ViewAndAddAnnotations": "%s için notları göster ve yeni not ekle...",
- "YouCannotModifyThisNote": "Bunu değiştiremezsiniz. Bunun için bu siteye yönetici erişiminiz olması gerekli."
+ "PluginDescription": "Bu özellik web sitenizde farklı günlerde yaptığınız değişiklikleri veri incelemeleri ve düşüncelerinizi çalışma arkadaşlarınızla paylaşmak için notlar eklenmesini sağlar. Verilerinize not ekleyerek neden bu şekilde görüntülendiklerini hatırlayabilirsiniz.",
+ "ViewAndAddAnnotations": "%s için notları görüntüle ve yeni not ekle...",
+ "YouCannotModifyThisNote": "Bu notu siz oluşturmadığınız ya da yönetici yetkileriniz olmadığı için düzenleyemezsiniz."
}
} \ No newline at end of file
diff --git a/plugins/Contents/lang/es.json b/plugins/Contents/lang/es.json
index 67631c79bf..d225a74971 100644
--- a/plugins/Contents/lang/es.json
+++ b/plugins/Contents/lang/es.json
@@ -8,6 +8,9 @@
"ContentName": "Nombre del contenido",
"ContentPiece": "Pieza de contenido",
"ContentTarget": "Objetivo del contenido",
- "Contents": "Contenidos"
+ "Contents": "Contenidos",
+ "InteractionsMetricDocumentation": "El número de veces que se interactuo con un bloque de contenido (ej, un 'clic' en un banner o anuncio).",
+ "ImpressionsMetricDocumentation": "El número de veces que un bloque de contenido, como un banner o un anuncio, fue mostrado en una página.",
+ "InteractionRateMetricDocumentation": "La proporción de impresiones de contenido a interacciones."
}
} \ No newline at end of file
diff --git a/plugins/CoreAdminHome/lang/es.json b/plugins/CoreAdminHome/lang/es.json
index 9ff7c4b667..4f19b725e1 100644
--- a/plugins/CoreAdminHome/lang/es.json
+++ b/plugins/CoreAdminHome/lang/es.json
@@ -3,6 +3,7 @@
"Administration": "Administración",
"ArchivingSettings": "Configuración de archivado",
"BrandingSettings": "Configuración del Branding",
+ "ReleaseChannel": "Canal de lanzamiento",
"ClickHereToOptIn": "Haga clic aquí para optar.",
"ClickHereToOptOut": "Haga clic aquí para no ser seguido.",
"CustomLogoFeedbackInfo": "Si personaliza el logo de Piwik, puede que también esté interesado en ocultar el enlace %1$s en el menú superior. Para hacerlo, puede deshabilitar el complemento Feedback en la página de %2$sAdministración de complementos%3$s.",
diff --git a/plugins/CoreAdminHome/tests/Integration/SetConfigTest.php b/plugins/CoreAdminHome/tests/Integration/SetConfigTest.php
index bd1ed5e618..93cf57e7c5 100644
--- a/plugins/CoreAdminHome/tests/Integration/SetConfigTest.php
+++ b/plugins/CoreAdminHome/tests/Integration/SetConfigTest.php
@@ -36,6 +36,12 @@ class SetConfigTest extends ConsoleCommandTestCase
parent::setUp();
}
+ public function tearDown()
+ {
+ parent::tearDown();
+ $this->makeLocalConfigWritable();
+ }
+
public function test_Command_SucceedsWhenOptionsUsed()
{
$code = $this->applicationTester->run(array(
@@ -80,6 +86,22 @@ class SetConfigTest extends ConsoleCommandTestCase
);
}
+ public function test_Command_FailsWithMissingFilePermissionException_whenConfigFileNotWritable()
+ {
+ $this->makeLocalConfigNotWritable();
+
+ $code = $this->applicationTester->run(array(
+ 'command' => 'config:set',
+ 'assignment' => array(
+ 'MySection.other_array_value=[]',
+ ),
+ '-vvv' => false,
+ ));
+
+ $this->assertNotEquals(0, $code, $this->getCommandDisplayOutputErrorMessage());
+ $this->assertContains('[Piwik\Exception\MissingFilePermissionException]', $this->applicationTester->getDisplay());
+ }
+
public function test_Command_SucceedsWhenArgumentsUsed()
{
$config = Config::getInstance();
@@ -191,4 +213,23 @@ class SetConfigTest extends ConsoleCommandTestCase
unlink($configPath);
}
}
+
+ protected function makeLocalConfigNotWritable()
+ {
+ $local = Config::getInstance()->getLocalPath();
+ touch($local);
+ chmod($local, 0444);
+ $this->assertFalse(is_writable($local));
+ }
+
+ protected function makeLocalConfigWritable()
+ {
+ $local = Config::getInstance()->getLocalPath();
+ @chmod(dirname($local), 0755);
+ @chmod($local, 0755);
+ $this->assertTrue(is_writable(dirname($local)));
+ if(file_exists($local)) {
+ $this->assertTrue(is_writable($local));
+ }
+ }
}
diff --git a/plugins/CoreHome/Tracker/VisitRequestProcessor.php b/plugins/CoreHome/Tracker/VisitRequestProcessor.php
index 019965a958..033399e196 100644
--- a/plugins/CoreHome/Tracker/VisitRequestProcessor.php
+++ b/plugins/CoreHome/Tracker/VisitRequestProcessor.php
@@ -87,8 +87,7 @@ class VisitRequestProcessor extends RequestProcessor
// the IP is needed by isExcluded() and GoalManager->recordGoals()
$visitProperties->setProperty('location_ip', $request->getIp());
- // TODO: move VisitExcluded logic to here (or move to service class stored in DI)
- $excluded = new VisitExcluded($request, $visitProperties->getProperty('location_ip'));
+ $excluded = new VisitExcluded($request);
if ($excluded->isExcluded()) {
return true;
}
diff --git a/plugins/CoreHome/javascripts/popover.js b/plugins/CoreHome/javascripts/popover.js
index bdde52e0d8..e1a303931e 100644
--- a/plugins/CoreHome/javascripts/popover.js
+++ b/plugins/CoreHome/javascripts/popover.js
@@ -227,8 +227,9 @@ var Piwik_Popover = (function () {
* @param {string} url
* @param {string} loadingName
* @param {string} [dialogClass] css class to add to dialog
+ * @param {object} [ajaxRequest] optional instance of ajaxHelper
*/
- createPopupAndLoadUrl: function (url, loadingName, dialogClass) {
+ createPopupAndLoadUrl: function (url, loadingName, dialogClass, ajaxRequest) {
// make sure the minimum top position of the popover is 15px
var ensureMinimumTop = function () {
var popoverContainer = $('#Piwik_Popover').parent();
@@ -254,11 +255,14 @@ var Piwik_Popover = (function () {
setPopoverTitleIfOneFoundInContainer();
ensureMinimumTop();
};
- var ajaxRequest = new ajaxHelper();
+
+ if ('undefined' === typeof ajaxRequest) {
+ ajaxRequest = new ajaxHelper();
+ }
ajaxRequest.addParams(piwikHelper.getArrayFromQueryString(url), 'get');
ajaxRequest.setCallback(callback);
ajaxRequest.setFormat('html');
ajaxRequest.send(false);
}
};
-})(); \ No newline at end of file
+})();
diff --git a/plugins/CorePluginsAdmin/MarketplaceApiClient.php b/plugins/CorePluginsAdmin/MarketplaceApiClient.php
index 0423f72600..ee20abc918 100644
--- a/plugins/CorePluginsAdmin/MarketplaceApiClient.php
+++ b/plugins/CorePluginsAdmin/MarketplaceApiClient.php
@@ -9,6 +9,7 @@
namespace Piwik\Plugins\CorePluginsAdmin;
use Piwik\Cache;
+use Piwik\Container\StaticContainer;
use Piwik\Http;
use Piwik\Version;
@@ -123,9 +124,16 @@ class MarketplaceApiClient
return array();
}
+ public static function getPiwikVersion()
+ {
+ return StaticContainer::get('marketplacePiwikVersion');
+ }
+
private function fetch($action, $params)
{
ksort($params);
+ $params['piwik'] = self::getPiwikVersion();
+ $params['php'] = PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '.' . PHP_RELEASE_VERSION;
$query = http_build_query($params);
$cacheId = $this->getCacheKey($action, $query);
@@ -180,7 +188,7 @@ class MarketplaceApiClient
$latestVersion = array_pop($plugin['versions']);
$downloadUrl = $latestVersion['download'];
- return $this->domain . $downloadUrl . '?coreVersion=' . Version::VERSION;
+ return $this->domain . $downloadUrl . '?coreVersion=' . self::getPiwikVersion();
}
}
diff --git a/plugins/CorePluginsAdmin/PluginInstaller.php b/plugins/CorePluginsAdmin/PluginInstaller.php
index ed140d27bc..ab4f7b8622 100644
--- a/plugins/CorePluginsAdmin/PluginInstaller.php
+++ b/plugins/CorePluginsAdmin/PluginInstaller.php
@@ -12,6 +12,7 @@ use Piwik\Container\StaticContainer;
use Piwik\Filechecks;
use Piwik\Filesystem;
use Piwik\Piwik;
+use Piwik\Plugin\Manager as PluginManager;
use Piwik\Plugin\Dependency as PluginDependency;
use Piwik\Unzip;
@@ -49,6 +50,11 @@ class PluginInstaller
Filesystem::deleteAllCacheOnUpdate($this->pluginName);
+ $plugin = PluginManager::getInstance()->getLoadedPlugin($this->pluginName);
+ if (!empty($plugin)) {
+ $plugin->reloadPluginInformation();
+ }
+
} catch (\Exception $e) {
$this->removeFileIfExists($tmpPluginZip);
@@ -160,7 +166,10 @@ class PluginInstaller
$requires = (array) $metadata->require;
}
+ $piwikVersion = MarketplaceApiClient::getPiwikVersion();
+
$dependency = new PluginDependency();
+ $dependency->setPiwikVersion($piwikVersion);
$missingDependencies = $dependency->getMissingDependencies($requires);
if (!empty($missingDependencies)) {
diff --git a/plugins/CorePluginsAdmin/config/config.php b/plugins/CorePluginsAdmin/config/config.php
new file mode 100644
index 0000000000..5d30748a94
--- /dev/null
+++ b/plugins/CorePluginsAdmin/config/config.php
@@ -0,0 +1,7 @@
+<?php
+
+return array(
+ 'marketplacePiwikVersion' => function () {
+ return \Piwik\Version::VERSION;
+ }
+);
diff --git a/plugins/CorePluginsAdmin/lang/es.json b/plugins/CorePluginsAdmin/lang/es.json
index b0407c02ae..b4a91d7d0a 100644
--- a/plugins/CorePluginsAdmin/lang/es.json
+++ b/plugins/CorePluginsAdmin/lang/es.json
@@ -38,6 +38,10 @@
"LastCommitTime": "(último cambio %s)",
"LastUpdated": "Última actualización",
"LicenseHomepage": "Página de la licencia",
+ "LikeThisPlugin": "¿Satisfecho con este complemento?",
+ "ConsiderDonating": "Considere una donación",
+ "CommunityContributedPlugin": "Este es un complemento basado en la suma de voluntades de una comunidad ofrendada de manera gratuita.",
+ "ConsiderDonatingCreatorOf": "Por favor considere donar al creador de %s",
"PluginsExtendPiwik": "Los complementos extienden y amplían las funcionalidades de Piwik.",
"OncePluginIsInstalledYouMayActivateHere": "Una vez que el complemento está instalado, puede activarlo o desactivarlo desde aquí.",
"Marketplace": "Mercado",
diff --git a/plugins/CoreUpdater/Controller.php b/plugins/CoreUpdater/Controller.php
index df52b296aa..1122778cfb 100644
--- a/plugins/CoreUpdater/Controller.php
+++ b/plugins/CoreUpdater/Controller.php
@@ -98,6 +98,8 @@ class Controller extends \Piwik\Plugin\Controller
$messages = $e->getUpdateLogMessages();
}
+ Filesystem::deleteAllCacheOnUpdate();
+
$view->feedbackMessages = $messages;
$this->addCustomLogoInfo($view);
return $view->render();
diff --git a/plugins/CoreUpdater/Updater.php b/plugins/CoreUpdater/Updater.php
index 6912dba335..316f325690 100644
--- a/plugins/CoreUpdater/Updater.php
+++ b/plugins/CoreUpdater/Updater.php
@@ -10,17 +10,20 @@ namespace Piwik\Plugins\CoreUpdater;
use Exception;
use Piwik\ArchiveProcessor\Rules;
-use Piwik\Config;
+use Piwik\Container\StaticContainer;
use Piwik\Filechecks;
use Piwik\Filesystem;
use Piwik\Http;
use Piwik\Option;
use Piwik\Plugin\Manager as PluginManager;
use Piwik\Plugin\ReleaseChannels;
+use Piwik\Plugins\CorePluginsAdmin\CorePluginsAdmin;
+use Piwik\Plugins\CorePluginsAdmin\MarketplaceApiClient;
+use Piwik\Plugins\CorePluginsAdmin\MarketplaceApiException;
+use Piwik\Plugins\CorePluginsAdmin\PluginInstaller;
use Piwik\SettingsServer;
use Piwik\Translation\Translator;
use Piwik\Unzip;
-use Piwik\UpdateCheck;
use Piwik\Version;
class Updater
@@ -112,19 +115,58 @@ class Updater
$this->verifyDecompressedArchive($extractedArchiveDirectory);
$messages[] = $this->translator->translate('CoreUpdater_VerifyingUnpackedFiles');
- $disabledPluginNames = $this->disableIncompatiblePlugins($newVersion);
- if (!empty($disabledPluginNames)) {
- $messages[] = $this->translator->translate('CoreUpdater_DisablingIncompatiblePlugins', implode(', ', $disabledPluginNames));
- }
+ // we need to load the marketplace already here, otherwise it will use the new, updated file in Piwik 3
+ $marketplace = new MarketplaceApiClient();
+ require_once PIWIK_DOCUMENT_ROOT . '/plugins/CorePluginsAdmin/PluginInstaller.php';
+ require_once PIWIK_DOCUMENT_ROOT . '/plugins/CorePluginsAdmin/MarketplaceApiException.php';
$this->installNewFiles($extractedArchiveDirectory);
$messages[] = $this->translator->translate('CoreUpdater_InstallingTheLatestVersion');
+
} catch (ArchiveDownloadException $e) {
throw $e;
} catch (Exception $e) {
throw new UpdaterException($e, $messages);
}
+ try {
+ if (CorePluginsAdmin::isMarketplaceEnabled()) {
+ $messages[] = $this->translator->translate('CoreUpdater_CheckingForPluginUpdates');
+
+ $pluginManager = PluginManager::getInstance();
+ $pluginManager->loadAllPluginsAndGetTheirInfo();
+ $loadedPlugins = $pluginManager->getLoadedPlugins();
+
+ MarketplaceApiClient::clearAllCacheEntries();
+ StaticContainer::getContainer()->set('marketplacePiwikVersion', $newVersion);
+
+ $pluginsWithUpdate = $marketplace->checkUpdates($loadedPlugins);
+
+ foreach ($pluginsWithUpdate as $pluginWithUpdate) {
+ $pluginName = $pluginWithUpdate['name'];
+
+ $messages[] = $this->translator->translate('CoreUpdater_UpdatingPluginXToVersionY',
+ array($pluginName, $pluginWithUpdate['version']));
+
+ $pluginInstaller = new PluginInstaller($pluginName);
+ $pluginInstaller->installOrUpdatePluginFromMarketplace();
+ }
+ }
+ } catch (MarketplaceApiException $e) {
+ // there is a problem with the connection to the server, ignore for now
+ } catch (Exception $e) {
+ throw new UpdaterException($e, $messages);
+ }
+
+ try {
+ $disabledPluginNames = $this->disableIncompatiblePlugins($newVersion);
+ if (!empty($disabledPluginNames)) {
+ $messages[] = $this->translator->translate('CoreUpdater_DisablingIncompatiblePlugins', implode(', ', $disabledPluginNames));
+ }
+ } catch (Exception $e) {
+ throw new UpdaterException($e, $messages);
+ }
+
return $messages;
}
diff --git a/plugins/CoreUpdater/lang/en.json b/plugins/CoreUpdater/lang/en.json
index 8086f16b36..ad6d230ce9 100644
--- a/plugins/CoreUpdater/lang/en.json
+++ b/plugins/CoreUpdater/lang/en.json
@@ -1,5 +1,6 @@
{
"CoreUpdater": {
+ "CheckingForPluginUpdates": "Checking for new plugin updates",
"ClickHereToViewSqlQueries": "Click here to view and copy the list of SQL queries that will get executed",
"CriticalErrorDuringTheUpgradeProcess": "Critical Error during the update process:",
"DatabaseUpgradeRequired": "Database Upgrade Required",
@@ -23,7 +24,7 @@
"HelpMessageIntroductionWhenError": "The above is the core error message. It should help explain the cause, but if you require further help please:",
"HelpMessageIntroductionWhenWarning": "The update completed successfuly, however there were issues during the process. Please read the above descriptions for details. For further help:",
"HighTrafficPiwikServerEnableMaintenance": "If you manage a high traffic Piwik server, we recommend to %1$smomentarily disable visitor Tracking and put the Piwik User Interface in maintenance mode%2$s.",
- "IncompatbilePluginsWillBeDisabledInfo": "Note: some plugins are not compatible with Piwik %s. They will be disabled when you upgrade:",
+ "IncompatbilePluginsWillBeDisabledInfo": "Note: some plugins are not compatible with Piwik %s. We will update them if there is an update on the Marketplace, otherwise we will be disable them when you upgrade:",
"InstallingTheLatestVersion": "Installing the latest version",
"LatestBetaRelease": "Latest beta release",
"LatestStableRelease": "Latest stable release",
@@ -52,6 +53,7 @@
"UpdateAutomatically": "Update Automatically",
"UpdateHasBeenCancelledExplanation": "Piwik One Click Update has been cancelled. If you can't fix the above error message, it is recommended that you manually update Piwik. %1$s Please check out the %2$sUpdate documentation%3$s to get started!",
"UpdateTitle": "Update",
+ "UpdatingPluginXToVersionY": "Updating plugin %1$s to version %2$s",
"UpdateSuccessTitle": "Piwik has been successfully updated!",
"UpdateErrorTitle": "Update error",
"ThankYouUpdatePiwik": "Thank you for using Piwik and keeping it up to date!",
diff --git a/plugins/CoreUpdater/lang/tr.json b/plugins/CoreUpdater/lang/tr.json
index 1fcd436d79..54242c23ae 100644
--- a/plugins/CoreUpdater/lang/tr.json
+++ b/plugins/CoreUpdater/lang/tr.json
@@ -9,13 +9,22 @@
"EmptyDatabaseError": "%s veritabanı boş. Piwik ayar dosyanızı değiştirmeniz ya da silmeniz gerekli.",
"ErrorDIYHelp": "İleri düzey bir kullanıcıysanız ve veritabanı güncellemesinde bir sorun ile karşılaşırsanız:",
"ErrorDIYHelp_1": "Sorunun kaynağını bulup düzeltin (memory_limit ya da max_execution_time gibi)",
- "ErrorDIYHelp_2": "Başarız olan güncellemedeki kalan sorguları çalıştır",
- "ErrorDuringPluginsUpdates": "Eklenti güncellenirken hata meydana geldi:",
- "ExceptionAlreadyLatestVersion": "Piwik versiyonunuz %s günceldir.",
- "ExceptionArchiveEmpty": "Boş arşiv.",
- "ExceptionArchiveIncompatible": "Uyumsuz arşiv: %s",
- "ExceptionArchiveIncomplete": "Arşiv tamamlanmadı: bazı dosyalar kayıp (ör. %s).",
- "InstallingTheLatestVersion": "Son versiyon yükleniyor",
+ "ErrorDIYHelp_2": "güncelleme yarım kaldığı sırada eksik kalan sorguları yürüt",
+ "ErrorDIYHelp_3": "version_core değişkeninin değerini yarım kalan güncellemenin sürümüne ayarlayarak, Piwik veritabanınızdaki `option` tablosunu el ile güncelleyin",
+ "ErrorDIYHelp_4": "kalan güncellemeleri tamamlamak için güncelleyiciyi yeniden çalıştırın (tarayıcı ya da komut satırından)",
+ "ErrorDIYHelp_5": "sorunu (ve çözümü) bildirin böylece Piwik yazılımını daha iyi yapabiliriz",
+ "ErrorDuringPluginsUpdates": "Uygulama eki güncellemelerinde bir sorun çıktı:",
+ "ExceptionAlreadyLatestVersion": "Kullandığınız Piwik %s sürümü güncel.",
+ "ExceptionArchiveEmpty": "Arşiv boş.",
+ "ExceptionArchiveIncompatible": "Arşiv uyumsuz: %s",
+ "ExceptionArchiveIncomplete": "Arşiv eksik: Bazı dosyalar kayıp (%s gibi).",
+ "FeedbackRequest": "Görüş ve önerilerinizi Piwik ekibi ile paylaşmaya çekinmeyin:",
+ "InstallingTheLatestVersion": "Son sürüm yükleniyor",
+ "LatestBetaRelease": "Son Beta sürümü",
+ "LatestStableRelease": "Son kararlı sürüm",
+ "Latest2XStableRelease": "Son kararlı 2.X sürümü",
+ "Latest2XBetaRelease": "Son Beta 2.X sürümü",
+ "LtsSupportVersion": "Uzun Dönem Desteklenen Sürüm",
"MajorUpdateWarning1": "Bu büyük bir güncelleştirme. Alışkın olduğunuz süreden daha uzun sürecektir.",
"NoteForLargePiwikInstances": "Büyük Piwik güncellemesi için önemli not",
"NotificationClickToUpdatePlugins": "Eklentileriniz güncellemek için burayı tıklayın:",
diff --git a/plugins/CustomPiwikJs/File.php b/plugins/CustomPiwikJs/File.php
index 5ef1a13c6f..03d874e61d 100644
--- a/plugins/CustomPiwikJs/File.php
+++ b/plugins/CustomPiwikJs/File.php
@@ -38,7 +38,9 @@ class File
public function save($content)
{
- file_put_contents($this->file, $content);
+ if(false === file_put_contents($this->file, $content)) {
+ throw new AccessDeniedException(sprintf("Could not write to %s", $this->file));
+ }
}
public function getContent()
@@ -60,7 +62,10 @@ class File
*/
public function hasWriteAccess()
{
- return is_writable($this->file);
+ if (file_exists($this->file) && !is_writable($this->file)) {
+ return false;
+ }
+ return is_writable(dirname($this->file)) || is_writable($this->file);
}
/**
diff --git a/plugins/CustomPiwikJs/lang/cs.json b/plugins/CustomPiwikJs/lang/cs.json
new file mode 100644
index 0000000000..f793e430fa
--- /dev/null
+++ b/plugins/CustomPiwikJs/lang/cs.json
@@ -0,0 +1,7 @@
+{
+ "CustomPiwikJs": {
+ "DiagnosticPiwikJsWritable": "Zapisovatelný JavaScript záznam (\"\/piwik.js\")",
+ "DiagnosticPiwikJsNotWritable": "Piwik JavaScript záznam \"\/piwik.js\" není zapisovatelný, což znamená, že ostatní zásuvné moduly nemohou tento JavaScript záznam rozšiřovat. V budoucnosti mohou být z tohoto důvodu omezeny i další hlavní služby.",
+ "DiagnosticPiwikJsMakeWritable": "Doporučujeme povolit zápis do Piwik.js například pomocí příkazu: %s"
+ }
+} \ No newline at end of file
diff --git a/plugins/CustomPiwikJs/lang/de.json b/plugins/CustomPiwikJs/lang/de.json
new file mode 100644
index 0000000000..7aa50965a5
--- /dev/null
+++ b/plugins/CustomPiwikJs/lang/de.json
@@ -0,0 +1,5 @@
+{
+ "CustomPiwikJs": {
+ "DiagnosticPiwikJsWritable": "Schreibbarer JavaScript-Tracker (\"\/piwik.js\")"
+ }
+} \ No newline at end of file
diff --git a/plugins/CustomPiwikJs/lang/el.json b/plugins/CustomPiwikJs/lang/el.json
new file mode 100644
index 0000000000..7a3c1c1aaa
--- /dev/null
+++ b/plugins/CustomPiwikJs/lang/el.json
@@ -0,0 +1,7 @@
+{
+ "CustomPiwikJs": {
+ "DiagnosticPiwikJsWritable": "Αρχείο παρακολούθησης JavaScript (\"\/piwik.js\")",
+ "DiagnosticPiwikJsNotWritable": "Το αρχείο παρακολούθησης JavaScript \"\/piwik.js\" δεν είναι εγγράψιμο που σημαίνει ότι άλλα πρόσθετα δεν μπορούν να επεκτείνουν την κλάση παρακολούθησης. Στο μέλλον ορισμένα χαρακτηριστικά του πυρήνα δε θα δουλεύουν όπως πρέπει.",
+ "DiagnosticPiwikJsMakeWritable": "Προτείνεται να κάνετε το αρχείο Piwik.js εγγράψιμο εκτελώντας αυτή την εντολή: %s"
+ }
+} \ No newline at end of file
diff --git a/plugins/CustomPiwikJs/lang/es.json b/plugins/CustomPiwikJs/lang/es.json
new file mode 100644
index 0000000000..89f6ed78cc
--- /dev/null
+++ b/plugins/CustomPiwikJs/lang/es.json
@@ -0,0 +1,7 @@
+{
+ "CustomPiwikJs": {
+ "DiagnosticPiwikJsWritable": "Archivo de seguimiento Javascript modificable (\"\/piwik.js\")",
+ "DiagnosticPiwikJsNotWritable": "El archivo de seguimiento JavaScript de Piwik \"\/piwik.js\" no se puede modificar lo que significa que otros complementos no pueden mejorarlo. En el futuro, incluso algunas de las características básicas podrían no funcionar como se espera.",
+ "DiagnosticPiwikJsMakeWritable": "Recomendamos Piwik.js modificable mediante la ejecución de este comando: %s"
+ }
+} \ No newline at end of file
diff --git a/plugins/CustomPiwikJs/lang/fr.json b/plugins/CustomPiwikJs/lang/fr.json
new file mode 100644
index 0000000000..84853489f6
--- /dev/null
+++ b/plugins/CustomPiwikJs/lang/fr.json
@@ -0,0 +1,7 @@
+{
+ "CustomPiwikJs": {
+ "DiagnosticPiwikJsWritable": "Traceur JavaScript inscriptible (\"\/piwik.js\")",
+ "DiagnosticPiwikJsNotWritable": "Le fichier du traceur JavaScript Piwik \"\/piwik.js\" ne peut pas être modifié ce qui signifie que les autres composants ne peuvent pas l'enrichir. A l'avenir même certaines fonctionnalités natives pourraient ne pas fonctionner comme prévu.",
+ "DiagnosticPiwikJsMakeWritable": "Nous vous recommandons de permettre l'écriture de Piwik.js en exécutant la commande suivante : %s"
+ }
+} \ No newline at end of file
diff --git a/plugins/CustomPiwikJs/lang/nb.json b/plugins/CustomPiwikJs/lang/nb.json
new file mode 100644
index 0000000000..e568140ece
--- /dev/null
+++ b/plugins/CustomPiwikJs/lang/nb.json
@@ -0,0 +1,7 @@
+{
+ "CustomPiwikJs": {
+ "DiagnosticPiwikJsWritable": "Skrivbar JavaScript Sporer (\"\/piwik.js\")",
+ "DiagnosticPiwikJsNotWritable": "Piwik JavaScript Sporer filen \"\/piwik.js\" er ikke skrivbar som betyr andre plugins kan ikke forlenge Javascript Sporer. I fremtiden enda noen sentrale funksjoner kanskje ikke fungerer som forventet.",
+ "DiagnosticPiwikJsMakeWritable": "Vi anbefaler å Piwik.js skrivbar ved å kjøre denne kommandoen: %s"
+ }
+} \ No newline at end of file
diff --git a/plugins/CustomPiwikJs/tests/Integration/FileTest.php b/plugins/CustomPiwikJs/tests/Integration/FileTest.php
index 4d96bd6478..aa8cee9c5d 100644
--- a/plugins/CustomPiwikJs/tests/Integration/FileTest.php
+++ b/plugins/CustomPiwikJs/tests/Integration/FileTest.php
@@ -19,7 +19,8 @@ use Piwik\Tests\Framework\TestCase\IntegrationTestCase;
*/
class FileTest extends IntegrationTestCase
{
- const NOT_EXISTING_FILE = 'notExisTinGFile.js';
+ const NOT_EXISTING_FILE_IN_WRITABLE_DIRECTORY = 'notExisTinGFile.js';
+ const NOT_EXISTING_FILE_IN_NON_WRITABLE_DIRECTORY = 'is-not-writable/notExisTinGFile.js';
/**
* @var string
@@ -30,14 +31,23 @@ class FileTest extends IntegrationTestCase
{
parent::setUp();
$this->dir = PIWIK_DOCUMENT_ROOT . '/plugins/CustomPiwikJs/tests/resources/';
+
+ // make directory not writable
+ $nonWritableDir = dirname($this->dir . self::NOT_EXISTING_FILE_IN_NON_WRITABLE_DIRECTORY);
+ @chmod($nonWritableDir, 0444);
+ if(is_writable($nonWritableDir)) {
+ throw new \Exception("The directory $nonWritableDir should have been made non writable by this test, but it didn't work");
+ }
}
public function tearDown()
{
- if (file_exists($this->dir . self::NOT_EXISTING_FILE)) {
- unlink($this->dir . self::NOT_EXISTING_FILE);
- }
+ // restore permissions changed by makeNotWritableFile()
+ chmod($this->dir, 0777);
+ if (file_exists($this->dir . self::NOT_EXISTING_FILE_IN_WRITABLE_DIRECTORY)) {
+ unlink($this->dir . self::NOT_EXISTING_FILE_IN_WRITABLE_DIRECTORY);
+ }
parent::tearDown();
}
@@ -46,9 +56,40 @@ class FileTest extends IntegrationTestCase
return new File($this->dir . $fileName);
}
+ private function makeNotWritableFile()
+ {
+ $path = $this->dir . 'file-made-non-writable.js';
+ if(file_exists($path)) {
+ chmod($path, 0777);
+ }
+ $file = new File($path);
+ $file->save('will be saved OK, and then we make it non writable.');
+
+ if (!chmod($path, 0444)) {
+ throw new \Exception("chmod on the file didn't work");
+ }
+ if (!chmod(dirname($path), 0755)) {
+ throw new \Exception("chmod on the directory didn't work");
+ }
+ $this->assertTrue(is_writable(dirname($path)));
+ $this->assertFalse(is_writable($path));
+ $this->assertTrue(file_exists($path));
+ return $file;
+ }
+
private function makeNotReadableFile()
{
- return $this->makeFile(self::NOT_EXISTING_FILE);
+ return $this->makeNotReadableFile_inWritableDirectory();
+ }
+
+ private function makeNotReadableFile_inNonWritableDirectory()
+ {
+ return $this->makeFile(self::NOT_EXISTING_FILE_IN_NON_WRITABLE_DIRECTORY);
+ }
+
+ private function makeNotReadableFile_inWritableDirectory()
+ {
+ return $this->makeFile(self::NOT_EXISTING_FILE_IN_WRITABLE_DIRECTORY);
}
public function test_getName()
@@ -66,7 +107,13 @@ class FileTest extends IntegrationTestCase
public function test_hasWriteAccess()
{
$this->assertTrue($this->makeFile()->hasWriteAccess());
- $this->assertFalse($this->makeNotReadableFile()->hasWriteAccess());
+ $this->assertTrue($this->makeNotReadableFile_inWritableDirectory()->hasWriteAccess());
+ $this->assertFalse($this->makeNotReadableFile_inNonWritableDirectory()->hasWriteAccess());
+ }
+
+ public function test_hasWriteAccess_whenFileExistAndIsNotWritable()
+ {
+ $this->assertFalse($this->makeNotWritableFile()->hasWriteAccess());
}
public function test_checkReadable_shouldNotThrowException_IfIsReadable()
@@ -96,7 +143,12 @@ class FileTest extends IntegrationTestCase
*/
public function test_checkWritable_shouldThrowException_IfNotIsWritable()
{
- $this->makeNotReadableFile()->checkWritable();
+ $this->makeNotReadableFile_inNonWritableDirectory()->checkWritable();
+ }
+
+ public function test_checkWritable_shouldNotThrowException_IfDirectoryIsWritable()
+ {
+ $this->makeNotReadableFile_inWritableDirectory()->checkWritable();
}
public function test_getContent()
@@ -111,9 +163,9 @@ class FileTest extends IntegrationTestCase
public function test_save()
{
- $notExistingFile = $this->makeNotReadableFile();
+ $notExistingFile = $this->makeNotReadableFile_inWritableDirectory();
$this->assertFalse($notExistingFile->hasReadAccess());
- $this->assertFalse($notExistingFile->hasWriteAccess());
+ $this->assertTrue($notExistingFile->hasWriteAccess());
$notExistingFile->save('myTestContent');
diff --git a/plugins/CustomPiwikJs/tests/Integration/TrackerUpdaterTest.php b/plugins/CustomPiwikJs/tests/Integration/TrackerUpdaterTest.php
index 240638c5e9..58650adf7e 100644
--- a/plugins/CustomPiwikJs/tests/Integration/TrackerUpdaterTest.php
+++ b/plugins/CustomPiwikJs/tests/Integration/TrackerUpdaterTest.php
@@ -62,7 +62,13 @@ class TrackerUpdaterTest extends IntegrationTestCase
* @expectedException \Piwik\Plugins\CustomPiwikJs\Exception\AccessDeniedException
* @expectedExceptionMessage not writable
*/
- public function test_checkWillSucceed_shouldThrowExceptionIfTargetIsNotWritable()
+ public function test_checkWillSucceed_shouldNotThrowExceptionIfTargetIsNotWritable()
+ {
+ $updater = $this->makeUpdater(null, $this->dir . 'not-writable/MyNotExisIngFilessss.js');
+ $updater->checkWillSucceed();
+ }
+
+ public function test_checkWillSucceed_shouldNotThrowExceptionIfTargetIsWritable()
{
$updater = $this->makeUpdater(null, $this->dir . 'MyNotExisIngFilessss.js');
$updater->checkWillSucceed();
diff --git a/plugins/CustomVariables/lang/es.json b/plugins/CustomVariables/lang/es.json
index 012d4797a6..fde28a873d 100644
--- a/plugins/CustomVariables/lang/es.json
+++ b/plugins/CustomVariables/lang/es.json
@@ -6,6 +6,18 @@
"CustomVariablesReportDocumentation": "Este informe contiene información sobre sus Variables Personalizadas. Haga clic en el nombre de una variable para ver la distribución de los valores. %1$s Para más información sobre las Variables Personalizadas en general, lea la %2$sdocumentación de Variables Personalizadas en piwik.org%3$s",
"PluginDescription": "Variables Personalizadas (nombre, valor) son pares que se pueden asignar mediante la API de Javascript a los visitantes o cualquiera de sus acciones. Piwik luego informará el número de visitas, páginas, las conversiones para cada uno de estos nombres y valores personalizados. Vea las variables personalizadas detalladas para cada usuario y su acción en el registro de visitantes. <br \/> Requerida para utilizar la función de <a href=\"http:\/\/piwik.org\/docs\/ecommerce-analytics\/\"> Ecommerce Analytics <\/a>!",
"ScopePage": "ámbito de la página",
- "ScopeVisit": "alcance de la visita"
+ "ScopeVisit": "alcance de la visita",
+ "ScopeX": "Ambito %s",
+ "Index": "Indice",
+ "Usages": "Usos",
+ "Unused": "No usado",
+ "CreateNewSlot": "Aumente el número de vacantes disponibles de Medidas personalizadas",
+ "UsageDetails": "%1$s visitas y %2$s acciones desde la creación de este sitio.",
+ "CreatingCustomVariableTakesTime": "Crear una nueva variable personalizada puede tomar un cierto tiempo dependiendo del tamaño de su base de datos. Por lo tanto, sólo es posible hacerlo vía un comando que necesita ser ejecutado desde la línea de comando.",
+ "CurrentAvailableCustomVariables": "Actualmente puede usar hasta %s Variables personalizadas por sitio.",
+ "ToCreateCustomVarExecute": "Para crear una nueva variable personalizada ejecute el siguiente comando dentro de su instalación Piwik:",
+ "SlotsReportIsGeneratedOverTime": "Los datos de este informe irán aumentando con el tiempo. Puede tomar un día o dos para ver cualquier dato y unas pocas semanas hasta que el informe sea totalmente exacto.",
+ "MetricsAreOnlyAvailableForVisitScope": "Nota: %1$s métricas están disponibles solo para las Variables personalizadas de alcance %2$s.",
+ "MetricsNotAvailableForPageScope": "Para Variables personalizadas de alcance %1$s, el valor de estas métricas es %2$s"
}
} \ No newline at end of file
diff --git a/plugins/DevicePlugins/lang/es.json b/plugins/DevicePlugins/lang/es.json
index 115de91a27..a8b8499033 100644
--- a/plugins/DevicePlugins/lang/es.json
+++ b/plugins/DevicePlugins/lang/es.json
@@ -3,6 +3,7 @@
"BrowserWithNoPluginsEnabled": "%1$s sin complementos habilitados",
"BrowserWithPluginsEnabled": "%1$s con los complementos %2$s habilitados",
"PluginDescription": "Informa la lista de complementos que están admitidos en los navegadores de internet de los visitantes.",
+ "PluginDetectionDoesNotWorkInIE": "Nota: La detección de complementos no funciona en Internet Explorer antes de 11. Este reporte está basado solamente en navegadores no-IE y nuevas versiones de IE.",
"WidgetPlugins": "Lista de Complementos",
"WidgetPluginsDocumentation": "Este informe muestra que extensiones del navegador sus visitantes han habilitado. Esta información puede ser importante sea para elegir el método eficiente de enviar su contenido."
}
diff --git a/plugins/DevicePlugins/lang/tr.json b/plugins/DevicePlugins/lang/tr.json
index 9a4de058ba..9863f35f85 100644
--- a/plugins/DevicePlugins/lang/tr.json
+++ b/plugins/DevicePlugins/lang/tr.json
@@ -1,5 +1,10 @@
{
"DevicePlugins": {
- "WidgetPlugins": "Eklenti Listesi"
+ "BrowserWithNoPluginsEnabled": "%1$s için bir eklenti yüklenmemiş",
+ "BrowserWithPluginsEnabled": "%1$s için %2$s eklenti yüklenmiş",
+ "PluginDescription": "Ziyaretçilerin web tarayıcıları tarafından desteklenen eklentilerin listesini görüntüler.",
+ "PluginDetectionDoesNotWorkInIE": "Not: Eklenti algılaması Internet Explorer 11 öncesindeki sürümleri desteklemez. Bu raporda yalnız IE dışındaki tarayıcılar ve yeni IE tarayıcıları için veriler bulunur.",
+ "WidgetPlugins": "Tarayıcı Eklentileri",
+ "WidgetPluginsDocumentation": "Bu raporda ziyaretçilerinizin web tarayıcılarında hangi eklentilerin etkin olduğu görüntülenir. Bu bilgiler içeriğinizi doğru şekilde sunmanız için önemli olabilir."
}
} \ No newline at end of file
diff --git a/plugins/Diagnostics/lang/es.json b/plugins/Diagnostics/lang/es.json
new file mode 100644
index 0000000000..3793481bb5
--- /dev/null
+++ b/plugins/Diagnostics/lang/es.json
@@ -0,0 +1,8 @@
+{
+ "Diagnostics": {
+ "ConfigFileTitle": "Archivo de configuración",
+ "ConfigFileIntroduction": "Aquí puede ver la configuración de Piwik. Si está ejecutando Piwik en un ecosistema balanceado puede que la página sea diferente sea por el servidor que la esté cargando. Las files con un color de fondo diferente son valores de configuración modificados que son especificados por ejemplo en el archivo %1$s.",
+ "HideUnchanged": "Si desea ver solo los valores modificados puede %1$socultar todos los valores no modificados%2$s.",
+ "Sections": "Secciones"
+ }
+} \ No newline at end of file
diff --git a/plugins/Feedback/lang/cs.json b/plugins/Feedback/lang/cs.json
index 3cd43a1eb8..415390b5a0 100644
--- a/plugins/Feedback/lang/cs.json
+++ b/plugins/Feedback/lang/cs.json
@@ -19,10 +19,14 @@
"ViewUserGuides": "Naučte se, jak konfigurovat Piwik a efektivně analyzovat data s našimi %1$suživatelskými příručkami%2$s",
"CommunityHelp": "Komunitní pomoc",
"ProfessionalHelp": "Profesionální pomoc",
+ "ProfessionalServicesIntro": "Naše celosvětová síť profesionálních Piwik konzultantů podporuje klienty, kteří hostují Piwik na vlastní infrastruktuře.",
+ "ProfessionalServicesOfferIntro": "Ze kterých služeb můžete profitovat?",
"ProfessionalServicesReviewPiwikSetup": "Kontrola vaší instalace Piwiku",
+ "ProfessionalServicesOptimizationMaintenance": "Služby optimalizace a údržby Piwiku",
"ProfessionalServicesPhoneEmailSupport": "Telefonická a e-mailová podpora",
"ProfessionalServicesTraining": "Školení uživatelů, techniků a vývoářů",
"ProfessionalServicesPremiumFeatures": "Prémiové funkce",
+ "ProfessionalServicesCustomDevelopment": "Vývojářské služby na míru",
"ProfessionalServicesAnalystConsulting": "Služby konzultace analytika",
"ContactUs": "Kontaktujte nás",
"VisitTheForums": "Navštivte %1$s fóra%2$s a nechte si pomoci komunitou uživatelů aplikace Piwik"
diff --git a/plugins/Feedback/lang/es.json b/plugins/Feedback/lang/es.json
index 043c642780..a4e07c8a65 100644
--- a/plugins/Feedback/lang/es.json
+++ b/plugins/Feedback/lang/es.json
@@ -22,6 +22,7 @@
"ProfessionalServicesIntro": "Nuestra red mundial de consultores profesionales que brindan asistencia a todos los clientes que hospedan Piwik en su propia infraestructura.",
"ProfessionalServicesOfferIntro": "¿Qué servicios puede beneficiarse?",
"ProfessionalServicesReviewPiwikSetup": "Reseña de su instalación Piwik",
+ "ProfessionalServicesOptimizationMaintenance": "Servicios de mantenimiento & optimización Piwik",
"ProfessionalServicesPhoneEmailSupport": "Asistencia por teléfono y correo electrónico",
"ProfessionalServicesTraining": "Usuario, técnico y entrenamiento del desarrollador",
"ProfessionalServicesPremiumFeatures": "Funciones premium",
diff --git a/plugins/Feedback/lang/nb.json b/plugins/Feedback/lang/nb.json
index f268816761..0b0a28fc40 100644
--- a/plugins/Feedback/lang/nb.json
+++ b/plugins/Feedback/lang/nb.json
@@ -9,7 +9,10 @@
"SendFeedback": "Send tilbakemelding",
"ThankYou": "Takk for at du hjelper oss å lage Piwik bedre!",
"TopLinkTooltip": "Fortell oss hva du synes eller be om profesjonell støtte.",
+ "CommunityHelp": "Samfunns Hjelpere",
"ProfessionalHelp": "Profesjonell hjelp",
+ "ProfessionalServicesPhoneEmailSupport": "Telefon og e-post-støtte",
+ "ProfessionalServicesPremiumFeatures": "Premium-funksjoner",
"ContactUs": "Kontakt oss"
}
} \ No newline at end of file
diff --git a/plugins/Goals/lang/es.json b/plugins/Goals/lang/es.json
index d8c0dcb091..be3da50bb9 100644
--- a/plugins/Goals/lang/es.json
+++ b/plugins/Goals/lang/es.json
@@ -77,6 +77,7 @@
"NewGoalIntro": "El seguimiento de las conversiones del objetivo es una de las maneras más eficaces para medir y mejorar las metas de negocio.",
"NewVisitorsConversionRateIs": "La tasa de visitantes nuevos es %s",
"NoGoalsNeedAccess": "Solo un Administrador o un usuario con permisos de Super Usuario puede gestionar Objetivos para un determinado sitio web. Por favor, consulte a su administrador de Piwik para establecer Objetivos para su sitio web. <br> ¡Hacer un seguimiento de los Objetivos es una gran manera de ayudar a entender y maximizar el rendimiento de su sitio web!",
+ "NoConversionsNoReportsMessage": "Los informes no se muestran porque no hay datos de conversión para el objetivo y período seleccionado.",
"NeedAccess": "Solo un Administrador o un usuario con permisos de Super Usuario puede gestionar Objetivos para un determinado sitio web.",
"Optional": "(opcional)",
"OverallConversionRate": "%s tasa global de la conversión (visitas con un objetivo completado)",
diff --git a/plugins/Installation/lang/cs.json b/plugins/Installation/lang/cs.json
index 70abe1a1b8..ba78860a1b 100644
--- a/plugins/Installation/lang/cs.json
+++ b/plugins/Installation/lang/cs.json
@@ -45,6 +45,8 @@
"PasswordRepeat": "Heslo (zopakujte)",
"PercentDone": "%s %% hotovo",
"ProfessionalServicesAdTitle": "Pokročilá analytika & služby",
+ "ProfessionalServicesfessionalServicesAdText": "Naše síť expertů může pomoci vaší organizaci odkrýt celou sílu Piwik analýz.",
+ "ProfessionalServicesfessionalDiscoverHow": "Více informací o %1$sdalších produktech a službách%2$s pro Piwik a jak navýšit svůj obrat a výnos.",
"PleaseFixTheFollowingErrors": "Prosím opravte následující chyby",
"DefaultSettings": "Výchozí nastavení Piwiku",
"DefaultSettingsHelp": "Piwik má výchozí nastavení. Můžete je změnit teď, nebo později z administračního rozhraní.",
@@ -52,6 +54,7 @@
"RestartWebServer": "Po uložení změn restartujte Vás web server.",
"ReusingTables": "Použití existujících tabulek",
"PiwikOrgNewsletter": "odesílat e-maily s důležitými událostmi v komunitě Piwiku",
+ "ProfessionalServicesNewsletter": "pošlete mi informace o %1$sProfesionálních službách a produktech%2$s pro Piwik",
"SeeBelowForMoreInfo": "Pro více informací se podívejte níže.",
"SetupWebsite": "Nastavit Web",
"SetupWebsiteError": "Při přidávání Webu se vyskytla chyba",
diff --git a/plugins/Installation/lang/de.json b/plugins/Installation/lang/de.json
index 28050912eb..301aeec2a4 100644
--- a/plugins/Installation/lang/de.json
+++ b/plugins/Installation/lang/de.json
@@ -62,7 +62,7 @@
"SetupWebsiteSetupSuccess": "Website %s erfolgreich angelegt!",
"SetupWebSiteURL": "URL der Website",
"SiteSetup": "Konfigurieren Sie Ihre erste Website, welche über Piwik getrackt und analyisert werden soll:",
- "SiteSetupFootnote": "Hinweis: Nachdem die Installation von Piwik fertiggestellt wurde ist es möglich weitere Websites hinzuzufügen!",
+ "SiteSetupFootnote": "Hinweis: Sie können weitere Websites hinzuzufügen sobald die Installation von Piwik abgeschlossen wurde!",
"SuperUser": "Hauptadministrator",
"SuperUserLogin": "Hauptadministrator Login",
"SuperUserSetupError": "Beim Hinzufügen des Hauptadministrators ist ein Fehler aufgetreten.",
diff --git a/plugins/LanguagesManager/Commands/CreatePull.php b/plugins/LanguagesManager/Commands/CreatePull.php
index af46dc7000..fca1fc76aa 100644
--- a/plugins/LanguagesManager/Commands/CreatePull.php
+++ b/plugins/LanguagesManager/Commands/CreatePull.php
@@ -19,6 +19,8 @@ use Symfony\Component\Console\Output\OutputInterface;
*/
class CreatePull extends TranslationBase
{
+ const GIT_BASE_BRANCH = '2.x-dev';
+
protected function configure()
{
$this->setName('translations:createpull')
@@ -38,7 +40,7 @@ class CreatePull extends TranslationBase
return;
}
- $unpushedCommits = shell_exec('git log origin/master..HEAD');
+ $unpushedCommits = shell_exec('git log origin/' . self::GIT_BASE_BRANCH . '..HEAD');
if (!empty($unpushedCommits)) {
@@ -49,7 +51,7 @@ class CreatePull extends TranslationBase
chdir(PIWIK_DOCUMENT_ROOT);
shell_exec('
- git checkout -f master > /dev/null 2>&1
+ git checkout -f ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1
git pull > /dev/null 2>&1
git submodule init > /dev/null 2>&1
git submodule update > /dev/null 2>&1
@@ -60,7 +62,7 @@ class CreatePull extends TranslationBase
chdir(PIWIK_DOCUMENT_ROOT.DIRECTORY_SEPARATOR.'plugins'.DIRECTORY_SEPARATOR.$plugin);
shell_exec('
- git checkout master > /dev/null 2>&1
+ git checkout ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1
git pull > /dev/null 2>&1
');
}
@@ -73,10 +75,10 @@ class CreatePull extends TranslationBase
shell_exec('git checkout -b translationupdates origin/translationupdates');
}
- // switch to branch and update it to latest master
+ // switch to branch and update it to latest $GIT_BASE_BRANCH
shell_exec('
git checkout -f translationupdates > /dev/null 2>&1
- git merge master > /dev/null 2>&1
+ git reset --hard origin/' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1
git push origin translationupdates > /dev/null 2>&1
');
@@ -105,7 +107,7 @@ class CreatePull extends TranslationBase
if (empty($changes)) {
$output->writeln("Nothing changed. Everything is already up to date.");
- shell_exec('git checkout master > /dev/null 2>&1');
+ shell_exec('git checkout ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1');
return;
}
@@ -163,7 +165,7 @@ class CreatePull extends TranslationBase
shell_exec('git commit -m "language update ${pluginName}"');
shell_exec('git push');
- shell_exec('git checkout master > /dev/null 2>&1');
+ shell_exec('git checkout ' . self::GIT_BASE_BRANCH . ' > /dev/null 2>&1');
$this->createPullRequest($output, $title, $message);
}
@@ -195,7 +197,7 @@ class CreatePull extends TranslationBase
--stderr /dev/null \
-o /dev/null \
-u '.$username.' \
- --data "{\"title\":\"[automatic translation update] '.$title.'\",\"body\":\"'.$message.'\",\"head\":\"translationupdates\",\"base\":\"master\"}" \
+ --data "{\"title\":\"[automatic translation update] '.$title.'\",\"body\":\"'.$message.'\",\"head\":\"translationupdates\",\"base\":\"' . self::GIT_BASE_BRANCH . '\"}" \
-H "Accept: application/json" \
https://api.github.com/repos/piwik/piwik/pulls');
diff --git a/plugins/Live/javascripts/visitorProfile.js b/plugins/Live/javascripts/visitorProfile.js
index c5bea438af..38cf21765d 100644
--- a/plugins/Live/javascripts/visitorProfile.js
+++ b/plugins/Live/javascripts/visitorProfile.js
@@ -51,7 +51,10 @@
url += '&showMap=0';
}
- Piwik_Popover.createPopupAndLoadUrl(url, _pk_translate('Live_VisitorProfile'), 'visitor-profile-popup');
+ var ajaxRequest = new ajaxHelper();
+ ajaxRequest.removeDefaultParameter('segment');
+
+ Piwik_Popover.createPopupAndLoadUrl(url, _pk_translate('Live_VisitorProfile'), 'visitor-profile-popup', ajaxRequest);
};
$.extend(VisitorProfileControl.prototype, UIControl.prototype, {
diff --git a/plugins/Live/lang/es.json b/plugins/Live/lang/es.json
index dfd02688b6..495242ead6 100644
--- a/plugins/Live/lang/es.json
+++ b/plugins/Live/lang/es.json
@@ -4,6 +4,7 @@
"CalculatedOverNPageViews": "Calculado usando las últimas %1$s páginas vistas de este visitante.",
"ClickToViewMoreAboutVisit": "Clic para ver más información acerca de esta visita.",
"ConvertedNGoals": "%s Objetivos convertidos",
+ "EcommerceSummaryConversions": "%1$s pedidos%2$s por un total de %3$s%4$s, comprando %5$s artículos%6$s.",
"FirstVisit": "Primer visita",
"GoalType": "Tipo",
"HideMap": "ocultar mapa",
@@ -33,6 +34,8 @@
"VisitorsInRealTime": "Visitantes en tiempo real",
"VisitorsLastVisit": "La última visita de este visitante fue hace %s días.",
"VisitsFrom": "%1$s%2$s visitas%3$s desde",
+ "VisitSummary": "Pasó un total de %1$s%2$s en el sitio de internet%3$s, y vió %4$s páginas%5$s en %6$s visitas%7$s.",
+ "VisitSummaryWithActionDetails": "Pasó un total de %1$s%2$s en el sitio de internet%3$s, y ejecutó %4$s acciones%5$s (%6$s) en %7$s visitas%8$s.",
"RowActionTooltipDefault": "Mostrar registro de visitante segmentado por esta fila",
"RowActionTooltipWithDimension": "Mostrar registro de visitante segmentado por este %s",
"RowActionTooltipTitle": "Abrir registro de visitante segmentado",
diff --git a/plugins/Login/lang/es.json b/plugins/Login/lang/es.json
index ec597a1b5e..79ee9ce391 100644
--- a/plugins/Login/lang/es.json
+++ b/plugins/Login/lang/es.json
@@ -5,12 +5,14 @@
"ExceptionInvalidSuperUserAccessAuthenticationMethod": "Un usuario con acceso Super Usuario no puede ser autenticado usando el mecanismo '%s'.",
"ExceptionPasswordMD5HashExpected": "Se espera que el parámetro contraseña sea un hash MD5 de la contraseña.",
"InvalidNonceOrHeadersOrReferrer": "La seguridad del formulario falló. Por favor cargue nuevamente el formulario y compruebe que sus cookies están habilitadas. Si usa un proxy, debe %1$s configurar Piwik para aceptar la cabecera proxy%2$s que precede a la cabecera Host. Compruebe también que su cabecera Referrer se envía correctamente.",
+ "InvalidNonceSSLMisconfigured": "También, puede %1$s forzar a Piwik a usar una conexión segura%2$s: en su archivo de configuración %3$s establezca %4$s bajo la sección %5$s.",
"InvalidOrExpiredToken": "El Token no es válido o ha caducado",
"InvalidUsernameEmail": "Nombre de usuario y\/o correo electrónico incorrectos.",
"LogIn": "Iniciar sesión",
"LoginOrEmail": "Usuario o correo electrónico",
"LoginPasswordNotCorrect": "Usuario y contraseña incorrectos.",
"LostYourPassword": "¿Olvidó la contraseña?",
+ "MailPasswordChangeBody": "Hola %1$s,\n\nUna solicitud de reestablecimiento de contraseña fue recibida desde %2$s. Para confirmar este cambio de contraseña para iniciar sesión con sus nuevas credenciales, visite el siguiente enlace:\n\n%3$s\n\nAtención: Cambiar su contraseña hará también que cambie su token_auth. Puede verificarlo en su página de ajustes.\n\nSi está utilizando su API token_auth en cualquier aplicación externa o a solo fines de archivado, asegúrese de actualizar su token_auth en tanto que cualquier petición a la API generá un error.\n\nNota: este enlace caducará transcurridas 24 horas.\n\nGracias por usar Piwik!",
"MailTopicPasswordChange": "Confirma el cambio de contraseña",
"PasswordChanged": "Su contraseña ha sido modificada.",
"PasswordRepeat": "Contraseña (repetir)",
diff --git a/plugins/Login/lang/tr.json b/plugins/Login/lang/tr.json
index 1ba717c60b..88f8d5975a 100644
--- a/plugins/Login/lang/tr.json
+++ b/plugins/Login/lang/tr.json
@@ -1,21 +1,21 @@
{
"Login": {
- "ConfirmationLinkSent": "Onaylama bağlantısı gelen kutunuza gönderildi. Şifre değişikliğinı onaylamak için e-posta hesabınızı kontrol edin ve bağlantıyı ziyaret edin.",
- "ContactAdmin": "Olası nedeni: Sunucunuzda mail() fonksiyonunu devre dışı bırakmış olabilir. <br \/>Lütfen Piwik yöneticinizle iletişime geçiniz.",
- "ExceptionInvalidSuperUserAccessAuthenticationMethod": "'%s' mekanizması kullanılarak bir süper kullanıcı girişi yetkilendirilemez.",
- "ExceptionPasswordMD5HashExpected": "Bu şifre parametresi şifrenin MD5 ile hashlenmiş halini beklemektedir.",
+ "ConfirmationLinkSent": "Size onaylama bağlantısını içeren bir e-posta önderildi. Parola değişikliği isteğinizi onaylamak için e-postalarınıza bakın ve onaylama bağlantısını açın.",
+ "ContactAdmin": "Olası neden: Sunucunuzda mail() işlevi devre dışı bırakılmış olabilir. <br \/>Lütfen Piwik yöneticinizle görüşün.",
+ "ExceptionInvalidSuperUserAccessAuthenticationMethod": "Süper kullanıcı yetkileri olan bir kullanıcının kimliği '%s' yöntemi ile doğrulanamaz.",
+ "ExceptionPasswordMD5HashExpected": "Parola parametresinin parolanın MD5 yöntemi ile karılmış biçimi olması beklenir.",
"InvalidNonceOrHeadersOrReferrer": "Form güvenliği sağlanamadı. Lütfen formu tekrar yükleyin ve çerezlerin aktif olduğundan emin olun. Eğer bir proxy sunucusu kullanıyorsanız, %2$s proxy başlığını kabul etmek için Piwik'i %1$s olarak ayarlamalısınız. Bununla birlikte Referans başlaığınızın doğru gönderildiğini kontrol edin.",
"InvalidOrExpiredToken": "Güvenlik kodu yanlış yada süresi dolmuş.",
- "InvalidUsernameEmail": "Geçersiz kullanıcı adı ve\/veya e-posta adresi",
+ "InvalidUsernameEmail": "Kullanıcı adı ya da e-posta adresi geçersiz.",
"LogIn": "Oturum aç",
- "LoginOrEmail": "Giriş veya E-posta",
- "LoginPasswordNotCorrect": "Kullanıcı adı & Şifre yanlış",
- "LostYourPassword": "Şifrenizi mi unuttunuz?",
+ "LoginOrEmail": "Kullanıcı Adı ya da E-posta",
+ "LoginPasswordNotCorrect": "Kullanıcı adı ile parola uyuşmuyor.",
+ "LostYourPassword": "Parolamı unuttum",
"MailTopicPasswordChange": "Parola Değişikliğini Onayla",
"PasswordChanged": "Parolanız değiştirildi.",
- "PasswordRepeat": "Şifre (Tekrar)",
- "PasswordsDoNotMatch": "Şifre eşleşmedi",
+ "PasswordRepeat": "Parola onayı",
+ "PasswordsDoNotMatch": "Parola ve onayı aynı değil",
"RememberMe": "Beni Hatırla",
- "ResetPasswordInstructions": "Hesabınız için yeni parolanızı giriniz."
+ "ResetPasswordInstructions": "Hesabınıza yeni bir parola yazın."
}
} \ No newline at end of file
diff --git a/plugins/Morpheus/javascripts/ajaxHelper.js b/plugins/Morpheus/javascripts/ajaxHelper.js
index 8050539192..71001c722e 100644
--- a/plugins/Morpheus/javascripts/ajaxHelper.js
+++ b/plugins/Morpheus/javascripts/ajaxHelper.js
@@ -149,6 +149,8 @@ function ajaxHelper() {
*/
this.requestHandle = null;
+ this.defaultParams = ['idSite', 'period', 'date', 'segment'];
+
/**
* Adds params to the request.
* If params are given more then once, the latest given value is used for the request
@@ -312,6 +314,42 @@ function ajaxHelper() {
};
/**
+ * Detect whether are allowed to use the given default parameter or not
+ * @param string parameter
+ * @returns {boolean}
+ * @private
+ */
+ this._useGETDefaultParameter = function (parameter) {
+ if (parameter && this.defaultParams) {
+ var i;
+ for (i = 0; i < this.defaultParams.length; i++) {
+ if (this.defaultParams[i] === parameter) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Removes a default parameter that is usually send automatically along the request.
+ *
+ * @param {String} parameter A name such as "period", "date", "segment".
+ */
+ this.removeDefaultParameter = function (parameter) {
+ if (parameter && this.defaultParams) {
+
+ var i;
+ for (i = 0; i < this.defaultParams.length; i++) {
+ if (this.defaultParams[i] === parameter) {
+ this.defaultParams.splice(i, 1);
+ }
+ }
+ }
+ }
+
+ /**
* Send the request
* @param {Boolean} [sync] indicates if the request should be synchronous (defaults to false)
* @return {void}
@@ -482,13 +520,13 @@ function ajaxHelper() {
}
for (var key in defaultParams) {
- if (!params[key] && !this.postParams[key] && defaultParams[key]) {
+ if (this._useGETDefaultParameter(key) && !params[key] && !this.postParams[key] && defaultParams[key]) {
params[key] = defaultParams[key];
}
}
// handle default date & period if not already set
- if (!params.date && !this.postParams.date) {
+ if (this._useGETDefaultParameter('date') && !params.date && !this.postParams.date) {
params.date = piwik.currentDateString || broadcast.getValueFromUrl('date');
if (params.period == 'range' && piwik.currentDateString) {
params.date = piwik.startDateString + ',' + params.date;
diff --git a/plugins/ScheduledReports/lang/cs.json b/plugins/ScheduledReports/lang/cs.json
index 1eea0758c1..cb0eaca715 100644
--- a/plugins/ScheduledReports/lang/cs.json
+++ b/plugins/ScheduledReports/lang/cs.json
@@ -29,6 +29,7 @@
"PluginDescription": "Vytvořte vlastní e-mailová hlášení a naplánujte jejich zaslání denně, týdně nebo měsíčně jednomu nebo více lidem. Je podporováno několik formátů (HTML, PDF, CSV, obrázky).",
"ReportFormat": "Formát hlášení",
"ReportHour": "Odeslat hlášení v %s hodin",
+ "ReportHourWithUTC": "Odeslat hlášení v %1$s hodin (%2$s hodin UTC)",
"ReportIncludeNWebsites": "Hlášení bude obsahovat hlavní měření pro všechny weby, které mají aspoň jednu návštěvu (z %s aktuálně dostupných webů).",
"ReportSent": "Hlášení posláno",
"ReportsIncluded": "Zahrnuté statistiky",
diff --git a/plugins/ScheduledReports/lang/el.json b/plugins/ScheduledReports/lang/el.json
index 5c5ea4b5ec..10f56acac4 100644
--- a/plugins/ScheduledReports/lang/el.json
+++ b/plugins/ScheduledReports/lang/el.json
@@ -29,6 +29,7 @@
"PluginDescription": "Δημιουργεί προσαρμοσμένες αναφορές και τις προγραμματίζει για καθημερινή, εβδομαδιαία ή μηνιαία αναφορά σε ένα ή περισσότερα άτομα. Υποστηρίζονται αρκετοί τύποι αναφορών (html, pdf, csv, εικόνες).",
"ReportFormat": "Μορφή Αναφοράς",
"ReportHour": "Αποστολή αναφοράς στις %s",
+ "ReportHourWithUTC": "Αποστολή αναφοράς στις %1$s (%2$s ώρα UTC)",
"ReportIncludeNWebsites": "Η αναφορά θα περιλαμβάνει βασικές μετρήσεις για όλες τις ιστοσελίδες που έχουν τουλάχιστον μια επισκεψη (από τις συνολικά %s διαθέσιμες ιστοσελίδες).",
"ReportSent": "Η αναφορά στάλθηκε.",
"ReportsIncluded": "Συμπερίληψη στατιστικών",
diff --git a/plugins/ScheduledReports/lang/es.json b/plugins/ScheduledReports/lang/es.json
index 53b295f107..7e0f117781 100644
--- a/plugins/ScheduledReports/lang/es.json
+++ b/plugins/ScheduledReports/lang/es.json
@@ -29,6 +29,7 @@
"PluginDescription": "Cree informes personalizados y prográmelos para ser enviados por correo electrónico diaria, semanal o mensualmente a uno o varias personas. Algunos formatos de informe están soportados (html, pdf, csv, imágenes).",
"ReportFormat": "Formato del informe",
"ReportHour": "Enviar informe a las %s horas",
+ "ReportHourWithUTC": "Enviar informe a las %1$s en punto (%2$s UTC)",
"ReportIncludeNWebsites": "El informe incluirá las principales métricas para todos los sitios de internet con al menos una visita (de todo %s los sitios de internet disponibles).",
"ReportSent": "Informe enviado",
"ReportsIncluded": "Estadísticas incluidas",
diff --git a/plugins/SitesManager/lang/es.json b/plugins/SitesManager/lang/es.json
index 434f0d5815..703e87b049 100644
--- a/plugins/SitesManager/lang/es.json
+++ b/plugins/SitesManager/lang/es.json
@@ -67,12 +67,18 @@
"SiteSearchUse": "Puede utilizar Piwik para rastrear y obtener un informe que es lo que están buscando sus visitantes en el motor de búsqueda interno de su sitio de internet.",
"SiteWithoutDataTitle": "Aun no se han grabado datos",
"SiteWithoutDataDescription": "Aun no se han registrado datos analíticos para este sitio de internet.",
+ "SiteWithoutDataSetupTracking": "Por favor configure el %1$scódigo de rastreo Javascript%2$s en su sitio de internet si ya no lo ha hecho.",
+ "SiteWithoutDataMessageDisappears": "Este mensaje desaparecerá tan pronto como algún dato sea rastreado en este sitio de internet.",
+ "SiteWithoutDataSetupGoals": "Mientras tanto, tal vez le gustaría %1$sestablecer algunas metas%2$s.",
"SuperUserAccessCan": "Un usuario con acceso Super Usuario también puede %1$s especificar la configuración global%2$s para nuevos sitios de internet.",
"Timezone": "Zona Horaria",
"TrackingSiteSearch": "Seguimiento en el Buscador interno del sitio",
"TrackingTags": "Código de seguimiento para %s",
"Urls": "URLs",
"UTCTimeIs": "La hora UTC es %s.",
+ "OnlyMatchedUrlsAllowed": "Solo rastrear visitas y acciones cuando la acción URL comienza con una de las siguientes URLs.",
+ "OnlyMatchedUrlsAllowedHelp": "Cuando es habilitado, Piwik solo rastreará acciones internas cuando la URL de la página es una URL conocida del sitio. Esto evita que la gente genere datos basura en sus analíticas con direcciones URL de otros sitios.",
+ "OnlyMatchedUrlsAllowedHelpExamples": "El dominio y el camino tiene que ser una coincidencia total y cada subdominio válido tiene que especificarse por separado. Por ejemplo, cuando las URLs conocidas son 'http:\/\/example.com\/path' y 'http:\/\/good.example.com', las peticiones de rastreo para 'http:\/\/example.com\/otherpath' o 'http:\/\/bad.example.com' son ignoradas.",
"WebsitesManagement": "Administración de sitios de internet",
"XManagement": "Administrar %s",
"ChooseMeasurableTypeHeadline": "Qué le gustaría medir?",
diff --git a/plugins/Transitions/lang/tr.json b/plugins/Transitions/lang/tr.json
index cd5fed6a05..4a82e65986 100644
--- a/plugins/Transitions/lang/tr.json
+++ b/plugins/Transitions/lang/tr.json
@@ -1,28 +1,28 @@
{
"Transitions": {
- "BouncesInline": "%s sıçramalar",
- "DirectEntries": "Direk Girişler",
- "ErrorBack": "Bir önceki işleme dön",
- "ExitsInline": "%s çıkışlar",
+ "BouncesInline": "%s hemen çıkma",
+ "DirectEntries": "Doğrudan Girişler",
+ "ErrorBack": "Önceki işleme dön",
+ "ExitsInline": "%s çıkış",
"FromCampaigns": "Kampanyalardan Geçişler",
- "FromPreviousPages": "İç sayfalardan",
+ "FromPreviousPages": "İç Sayfalardan",
"FromPreviousPagesInline": "%s iç sayfalardan",
- "FromPreviousSiteSearches": "İnternet Aramalarından",
- "FromPreviousSiteSearchesInline": "%s internet aramalarından",
+ "FromPreviousSiteSearches": "İç Aramalardan",
+ "FromPreviousSiteSearchesInline": "%s iç aramalardan",
"FromSearchEngines": "Arama Motorlarından",
- "FromWebsites": "Websitelerden",
- "IncomingTraffic": "Gelen trafik",
- "LoopsInline": "%s sayfa yüklemeleri",
- "NoDataForAction": "%s için veri yok",
- "NoDataForActionDetails": "%s süresi boyunca hiç sayfa görüntülenmemiş ve aksiyon alınmamıştır veya o hatalıdır.",
- "OutgoingTraffic": "Giden trafik",
- "PluginDescription": "Yeni iconu ile ulaşılan Aksiyon raporları sayfasında yeni geçişler raporunun içindeki her sayfaya ait URL'yi önceki ve takip eden aksiyonları için raporlar.",
- "ShareOfAllPageviews": "Bu sayfa %1$s sayfa görünütülemesine sahiptir ( %2$s tüm sayfa görüntülemesi).",
+ "FromWebsites": "Web Sitelerinden",
+ "IncomingTraffic": "Gelen Trafik",
+ "LoopsInline": "%s sayfa yüklemesi",
+ "NoDataForAction": "%s için herhangi bir veri yok",
+ "NoDataForActionDetails": "%s süresi boyunca işlem için hiç bir sayfa görüntülenmemiş ya da geçersiz.",
+ "OutgoingTraffic": "Giden Trafik",
+ "PluginDescription": "İşlem raporları bölümündeki yeni simgesi ile erişilebilen yeni geçiş raporundaki her sayfanın İnternet adresi için önceki ve sonraki işlemleri görüntüler.",
+ "ShareOfAllPageviews": "Bu sayfa %1$s kez görüntülenmiş (toplam sayfa görüntülemelerinden %2$s).",
"ToFollowingPages": "İç Sayfalara",
- "ToFollowingPagesInline": "%s İç Sayfalara",
+ "ToFollowingPagesInline": "%s iç sayfalara",
"ToFollowingSiteSearches": "İç Aramalar",
- "ToFollowingSiteSearchesInline": "%s İç Aramalar",
- "XOfAllPageviews": "Bu sayfadaki tüm görüntülenmelerin %s'i",
- "XOutOfYVisits": "%1$s (%2$s'nin dışında)"
+ "ToFollowingSiteSearchesInline": "%s iç arama",
+ "XOfAllPageviews": "Bu sayfanın tüm görüntülenmelerinden %s",
+ "XOutOfYVisits": "%1$s (toplam %2$s)"
}
} \ No newline at end of file
diff --git a/plugins/UserId/lang/es.json b/plugins/UserId/lang/es.json
index 98b725a25a..904563e8a4 100644
--- a/plugins/UserId/lang/es.json
+++ b/plugins/UserId/lang/es.json
@@ -1,5 +1,7 @@
{
"UserId": {
- "UserReportTitle": "Usuarios"
+ "UserId": "UserId",
+ "UserReportTitle": "Usuarios",
+ "PluginDescription": "Muestra reportes de usuario"
}
} \ No newline at end of file
diff --git a/plugins/UsersManager/lang/es.json b/plugins/UsersManager/lang/es.json
index fb5557dfb7..57277f127b 100644
--- a/plugins/UsersManager/lang/es.json
+++ b/plugins/UsersManager/lang/es.json
@@ -13,6 +13,7 @@
"ClickHereToSetTheCookieOnDomain": "Haga clic aquí para configurar la cookie que excluirá sus visitas a los sitios de internet a los que Piwik realiza seguimiento en %s",
"ConfirmGrantSuperUserAccess": "¿Estás seguro que desea conceder acceso 'Super User' a '%s'? Atención: el usuario tendrá acceso a todos los sitios de internet y podrá realizar tareas administrativas.",
"ConfirmProhibitMySuperUserAccess": "¿%s, está seguro que desea eliminar su acceso Super Usuario? Perderá todos los permisos y accesos a todos los sitios de internet y será desconectado de Piwik.",
+ "ConfirmProhibitOtherUsersSuperUserAccess": "¿Está seguro que desea quitar el acceso Super Usuario de '%s'? Este perderá todos los permisos y accesos a todos los sitios. Asegúrese de dar acceso a los sitios necesarios después si es necesario.",
"DeleteConfirm": "¿Está seguro que desea eliminar al usuario %s?",
"Email": "Correo electrónico",
"EmailYourAdministrator": "%1$sEnviar un correo electrónico a su administrador acerca de este problema%2$s.",
@@ -37,9 +38,12 @@
"ExcludeVisitsViaCookie": "Excluir sus visitas usando una cookie",
"ForAnonymousUsersReportDateToLoadByDefault": "Para los usuarios anónimos, fecha del informe a cargar por defecto",
"GiveViewAccess": "Otorgar acceso a la visualización",
+ "GiveViewAccessTitle": "Otorgar a un actual usuario acceso a ver los informes de %s",
+ "GiveViewAccessInstructions": "Para otorgar atributos de visualización a actuales usuarios de %s suministre o el nombre de usuario o su correo electrónico",
"IfYouWouldLikeToChangeThePasswordTypeANewOne": "Si desea cambiar la contraseña ingrese una nueva. Si no, déjelo vacío.",
"InjectedHostCannotChangePwd": "Está actualmente visitando con un medio desconocido (%1$s). No puede cambiar su contraseña hasta que el problema esté soluionado.",
"LastSeen": "Última visita",
+ "MainDescription": "Decida qué usuarios poseen acceso a sus sitios de internet. También puede otorgarles acceso a todos los sitios de una vez simplemente eligiendo la opción \"Usar en todos los sitios\" en el selector de los mismos.",
"ManageAccess": "Administrar el acceso",
"MenuAnonymousUserSettings": "Configuración de usuario anónimo",
"MenuUsers": "Usuarios",
@@ -48,6 +52,7 @@
"PersonalSettings": "Ajustes personales",
"NoteNoAnonymousUserAccessSettingsWontBeUsed2": "Nota: No puede modificar la configuración en esta sección, debido a que no posee ningún sitio de internet que pueda ser contactado por un usuario anónimo.",
"NoUsersExist": "Todavía no hay usuarios.",
+ "PluginDescription": "La Gestión de Usuarios le permite agregar nuevos usuarios, editar los actuales y otorgarles acceso a observar o administrar sitios de internet.",
"PrivAdmin": "Administrador",
"PrivNone": "Sin acceso",
"PrivView": "Ver",
diff --git a/plugins/VisitFrequency/lang/tr.json b/plugins/VisitFrequency/lang/tr.json
new file mode 100644
index 0000000000..45b4c613f9
--- /dev/null
+++ b/plugins/VisitFrequency/lang/tr.json
@@ -0,0 +1,26 @@
+{
+ "VisitFrequency": {
+ "ColumnActionsByReturningVisits": "Geri Gelen Ziyaretlere Göre Eylemler",
+ "ColumnAverageVisitDurationForReturningVisitors": "Ortalama Geri Gelen Ziyaret Süresi (saniye)",
+ "ColumnAvgActionsPerReturningVisit": "Geri Gelen Ziyaretlerin Ortalama Eylemleri",
+ "ColumnBounceCountForReturningVisits": "Geri Gelen Ziyaretlerin Sekme Sayısı",
+ "ColumnBounceRateForReturningVisits": "Geri Gelen Ziyaretlerin Sekme Oranı",
+ "ColumnMaxActionsInReturningVisit": "Bir geri gelen ziyaret için en fazla eylem sayısı",
+ "ColumnNbReturningVisitsConverted": "Dönüştürülmüş geri gelen ziyaret sayısı",
+ "ColumnReturningVisits": "Geri Gelen Ziyaretler",
+ "ColumnSumVisitLengthReturning": "Geri gelen ziyaretçilerin harcadığı toplam süre (saniye)",
+ "ColumnUniqueReturningVisitors": "Tekil geri gelen ziyaretçi sayısı",
+ "ColumnReturningUsers": "Geri Gelen Kullanıcılar",
+ "PluginDescription": "İlk kez gelen ziyaretçiler ile geri gelen ziyaretçi ölçeklerini raporlar.",
+ "ReturnActions": "Geri gelen ziyaretlerin eylemleri %s",
+ "ReturnAverageVisitDuration": "Geri gelen ziyaretçilerin ortalama ziyaret süresi %s",
+ "ReturnAvgActions": "Her geri gelen ziyaret için %s eylem",
+ "ReturnBounceRate": "%s geri gelen ziyaret sekti (bir sayfadan sonra siteyi terk etti)",
+ "ReturningVisitDocumentation": "Geri gelen ziyaret (yeni ziyaretten farklı olarak) daha önce siteyi en az bir kez ziyaret etmiş birisi tarafından yapılır.",
+ "ReturningVisitsDocumentation": "Geri gelen ziyaretlerin özeti.",
+ "ReturnVisits": "%s geri gelen ziyaret",
+ "SubmenuFrequency": "Sıklık",
+ "WidgetGraphReturning": "Zamana Göre Geri Gelen Ziyaretler",
+ "WidgetOverview": "Sıklık Özeti"
+ }
+} \ No newline at end of file
diff --git a/tests/PHPUnit/Framework/Mock/Tracker/RequestAuthenticated.php b/tests/PHPUnit/Framework/Mock/Tracker/RequestAuthenticated.php
new file mode 100644
index 0000000000..0b3c0a3555
--- /dev/null
+++ b/tests/PHPUnit/Framework/Mock/Tracker/RequestAuthenticated.php
@@ -0,0 +1,10 @@
+<?php
+namespace Piwik\Tests\Framework\Mock\Tracker;
+
+use Piwik\Tracker\Request;
+
+class RequestAuthenticated extends Request
+{
+ protected $isAuthenticated = true;
+
+} \ No newline at end of file
diff --git a/tests/PHPUnit/Integration/Tracker/VisitTest.php b/tests/PHPUnit/Integration/Tracker/VisitTest.php
index f4bc1fd5ed..b1b42eb5b2 100644
--- a/tests/PHPUnit/Integration/Tracker/VisitTest.php
+++ b/tests/PHPUnit/Integration/Tracker/VisitTest.php
@@ -16,6 +16,7 @@ use Piwik\Plugin\Manager;
use Piwik\Plugins\SitesManager\API;
use Piwik\Tests\Framework\Fixture;
use Piwik\Tests\Framework\Mock\FakeAccess;
+use Piwik\Tests\Framework\Mock\Tracker\RequestAuthenticated;
use Piwik\Tracker\Request;
use Piwik\Tracker\Visit;
use Piwik\Tracker\VisitExcluded;
@@ -88,14 +89,14 @@ class VisitTest extends IntegrationTestCase
$idsite = API::getInstance()->addSite("name", "http://piwik.net/", $ecommerce = 0,
$siteSearch = 1, $searchKeywordParameters = null, $searchCategoryParameters = null, $excludedIp);
- $request = new Request(array('idsite' => $idsite));
+ $request = new RequestAuthenticated(array('idsite' => $idsite));
// test that IPs within the range, or the given IP, are excluded
foreach ($tests as $ip => $expected) {
- $testIpIsExcluded = IPUtils::stringToBinaryIP($ip);
+ $request->setParam('cip', $ip);
- $excluded = new VisitExcluded_public($request, $testIpIsExcluded);
- $this->assertSame($expected, $excluded->public_isVisitorIpExcluded($testIpIsExcluded));
+ $excluded = new VisitExcluded_public($request);
+ $this->assertSame($expected, $excluded->public_isVisitorIpExcluded($ip));
}
}
@@ -176,13 +177,12 @@ class VisitTest extends IntegrationTestCase
$idsite = API::getInstance()->addSite("name", "http://piwik.net/", $ecommerce = 0,
$siteSearch = 1, $searchKeywordParameters = null, $searchCategoryParameters = null);
- $request = new Request(array('idsite' => $idsite));
- $testIpIsExcluded = IPUtils::stringToBinaryIP($ip);
+ $request = new RequestAuthenticated(array('idsite' => $idsite, 'cip' => $ip));
$_SERVER['HTTP_VIA'] = '1.1 Chrome-Compression-Proxy';
- $excluded = new VisitExcluded_public($request, $testIpIsExcluded);
- $isBot = $excluded->public_isNonHumanBot($testIpIsExcluded);
+ $excluded = new VisitExcluded_public($request);
+ $isBot = $excluded->public_isNonHumanBot();
unset($_SERVER['HTTP_VIA']);
$this->assertSame($isNonHumanBot, $isBot);
}
@@ -239,7 +239,8 @@ class VisitTest extends IntegrationTestCase
// test that user agents that contain excluded user agent strings are excluded
foreach ($tests as $ua => $expected) {
- $excluded = new VisitExcluded_public($request, $ip = false, $ua);
+ $request->setParam('ua', $ua);
+ $excluded = new VisitExcluded_public($request);
$this->assertSame($expected, $excluded->public_isUserAgentExcluded(), "Result if isUserAgentExcluded('$ua') was not " . ($expected ? 'true' : 'false') . ".");
}
@@ -306,10 +307,11 @@ class VisitTest extends IntegrationTestCase
);
$idsite = API::getInstance()->addSite("name", "http://piwik.net/");
- $request = new Request(array('idsite' => $idsite, 'bots' => 0));
+ $request = new RequestAuthenticated(array('idsite' => $idsite, 'bots' => 0));
foreach ($isIpBot as $ip => $isBot) {
- $excluded = new VisitExcluded_public($request, IPUtils::stringToBinaryIP($ip));
+ $request->setParam('cip', $ip);
+ $excluded = new VisitExcluded_public($request);
$this->assertSame($isBot, $excluded->public_isNonHumanBot(), $ip);
}
diff --git a/tests/PHPUnit/Integration/UpdaterTest.php b/tests/PHPUnit/Integration/UpdaterTest.php
index aeee654848..a4bec9f93c 100644
--- a/tests/PHPUnit/Integration/UpdaterTest.php
+++ b/tests/PHPUnit/Integration/UpdaterTest.php
@@ -18,6 +18,21 @@ use Piwik\Tests\Framework\Fixture;
*/
class UpdaterTest extends IntegrationTestCase
{
+ public function test_doUpdate_reportsAnError_whenMissingFilePermissionException()
+ {
+ $updater = new Updater($pathToCoreUpdates = null, PIWIK_INCLUDE_PATH . '/tests/resources/Updater/%s/');
+ $updater->markComponentSuccessfullyUpdated('testpluginUpdates', '0.4');
+ $componentsWithUpdateFile = $updater->getComponentsWithUpdateFile(array('testpluginUpdates' => '0.5'));
+
+ $this->assertEquals(1, count($componentsWithUpdateFile));
+
+ $result = $updater->updateComponents($componentsWithUpdateFile);
+
+ $this->assertTrue( count ($result['errors']) > 0, 'when an update fails because config file is not writable, we expect the updater to report a critical error');
+ $this->assertEquals( 'make sure this exception is thrown', $result['errors'][0]);
+ }
+
+
public function testUpdaterChecksCoreVersionAndDetectsUpdateFile()
{
$updater = new Updater(PIWIK_INCLUDE_PATH . '/tests/resources/Updater/core/');
diff --git a/tests/UI/expected-screenshots/CoreUpdaterCode_newVersion.png b/tests/UI/expected-screenshots/CoreUpdaterCode_newVersion.png
index 3d450aaac0..3b3781dc8c 100644
--- a/tests/UI/expected-screenshots/CoreUpdaterCode_newVersion.png
+++ b/tests/UI/expected-screenshots/CoreUpdaterCode_newVersion.png
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:dcbcc69e9e1fee906e196cfdfcbd622c24a5c042caca5c790b491e24959360fa
-size 70744
+oid sha256:0ccb9b1ad53b1b53a4b525618d414ac4dece5231df2ab478c7e5c1dd7596fc62
+size 73430
diff --git a/tests/UI/expected-screenshots/UIIntegrationTest_visitor_profile_not_segmented.png b/tests/UI/expected-screenshots/UIIntegrationTest_visitor_profile_not_segmented.png
new file mode 100644
index 0000000000..91125c7a9c
--- /dev/null
+++ b/tests/UI/expected-screenshots/UIIntegrationTest_visitor_profile_not_segmented.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:0643bf59751bacd616d9939d172df5b3a962993ec72a93cc3547d56974b5a15d
+size 471571
diff --git a/tests/UI/specs/UIIntegration_spec.js b/tests/UI/specs/UIIntegration_spec.js
index 9c903f7442..342d344433 100644
--- a/tests/UI/specs/UIIntegration_spec.js
+++ b/tests/UI/specs/UIIntegration_spec.js
@@ -43,7 +43,6 @@ describe("UIIntegrationTest", function () { // TODO: Rename to Piwik?
testEnvironment.save();
});
-
// dashboard tests
it("should load dashboard1 correctly", function (done) {
expect.screenshot("dashboard1").to.be.captureSelector('.pageWrap,.expandDataTableFooterDrawer', function (page) {
@@ -699,4 +698,29 @@ describe("UIIntegrationTest", function () { // TODO: Rename to Piwik?
page.click('a.actionSegmentVisitorLog:visible');
}, done);
});
+
+ it('should not apply current segmented when opening visitor log', function (done) {
+ var url = "?" + widgetizeParams + "&" + generalParams + "&moduleToWidgetize=Live&actionToWidgetize=getVisitorLog&segment=visitCount==2&enableAnimation=0";
+
+ delete testEnvironment.queryParamOverride.visitorId;
+ testEnvironment.save();
+
+ expect.screenshot("visitor_profile_not_segmented").to.be.capture(function (page) {
+ page.load(url);
+
+ page.evaluate(function () {
+ $('.visitor-log-visitor-profile-link').first().click();
+ });
+
+ page.evaluate(function () {
+ $(document).ready(function () {
+ $('.visitor-profile-show-map').click();
+ });
+ });
+
+ page.wait(1000);
+ }, done);
+ });
+
+
});
diff --git a/tests/javascript/index.php b/tests/javascript/index.php
index 143608df4e..a2e49bd59c 100644
--- a/tests/javascript/index.php
+++ b/tests/javascript/index.php
@@ -28,8 +28,6 @@ $targetFileName = '/tests/resources/piwik.test.js';
$sourceFile = PIWIK_DOCUMENT_ROOT . TrackerUpdater::DEVELOPMENT_PIWIK_JS;
$targetFile = PIWIK_DOCUMENT_ROOT . $targetFileName;
-file_put_contents($targetFile, '');
-
$updater = new TrackerUpdater($sourceFile, $targetFile);
$updater->setTrackerFiles(new JsTestPluginTrackerFiles());
$updater->checkWillSucceed();
diff --git a/tests/resources/Updater/testpluginUpdates/0.5.php b/tests/resources/Updater/testpluginUpdates/0.5.php
new file mode 100644
index 0000000000..944dcffaf2
--- /dev/null
+++ b/tests/resources/Updater/testpluginUpdates/0.5.php
@@ -0,0 +1,12 @@
+<?php
+namespace Piwik\Plugins\testpluginUpdates;
+
+use Piwik\Updates as PiwikUpdates;
+
+class Updates_0_5 extends PiwikUpdates
+{
+ function doUpdate(\Piwik\Updater $updater)
+ {
+ throw new \Piwik\Exception\MissingFilePermissionException('make sure this exception is thrown');
+ }
+}