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:
-rw-r--r--.travis.yml10
-rw-r--r--composer.json32
-rw-r--r--composer.lock84
-rw-r--r--config/global.ini.php3
-rw-r--r--core/API/Request.php3
-rw-r--r--core/Config.php1
-rw-r--r--core/Date.php53
-rw-r--r--core/Error.php16
-rw-r--r--core/Log.php14
-rw-r--r--core/Plugin/Widgets.php39
-rw-r--r--lang/cs.json1
-rw-r--r--lang/fa.json4
-rw-r--r--lang/ru.json2
-rwxr-xr-xmisc/composer/build-xhprof.sh17
-rwxr-xr-xmisc/composer/clean-xhprof.sh12
-rw-r--r--plugins/API/ProcessedReport.php10
-rw-r--r--plugins/Actions/lang/ja.json1
-rw-r--r--plugins/Actions/lang/ru.json1
-rw-r--r--plugins/CoreAdminHome/lang/fa.json3
-rw-r--r--plugins/CoreAdminHome/lang/ja.json8
-rw-r--r--plugins/CoreAdminHome/lang/ru.json2
-rw-r--r--plugins/CoreConsole/Commands/GenerateTravisYmlFile.php104
-rw-r--r--plugins/CoreConsole/Commands/GenerateWidget.php29
-rw-r--r--plugins/CoreConsole/TravisYmlView.php140
-rw-r--r--plugins/CoreConsole/templates/travis.yml.twig74
-rw-r--r--plugins/CoreConsole/tests/Unit/TravisYmlViewTest.php165
-rw-r--r--plugins/CoreConsole/tests/resources/test.travis.yml55
-rw-r--r--plugins/CoreHome/CoreHome.php2
-rw-r--r--plugins/CoreHome/angularjs/common/services/piwik-api.js41
-rw-r--r--plugins/CoreHome/angularjs/common/services/piwik-api_spec.js3
-rw-r--r--plugins/CoreHome/lang/fa.json2
-rw-r--r--plugins/CoreHome/lang/ja.json10
-rw-r--r--plugins/CoreHome/lang/nl.json1
-rw-r--r--plugins/CorePluginsAdmin/lang/ja.json27
-rw-r--r--plugins/CoreUpdater/lang/fa.json3
-rw-r--r--plugins/CoreUpdater/lang/ja.json11
-rw-r--r--plugins/Events/lang/fa.json5
-rw-r--r--plugins/Events/lang/ru.json1
-rw-r--r--plugins/ExamplePlugin/Widgets.php13
-rw-r--r--plugins/ExamplePlugin/tests/travis/after_script.after.yml1
-rw-r--r--plugins/ExamplePlugin/tests/travis/after_script.before.yml1
-rw-r--r--plugins/ExamplePlugin/tests/travis/after_success.after.yml1
-rw-r--r--plugins/ExamplePlugin/tests/travis/after_success.before.yml1
-rw-r--r--plugins/ExamplePlugin/tests/travis/before_install.after.yml2
-rw-r--r--plugins/ExamplePlugin/tests/travis/before_install.before.yml1
-rw-r--r--plugins/ExamplePlugin/tests/travis/before_script.after.yml1
-rw-r--r--plugins/ExamplePlugin/tests/travis/before_script.before.yml2
-rw-r--r--plugins/ExamplePlugin/tests/travis/install.after.yml1
-rw-r--r--plugins/ExamplePlugin/tests/travis/install.before.yml1
-rw-r--r--plugins/Goals/lang/cs.json2
-rw-r--r--plugins/Insights/lang/fa.json13
-rw-r--r--plugins/Installation/lang/fa.json2
-rw-r--r--plugins/LanguagesManager/lang/fa.json3
-rw-r--r--plugins/LeftMenu/lang/tr.json5
-rw-r--r--plugins/Live/lang/tr.json14
-rw-r--r--plugins/UserSettings/lang/en.json2
-rw-r--r--plugins/UsersManager/lang/fa.json1
-rw-r--r--plugins/ZenMode/lang/fa.json5
-rw-r--r--plugins/ZenMode/lang/ru.json5
-rw-r--r--tests/PHPUnit/Core/DateTest.php32
-rw-r--r--tests/PHPUnit/Core/Period/RangeTest.php3
-rw-r--r--tests/PHPUnit/Core/ReleaseCheckListTest.php2
-rw-r--r--tests/PHPUnit/Integration/Core/LogTest.php24
63 files changed, 897 insertions, 230 deletions
diff --git a/.travis.yml b/.travis.yml
index ee917b3fbc..090a4291b3 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,11 @@
# do not edit this file manually, instead run the generate:travis-yml console command
-# if you are a Piwik core developer, edit this template file to auto generate the travis.yml: https://github.com/piwik/piwik/blob/master/plugins/CoreConsole/templates/travis.yml.twig
+# if you are a Piwik core developer, edit this template file to auto generate the .travis.yml: https://github.com/piwik/piwik/blob/master/plugins/CoreConsole/templates/travis.yml.twig
+
+# when modifying this file, please consider whether your changes should apply to plugin .travis.yml files. if not, check whether the pluginName twig var is empty,
+# otherwise your changes will be synced with every plugin that uses an auto generated .travis.yml
+
+# also please test generation before committing by running ./console generate:travis-yml --core and ./console generate:travis-yml --plugin=CustomAlerts
+# and making sure the .travis.yml files are changed correctly
language: php
@@ -150,7 +156,7 @@ before_script:
- ./tests/travis/prepare.sh
- ./tests/travis/setup_webserver.sh
- - export GENERATE_TRAVIS_YML_COMMAND='php ./console generate:travis-yml --core'
+ - export GENERATE_TRAVIS_YML_COMMAND="php ./console generate:travis-yml --core"
- ./tests/travis/autoupdate_travis_yml.sh
- cd tests/PHPUnit
diff --git a/composer.json b/composer.json
index 6ea410b5fa..be32b796bf 100644
--- a/composer.json
+++ b/composer.json
@@ -45,11 +45,39 @@
},
"repositories": [
{
- "type": "vcs",
- "url": "https://github.com/phacility/xhprof"
+ "type": "package",
+ "package": {
+ "name": "facebook/xhprof",
+ "type": "library",
+ "description": "XHProf: A Hierarchical Profiler for PHP",
+ "keywords": ["profiling", "performance"],
+ "homepage": "http://pecl.php.net/package/xhprof",
+ "license": "Apache-2.0",
+ "version": "master",
+ "require": {
+ "php": ">=5.2.0"
+ },
+ "autoload": {
+ "files": [
+ "xhprof_lib/utils/xhprof_lib.php",
+ "xhprof_lib/utils/xhprof_runs.php"
+ ]
+ },
+ "source": {
+ "type": "git",
+ "url": "https://github.com/phacility/xhprof",
+ "reference": "master"
+ }
+ }
}
],
"scripts": {
+ "pre-update-cmd": [
+ "misc/composer/clean-xhprof.sh"
+ ],
+ "pre-install-cmd": [
+ "misc/composer/clean-xhprof.sh"
+ ],
"post-update-cmd": [
"misc/composer/build-xhprof.sh"
],
diff --git a/composer.lock b/composer.lock
index 7ae0681d61..7a30ec861b 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
- "hash": "1f130896dd9e74174a38115d905d0f32",
+ "hash": "d04c8063669dd6287714505fbcdc99cc",
"packages": [
{
"name": "leafo/lessphp",
@@ -298,17 +298,11 @@
"packages-dev": [
{
"name": "facebook/xhprof",
- "version": "dev-master",
+ "version": "master",
"source": {
"type": "git",
- "url": "https://github.com/phacility/xhprof.git",
- "reference": "0a7a5f69f5d762c34056164eb08dd13d41156015"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/phacility/xhprof/zipball/0a7a5f69f5d762c34056164eb08dd13d41156015",
- "reference": "0a7a5f69f5d762c34056164eb08dd13d41156015",
- "shasum": ""
+ "url": "https://github.com/phacility/xhprof",
+ "reference": "master"
},
"require": {
"php": ">=5.2.0"
@@ -329,23 +323,20 @@
"performance",
"profiling"
],
- "support": {
- "source": "https://github.com/phacility/xhprof/tree/master"
- },
- "time": "2014-04-22 20:02:16"
+ "time": "2014-08-28 17:34:52"
},
{
"name": "ocramius/instantiator",
- "version": "1.1.2",
+ "version": "1.1.3",
"source": {
"type": "git",
"url": "https://github.com/Ocramius/Instantiator.git",
- "reference": "a7abbb5fc9df6e7126af741dd6c140d1a7369435"
+ "reference": "e24a12178906ff2e7471b8aaf3a0eb789b59f881"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/Ocramius/Instantiator/zipball/a7abbb5fc9df6e7126af741dd6c140d1a7369435",
- "reference": "a7abbb5fc9df6e7126af741dd6c140d1a7369435",
+ "url": "https://api.github.com/repos/Ocramius/Instantiator/zipball/e24a12178906ff2e7471b8aaf3a0eb789b59f881",
+ "reference": "e24a12178906ff2e7471b8aaf3a0eb789b59f881",
"shasum": ""
},
"require": {
@@ -387,7 +378,7 @@
"constructor",
"instantiate"
],
- "time": "2014-08-14 15:10:55"
+ "time": "2014-08-25 14:48:16"
},
{
"name": "ocramius/lazy-map",
@@ -449,29 +440,29 @@
},
{
"name": "phpunit/php-code-coverage",
- "version": "2.0.10",
+ "version": "2.0.11",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "6d196af48e8c100a3ae881940123e693da5a9217"
+ "reference": "53603b3c995f5aab6b59c8e08c3a663d2cc810b7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/6d196af48e8c100a3ae881940123e693da5a9217",
- "reference": "6d196af48e8c100a3ae881940123e693da5a9217",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/53603b3c995f5aab6b59c8e08c3a663d2cc810b7",
+ "reference": "53603b3c995f5aab6b59c8e08c3a663d2cc810b7",
"shasum": ""
},
"require": {
"php": ">=5.3.3",
- "phpunit/php-file-iterator": "~1.3.1",
- "phpunit/php-text-template": "~1.2.0",
- "phpunit/php-token-stream": "~1.2.2",
- "sebastian/environment": "~1.0.0",
- "sebastian/version": "~1.0.3"
+ "phpunit/php-file-iterator": "~1.3",
+ "phpunit/php-text-template": "~1.2",
+ "phpunit/php-token-stream": "~1.3",
+ "sebastian/environment": "~1.0",
+ "sebastian/version": "~1.0"
},
"require-dev": {
"ext-xdebug": ">=2.1.4",
- "phpunit/phpunit": "~4.0.14"
+ "phpunit/phpunit": "~4.1"
},
"suggest": {
"ext-dom": "*",
@@ -510,7 +501,7 @@
"testing",
"xunit"
],
- "time": "2014-08-06 06:39:42"
+ "time": "2014-08-31 06:33:04"
},
{
"name": "phpunit/php-file-iterator",
@@ -647,45 +638,44 @@
},
{
"name": "phpunit/php-token-stream",
- "version": "1.2.2",
+ "version": "1.3.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-token-stream.git",
- "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32"
+ "reference": "f8d5d08c56de5cfd592b3340424a81733259a876"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/ad4e1e23ae01b483c16f600ff1bebec184588e32",
- "reference": "ad4e1e23ae01b483c16f600ff1bebec184588e32",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/f8d5d08c56de5cfd592b3340424a81733259a876",
+ "reference": "f8d5d08c56de5cfd592b3340424a81733259a876",
"shasum": ""
},
"require": {
"ext-tokenizer": "*",
"php": ">=5.3.3"
},
+ "require-dev": {
+ "phpunit/phpunit": "~4.2"
+ },
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.2-dev"
+ "dev-master": "1.3-dev"
}
},
"autoload": {
"classmap": [
- "PHP/"
+ "src/"
]
},
"notification-url": "https://packagist.org/downloads/",
- "include-path": [
- ""
- ],
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Sebastian Bergmann",
- "email": "sb@sebastian-bergmann.de",
- "role": "lead"
+ "email": "sebastian@phpunit.de"
}
],
"description": "Wrapper around PHP's tokenizer extension.",
@@ -693,20 +683,20 @@
"keywords": [
"tokenizer"
],
- "time": "2014-03-03 05:10:30"
+ "time": "2014-08-31 06:12:13"
},
{
"name": "phpunit/phpunit",
- "version": "4.2.2",
+ "version": "4.2.4",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "a33fa68ece9f8c68589bfc2da8d2794e27b820bc"
+ "reference": "f0c2d374ad06ec1e56c721f4ed87c59ff35f440e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/a33fa68ece9f8c68589bfc2da8d2794e27b820bc",
- "reference": "a33fa68ece9f8c68589bfc2da8d2794e27b820bc",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f0c2d374ad06ec1e56c721f4ed87c59ff35f440e",
+ "reference": "f0c2d374ad06ec1e56c721f4ed87c59ff35f440e",
"shasum": ""
},
"require": {
@@ -767,7 +757,7 @@
"testing",
"xunit"
],
- "time": "2014-08-18 05:12:30"
+ "time": "2014-08-31 06:46:49"
},
{
"name": "phpunit/phpunit-mock-objects",
diff --git a/config/global.ini.php b/config/global.ini.php
index 008d99cd3b..62552298cd 100644
--- a/config/global.ini.php
+++ b/config/global.ini.php
@@ -204,10 +204,9 @@ default_day = yesterday
default_period = day
; Time in seconds after which an archive will be computed again. This setting is used only for today's statistics.
-; Defaults to 10 seconds so that by default, Piwik provides real time reporting.
; This setting is overriden in the UI, under "General Settings".
; This setting is only used if it hasn't been overriden via the UI yet, or if enable_general_settings_admin=0
-time_before_today_archive_considered_outdated = 10
+time_before_today_archive_considered_outdated = 150
; This setting is overriden in the UI, under "General Settings".
; The default value is to allow browsers to trigger the Piwik archiving process.
diff --git a/core/API/Request.php b/core/API/Request.php
index d4bdee5d24..03b555ad18 100644
--- a/core/API/Request.php
+++ b/core/API/Request.php
@@ -17,6 +17,7 @@ use Piwik\PluginDeactivatedException;
use Piwik\SettingsServer;
use Piwik\Url;
use Piwik\UrlHelper;
+use Piwik\Log;
/**
* Dispatches API requests to the appropriate API method.
@@ -216,6 +217,8 @@ class Request
$toReturn = $response->getResponse($returnedValue, $module, $method);
} catch (Exception $e) {
+ Log::debug($e);
+
$toReturn = $response->getResponseException($e);
}
return $toReturn;
diff --git a/core/Config.php b/core/Config.php
index 8183b3fdc2..9d6326bb2e 100644
--- a/core/Config.php
+++ b/core/Config.php
@@ -135,7 +135,6 @@ class Config extends Singleton
// Ensure local mods do not affect tests
if (empty($pathGlobal)) {
- $this->configCache['log'] = $this->configGlobal['log'];
$this->configCache['Debug'] = $this->configGlobal['Debug'];
$this->configCache['mail'] = $this->configGlobal['mail'];
$this->configCache['General'] = $this->configGlobal['General'];
diff --git a/core/Date.php b/core/Date.php
index 7af59e1f2a..c5b4cd7af6 100644
--- a/core/Date.php
+++ b/core/Date.php
@@ -41,6 +41,26 @@ class Date
const DATE_TIME_FORMAT = 'Y-m-d H:i:s';
/**
+ * Max days for months (non-leap-year). See {@link addPeriod()} implementation.
+ *
+ * @var int[]
+ */
+ private static $maxDaysInMonth = array(
+ '1' => 31,
+ '2' => 28,
+ '3' => 31,
+ '4' => 30,
+ '5' => 31,
+ '6' => 30,
+ '7' => 31,
+ '8' => 31,
+ '9' => 30,
+ '10' => 31,
+ '11' => 30,
+ '12' => 31
+ );
+
+ /**
* The stored timestamp is always UTC based.
* The returned timestamp via getTimestamp() will have the conversion applied
* @var int|null
@@ -673,14 +693,41 @@ class Date
*/
public function addPeriod($n, $period)
{
- if ($n < 0) {
- $ts = strtotime("$n $period", $this->timestamp);
+ if (strtolower($period) == 'month') { // TODO: comments
+ $dateInfo = getdate($this->timestamp);
+
+ $ts = mktime(
+ $dateInfo['hours'],
+ $dateInfo['minutes'],
+ $dateInfo['seconds'],
+ $dateInfo['mon'] + (int)$n,
+ 1,
+ $dateInfo['year']
+ );
+
+ $daysToAdd = min($dateInfo['mday'], self::getMaxDaysInMonth($ts)) - 1;
+ $ts += self::NUM_SECONDS_IN_DAY * $daysToAdd;
} else {
- $ts = strtotime("+$n $period", $this->timestamp);
+ $time = $n < 0 ? "$n $period" : "+$n $period";
+
+ $ts = strtotime($time, $this->timestamp);
}
+
return new Date($ts, $this->timezone);
}
+ private static function getMaxDaysInMonth($timestamp)
+ {
+ $month = (int)date('m', $timestamp);
+ if (date('L', $timestamp) == 1
+ && $month == 2
+ ) {
+ return 29;
+ } else {
+ return self::$maxDaysInMonth[$month];
+ }
+ }
+
/**
* Subtracts a period from `$this` date and returns the result in a new Date instance.
*
diff --git a/core/Error.php b/core/Error.php
index ac0029d987..7cff6fac0b 100644
--- a/core/Error.php
+++ b/core/Error.php
@@ -76,9 +76,15 @@ class Error
$this->backtrace = $backtrace;
}
- public function getErrNoString()
+ /**
+ * Returns a string description of a PHP error number.
+ *
+ * @param int $errno `E_ERROR`, `E_WARNING`, `E_PARSE`, etc.
+ * @return string
+ */
+ public static function getErrNoString($errno)
{
- switch ($this->errno) {
+ switch ($errno) {
case E_ERROR:
return "Error";
case E_WARNING:
@@ -110,14 +116,14 @@ class Error
case E_USER_DEPRECATED:
return "User Deprecated";
default:
- return "Unknown error ({$this->errno})";
+ return "Unknown error ($errno)";
}
}
public static function formatFileAndDBLogMessage(&$message, $level, $tag, $datetime, $log)
{
if ($message instanceof Error) {
- $message = $message->errfile . '(' . $message->errline . '): ' . $message->getErrNoString()
+ $message = $message->errfile . '(' . $message->errline . '): ' . Error::getErrNoString($message->errno)
. ' - ' . $message->errstr . "\n" . $message->backtrace;
$message = $log->formatMessage($level, $tag, $datetime, $message);
@@ -146,7 +152,7 @@ class Error
<strong>There is an error. Please report the message (Piwik " . (class_exists('Piwik\Version') ? Version::VERSION : '') . ")
and full backtrace in the <a href='?module=Proxy&action=redirect&url=http://forum.piwik.org' target='_blank'>Piwik forums</a> (please do a Search first as it might have been reported already!).<br /><br/>
";
- $htmlString .= $message->getErrNoString();
+ $htmlString .= Error::getErrNoString($message->errno);
$htmlString .= ":</strong> <em>{$message->errstr}</em> in <strong>{$message->errfile}</strong>";
$htmlString .= " on line <strong>{$message->errline}</strong>\n";
$htmlString .= "<br /><br />Backtrace --&gt;<div style=\"font-family:Courier;font-size:10pt\"><br />\n";
diff --git a/core/Log.php b/core/Log.php
index 4e505f7b63..a860dd1989 100644
--- a/core/Log.php
+++ b/core/Log.php
@@ -256,7 +256,7 @@ class Log extends Singleton
{
return str_replace(
array("%tag%", "%message%", "%datetime%", "%level%"),
- array($tag, $message, $datetime, $this->getStringLevel($level)),
+ array($tag, trim($message), $datetime, $this->getStringLevel($level)),
$this->logMessageFormat
);
}
@@ -418,6 +418,13 @@ class Log extends Singleton
if (is_string($message)
&& !empty($sprintfParams)
) {
+ // handle array sprintf parameters
+ foreach ($sprintfParams as &$param) {
+ if (is_array($param)) {
+ $param = json_encode($param);
+ }
+ }
+
$message = vsprintf($message, $sprintfParams);
}
@@ -583,6 +590,7 @@ class Log extends Singleton
*/
Piwik::postEvent(self::FORMAT_SCREEN_MESSAGE_EVENT, array(&$message, $level, $tag, $datetime, $logger));
}
+ $message = trim($message);
return $message . "\n";
}
@@ -636,6 +644,7 @@ class Log extends Singleton
*/
Piwik::postEvent(self::FORMAT_DATABASE_MESSAGE_EVENT, array(&$message, $level, $tag, $datetime, $logger));
}
+ $message = trim($message);
return $message;
}
@@ -676,6 +685,9 @@ class Log extends Singleton
*/
Piwik::postEvent(self::FORMAT_FILE_MESSAGE_EVENT, array(&$message, $level, $tag, $datetime, $logger));
}
+
+ $message = trim($message);
+ $message = str_replace("\n", "\n ", $message);
return $message . "\n";
}
}
diff --git a/core/Plugin/Widgets.php b/core/Plugin/Widgets.php
index ef8b059b77..3199e7a80b 100644
--- a/core/Plugin/Widgets.php
+++ b/core/Plugin/Widgets.php
@@ -14,9 +14,9 @@ use Piwik\WidgetsList;
/**
* Base class of all plugin widget providers. Plugins that define their own widgets can extend this class to easily
- * add new widgets, to remove or to rename existing items.
+ * add new widgets or to remove widgets defined by other plugins.
*
- * For an example, see the {@link https://github.com/piwik/piwik/blob/master/plugins/ExampleRssWidget/Widget.php} plugin.
+ * For an example, see the {@link https://github.com/piwik/piwik/blob/master/plugins/ExamplePlugin/Widgets.php} plugin.
*
* @api
*/
@@ -27,11 +27,17 @@ class Widgets
private $module = '';
+ /**
+ * @ignore
+ */
public function __construct()
{
$this->module = $this->getModule();
}
+ /**
+ * @ignore
+ */
public function getCategory()
{
return $this->category;
@@ -46,16 +52,23 @@ class Widgets
}
/**
+ * Adds a widget. You can add a widget by calling this method and passing the name of the widget as well as a method
+ * name that will be executed to render the widget. The method can be defined either directly here in this widget
+ * class or in the controller in case you want to reuse the same action for instance in the menu etc.
* @api
*/
protected function addWidget($name, $method, $parameters = array())
{
- // to be developer friendly we could check whether such a method exists (in controller or widget) and if
- // not throw an exception so the developer does not have to handle with typos etc. I do not want to do this
- // right now because of performance but if we add a development setting in config we could do such check
$this->addWidgetWithCustomCategory($this->category, $name, $method, $parameters);
}
+ /**
+ * Adds a widget with a custom category. By default all widgets that you define in your class will be added under
+ * the same category which is defined in the {@link $category} property. Sometimes you may have a widget that
+ * belongs to a different category where this method comes handy. It does the same as {@link addWidget()} but
+ * allows you to define the category name as well.
+ * @api
+ */
protected function addWidgetWithCustomCategory($category, $name, $method, $parameters = array())
{
$this->checkIsValidWidget($name, $method);
@@ -68,12 +81,17 @@ class Widgets
}
/**
+ * Here you can add one or multiple widgets. To do so call the method {@link addWidget()} or
+ * {@link addWidgetWithCustomCategory()}.
* @api
*/
protected function init()
{
}
+ /**
+ * @ignore
+ */
public function getWidgets()
{
$this->widgets = array();
@@ -84,7 +102,12 @@ class Widgets
}
/**
- * Configures the widgets. Here you can for instance remove widgets.
+ * Allows you to configure previously added widgets.
+ * For instance you can remove any widgets defined by any plugin by calling the
+ * {@link \Piwik\WidgetsList::remove()} method.
+ *
+ * @param WidgetsList $widgetsList
+ * @api
*/
public function configureWidgetsList(WidgetsList $widgetsList)
{
@@ -93,12 +116,16 @@ class Widgets
/**
* @return \Piwik\Plugin\Widgets[]
+ * @ignore
*/
public static function getAllWidgets()
{
return PluginManager::getInstance()->findComponents('Widgets', 'Piwik\\Plugin\\Widgets');
}
+ /**
+ * @ignore
+ */
public static function factory($module, $action)
{
if (empty($module) || empty($action)) {
diff --git a/lang/cs.json b/lang/cs.json
index ac9a4ff71f..7fccf65c86 100644
--- a/lang/cs.json
+++ b/lang/cs.json
@@ -32,6 +32,7 @@
"ChooseLanguage": "Zvolte jazyk",
"ChoosePeriod": "Zvolte období",
"ChooseWebsite": "Zvolte web",
+ "Clear": "Vyčistit",
"ClickHere": "Klikněte zde pro více informací",
"ClickToChangePeriod": "Klikni znovu pro změnu období.",
"Close": "Zavřít",
diff --git a/lang/fa.json b/lang/fa.json
index ec41926c0e..a4dadb0358 100644
--- a/lang/fa.json
+++ b/lang/fa.json
@@ -153,8 +153,10 @@
"ExceptionPrivilege": "شما نمی توانید به این منبع دسترسی داشته باشید زیرا این به دسترسی %s نیاز دارد.",
"ExceptionPrivilegeAccessWebsite": "شما می توانید به این منبع دسترسی داشته باشید نه به عنوان آن نیاز به %s دسترسی به سایت id = %d.",
"ExceptionPrivilegeAtLeastOneWebsite": "شما نمی توانید به این منبع دسترسی پیدا کنید زیرا این حداقل به دسترسی %s برای یک وبسایت نیاز دارید.",
+ "ExceptionReportNotFound": "گزارش درخواست شده وجود ندارد.",
"ExceptionUnableToStartSession": "قادر به شروع جلسه نیست.",
"ExceptionUndeletableFile": "غیر قابل حذف %s",
+ "ExceptionWidgetNotFound": "ویجت درخواست شده وجود ندارد.",
"Export": "خروجی گرفتن",
"ExportAsImage": "عکس به عنوان خروجی",
"ExportThisReport": "این مجموعه داده ها را در قالب های دیگری خروجی بده",
@@ -328,6 +330,7 @@
"Seconds": "%sثانیه",
"SeeAll": "دیدن همه",
"SeeTheOfficialDocumentationForMoreInformation": "برای اطلاعات بیشتر %sمستندات رسمی%s را ببینید.",
+ "Segment": "سگمنت",
"SelectYesIfYouWantToSendEmailsViaServer": "انتخاب \"بله\" اگر شما می خواهید و یا مجبور به ارسال ایمیل از طریق یک سرور به جای تابع ایمیل محلی به نام",
"Settings": "تنظيمات",
"Shipping": "هزینه پستی",
@@ -435,6 +438,7 @@
"ChooseHttpTimeout": "مقدار فاصله را انتخاب کنید HTTP",
"ChooseMetric": "معیار را انتخاب کنید",
"ChooseReport": "یک گزارش را انتخاب کنید",
+ "ChooseSegment": "انتخاب سگمنت",
"ConfirmRemoveAccount": "آیا شما می خواهیداین حساب را حذف کنید؟",
"DefaultReportDate": "تاریخ گزارش",
"EmailUs": "به ما ایمیل بزنید",
diff --git a/lang/ru.json b/lang/ru.json
index f210220727..3cc4177dc2 100644
--- a/lang/ru.json
+++ b/lang/ru.json
@@ -99,7 +99,7 @@
"Date": "Дата",
"DateRange": "Временной период:",
"DateRangeFrom": "От",
- "DateRangeFromTo": "Из %s в %s",
+ "DateRangeFromTo": "С %s по %s",
"DateRangeInPeriodList": "Период",
"DateRangeTo": "До",
"DayFr": "Пт",
diff --git a/misc/composer/build-xhprof.sh b/misc/composer/build-xhprof.sh
index 46637f2bbb..95057dc26e 100755
--- a/misc/composer/build-xhprof.sh
+++ b/misc/composer/build-xhprof.sh
@@ -1,27 +1,32 @@
#!/bin/bash
+if ! type phpize &> /dev/null; then
+ echo "phpize missing, skipping build"
+ echo "If you installed PHP via Aptitude, you can install phpize w/ 'sudo apt-get install php5-dev'"
+ exit
+fi
+
+if ! type make &> /dev/null; then
+ echo "make missing, skipping build"
+ exit
+fi
+
mkdir -p tmp/xhprof-logs
cd vendor/facebook/xhprof/extension
echo "Building xhprof..."
-git fetch origin pull/33/head:33_pull_request
-git merge 33_pull_request
-
-echo "Running phpize..."
if ! phpize &> ../../../../tmp/xhprof-logs/phpize.log; then
echo "Fatal error: phpize failed! View tmp/xhprof-logs/phpize.log for more info."
exit 1
fi
-echo "Running configure script..."
if ! ./configure &> ../../../../tmp/xhprof-logs/configure.log; then
echo "Fatal error: configure script failed! View tmp/xhprof-logs/configure.log for more info."
exit 2
fi
-echo "Building..."
if ! make &> ../../../../tmp/xhprof-logs/make.log; then
echo "Fatal error: could not build extension (make failed)! View tmp/xhprof-logs/make.log for more info."
exit 3
diff --git a/misc/composer/clean-xhprof.sh b/misc/composer/clean-xhprof.sh
new file mode 100755
index 0000000000..d20c17dd48
--- /dev/null
+++ b/misc/composer/clean-xhprof.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# if xhprof exists but points to a non-master branch, checkout master so composer won't fail
+
+if [ -d "vendor/facebook/xhprof/extension" ]; then
+ cd vendor/facebook/xhprof/extension
+
+ GIT_BRANCH=$(git symbolic-ref HEAD 2>/dev/null)
+
+ git reset --hard &> /dev/null
+ git checkout master &> /dev/null
+fi \ No newline at end of file
diff --git a/plugins/API/ProcessedReport.php b/plugins/API/ProcessedReport.php
index 09cbc54625..e174d3e4a4 100644
--- a/plugins/API/ProcessedReport.php
+++ b/plugins/API/ProcessedReport.php
@@ -498,12 +498,16 @@ class ProcessedReport
$columns
);
- if (isset($reportMetadata['processedMetrics'])) {
+ if (isset($reportMetadata['processedMetrics']) && is_array($reportMetadata['processedMetrics'])) {
$processedMetricsAdded = Metrics::getDefaultProcessedMetrics();
- foreach ($processedMetricsAdded as $processedMetricId => $processedMetricTranslation) {
+ foreach ($reportMetadata['processedMetrics'] as $processedMetricId => $processedMetricTranslation) {
// this processed metric can be displayed for this report
- if (isset($reportMetadata['processedMetrics'][$processedMetricId])) {
+
+ if ($processedMetricTranslation && $processedMetricId !== $processedMetricTranslation) {
$columns[$processedMetricId] = $processedMetricTranslation;
+ } elseif (isset($processedMetricsAdded[$processedMetricId])) {
+ // for instance in case 'nb_visits' => 'nb_visits' we will translate it
+ $columns[$processedMetricId] = $processedMetricsAdded[$processedMetricId];
}
}
}
diff --git a/plugins/Actions/lang/ja.json b/plugins/Actions/lang/ja.json
index 7a36ada7ca..0319b5aa8a 100644
--- a/plugins/Actions/lang/ja.json
+++ b/plugins/Actions/lang/ja.json
@@ -1,5 +1,6 @@
{
"Actions": {
+ "AvgGenerationTimeTooltip": "%s ~ %s の間の %s のヒット %s に基づく平均",
"ColumnClickedURL": "クリックされた URL",
"ColumnClicks": "クリック数",
"ColumnClicksDocumentation": "このリンクがクリックされた回数",
diff --git a/plugins/Actions/lang/ru.json b/plugins/Actions/lang/ru.json
index 58e6c906a3..f47d056517 100644
--- a/plugins/Actions/lang/ru.json
+++ b/plugins/Actions/lang/ru.json
@@ -42,6 +42,7 @@
"SiteSearchCategories2": "Например, сайты электронной коммерции обычно имеют выбор `Категорий` товаровуслуг, чтобы посетителям было удобно их сортировать и искать.",
"SiteSearchFollowingPagesDoc": "Когда посетители ищут что-то на вашем сайте, они хотят найти определенную страницу, контент, продукт или услугу. Этот отчет отображает страницы, по которым посетители кликают наиболее часто при поиске. Иными словами, это список страниц, которые ищутся наиболее часто на вашем сайте.",
"SiteSearchIntro": "Отслеживание поиска на вашем сайте - эффективный способ узнать, чем именно интересуется ваша аудитория. Это может помочь найти идеи для нового контента, новых продуктов и улучшить взаимодействие посетителей с вашим сайта в целом.",
+ "SiteSearchKeyword": "Ключевое слово (поиск по сайту)",
"SiteSearchKeywordsDocumentation": "Эти отчет показывает список ключевых слов, которые посетители искали на вашем сайте через ваш поиск.",
"SiteSearchKeywordsNoResultDocumentation": "Этот отчет отображает список ключевых слов, по которым не было ничего найдено на вашем сайте: возможно, стоит улучшить поисковый алгоритм на вашем сайте или посетители ищут то, чего на вашем сайте нет?",
"SubmenuPagesEntry": "Страницы входа",
diff --git a/plugins/CoreAdminHome/lang/fa.json b/plugins/CoreAdminHome/lang/fa.json
index ff0bbcccbf..ca13edcb5b 100644
--- a/plugins/CoreAdminHome/lang/fa.json
+++ b/plugins/CoreAdminHome/lang/fa.json
@@ -1,6 +1,7 @@
{
"CoreAdminHome": {
"Administration": "مدیریت",
+ "ArchivingSettings": "تنظیمات بایگانی",
"BrandingSettings": "تنظیمات نام تجاری",
"CheckReleaseGetVersion": "زمانی که برای نسخه جدید پیویک چک میکنید , همیشه ان را بگیرید",
"ClickHereToOptIn": "اینجا را کلیک کنید تا انتخاب شوید.",
@@ -8,6 +9,7 @@
"CustomLogoFeedbackInfo": "اگر شما آرم پیویک را سفارشی کنید , شاید برایتان جالب باشد که لینک %s را در منوی بالایی پنهان کنید.برای این کار شما می توانید افزونه ی بازخورد را در صفحه %sمدیریت افزونه ها%s غیرفعال کنید.",
"CustomLogoHelpText": "شما می توانید آرم Piwik سفارشی است که در رابط کاربری و گزارش پست الکترونیک نمایش داده خواهد شد.",
"EmailServerSettings": "تنضیمات میل سرور",
+ "FaviconUpload": "یک Favicon انتخاب کنید تا آپلود شود.",
"ForBetaTestersOnly": "فقط برای استفاده کنندهای موقطی",
"ImageTracking": "ردیابی تصویر",
"ImageTrackingIntro1": "زمانی که مشاهده کنندگان جاوا اسکریپت رو غیر فعال کنند , یا از جاوا اسکریپت استفاده نکنند , شما میتونید از عکس اسفاده کنید و لینک را به یازدید کننده بدهید.",
@@ -46,6 +48,7 @@
"PluginSettings": "تنظیمات افزونه ها",
"PluginSettingsIntro": "در اینجا شما می توانید تغییراتی در تنظیمات پلاگین های زیر انجام دهید :",
"PluginSettingsValueNotAllowed": "مقدار این رشته \"%s\" در پلاگین \"%s\" مورد قبول نیست",
+ "SendPluginUpdateCommunication": "زمانی که یک بروزرسانی از پلاگین وجود داشت برای من یک ایمیل بفرست",
"TrackAGoal": "به دنبال یک هدف",
"TrackingCode": "کد ردیابی",
"TrustedHostConfirm": "آیا از تغییر نام هاست مورد اعتماد پیویک اطمینان دارید؟",
diff --git a/plugins/CoreAdminHome/lang/ja.json b/plugins/CoreAdminHome/lang/ja.json
index e86484f3c0..98153e42d2 100644
--- a/plugins/CoreAdminHome/lang/ja.json
+++ b/plugins/CoreAdminHome/lang/ja.json
@@ -11,6 +11,7 @@
"DevelopmentProcess": "私たちの%s開発プロセス%sは自動化された数千のテストを含んでいますが、ベータテスターはPiwikの\"No bug policy\"達成のための重要な役割を果たしています。",
"EmailServerSettings": "メールサーバの設定",
"FaviconUpload": "アップロードするファビコンを選択",
+ "FileUploadDisabled": "PHP の設定で、ファイルのアップロードが有効になっていません。カスタムロゴをアップロードするには、 php.ini で %s を設定し、 Web サーバを再起動してください。",
"ForBetaTestersOnly": "ベータテスターのみ",
"ImageTracking": "画像によるトラッキング",
"ImageTrackingIntro1": "訪問者がJavaScriptを無効にしている、またはJavaScriptを利用できない場合、訪問者を追跡する為に画像でトラッキングするリンクを使うことができます。",
@@ -19,6 +20,8 @@
"ImageTrackingLink": "画像によるトラッキングのリンク",
"ImportingServerLogs": "サーバーログのインポート",
"ImportingServerLogsDesc": "ブラウザ(JavaScriptまたは画像リンクによる)を通して訪問者を追跡するのでは無く、継続的にサーバーのログをインポートします。%1$sサーバーログファイル解析%2$sの詳細はこちら。",
+ "InvalidPluginsWarning": "以下のプラグインは、 %1$s と互換性がないためロードできませんでした。 :%2$s.",
+ "InvalidPluginsYouCanUninstall": "これらのプラグインは、 %1$sManage Plugins%2$s ページでアップデートまたはアンインストールすることができます。",
"JavaScriptTracking": "JavaScriptトラッキング",
"JSTracking_CampaignKwdParam": "キャンペーン用キーワードのパラメーター",
"JSTracking_CampaignNameParam": "キャンペーン名のパラメーター",
@@ -45,8 +48,10 @@
"JSTrackingIntro5": "ページビューを追跡する以上のことをしたい場合は、%1$sPiwik Javascriptトラッキングドキュメント%2$sの使用可能な機能のリストを参照してください。これらの機能を使って、ゴール(目標)、カスタム変数、eコマース注文、破棄されたショッピングカート等々の追跡が可能です。",
"LatestBetaRelease": "最新のベータ版リリース",
"LatestStableRelease": "最新の安定版リリース",
+ "LogoNotWriteableInstruction": "Piwik デフォルトロゴの代わりにカスタムロゴを使用するには、このディレクトリへの書込権限を与えて下さい。 :%1$s ロゴを %2$s ファイルに保存するには、書込アクセスが必要です。",
"LogoUpload": "アップロードするロゴを選択",
"LogoUploadHelp": "%s ピクセル以上の高さで %s 形式のファイルをアップロードしてください",
+ "MenuDevelopment": "開発",
"MenuDiagnostic": "診断",
"MenuGeneralSettings": "全般の設定",
"MenuManage": "管理",
@@ -57,8 +62,11 @@
"OptOutForYourVisitors": "ビジターの Piwik オプトアウト",
"PiwikIsInstalledAt": "Piwikがインストールされているのは",
"PluginDescription": "Piwik の管理エリアです。",
+ "PluginSettingChangeNotAllowed": "\"%s\" プラグインで \"%s\" 設定されている値変更は許可されていません。",
+ "PluginSettingReadNotAllowed": "\"%s\" プラグインで \"%s\" 設定されている値の読み取りは許可されていません。",
"PluginSettings": "プラグインの設定",
"PluginSettingsIntro": "ここでは、次のサードパーティのプラグインの設定変更ができます",
+ "PluginSettingsValueNotAllowed": "\"%s\" プラグインの \"%s\" フィールドの値は許可されていません。",
"SendPluginUpdateCommunication": "プラグインのアップデートがあった場合のメール通知",
"SendPluginUpdateCommunicationHelp": "使用可能な新しいプラグインのバージョンがある場合、管理者ユーザーへメールが通知されます。",
"StableReleases": "Piwikがビジネスの重要な一部である場合、最新の安定版を使用することを推奨します。また、最新のベータ版を使用し、バグを見つけたり、提案があれば、%sこちらをご覧ください%s。",
diff --git a/plugins/CoreAdminHome/lang/ru.json b/plugins/CoreAdminHome/lang/ru.json
index 08915a2e10..dcf244d77d 100644
--- a/plugins/CoreAdminHome/lang/ru.json
+++ b/plugins/CoreAdminHome/lang/ru.json
@@ -59,6 +59,8 @@
"OptOutForYourVisitors": "Исключение из политики конфиденциальности Piwik для посетителей",
"PiwikIsInstalledAt": "Piwik установлен в",
"PluginDescription": "Админпанель Piwik.",
+ "PluginSettingChangeNotAllowed": "Вам не разрешено менять значение \"%s\" для плагина \"%s\"",
+ "PluginSettingReadNotAllowed": "Вам не разрешено читать значение \"%s\" плагина \"%s\"",
"PluginSettings": "Настройки плагина",
"PluginSettingsIntro": "Здесь вы можете изменить настройки для следующих плагинов:",
"SendPluginUpdateCommunication": "Отправить мне уведомление по электронной почте, когда есть новое обновление плагина",
diff --git a/plugins/CoreConsole/Commands/GenerateTravisYmlFile.php b/plugins/CoreConsole/Commands/GenerateTravisYmlFile.php
index 7b5f2e5e0c..1bd68cf0f7 100644
--- a/plugins/CoreConsole/Commands/GenerateTravisYmlFile.php
+++ b/plugins/CoreConsole/Commands/GenerateTravisYmlFile.php
@@ -37,28 +37,34 @@ class GenerateTravisYmlFile extends ConsoleCommand
"Github token of a user w/ push access to this repository. Used to auto-commit updates to the "
. ".travis.yml file and checkout dependencies. Will be encrypted in the .travis.yml file.\n\n"
. "If not supplied, the .travis.yml will fail the build if it needs updating.")
- ->addOption('before-install', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL,
- "Custom shell command(s) to run at the end of the before_install .travis.yml section.")
- ->addOption('install', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL,
- "Custom shell command(s) to run at the end of the install .travis.yml section.")
- ->addOption('before-script', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL,
- "Custom shell command(s) to run at the end of the before_script .travis.yml section.")
- ->addOption('after-script', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL,
- "Custom shell command(s) to run at the end of the after_script .travis.yml section.")
- ->addOption('after-success', null, InputOption::VALUE_IS_ARRAY | InputOption::VALUE_OPTIONAL,
- "Custom shell command(s) to run at the end of the after_success .travis.yml section.")
+ ->addOption('php-versions', null, InputOption::VALUE_OPTIONAL,
+ "List of PHP versions to test against, ie, 5.4,5.5,5.6. Defaults to: 5.3.3,5.4,5.5,5.6.")
->addOption('dump', null, InputOption::VALUE_REQUIRED, "Debugging option. Saves the output .travis.yml to the specified file.");
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$targetPlugin = $input->getOption('plugin');
- $artifactsPass = $input->getOption('artifacts-pass');
- $githubToken = $input->getOption('github-token');
$outputYmlPath = $this->getTravisYmlOutputPath($input, $targetPlugin);
- $thisConsoleCommand = $this->getExecutedConsoleCommandForTravis($input);
+ $view = $this->createTravisYmlView($input, $output, $targetPlugin, $outputYmlPath);
+ $travisYmlContents = $view->render();
+
+ $this->dumpTravisYmlContents($input, $output, $outputYmlPath, $travisYmlContents);
+ }
+
+ private function createTravisYmlView(InputInterface $input, OutputInterface $output, $targetPlugin, $outputYmlPath)
+ {
$view = new TravisYmlView();
+ $view->setPlugin($targetPlugin);
+
+ $thisConsoleCommand = $this->getExecutedConsoleCommandForTravis($input);
+ $view->setGenerateYmlCommand($thisConsoleCommand);
+
+ $phpVersions = $input->getOption('php-versions');
+ if (!empty($phpVersions)) {
+ $view->setPhpVersions(explode(',', $phpVersions));
+ }
if (file_exists($outputYmlPath)) {
$output->writeln("<info>Found existing YAML file at $outputYmlPath.</info>");
@@ -68,17 +74,13 @@ class GenerateTravisYmlFile extends ConsoleCommand
$output->writeln("<info>Could not find existing YAML file at $outputYmlPath, generating a new one.</info>");
}
- $customTravisSteps = array(
- 'before_install' => $input->getOption('before-install'),
- 'install' => $input->getOption('install'),
- 'before_script' => $input->getOption('before-script'),
- 'after_script' => $input->getOption('after-script'),
- 'after_success' => $input->getOption('after-success')
- );
+ $this->setExtraEnvironmentVariables($view, $input, $output);
- $view->configure($targetPlugin, $artifactsPass, $githubToken, $thisConsoleCommand, $customTravisSteps, $output);
- $travisYmlContents = $view->render();
+ return $view;
+ }
+ private function dumpTravisYmlContents(InputInterface $input, OutputInterface $output, $outputYmlPath, $travisYmlContents)
+ {
$writePath = $input->getOption('dump');
if (empty($writePath)) {
$writePath = $outputYmlPath;
@@ -89,6 +91,28 @@ class GenerateTravisYmlFile extends ConsoleCommand
$this->writeSuccessMessage($output, array("Generated .travis.yml file at '$writePath'!"));
}
+ private function setExtraEnvironmentVariables(TravisYmlView $view, InputInterface $input, OutputInterface $output)
+ {
+ if (!empty($view->existingEnv)) {
+ $output->writeln("<info>Existing .yml file found, ignoring global variables specified on command line.</info>");
+ return;
+ }
+
+ $extraVars = array();
+
+ $artifactsPass = $input->getOption('artifacts-pass');
+ if (!empty($artifactsPass)) {
+ $extraVars[] = $this->travisEncrypt("ARTIFACTS_PASS=" . $artifactsPass, $view, $output);
+ }
+
+ $githubToken = $input->getOption('github-token');
+ if (!empty($githubToken)) {
+ $extraVars[] = $this->travisEncrypt("GITHUB_USER_TOKEN=" . $githubToken, $view, $output);
+ }
+
+ $view->setExtraGlobalEnvVars($extraVars);
+ }
+
private function getTravisYmlOutputPath(InputInterface $input, $targetPlugin)
{
if ($input->getOption('core')) {
@@ -135,4 +159,40 @@ class GenerateTravisYmlFile extends ConsoleCommand
return $command;
}
+
+
+ private function travisEncrypt($data, TravisYmlView $view, OutputInterface $output)
+ {
+ $output->writeln("Encrypting \"$data\"...");
+
+ $command = "travis encrypt \"$data\"";
+
+ // change dir to target plugin since plugin will be in its own git repo
+ if (!empty($view->pluginName)) {
+ $command = "cd \"" . $view->getPluginRootFolder() . "\" && " . $command;
+ }
+
+ exec($command, $commandOutput, $returnCode);
+ if ($returnCode !== 0) {
+ throw new Exception("Cannot encrypt \"$data\" for travis! Please make sure you have the travis command line "
+ . "utility installed (see http://blog.travis-ci.com/2013-01-14-new-client/).\n\n"
+ . "return code: $returnCode\n\n"
+ . "travis output:\n\n" . implode("\n", $commandOutput));
+ }
+
+ if (empty($commandOutput)) {
+ throw new Exception("Cannot parse travis encrypt output:\n\n" . implode("\n", $commandOutput));
+ }
+
+ // when not executed from a command line travis encrypt will return only the encrypted data
+ $encryptedData = $commandOutput[0];
+
+ if (substr($encryptedData, 0, 1) != '"'
+ || substr($encryptedData, -1) != '"'
+ ) {
+ $encryptedData = '"' . addslashes($encryptedData) . '"';
+ }
+
+ return "secure: " . $encryptedData;
+ }
} \ No newline at end of file
diff --git a/plugins/CoreConsole/Commands/GenerateWidget.php b/plugins/CoreConsole/Commands/GenerateWidget.php
index 53552e6844..31468921ad 100644
--- a/plugins/CoreConsole/Commands/GenerateWidget.php
+++ b/plugins/CoreConsole/Commands/GenerateWidget.php
@@ -33,6 +33,11 @@ class GenerateWidget extends GeneratePluginBase
$pluginName = $this->getPluginName($input, $output);
$category = $this->getCategory($input, $output);
+ if ($category === Piwik::translate($category)) {
+ // no translation found...
+ $category = $this->makeTranslationIfPossible($pluginName, $category);
+ }
+
$exampleFolder = PIWIK_INCLUDE_PATH . '/plugins/ExamplePlugin';
$replace = array('ExamplePlugin' => $pluginName,
'Example Category' => $category);
@@ -47,6 +52,19 @@ class GenerateWidget extends GeneratePluginBase
));
}
+ protected function getExistingCategories()
+ {
+ $categories = array();
+ foreach (Widgets::getAllWidgets() as $widget) {
+ if ($widget->getCategory()) {
+ $categories[] = Piwik::translate($widget->getCategory());
+ }
+ }
+ $categories = array_values(array_unique($categories));
+
+ return $categories;
+ }
+
/**
* @param InputInterface $input
* @param OutputInterface $output
@@ -63,15 +81,8 @@ class GenerateWidget extends GeneratePluginBase
return $category;
};
- $category = $input->getOption('category');
-
- $categories = array();
- foreach (Widgets::getAllWidgets() as $widget) {
- if ($widget->getCategory()) {
- $categories[] = Piwik::translate($widget->getCategory());
- }
- }
- $categories = array_values(array_unique($categories));
+ $category = $input->getOption('category');
+ $categories = $this->getExistingCategories();
if (empty($category)) {
$dialog = $this->getHelperSet()->get('dialog');
diff --git a/plugins/CoreConsole/TravisYmlView.php b/plugins/CoreConsole/TravisYmlView.php
index 78eb46f4b3..d11218cc5d 100644
--- a/plugins/CoreConsole/TravisYmlView.php
+++ b/plugins/CoreConsole/TravisYmlView.php
@@ -35,6 +35,22 @@ class TravisYmlView extends View
);
/**
+ * The names of .travis.yml sections that can be extended w/ custom steps by plugins. Twig templates
+ * in the plugins/PluginName/tests/travis directory can be used to insert travis commands at the
+ * beginning or end of a section. For example, before_install.before.yml will add steps
+ * at the beginning of the before_install: section.
+ *
+ * @var string[]
+ */
+ private static $travisYmlExtendableSectionNames = array(
+ 'before_install',
+ 'install',
+ 'before_script',
+ 'after_script',
+ 'after_success'
+ );
+
+ /**
* Constructor.
*/
public function __construct()
@@ -64,37 +80,72 @@ class TravisYmlView extends View
}
/**
- * Configures the view for generation.
+ * Sets the name of plugin the generated .travis.yml file is for.
*
- * @param string|null $targetPlugin The plugin target or `null` if generating for core.
- * @param string|null $artifactsPass The password for the builds artifacts server. Encrypted in output.
- * @param string $generateYmlCommand The command to use in travis when checking if a .travis.yml file is out
- * of date.
- * @param OutputInterface $output OutputInterface to output warnings and the like.
+ * @param string $pluginName ie, ExamplePlugin, UserSettings, etc.
*/
- public function configure($targetPlugin, $artifactsPass, $githubToken, $generateYmlCommand, $customTravisSteps,
- OutputInterface $output)
+ public function setPlugin($pluginName)
{
- $this->pluginName = $targetPlugin;
+ $this->pluginName = $pluginName;
+
+ $customTravisBuildSteps = array();
+ foreach (self::$travisYmlExtendableSectionNames as $name) {
+ $customTravisBuildSteps[$name] = array();
- if (empty($this->existingEnv)) {
- $artifactsPass = $artifactsPass;
- if (!empty($artifactsPass)) {
- $this->artifactsPass = $this->travisEncrypt("ARTIFACTS_PASS=" . $artifactsPass, $output);
+ $beforeStepsTemplate = $this->getPathToCustomTravisStepsFile($name, 'before');
+ if (file_exists($beforeStepsTemplate)) {
+ $customTravisBuildSteps[$name]['before'] = $this->changeIndent(file_get_contents($beforeStepsTemplate), ' ');
}
- $githubToken = $githubToken;
- if (!empty($githubToken)) {
- $this->githubToken = $this->travisEncrypt("GITHUB_USER_TOKEN=" . $githubToken, $output);
+ $afterStepsTemplate = $this->getPathToCustomTravisStepsFile($name, 'after');
+ if (file_exists($afterStepsTemplate)) {
+ $customTravisBuildSteps[$name]['after'] = $this->changeIndent(file_get_contents($afterStepsTemplate), ' ');
}
- } else {
- $output->writeln("<info>Existing .yml files found, ignoring global variables specified on command line.</info>");
}
+ $this->customTravisBuildSteps = $customTravisBuildSteps;
+ }
+ /**
+ * Set extra global environment variables that should be set in the generated .travis.yml file. The entries
+ * should be whole statements like `"MY_VAR=myvalue"` or `"secure: mysecurevalue"`.
+ *
+ * @param string[] $extraVars
+ */
+ public function setExtraGlobalEnvVars($extraVars)
+ {
+ $this->extraGlobalEnvVars = $extraVars;
+ }
+
+ /**
+ * Sets the self-referential command that will generate the .travis.yml file on travis.
+ *
+ * @param string $consoleCommand ie, `"./console generate:travis-yml ..."`
+ */
+ public function setGenerateYmlCommand($consoleCommand)
+ {
+ $this->consoleCommand = addslashes($consoleCommand);
+ }
+
+ /**
+ * Sets the PHP versions to run tests against in travis.
+ *
+ * @param string[] $phpVersions ie, `array("5.3.3", "5.4", "5.5")`.
+ */
+ public function setPhpVersions($phpVersions)
+ {
+ $this->phpVersions = $phpVersions;
+ }
+
+ /**
+ * Renders the view. See {@link Piwik\View::render()}.
+ *
+ * @return string
+ */
+ public function render()
+ {
list($this->testsToRun, $this->testsToExclude) = $this->getTestsToRun();
- $this->consoleCommand = $generateYmlCommand;
- $this->customTravisSteps = $customTravisSteps;
+ return parent::render();
}
/**
@@ -138,41 +189,6 @@ class TravisYmlView extends View
return substr($yamlText, $offset, $endPos - $offset);
}
- private function travisEncrypt($data, OutputInterface $output)
- {
- $output->writeln("Encrypting \"$data\"...");
-
- $command = "travis encrypt \"$data\"";
-
- // change dir to target plugin since plugin will be in its own git repo
- if (!empty($this->pluginName)) {
- $command = "cd \"" . $this->getPluginRootFolder() . "\" && " . $command;
- }
-
- exec($command, $output, $returnCode);
- if ($returnCode !== 0) {
- throw new Exception("Cannot encrypt \"$data\" for travis! Please make sure you have the travis command line "
- . "utility installed (see http://blog.travis-ci.com/2013-01-14-new-client/).\n\n"
- . "return code: $returnCode\n\n"
- . "travis output:\n\n" . implode("\n", $output));
- }
-
- if (empty($output)) {
- throw new Exception("Cannot parse travis encrypt output:\n\n" . implode("\n", $output));
- }
-
- // when not executed from a command line travis encrypt will return only the encrypted data
- $encryptedData = $output[0];
- if (substr($encryptedData, 0, 1) == '"') {
- $encryptedData = substr($encryptedData, 1);
- }
- if (substr($encryptedData, -1) == '"') {
- $encryptedData = substr($encryptedData, 0, strlen($encryptedData) - 1);
- }
-
- return $encryptedData;
- }
-
private function getTestsToRun()
{
$testsToRun = array();
@@ -236,8 +252,20 @@ class TravisYmlView extends View
return !empty($testFiles);
}
- private function getPluginRootFolder()
+ private function changeIndent($text, $newIndent)
+ {
+ $text = trim($text);
+
+ return preg_replace("/^\\s*/", $newIndent, $text);
+ }
+
+ public function getPluginRootFolder()
{
return PIWIK_INCLUDE_PATH . "/plugins/{$this->pluginName}";
}
+
+ private function getPathToCustomTravisStepsFile($sectionName, $type)
+ {
+ return $this->getPluginRootFolder() . "/tests/travis/$sectionName.$type.yml";
+ }
} \ No newline at end of file
diff --git a/plugins/CoreConsole/templates/travis.yml.twig b/plugins/CoreConsole/templates/travis.yml.twig
index 9252793494..e3c8c30efa 100644
--- a/plugins/CoreConsole/templates/travis.yml.twig
+++ b/plugins/CoreConsole/templates/travis.yml.twig
@@ -1,8 +1,17 @@
# do not edit this file manually, instead run the generate:travis-yml console command
-# if you are a Piwik core developer, edit this template file to auto generate the travis.yml: https://github.com/piwik/piwik/blob/master/plugins/CoreConsole/templates/travis.yml.twig
+{% if pluginName is empty %}
+# if you are a Piwik core developer, edit this template file to auto generate the .travis.yml: https://github.com/piwik/piwik/blob/master/plugins/CoreConsole/templates/travis.yml.twig
+
+# when modifying this file, please consider whether your changes should apply to plugin .travis.yml files. if not, check whether the pluginName twig var is empty,
+# otherwise your changes will be synced with every plugin that uses an auto generated .travis.yml
+
+# also please test generation before committing by running ./console generate:travis-yml --core and ./console generate:travis-yml --plugin=CustomAlerts
+# and making sure the .travis.yml files are changed correctly
+{% endif %}
language: php
+{% if phpVersions|default is empty %}
# We want to test against PHP 5.3.3/5.4/5.5
php:
- 5.6
@@ -10,6 +19,11 @@ php:
- 5.4
- 5.3.3
# - hhvm
+{% else %}
+php:
+{% for version in phpVersions %} - {{ version|raw }}
+{% endfor %}
+{% endif %}
# Separate different test suites
{% if existingEnv|default is empty -%}
@@ -21,10 +35,8 @@ env:
{% else %}
- PIWIK_ROOT_DIR=$TRAVIS_BUILD_DIR/piwik
{% endif %}
-{% if artifactsPass|default is not empty %} - secure: "{{ artifactsPass|raw }}"
-{% endif %}
-{% if githubToken|default is not empty %} - secure: "{{ githubToken|raw }}"
-{% endif %}
+{% if extraGlobalEnvVars|default is not empty %}{% for var in extraGlobalEnvVars %} - {{ var|raw }}
+{% endfor %}{% endif %}
matrix:
{% for test in testsToRun %} - TEST_SUITE={{ test.name|raw }} {{ test.vars|raw }}
{% endfor %}
@@ -52,17 +64,20 @@ matrix:
script: $PIWIK_ROOT_DIR/tests/travis/travis.sh
before_install:
+{% if customTravisBuildSteps.before_install.before|default is not empty %}{{ customTravisBuildSteps.before_install.before|raw }}
+
+{% endif %}
# do not use the Zend allocator on PHP 5.3 since it will randomly segfault after program execution
- '[[ "$TRAVIS_PHP_VERSION" == 5.3* ]] && export USE_ZEND_ALLOC=0 || true'
-{% if customTravisSteps is not empty and customTravisSteps.before_install %}
+{% if customTravisBuildSteps.before_install.after|default is not empty %}
- # custom before_install steps
-{% for step in customTravisSteps.before_install %}
- - {{ step|raw }}
-{% endfor %}
+{{ customTravisBuildSteps.before_install.after|raw }}
{% endif %}
install:
+{% if customTravisBuildSteps.install.before|default is not empty %}{{ customTravisBuildSteps.install.before|raw }}
+
+{% endif %}
{% if pluginName is not empty %}
# move all contents of current repo (which contains the plugin) to a new directory
- mkdir $PLUGIN_NAME
@@ -102,15 +117,15 @@ install:
- git fetch
- git checkout master -- ./tests/travis ./plugins/CoreConsole || true
{% endif %}
-{% if customTravisSteps is not empty and customTravisSteps.install %}
+{% if customTravisBuildSteps.install.after|default is not empty %}
- # custom install steps
-{% for step in customTravisSteps.install %}
- - {{ step|raw }}
-{% endfor %}
+{{ customTravisBuildSteps.install.after|raw }}
{% endif %}
before_script:
+{% if customTravisBuildSteps.before_script.before|default is not empty %}{{ customTravisBuildSteps.before_script.before|raw }}
+
+{% endif %}
- if [ -z "$TEST_SUITE" ];
then composer require satooshi/php-coveralls dev-master;
fi
@@ -157,19 +172,19 @@ before_script:
- ./tests/travis/prepare.sh
- ./tests/travis/setup_webserver.sh
- - export GENERATE_TRAVIS_YML_COMMAND='{{ consoleCommand|raw }}'
+ - export GENERATE_TRAVIS_YML_COMMAND="{{ consoleCommand|raw }}"
- ./tests/travis/autoupdate_travis_yml.sh
- cd tests/PHPUnit
-{% if customTravisSteps is not empty and customTravisSteps.before_script %}
+{% if customTravisBuildSteps.before_script.after|default is not empty %}
- # custom before_script steps
-{% for step in customTravisSteps.before_script %}
- - {{ step|raw }}
-{% endfor %}
+{{ customTravisBuildSteps.before_script.after|raw }}
{% endif %}
after_script:
+{% if customTravisBuildSteps.after_script.before|default is not empty %}{{ customTravisBuildSteps.after_script.before|raw }}
+
+{% endif %}
# change directory back to root travis dir
- cd $PIWIK_ROOT_DIR
@@ -185,24 +200,21 @@ after_script:
# upload test artifacts (for debugging travis failures)
- ./tests/travis/upload_artifacts.sh
-{% if customTravisSteps is not empty and customTravisSteps.after_script %}
+{% if customTravisBuildSteps.after_script.after|default is not empty %}
- # custom after_script steps
-{% for step in customTravisSteps.after_script %}
- - {{ step|raw }}
-{% endfor %}
+{{ customTravisBuildSteps.after_script.after|raw }}
{% endif %}
after_success:
+{% if customTravisBuildSteps.after_success.before|default is not empty %}{{ customTravisBuildSteps.after_success.before|raw }}
+
+{% endif %}
- cd $PIWIK_ROOT_DIR
{% if pluginName is empty %} - ./tests/travis/generate_docs.sh
{% endif %}
-{% if customTravisSteps is not empty and customTravisSteps.after_success %}
+{% if customTravisBuildSteps.after_success.after|default is not empty %}
- # custom after_success steps
-{% for step in customTravisSteps.after_success %}
- - {{ step|raw }}
-{% endfor %}
+{{ customTravisBuildSteps.after_success.after|raw }}
{% endif %}
{% if extraSections|default is not empty %}
diff --git a/plugins/CoreConsole/tests/Unit/TravisYmlViewTest.php b/plugins/CoreConsole/tests/Unit/TravisYmlViewTest.php
new file mode 100644
index 0000000000..eba77d25ba
--- /dev/null
+++ b/plugins/CoreConsole/tests/Unit/TravisYmlViewTest.php
@@ -0,0 +1,165 @@
+<?php
+/**
+ * Piwik - free/libre analytics platform
+ *
+ * @link http://piwik.org
+ * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
+ *
+ */
+namespace Piwik\Plugins\CoreConsole\tests\Unit;
+
+use Symfony\Component\Console\Output\ConsoleOutput;
+use Piwik\Plugins\CoreConsole\TravisYmlView;
+use Piwik\Plugin\Manager as PluginManager;
+use PHPUnit_Framework_TestCase;
+use Spyc; // DeviceDectector requires Spyc
+
+/**
+ * @group CoreConsole
+ * @group CoreConsole_TravisYmlViewTest
+ */
+class TravisYmlViewTest extends PHPUnit_Framework_TestCase
+{
+ public function setUp()
+ {
+ PluginManager::getInstance()->loadPlugin('Morpheus');
+ PluginManager::getInstance()->loadPlugin('CoreConsole');
+ }
+
+ public function testViewGeneratesCorrectLookingYAML()
+ {
+ $view = new TravisYmlView();
+ $view->setPlugin('ExamplePlugin');
+ $view->setExtraGlobalEnvVars(array('secure: artifactspass', 'secure: githubtoken'));
+ $view->setGenerateYmlCommand('./console generate:travis-yml \'arg1\' arg2');
+ $output = $view->render();
+
+ $yaml = Spyc::YAMLLoadString($output);
+
+ $this->assertNotEmpty($yaml['env']);
+ $this->assertNotEmpty($yaml['env']['global']);
+ $this->assertContains("PLUGIN_NAME=ExamplePlugin", $yaml['env']['global']);
+ $this->assertContains("PIWIK_ROOT_DIR=\$TRAVIS_BUILD_DIR/piwik", $yaml['env']['global']);
+ $this->assertContains(array('secure' => 'artifactspass'), $yaml['env']['global']);
+ $this->assertContains(array('secure' => 'githubtoken'), $yaml['env']['global']);
+
+ $this->assertNotEmpty($yaml['env']['matrix']);
+ $this->assertContains("TEST_SUITE=PluginTests MYSQL_ADAPTER=PDO_MYSQL", $yaml['env']['matrix']);
+ $this->assertContains("TEST_SUITE=PluginTests MYSQL_ADAPTER=PDO_MYSQL TEST_AGAINST_CORE=latest_stable", $yaml['env']['matrix']);
+ $this->assertNotContains("TEST_SUITE=UITests MYSQL_ADAPTER=PDO_MYSQL", $yaml['env']['matrix']);
+
+ $this->assertBuildSectionsNotEmpty($yaml);
+
+ $this->assertContains("export GENERATE_TRAVIS_YML_COMMAND=\"./console generate:travis-yml \\'arg1\\' arg2\"", $yaml['before_script']);
+
+ $this->assertViewUsesPluginSpecifiedTravisCommands($yaml);
+ }
+
+ public function testViewPreservesCommentsAndEnvVarsIfExistingYml()
+ {
+ $view = new TravisYmlView();
+ $view->setPlugin('ExamplePlugin');
+ $view->setExtraGlobalEnvVars(array('secure: artifactspass', 'secure: githubtoken'));
+ $view->setGenerateYmlCommand('./console generate:travis-yml arg1 arg2');
+ $view->processExistingTravisYml(PIWIK_INCLUDE_PATH . '/plugins/CoreConsole/tests/resources/test.travis.yml');
+ $output = $view->render();
+
+ $yaml = Spyc::YAMLLoadString($output);
+
+ $this->assertNotEmpty($yaml['env']);
+ $this->assertNotEmpty($yaml['env']['global']);
+
+ $this->assertContains("PRESERVED_VAR=123", $yaml['env']['global']);
+ $this->assertContains(array('secure' => 'anotherpreservedvar'), $yaml['env']['global']);
+ $this->assertNotContains("PLUGIN_NAME=ExamplePlugin", $yaml['env']['global']);
+ $this->assertNotContains("PIWIK_ROOT_DIR=\$TRAVIS_BUILD_DIR/piwik", $yaml['env']['global']);
+
+ $this->assertBuildSectionsNotEmpty($yaml);
+
+ $this->assertNotEmpty($yaml['custom_section']);
+ $this->assertContains("custom_section:\n - this will be preserved\n # as should this", $output);
+
+ $this->assertNotEmpty($yaml['notifications']);
+ $this->assertContains("notifications:\n # another section\n - a\n - b\n - c", $output);
+
+ $this->assertViewUsesPluginSpecifiedTravisCommands($yaml);
+ }
+
+ public function testViewGeneratesCorrectLookingYAMLForCore()
+ {
+ $view = new TravisYmlView();
+ // no setPlugin call here signifies generating for core
+ $view->processExistingTravisYml(PIWIK_INCLUDE_PATH . '/.travis.yml');
+ $view->setExtraGlobalEnvVars(array('secure: artifactspass', 'secure: githubtoken'));
+ $view->setGenerateYmlCommand('./console generate:travis-yml \'arg1\' arg2');
+ $output = $view->render();
+
+ $yaml = Spyc::YAMLLoadString($output);
+
+ $this->assertNotEmpty($yaml['env']);
+ $this->assertNotEmpty($yaml['env']['global']);
+
+ $this->assertBuildSectionsNotEmpty($yaml);
+
+ $this->assertViewDoesNotUsePluginSpecifiedTravisCommands($yaml);
+ }
+
+ public function testViewGeneratesCorrectLookingYAMLWhenCustomPhpVersionsUsed()
+ {
+ $view = new TravisYmlView();
+ $view->setPlugin('ExamplePlugin');
+ $view->setPhpVersions(array('5.4', '5.6', 'hhvm'));
+ $view->setGenerateYmlCommand('./console generate:travis-yml arg1 arg2');
+ $output = $view->render();
+
+ $yaml = Spyc::YAMLLoadString($output);
+
+ $this->assertNotEmpty($yaml['php']);
+ $this->assertEquals(array('5.4', '5.6', 'hhvm'), $yaml['php']);
+ }
+
+ private function assertBuildSectionsNotEmpty($yaml)
+ {
+ $this->assertNotEmpty($yaml['before_install']);
+ $this->assertNotEmpty($yaml['install']);
+ $this->assertNotEmpty($yaml['before_script']);
+ $this->assertNotEmpty($yaml['after_script']);
+ $this->assertNotEmpty($yaml['after_success']);
+ }
+
+ private function assertViewUsesPluginSpecifiedTravisCommands($yaml)
+ {
+ $this->assertEquals("before_install hook line 1", reset($yaml['before_install']));
+ $this->assertEquals("before_install hook line 2", end($yaml['before_install']));
+
+ $this->assertEquals("before_script hook line 1", reset($yaml['before_script']));
+ $this->assertEquals("before_script hook line 2", end($yaml['before_script']));
+
+ $this->assertEquals("install hook line 1", reset($yaml['install']));
+ $this->assertEquals("install hook line 2", end($yaml['install']));
+
+ $this->assertEquals("after_success hook line 1", reset($yaml['after_success']));
+ $this->assertEquals("after_success hook line 2", end($yaml['after_success']));
+
+ $this->assertEquals("after_script hook line 1", reset($yaml['after_script']));
+ $this->assertEquals("after_script hook line 2", end($yaml['after_script']));
+ }
+
+ private function assertViewDoesNotUsePluginSpecifiedTravisCommands($yaml)
+ {
+ $this->assertNotEquals("before_install hook line 1", reset($yaml['before_install']));
+ $this->assertNotEquals("before_install hook line 2", end($yaml['before_install']));
+
+ $this->assertNotEquals("before_script hook line 1", reset($yaml['before_script']));
+ $this->assertNotEquals("before_script hook line 2", end($yaml['before_script']));
+
+ $this->assertNotEquals("install hook line 1", reset($yaml['install']));
+ $this->assertNotEquals("install hook line 2", end($yaml['install']));
+
+ $this->assertNotEquals("after_success hook line 1", reset($yaml['after_success']));
+ $this->assertNotEquals("after_success hook line 2", end($yaml['after_success']));
+
+ $this->assertNotEquals("after_script hook line 1", reset($yaml['after_script']));
+ $this->assertNotEquals("after_script hook line 2", end($yaml['after_script']));
+ }
+} \ No newline at end of file
diff --git a/plugins/CoreConsole/tests/resources/test.travis.yml b/plugins/CoreConsole/tests/resources/test.travis.yml
new file mode 100644
index 0000000000..1cdc845f18
--- /dev/null
+++ b/plugins/CoreConsole/tests/resources/test.travis.yml
@@ -0,0 +1,55 @@
+language: php
+
+php:
+ - 5.3
+
+env:
+ global:
+ - PRESERVED_VAR=123
+ - secure: anotherpreservedvar
+ matrix:
+ - TEST_SUITE=CoreTests MYSQL_ADAPTER=PDO_MYSQL
+ - TEST_SUITE=PluginTests MYSQL_ADAPTER=PDO_MYSQL
+
+script: ./travis.sh
+
+install:
+ - TEST_PIWIK_VERSION=$(wget builds.piwik.org/LATEST -q -O -)
+ - TEST_PIWIK_VERSION=`echo $TEST_PIWIK_VERSION | tr -d ' ' | tr -d '\n'`
+ - mkdir ExamplePlugin
+ - cp -R !(ExamplePlugin) ExamplePlugin
+ - cp -R .git/ ExamplePlugin/
+ - git clone https://github.com/piwik/piwik.git piwik
+ - cd piwik
+ - git checkout "$TEST_PIWIK_VERSION"
+ - git submodule init
+ - git submodule update || true
+ - composer self-update
+ - composer install
+ - rm -rf plugins/ExamplePlugin
+ - cd ../
+ - mv ExamplePlugin piwik/plugins
+
+before_script:
+ - cd piwik
+ - uname -a
+ - date
+ - mysql -e 'create database piwik_tests;'
+ - ./tests/travis/prepare.sh
+ - ./tests/travis/setup_webserver.sh
+ - wget https://raw.github.com/piwik/piwik-tests-plugins/master/activateplugin.php
+ - php activateplugin.php ExamplePlugin
+ - cd tests/PHPUnit
+
+custom_section:
+ - this will be preserved
+ # as should this
+
+after_script:
+ - cat /var/log/nginx/error.log
+
+notifications:
+ # another section
+ - a
+ - b
+ - c
diff --git a/plugins/CoreHome/CoreHome.php b/plugins/CoreHome/CoreHome.php
index 6a7f6ab941..f45695e650 100644
--- a/plugins/CoreHome/CoreHome.php
+++ b/plugins/CoreHome/CoreHome.php
@@ -80,7 +80,7 @@ class CoreHome extends \Piwik\Plugin
$jsFiles[] = "libs/jquery/mwheelIntent.js";
$jsFiles[] = "libs/javascript/sprintf.js";
$jsFiles[] = "libs/mousetrap/mousetrap.min.js";
- $jsFiles[] = "libs/angularjs/angular.min.js";
+ $jsFiles[] = "libs/angularjs/angular.js";
$jsFiles[] = "libs/angularjs/angular-sanitize.min.js";
$jsFiles[] = "libs/angularjs/angular-animate.min.js";
$jsFiles[] = "libs/angularjs/angular-cookies.min.js";
diff --git a/plugins/CoreHome/angularjs/common/services/piwik-api.js b/plugins/CoreHome/angularjs/common/services/piwik-api.js
index 3830d657e8..bd5cfee4a2 100644
--- a/plugins/CoreHome/angularjs/common/services/piwik-api.js
+++ b/plugins/CoreHome/angularjs/common/services/piwik-api.js
@@ -90,28 +90,29 @@ angular.module('piwikApp.service').factory('piwikApi', function ($http, $q, $roo
// we can't modify requestPromise directly and add an abort method since for some reason it gets
// removed after then/finally/catch is called.
- var request = {
- then: function () {
- requestPromise.then.apply(requestPromise, arguments);
- return this;
- },
-
- 'finally': function () {
- requestPromise['finally'].apply(requestPromise, arguments);
- return this;
- },
-
- 'catch': function () {
- requestPromise['catch'].apply(requestPromise, arguments);
- return this;
- },
-
- abort: function () {
- deferred.reject();
- return this;
- }
+ var addAbortMethod = function (to) {
+ return {
+ then: function () {
+ return addAbortMethod(to.then.apply(to, arguments));
+ },
+
+ 'finally': function () {
+ return addAbortMethod(to['finally'].apply(to, arguments));
+ },
+
+ 'catch': function () {
+ return addAbortMethod(to['catch'].apply(to, arguments));
+ },
+
+ abort: function () {
+ deferred.reject();
+ return this;
+ }
+ };
};
+ var request = addAbortMethod(requestPromise);
+
allRequests.push(request);
return request;
diff --git a/plugins/CoreHome/angularjs/common/services/piwik-api_spec.js b/plugins/CoreHome/angularjs/common/services/piwik-api_spec.js
index e5d547ce9e..fecf56cde8 100644
--- a/plugins/CoreHome/angularjs/common/services/piwik-api_spec.js
+++ b/plugins/CoreHome/angularjs/common/services/piwik-api_spec.js
@@ -46,8 +46,11 @@ describe('piwikApiClient', function () {
method: "SomePlugin.action"
}).then(function (response) {
firstThenDone = true;
+
+ return "newval";
}).then(function (response) {
expect(firstThenDone).to.equal(true);
+ expect(response).to.equal("newval");
done();
}).catch(function (ex) {
diff --git a/plugins/CoreHome/lang/fa.json b/plugins/CoreHome/lang/fa.json
index d84140b1d8..7f560fd9f5 100644
--- a/plugins/CoreHome/lang/fa.json
+++ b/plugins/CoreHome/lang/fa.json
@@ -10,6 +10,7 @@
"DonateCall1": "استفاده از پیویک هیچگاه هزینه ای برای شما نخواهد داشت ، اما این به این معنا نیست که ما هم برای تولید آن هزینه ای نمی کنیم.",
"DonateCall2": "پیویک به حمایت همیشگی شما برای رشد و پیشرفت نیاز دارد.",
"DonateFormInstructions": "با کلیک بر روی نوار لغزنده و انتخاب مقدار کنید، و سپس دکمه ی مشترک به کمک مالی را بزنید",
+ "ExternalHelp": "راهنما (در tab جدید)",
"FlattenDataTable": "این گزارش سلسله مراتبی است %sآن را مسطح کن",
"HowMuchIsPiwikWorth": "چقدر پیویک برای شما ارزش دارد؟",
"InjectedHostEmailBody": "درود، من امروز برای دسترسی به پیویک تلاش کردم و هشدار نام هاست نامشخص را دریافت کردم.",
@@ -19,6 +20,7 @@
"MakeADifference": "یک تفاوت ایجاد کنید: %1$sبه پیویک هدیه بدهید%2$s تا در پیویک 2.0 سرمایه گذاری کنیم!",
"MakeOneTimeDonation": "یک بار کمک مالی انجام دهید.",
"NoPrivilegesAskPiwikAdmin": "شما به عنوان %s وارد شده اید , اما به نظر می رسد که شما اجازه دسترسی به هیچ بخشی از پیویک را ندارید. %s از مدیریت پیویک تان بخواهید (برای ارسال ایمیل کلیک کنید)%s تا به شما دسترسی \"مشاهده\" یک وبسایت را بدهد.",
+ "OnlyForSuperUserAccess": "این ویجت فقط برای کاربران با دسترسی ابرکاربر قابل مشاهده است.",
"PageOf": "%1$s از %2$s",
"PeriodDay": "روز",
"PeriodDays": "روزها",
diff --git a/plugins/CoreHome/lang/ja.json b/plugins/CoreHome/lang/ja.json
index 96caf85b30..0c3b569570 100644
--- a/plugins/CoreHome/lang/ja.json
+++ b/plugins/CoreHome/lang/ja.json
@@ -11,6 +11,7 @@
"Default": "デフォルト",
"DonateCall1": "Piwik を使用するのに費用はかかりません。しかし、 Piwik の制作に費用がかかっていないと言う意味ではありません",
"DonateCall2": "Piwik が成長し、成功するには、あなたの継続的なサポートが必要です",
+ "DonateCall3": "もし Piwik が少しでもあなたの事業の推進や成功に役に立ったと実感して頂けたら、 %1$splease consider donating!%2$s",
"DonateFormInstructions": "スライダで寄付する金額を選択して寄付するをクリック",
"ExcludeRowsWithLowPopulation": "全ての行を表示 %s 少ない数の行を除く",
"ExternalHelp": "ヘルプ(新しいタブで開きます)",
@@ -18,8 +19,14 @@
"HowMuchIsPiwikWorth": "あなたにとって Piwik の価値はどのくらいですか?",
"IncludeRowsWithLowPopulation": "数が少ない行は非表示 %s 全ての行を表示",
"InjectedHostEmailBody": "お知らせします。本日 Piwik へアクセスしたら、未知のホスト名の警告が発生しました。",
+ "InjectedHostEmailSubject": "Piwik が未知のホスト名にアクセスされました :%s",
+ "InjectedHostNonSuperUserWarning": "%1$sClick here to access Piwik safely%2$s この警告を削除して下さい。またこの問題を Piwik 管理者に通知することができます。 (%3$sclick here to email%4$s).",
+ "InjectedHostSuperUserWarning": "Piwik が誤って構成された可能性があります。( Piwik が最近新しいサーバーや URL に移動された等) 有効な Piwik ホスト名 (信用できる場合) として、%1$sclick here and add %2$s %3$s, または、 %4$sclick here and go to %5$s to access Piwik safely%6$s 。",
+ "InjectedHostWarningIntro": "現在 %1$s から Piwik にアクセスしていますが、 Piwik は以下のアドレスで実行するように設定されています。: %2$s",
"JavascriptDisabled": "Piwik を標準ビューで使用するには JavaScript が有効である必要がありますが、<br \/>あなたのブラウザでは無効になっているか、サポートされないようです。<br \/>標準ビューで使用するために、ブラウザのオプションを変更して JavaScript を有効にしてから<br \/>%1$s再試行してください%2$s。<br \/>",
"LongMonthFormat": "%longYear% 年 %longMonth%",
+ "LongWeekFormat": "%dayFrom% %longMonthFrom% - %dayTo% %longMonthTo% %longYearTo%",
+ "MakeADifference": "ぜひ、新しい変化を生み出してください : Piwik 2.0 基金に %1$sDonate now%2$s !",
"MakeOneTimeDonation": "代わりに寄与をする",
"NoPrivilegesAskPiwikAdmin": "'%s'としてログインしていますが、権限が設定されていないようです。 %s Piwikの管理者(クリックしてEメール)%s に'表示'の権限を与えてもらってください。",
"OnlyForSuperUserAccess": "このウィジェットは、スーパーユーザのアクセス権を持つユーザにのみ表示されます",
@@ -36,12 +43,15 @@
"PluginDescription": "ウェブ解析リポートのストラクチャーです。",
"ReportGeneratedOn": "%s に生成されたリポート",
"ReportGeneratedXAgo": "%s 前に生成されたリポート",
+ "SharePiwikLong": "素晴らしい無償ソフトウェアが見つかりました ! : Piwik です! Piwik はあなたのウェブサイト訪問者を無料で追跡します。要チェック !",
"SharePiwikShort": "Piwik !フリーでオープンソースのウェブ解析、あなたのデータを所有できます",
"ShareThis": "共有する",
"ShortDateFormat": "%shortMonth%%day%日%shortDay%",
"ShortDateFormatWithYear": "%shortYear% %shortMonth% %day%",
"ShortMonthFormat": "%longYear% %shortMonth%",
+ "ShortWeekFormat": "%dayFrom% %shortMonthFrom% - %dayTo% %shortMonthTo% %shortYearTo%",
"ShowJSCode": "挿入する javascript コードを表示",
+ "SubscribeAndBecomePiwikSupporter": "Piwik サポーターになるには、安全なクレジットカード決済 ( Paypal ) ページにお進みください !",
"SupportPiwik": "Piwik をサポート!",
"TableNoData": "このテーブルにはデータがありません",
"ThereIsNoDataForThisReport": "このリポートのデータがありません。",
diff --git a/plugins/CoreHome/lang/nl.json b/plugins/CoreHome/lang/nl.json
index ab06504d23..64de484c76 100644
--- a/plugins/CoreHome/lang/nl.json
+++ b/plugins/CoreHome/lang/nl.json
@@ -29,6 +29,7 @@
"MakeADifference": "Maak een verschil: %1$sDoneer nu%2$s om Piwik 2.0 te steunen!",
"MakeOneTimeDonation": "Doe een eennmalige donatie in de plaats.",
"NoPrivilegesAskPiwikAdmin": "U bent aangemeld as '%s'. Maar het lijkt er op dat u geen rechten hebt op Piwik te bezoeken. %sVraag aan uw webmaster (klik hier voor e-mail)%s of hij u de juiste rechten wilt geven om de statistieken te bekijken.",
+ "OnlyForSuperUserAccess": "Deze widget wordt alleen getoond aan superusers.",
"PageOf": "%1$s of %2$s",
"PeriodDay": "Dag",
"PeriodDays": "dagen",
diff --git a/plugins/CorePluginsAdmin/lang/ja.json b/plugins/CorePluginsAdmin/lang/ja.json
index f9607c1d89..accf6c7ef9 100644
--- a/plugins/CorePluginsAdmin/lang/ja.json
+++ b/plugins/CorePluginsAdmin/lang/ja.json
@@ -14,17 +14,27 @@
"BackToExtendPiwik": "マーケットプレイスへ戻る",
"BeCarefulUsingPlugins": "Piwik チームが作成していないプラグインは注意して使用して下さい:私たちはそれらを確認していません",
"BeCarefulUsingThemes": "Piwik チームが作成していないテーマは注意して使用して下さい:私たちはそれらを確認していません",
+ "ByDesigningOwnTheme": "by %sdesigning your own theme%s",
+ "ByInstallingNewPluginFromMarketplace": "by %sinstalling a new plugin from the Marketplace%s",
+ "ByInstallingNewThemeFromMarketplace": "by %sinstalling a new theme from the Marketplace%s",
+ "ByWritingOwnPlugin": "by %swriting your own plugin%s",
"ByXDevelopers": "%s の開発者",
"Changelog": "変更履歴",
+ "ChangeSettingsPossible": "このプラグインのために、 %ssettings%s を変更できます。",
"CorePluginTooltip": "コアプラグインは、 Piwik と一緒に配布されているため、バージョンはありません",
"Deactivate": "無効化",
"Developer": "開発者",
"DoMoreContactPiwikAdmins": "新しいプラグインやテーマをインストールするには、 Piwik の管理者に連絡をしてください",
+ "DownloadAndInstallPluginsFromMarketplace": "%sMarketplace%s から新しいプラグインを自動的にダウンロードし、インストールすることができます。",
+ "EmailToEnquireUpdatedVersion": "%1$s をメールで送付の上、%2$s の最新バージョンをお問い合わせください。",
"EnjoyAnotherLookAndFeelOfThemes": "別の外観と操作感をお楽しみください",
"FeaturedPlugin": "注目のプラグイン",
+ "GetEarlyAccessForPaidPlugins": "注 : 現在、全てのプラグインは無料で利用できます。今後マーケットプレイスでは有料プラグインが有効になります。 (有料プラグインについて、誰よりも早く知りたい方は、%scontact us%s )",
"GetNewFunctionality": "新しい機能の取得",
"History": "履歴",
"Inactive": "無効",
+ "InfoPluginUpdateIsRecommended": "最新の改良による恩恵を受けるには、今すぐプラグインをアップデートしてください。",
+ "InfoThemeIsUsedByOtherUsersAsWell": "注 : Piwikに登録されている他の %1$s のユーザーは、テーマ %2$s も使用しています。",
"InfoThemeUpdateIsRecommended": "最新バージョンを使用するするためにテーマを更新します。",
"InstallingPlugin": "%s のインストール",
"InstallNewPlugins": "新しいプラグインをインストール",
@@ -36,18 +46,28 @@
"Marketplace": "マーケットプレイス",
"MarketplaceSellPluginSubject": "マーケットプレイス - プラグインの販売",
"MenuPlatform": "プラットフォーム",
+ "MissingRequirementsNotice": "%1$s %3$s が必要です。 %1$s %2$s を最新バージョンにアップデートしてください。",
"NoPluginsFound": "プラグインは見つかりませんでした",
+ "NotAllowedToBrowseMarketplacePlugins": "Piwik プラットフォームのカスタマイズまたは拡張のために、インストール可能なプラグインのリストを閲覧することができます。もしこれらのいづれかのインストールが必要な場合は、管理者にお問い合わせください。",
+ "NotAllowedToBrowseMarketplaceThemes": "Piwik プラットフォームの外観をカスタマイズするのにインストール可能な Piwik テーマのリストをご確認ください。これらのいづれかをインストールしたい場合は、管理者にお問い合わせください。",
"NoThemesFound": "テーマは見つかりませんでした",
"NoZipFileSelected": "ZIP ファイルを選択してください。",
"NumDownloadsLatestVersion": "最新バージョン:%s のダウンロード",
"NumUpdatesAvailable": "%s アップデートがあります",
+ "OrByUploadingAPlugin": "または、by %suploading a plugin%s",
+ "OrByUploadingATheme": "または、by %suploading a plugin%s",
"Origin": "開発元",
"OriginCore": "コア",
"OriginThirdParty": "サードパーティ",
"PluginDescription": "プラグイン管理のインターフェースです。",
"PluginHomepage": "プラグインのホームページ",
"PluginKeywords": "キーワード",
+ "PluginNotCompatibleWith": "%1$s plugin is not compatible with %2$s.",
+ "PluginNotWorkingAlternative": "このプラグインを以前から使用している場合、マーケットプレイス上で、より最新のバージョンを見つけることができます。使用していない場合、アンインストールすることをお勧めします。",
+ "PluginRequirement": "%1$s requires %2$s.",
"PluginsManagement": "プラグインの管理",
+ "PluginUpdateAvailable": "あなたは現在、バージョン %s を使用しています。新しいバージョン %s が利用可能です。",
+ "PluginVersionInfo": "%1$s from %2$s",
"PluginWebsite": "プラグインのウェブサイト",
"Screenshots": "スクリーンショット",
"SortByAlpha": "アルファ",
@@ -56,10 +76,15 @@
"Status": "状態",
"StepDownloadingPluginFromMarketplace": "マーケットプレイスからプラグインをダウンロード",
"StepDownloadingThemeFromMarketplace": "マーケットプレイスからテーマをダウンロード",
+ "StepPluginSuccessfullyInstalled": "プラグイン %1$s %2$s のインストールに成功しました。",
+ "StepPluginSuccessfullyUpdated": "プラグイン %1$s %2$s のアップデートに成功しました。",
"StepReplaceExistingPlugin": "既存のプラグインを置き換える",
"StepReplaceExistingTheme": "既存のテーマを置き換える",
+ "StepThemeSuccessfullyInstalled": "テーマ %1$s %2$s のインストールに成功しました。",
+ "StepThemeSuccessfullyUpdated": "テーマ %1$s %2$s のアップデートに成功しました。",
"StepUnzippingPlugin": "プラグインを解凍",
"StepUnzippingTheme": "テーマを解凍",
+ "SuccessfullyActicated": "<strong> %s <\/strong> の有効化に成功しました。",
"Support": "サポート",
"TeaserExtendPiwik": "Piwik のプラグインとテーマを拡張",
"TeaserExtendPiwikByPlugin": "新しいプラグインをインストールして Piwik を拡張",
@@ -69,7 +94,9 @@
"Themes": "テーマ",
"ThemesDescription": "テーマは Piwik ユーザインターフェイスの外観を変更するだけでなく、解析レポートを楽しむ新しいビジュアルを備えています",
"ThemesManagement": "テーマの管理",
+ "UninstallConfirm": "プラグイン %s をアンインストールしようとしています。実行されると、プラグインは完全にプラットフォームから削除され、回復できなくなります。本当にアンインストールを実行してもよろしいですか?",
"Updated": "更新済",
+ "UpdatingPlugin": "%s のアップデート",
"UploadZipFile": "ZIPファイルをアップロード",
"Version": "バージョン",
"ViewRepositoryChangelog": "変更内容を表示",
diff --git a/plugins/CoreUpdater/lang/fa.json b/plugins/CoreUpdater/lang/fa.json
index fa35c9e499..7d78145a07 100644
--- a/plugins/CoreUpdater/lang/fa.json
+++ b/plugins/CoreUpdater/lang/fa.json
@@ -25,6 +25,9 @@
"MajorUpdateWarning2": "توصیه ای که در ادامه می آید به طور ویژه برای نصب های بزرگ مهم می باشد.",
"NoteForLargePiwikInstances": "نکات مهم برای نصب های بزرگ پیویک",
"NoteItIsExpectedThatQueriesFail": "توجه: اگر شما این پرس و جو ها را دستی انجام داده اید , انتظار می رود که بعضی از آنها به شکست بیانجامد. در این مورد , به سادگی از خطاها رد شوید و بعدی را اجرا کنید.",
+ "NotificationClickToUpdatePlugins": "برای بروزرسانی پلاگین ها اینجا کلیک کنید:",
+ "NotificationClickToUpdateThemes": "برای بروزرسانی قالب ها اینجا کلیک کنید:",
+ "NotificationSubjectAvailablePluginUpdate": "بروزرسانی های موجود برای پلاگین های پیویک",
"PiwikHasBeenSuccessfullyUpgraded": "پیویک با موفقیت به روزرسانی شد!",
"PiwikUpdatedSuccessfully": "پیویک با موفقیت به روز رسانی شد!",
"PiwikWillBeUpgradedFromVersionXToVersionY": "پایگاه داده ی پیویک از نسخه ی %1$s به نسخه ی %2$s ارتقا پیدا خواهد کرد.",
diff --git a/plugins/CoreUpdater/lang/ja.json b/plugins/CoreUpdater/lang/ja.json
index 8554962870..6e2aa2f923 100644
--- a/plugins/CoreUpdater/lang/ja.json
+++ b/plugins/CoreUpdater/lang/ja.json
@@ -4,6 +4,7 @@
"CreatingBackupOfConfigurationFile": "%s の設定ファイルのバックアップを作成中",
"CriticalErrorDuringTheUpgradeProcess": "アップグレード処理中の致命的なエラー:",
"DatabaseUpgradeRequired": "データベースのアップグレードが必要",
+ "DisablingIncompatiblePlugins": "互換性のないプラグインを無効にします: %s",
"DownloadingUpdateFromX": "%s からアップデートをダウンロード中",
"DownloadX": "ダウンロード %s",
"EmptyDatabaseError": "データベース %s は空です。 Piwik 設定ファイルを編集または削除する必要があります。",
@@ -18,19 +19,29 @@
"ExceptionArchiveEmpty": "空のアーカイブです。",
"ExceptionArchiveIncompatible": "互換性のないアーカイブ: %s",
"ExceptionArchiveIncomplete": "アーカイブが不完全です:いくつかのファイルが不足しています(%s など)。",
+ "FeedbackRequest": "あなたのアイデアや提案を、ここで Piwik チームにシェアしてください :",
"HelpMessageContent": "アップグレードの間、最も一般的なエラーを説明している %1$s Piwik FAQ %2$sをチェックしてください。%3$s システム管理者にお尋ねください - 彼らはたいていの場合、サーバや MySQL のセットアップに関係するエラーについて、あなたの手助けができるでしょう。",
"HelpMessageIntroductionWhenError": "上記はコアのエラーメッセージです。 原因の説明に役立つはずですが、さらなるヘルプが必要であればこちらをどうぞ:",
"HelpMessageIntroductionWhenWarning": "アップグレードは正常に完了しましたが、処理中に問題がありました。 詳細は上記の説明をお読みください。 さらなるヘルプ:",
+ "HighTrafficPiwikServerEnableMaintenance": "高トラフィックの Piwik サーバーを管理する場合、 %smomentarily disable visitor Tracking and put the Piwik User Interface in maintenance mode%s をお勧めします。",
+ "IncompatbilePluginsWillBeDisabledInfo": "注 : 一部のプラグインは、Piwik %s に互換性がありません。アップグレード時に、これらのプラグインは無効になります。",
"InstallingTheLatestVersion": "最新バージョンをインストール中",
"MajorUpdateWarning1": "これは最新版へのアップデートです!通常よりも時間がかかります",
+ "MajorUpdateWarning2": "以下のアドバイスは、特に大規模なインストールの際、重要です。",
"NoteForLargePiwikInstances": "Piwik のデータベースが大きい場合の重要注意",
"NoteItIsExpectedThatQueriesFail": "注意: これらのクエリーを手作業で実行する場合、クエリーのいくつかは失敗することが予想されます。 その場合は単にエラーを無視し、リスト内の次のクエリーを実行してください。",
+ "NotificationClickToUpdatePlugins": "お使いのプラグインを今すぐアップデートするにはここをクリック:",
+ "NotificationClickToUpdateThemes": "お使いのテーマを今すぐアップデートするにはここをクリック:",
+ "NotificationSubjectAvailableCoreUpdate": "新しい Piwik %s が利用可能です。",
+ "NotificationSubjectAvailablePluginUpdate": "お使いの Piwik プラグインのアップデートが可能です。",
"PiwikHasBeenSuccessfullyUpgraded": "Piwik は正常にアップグレードされました!",
"PiwikUpdatedSuccessfully": "Piwik は正常にアップデートされました!",
"PiwikWillBeUpgradedFromVersionXToVersionY": "Piwik データベースが %1$s から新バージョン %2$s にアップグレードされます。",
"PluginDescription": "Piwik アップデートメカニズム",
"ReadyToGo": "実行してもよろしいですか?",
+ "TheFollowingDimensionsWillBeUpgradedX": "以下の範囲をアップデートします: %s",
"TheFollowingPluginsWillBeUpgradedX": "次のプラグインはアップグレードされます: %s",
+ "ThereIsNewPluginVersionAvailableForUpdate": "お使いのいくつかのプラグインは、マーケットプレイス上でアップデートされています:",
"ThereIsNewVersionAvailableForUpdate": "アップデート可能な Piwik の新バージョンがあります。",
"TheUpgradeProcessMayFailExecuteCommand": "Piwik のデータベースが大きい場合、ブラウザでのアップデートの実行には長い時間がかかる場合があります。 このような場合、コマンドラインからアップデートを実行することができます: %s",
"TheUpgradeProcessMayTakeAWhilePleaseBePatient": "アップグレード処理には時間がかかる場合がありますが、しばらくお待ちください。",
diff --git a/plugins/Events/lang/fa.json b/plugins/Events/lang/fa.json
index a71de29afd..24c823ac96 100644
--- a/plugins/Events/lang/fa.json
+++ b/plugins/Events/lang/fa.json
@@ -1,10 +1,13 @@
{
"Events": {
+ "AvgValue": "میانگین",
"Event": "رویداد",
"EventAction": "اقدامات رویداد",
"EventCategory": "دسته رویداد",
"EventName": "نام رویداد",
"Events": "رویداد ها",
- "EventValue": "ارزش رویداد"
+ "EventValue": "ارزش رویداد",
+ "MaxValue": "بیشترین",
+ "MinValue": "کمترین"
}
} \ No newline at end of file
diff --git a/plugins/Events/lang/ru.json b/plugins/Events/lang/ru.json
index c0dac419b0..61d63e59c4 100644
--- a/plugins/Events/lang/ru.json
+++ b/plugins/Events/lang/ru.json
@@ -1,5 +1,6 @@
{
"Events": {
+ "Event": "Событие",
"MaxValue": "Максимальное значение",
"MaxValueDocumentation": "Максимальное значения для этого события",
"MinValue": "Минимальное значение",
diff --git a/plugins/ExamplePlugin/Widgets.php b/plugins/ExamplePlugin/Widgets.php
index 2d0e607fa8..82a4446c3f 100644
--- a/plugins/ExamplePlugin/Widgets.php
+++ b/plugins/ExamplePlugin/Widgets.php
@@ -9,6 +9,7 @@
namespace Piwik\Plugins\ExamplePlugin;
use Piwik\View;
+use Piwik\WidgetsList;
/**
* This class allows you to add your own widgets to the Piwik platform. In case you want to remove widgets from another
@@ -26,7 +27,7 @@ class Widgets extends \Piwik\Plugin\Widgets
protected $category = 'Example Category';
/**
- * Here you can add one or multiple widgets. You can add a widget by calling the method "addWidget" and pass the
+ * Here you can add one or multiple widgets. You can add a widget by calling the method "addWidget()" and pass the
* name of the widget as well as a method name that should be called to render the widget. The method can be
* defined either directly here in this widget class or in the controller in case you want to reuse the same action
* for instance in the menu etc.
@@ -53,4 +54,14 @@ class Widgets extends \Piwik\Plugin\Widgets
return 'My Widget Text';
}
+ /**
+ * Here you can remove any widgets defined by any plugin.
+ *
+ * @param WidgetsList $widgetsList
+ */
+ public function configureWidgetsList(WidgetsList $widgetsList)
+ {
+ // $widgetsList->remove('NameOfWidgetCategory'); // will remove all widgets having this category
+ // $widgetsList->remove('NameOfWidgetCategory', 'Widget name'); // will only remove a specific widget
+ }
}
diff --git a/plugins/ExamplePlugin/tests/travis/after_script.after.yml b/plugins/ExamplePlugin/tests/travis/after_script.after.yml
new file mode 100644
index 0000000000..09767fa550
--- /dev/null
+++ b/plugins/ExamplePlugin/tests/travis/after_script.after.yml
@@ -0,0 +1 @@
+- after_script hook line 2 \ No newline at end of file
diff --git a/plugins/ExamplePlugin/tests/travis/after_script.before.yml b/plugins/ExamplePlugin/tests/travis/after_script.before.yml
new file mode 100644
index 0000000000..3db8269eaa
--- /dev/null
+++ b/plugins/ExamplePlugin/tests/travis/after_script.before.yml
@@ -0,0 +1 @@
+- after_script hook line 1
diff --git a/plugins/ExamplePlugin/tests/travis/after_success.after.yml b/plugins/ExamplePlugin/tests/travis/after_success.after.yml
new file mode 100644
index 0000000000..dae338eac0
--- /dev/null
+++ b/plugins/ExamplePlugin/tests/travis/after_success.after.yml
@@ -0,0 +1 @@
+- after_success hook line 2 \ No newline at end of file
diff --git a/plugins/ExamplePlugin/tests/travis/after_success.before.yml b/plugins/ExamplePlugin/tests/travis/after_success.before.yml
new file mode 100644
index 0000000000..09d47bfbe1
--- /dev/null
+++ b/plugins/ExamplePlugin/tests/travis/after_success.before.yml
@@ -0,0 +1 @@
+- after_success hook line 1
diff --git a/plugins/ExamplePlugin/tests/travis/before_install.after.yml b/plugins/ExamplePlugin/tests/travis/before_install.after.yml
new file mode 100644
index 0000000000..c6c76728ce
--- /dev/null
+++ b/plugins/ExamplePlugin/tests/travis/before_install.after.yml
@@ -0,0 +1,2 @@
+ - before_install hook line 2
+ \ No newline at end of file
diff --git a/plugins/ExamplePlugin/tests/travis/before_install.before.yml b/plugins/ExamplePlugin/tests/travis/before_install.before.yml
new file mode 100644
index 0000000000..697f27bf09
--- /dev/null
+++ b/plugins/ExamplePlugin/tests/travis/before_install.before.yml
@@ -0,0 +1 @@
+- before_install hook line 1
diff --git a/plugins/ExamplePlugin/tests/travis/before_script.after.yml b/plugins/ExamplePlugin/tests/travis/before_script.after.yml
new file mode 100644
index 0000000000..9d491a2919
--- /dev/null
+++ b/plugins/ExamplePlugin/tests/travis/before_script.after.yml
@@ -0,0 +1 @@
+- before_script hook line 2 \ No newline at end of file
diff --git a/plugins/ExamplePlugin/tests/travis/before_script.before.yml b/plugins/ExamplePlugin/tests/travis/before_script.before.yml
new file mode 100644
index 0000000000..c55c1627e6
--- /dev/null
+++ b/plugins/ExamplePlugin/tests/travis/before_script.before.yml
@@ -0,0 +1,2 @@
+- before_script hook line 1
+ - before_script another hook \ No newline at end of file
diff --git a/plugins/ExamplePlugin/tests/travis/install.after.yml b/plugins/ExamplePlugin/tests/travis/install.after.yml
new file mode 100644
index 0000000000..337549c49d
--- /dev/null
+++ b/plugins/ExamplePlugin/tests/travis/install.after.yml
@@ -0,0 +1 @@
+- install hook line 2
diff --git a/plugins/ExamplePlugin/tests/travis/install.before.yml b/plugins/ExamplePlugin/tests/travis/install.before.yml
new file mode 100644
index 0000000000..79790493fa
--- /dev/null
+++ b/plugins/ExamplePlugin/tests/travis/install.before.yml
@@ -0,0 +1 @@
+- install hook line 1 \ No newline at end of file
diff --git a/plugins/Goals/lang/cs.json b/plugins/Goals/lang/cs.json
index a712c6c39a..71ba5995ba 100644
--- a/plugins/Goals/lang/cs.json
+++ b/plugins/Goals/lang/cs.json
@@ -60,6 +60,7 @@
"GoalX": "Cíl: %s",
"HelpOneConversionPerVisit": "Pokud byla stránka odpovídající cíli při návštěvě obnovena nebo zobrazena vícekrát, bude cíl započítán pouze jednou a to při prvním zobrazení.",
"IsExactly": "je přesně %s",
+ "LearnMoreAboutGoalTrackingDocumentation": "Více o %s sledování cílů %s se dozvíte v uživatelské dokumentaci Piwiku.",
"LeftInCart": "%s Zbylo v košíku",
"Manually": "ručně",
"ManuallyTriggeredUsingJavascriptFunction": "Cíl je ručně zaznamenáván pomocí JavaScriptového API trackGoal()",
@@ -81,6 +82,7 @@
"Products": "Produktů",
"ProductSKU": "SKU produktu",
"ReturningVisitorsConversionRateIs": "Poměr konverze navracejících se uživatelů je %s",
+ "SendEvent": "Poslat událost",
"SingleGoalOverviewDocumentation": "Toto je přehled konverzí jednoho cíle. %s Linky lze zvětšit kliknutím na ně.",
"UpdateGoal": "Aktualizovat cíl",
"URL": "URL",
diff --git a/plugins/Insights/lang/fa.json b/plugins/Insights/lang/fa.json
new file mode 100644
index 0000000000..cf80b66dec
--- /dev/null
+++ b/plugins/Insights/lang/fa.json
@@ -0,0 +1,13 @@
+{
+ "Insights": {
+ "DayComparedToPreviousDay": "روز گذشته",
+ "DayComparedToPreviousWeek": "همان روز در هفته گذشته",
+ "DayComparedToPreviousYear": "همان روز در سال گذشته",
+ "Filter": "فیلتر",
+ "FilterOnlyNew": "فقط جدید",
+ "MonthComparedToPreviousMonth": "ماه گذشته",
+ "MonthComparedToPreviousYear": "همان ماه در سال گذشته",
+ "WeekComparedToPreviousWeek": "هفته گذشته",
+ "YearComparedToPreviousYear": "سال گذشته"
+ }
+} \ No newline at end of file
diff --git a/plugins/Installation/lang/fa.json b/plugins/Installation/lang/fa.json
index 56ea3eb2d2..0d0b538952 100644
--- a/plugins/Installation/lang/fa.json
+++ b/plugins/Installation/lang/fa.json
@@ -1,5 +1,6 @@
{
"Installation": {
+ "CannotConnectToDb": "نمیتوان با پایگاه داده ارتباط برقرار کرد",
"CollaborativeProject": "پیویک یک پروژه گروهی است که با عشق و علاقه توسط افرادی از سراسر دنیا ساخته شده است.",
"ConfigurationHelp": "فایل پیکربندی Piwik شما به نظر می رسد بد باشد. شما هم می توانید پیکربندی \/ config.ini.php و حذف از سر نصب و راه اندازی و یا اصلاح تنظیمات اتصال پایگاه داده.",
"ConfirmDeleteExistingTables": "آیا شما مطمئن هستید که می خواهید این جدول ها را : %s از پایگاه داده تان حذف کنید؟ هشدار : داده های این جدول ها قابل بازیابی نخواهد بود!",
@@ -29,6 +30,7 @@
"NfsFilesystemWarningSuffixAdmin": "این به آن معنا است که پیویک بسیار کند خواهد بود هنگامی که از فایل مبتنی بر نشست ها(session) استفاده می کند.",
"NfsFilesystemWarningSuffixInstall": "استفاده از نشست های مبتنی بر فایل با NFS بسیار کند است، بنابراین پیویک نشست های مبتنی بر پایگاه داده را به کار خواهد برد. اگر شما کاربران همزمان بسیاری دارید ، احتمالا نیاز به افزایش تعداد اتصالات کاربر(Client Connection) به پایگاه داده دارید.",
"NoConfigFound": "Piwik فایل پیکربندی را می توان یافت نمی شود و شما در حال تلاش برای دسترسی به یک صفحه Piwik. <br\/><B> »می تواند href='index.php'> <a نصب Piwik در حال حاضر <\/a> <\/B> <br \/> <small> اگر شما نصب Piwik قبل و برخی از جداول در پایگاه داده خود را داشته باشند، نگران نباشید، شما می توانید جداول و استفاده مجدد از داده های موجود خود را حفظ کنید <\/small>",
+ "NotSupported": "پشتیبانی نمیشود",
"Optional": "اختیاری",
"Password": "کلمه عبور",
"PasswordDoNotMatch": "کلمه عبور یکی نیست",
diff --git a/plugins/LanguagesManager/lang/fa.json b/plugins/LanguagesManager/lang/fa.json
index c868f3b1a3..b8dc955a53 100644
--- a/plugins/LanguagesManager/lang/fa.json
+++ b/plugins/LanguagesManager/lang/fa.json
@@ -1,6 +1,7 @@
{
"LanguagesManager": {
"AboutPiwikTranslations": "درباره ترجمه های پیویک",
- "PluginDescription": "این پلاگین یک لیست از زبانهای در دسترس برای رابط Piwik را نمایش می دهد. زبان انتخاب شده در تنظیمات برای هر کاربر ذخیره خواهد شد."
+ "PluginDescription": "این پلاگین یک لیست از زبانهای در دسترس برای رابط Piwik را نمایش می دهد. زبان انتخاب شده در تنظیمات برای هر کاربر ذخیره خواهد شد.",
+ "TranslationSearch": "جستجوی ترجمه"
}
} \ No newline at end of file
diff --git a/plugins/LeftMenu/lang/tr.json b/plugins/LeftMenu/lang/tr.json
new file mode 100644
index 0000000000..ab8dbb51d8
--- /dev/null
+++ b/plugins/LeftMenu/lang/tr.json
@@ -0,0 +1,5 @@
+{
+ "LeftMenu": {
+ "UserSettingTitle": "Sol raporlama menüsünü etkinleştir"
+ }
+} \ No newline at end of file
diff --git a/plugins/Live/lang/tr.json b/plugins/Live/lang/tr.json
index 6ea54bcf09..6b6a0328ce 100644
--- a/plugins/Live/lang/tr.json
+++ b/plugins/Live/lang/tr.json
@@ -1,10 +1,24 @@
{
"Live": {
+ "ConvertedNGoals": "Dönüştürülen %s Hedef",
+ "FirstVisit": "İlk ziyaret",
"GoalType": "Tür",
+ "HideMap": "haritayı gizle",
+ "LastHours": "Son %s saat",
"LastMinutes": "Son %s dakika",
+ "LastVisit": "Son ziyaret",
"LinkVisitorLog": "Ayrıntılı ziyaretçi kayitlari",
+ "LoadMoreVisits": "Daha fazla ziyaretçi yükle",
+ "NbVisitor": "1 ziyaretçi",
+ "NbVisitors": "%s ziyaretçi",
+ "NextVisitor": "Sonraki ziyaretçi",
+ "NoMoreVisits": "Bu ziyaretçi için daha fazla ziyaret bilgisi yok.",
"PluginDescription": "Ziyaretçilerinizi gözleyin, canlı, gerçek zamanlı!",
+ "PreviousVisitor": "Önceki ziyaretçi",
+ "RealTimeVisitorCount": "Gerçek Zamanlı Ziyaretçi Sayacı",
"Referrer_URL": "Yönlendirme Siteleri",
+ "ViewVisitorProfile": "Ziyaretçi profiline bak",
+ "VisitedPages": "Ziyaret edilmiş sayfalar",
"VisitorLog": "Ziyaretçi kayıtları",
"VisitorsInRealTime": "Gerçek Zamanlı Ziyaretçiler"
}
diff --git a/plugins/UserSettings/lang/en.json b/plugins/UserSettings/lang/en.json
index fa87ec92e9..791f7e8f51 100644
--- a/plugins/UserSettings/lang/en.json
+++ b/plugins/UserSettings/lang/en.json
@@ -125,7 +125,7 @@
"Language_mt": "Maltese",
"Language_my": "Burmese",
"Language_na": "Nauru",
- "Language_nb": "Norwegian Bokma\u00b0l",
+ "Language_nb": "Norwegian Bokm\u00e5l",
"Language_nd": "North Ndebele",
"Language_ne": "Nepali",
"Language_ng": "Ndonga",
diff --git a/plugins/UsersManager/lang/fa.json b/plugins/UsersManager/lang/fa.json
index cd5cd32e9b..6761bde40e 100644
--- a/plugins/UsersManager/lang/fa.json
+++ b/plugins/UsersManager/lang/fa.json
@@ -27,6 +27,7 @@
"ForAnonymousUsersReportDateToLoadByDefault": "برای کاربران ناشناس، تاریخ گزارش به طور پیش فرض باز",
"IfYouWouldLikeToChangeThePasswordTypeANewOne": "اگر می خواهید از نوع رمز عبور را تغییر جدید است. در غیر این صورت این قسمت را خالی بگذارید.",
"InjectedHostCannotChangePwd": "شما هم اکنون در حال بازدید توسط یک میزبان ناشناخته هستید(%1$s). شما نمی توانید رمز عبورتان را تغییر دهید تا زمانی که این مشکل را حل نکرده اید.",
+ "LastSeen": "آخرین بازدید",
"MainDescription": "تصمیم بگیرید که کاربران که دسترسی Piwik را روی وب سایت خود را دارند. شما همچنین می توانید مجوز در تمام وب سایت در یک بار تنظیم شده است.",
"ManageAccess": "مدیریت دسترسی",
"MenuAnonymousUserSettings": "تنظیمات کاربران ناشناس",
diff --git a/plugins/ZenMode/lang/fa.json b/plugins/ZenMode/lang/fa.json
new file mode 100644
index 0000000000..d221d07b56
--- /dev/null
+++ b/plugins/ZenMode/lang/fa.json
@@ -0,0 +1,5 @@
+{
+ "ZenMode": {
+ "SearchForAnything": "جستجوی همه"
+ }
+} \ No newline at end of file
diff --git a/plugins/ZenMode/lang/ru.json b/plugins/ZenMode/lang/ru.json
new file mode 100644
index 0000000000..e941f5c672
--- /dev/null
+++ b/plugins/ZenMode/lang/ru.json
@@ -0,0 +1,5 @@
+{
+ "ZenMode": {
+ "Activated": "Режим Дзен активирован"
+ }
+} \ No newline at end of file
diff --git a/tests/PHPUnit/Core/DateTest.php b/tests/PHPUnit/Core/DateTest.php
index 2193d10674..84041f53fd 100644
--- a/tests/PHPUnit/Core/DateTest.php
+++ b/tests/PHPUnit/Core/DateTest.php
@@ -8,6 +8,9 @@
use Piwik\Date;
use Piwik\SettingsServer;
+/**
+ * @group Core_DateTest
+ */
class DateTest extends PHPUnit_Framework_TestCase
{
/**
@@ -241,6 +244,28 @@ class DateTest extends PHPUnit_Framework_TestCase
/**
* @group Core
*/
+ public function testAddPeriodMonthRespectsMaxDaysInMonth()
+ {
+ $date = Date::factory('2014-07-31');
+ $dateExpected = Date::factory('2014-06-30');
+ $dateActual = $date->subPeriod(1, 'month');
+ $this->assertEquals($dateExpected->toString(), $dateActual->toString());
+
+ // test leap year
+ $date = Date::factory('2000-03-31');
+ $dateExpected = Date::factory('2000-02-29');
+ $dateActual = $date->subPeriod(1, 'month');
+ $this->assertEquals($dateExpected->toString(), $dateActual->toString());
+
+ $date = Date::factory('2000-01-31');
+ $dateExpected = Date::factory('2000-02-29');
+ $dateActual = $date->addPeriod(1, 'month');
+ $this->assertEquals($dateExpected->toString(), $dateActual->toString());
+ }
+
+ /**
+ * @group Core
+ */
public function testIsLeapYear()
{
$date = Date::factory('2011-03-01');
@@ -260,8 +285,9 @@ class DateTest extends PHPUnit_Framework_TestCase
$date = Date::factory('2013-12-31');
$this->assertFalse($date->isLeapYear());
- $date = Date::factory('2052-01-01'); // dates after 19/01/2038 03:14:07 fail on 32-bit arch
- $this->assertTrue($date->isLeapYear());
-
+ if (PHP_INT_SIZE > 4) { // dates after 19/01/2038 03:14:07 fail on 32-bit arch
+ $date = Date::factory('2052-01-01');
+ $this->assertTrue($date->isLeapYear());
+ }
}
}
diff --git a/tests/PHPUnit/Core/Period/RangeTest.php b/tests/PHPUnit/Core/Period/RangeTest.php
index 380c69383d..b2114a4372 100644
--- a/tests/PHPUnit/Core/Period/RangeTest.php
+++ b/tests/PHPUnit/Core/Period/RangeTest.php
@@ -12,6 +12,9 @@ use Piwik\Period\Week;
use Piwik\Period\Year;
use Piwik\Translate;
+/**
+ * @group Core_Period_RangeTest
+ */
class Period_RangeTest extends PHPUnit_Framework_TestCase
{
// test range 1
diff --git a/tests/PHPUnit/Core/ReleaseCheckListTest.php b/tests/PHPUnit/Core/ReleaseCheckListTest.php
index d55b9453a7..ba70ff9410 100644
--- a/tests/PHPUnit/Core/ReleaseCheckListTest.php
+++ b/tests/PHPUnit/Core/ReleaseCheckListTest.php
@@ -77,7 +77,7 @@ class ReleaseCheckListTest extends PHPUnit_Framework_TestCase
$this->_checkEqual(array('Debug' => 'always_archive_data_day'), '0');
$this->_checkEqual(array('Debug' => 'always_archive_data_period'), '0');
$this->_checkEqual(array('Debug' => 'enable_sql_profiler'), '0');
- $this->_checkEqual(array('General' => 'time_before_today_archive_considered_outdated'), '10');
+ $this->_checkEqual(array('General' => 'time_before_today_archive_considered_outdated'), '150');
$this->_checkEqual(array('General' => 'enable_browser_archiving_triggering'), '1');
$this->_checkEqual(array('General' => 'default_language'), 'en');
$this->_checkEqual(array('Tracker' => 'record_statistics'), '1');
diff --git a/tests/PHPUnit/Integration/Core/LogTest.php b/tests/PHPUnit/Integration/Core/LogTest.php
index a2ef5b5502..f7d35e451b 100644
--- a/tests/PHPUnit/Integration/Core/LogTest.php
+++ b/tests/PHPUnit/Integration/Core/LogTest.php
@@ -19,6 +19,7 @@ require_once PIWIK_INCLUDE_PATH . '/tests/resources/TestPluginLogClass.php';
* Class Core_LogTest
*
* @group Core
+ * @group Core_LogTest
*/
class Core_LogTest extends DatabaseTestCase
{
@@ -31,14 +32,13 @@ class Core_LogTest extends DatabaseTestCase
<br />
--&gt; To temporarily debug this error further, set const PIWIK_PRINT_ERROR_BACKTRACE=true; in index.php',
'file' => '[Core_LogTest] LogTest.php(161): dummy error message
-dummy backtrace',
+ dummy backtrace',
'database' => '[Core_LogTest] LogTest.php(161): dummy error message
dummy backtrace'
);
public static $expectedErrorOutput = array(
- 'screen' => '
-<div style=\'word-wrap: break-word; border: 3px solid red; padding:4px; width:70%; background-color:#FFFF96;\'>
+ 'screen' => '<div style=\'word-wrap: break-word; border: 3px solid red; padding:4px; width:70%; background-color:#FFFF96;\'>
<strong>There is an error. Please report the message (Piwik 2.0)
and full backtrace in the <a href=\'?module=Proxy&action=redirect&url=http://forum.piwik.org\' target=\'_blank\'>Piwik forums</a> (please do a Search first as it might have been reported already!).<br /><br/>
Unknown error (102):</strong> <em>dummy error string</em> in <strong>dummyerrorfile.php</strong> on line <strong>145</strong>
@@ -46,7 +46,7 @@ dummy backtrace'
dummy backtrace</div><br />
</pre></div><br />',
'file' => '[Core_LogTest] dummyerrorfile.php(145): Unknown error (102) - dummy error string
-dummy backtrace',
+ dummy backtrace',
'database' => '[Core_LogTest] dummyerrorfile.php(145): Unknown error (102) - dummy error string
dummy backtrace'
);
@@ -202,6 +202,22 @@ dummy backtrace'
$this->checkNoMessagesLogged($backend);
}
+ /**
+ * @group Core
+ * @dataProvider getBackendsToTest
+ */
+ public function testLogMessagesAreTrimmed($backend)
+ {
+ Config::getInstance()->log['log_writers'] = array($backend);
+
+ ob_start();
+ TestLoggingUtility::doLog(" \n ".self::TESTMESSAGE."\n\n\n \n");
+ $this->screenOutput = ob_get_contents();
+ ob_end_clean();
+
+ $this->checkBackend($backend, self::TESTMESSAGE, $formatMessage = true, $tag = 'TestPlugin');
+ }
+
private function checkBackend($backend, $expectedMessage, $formatMessage = false, $tag = false)
{
if ($formatMessage) {