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:
authordiosmosis <benaka@piwik.pro>2015-03-16 19:57:39 +0300
committerdiosmosis <benaka@piwik.pro>2015-03-16 19:57:39 +0300
commit8976cfd575ce5673b0c52889ae43315006d01f9f (patch)
tree91e1110b99ed0c063ed99b658d9f4ecf7eca1b8b /plugins
parent8d1065144b6c309adb8067e8202a5ad41371abd7 (diff)
parent47a61c1ad87c9208db5a673346bb762cec7bf32f (diff)
Merge branch 'master' into 7276_update_command_progress
Conflicts: plugins/CoreUpdater/Controller.php
Diffstat (limited to 'plugins')
-rw-r--r--plugins/CoreConsole/Commands/DevelopmentSyncUITestScreenshots.php188
-rw-r--r--plugins/CoreHome/Widgets.php17
-rw-r--r--plugins/CoreUpdater/ArchiveDownloadException.php22
-rw-r--r--plugins/CoreUpdater/Controller.php219
-rw-r--r--plugins/CoreUpdater/Test/Fixtures/DbUpdaterTestFixture.php23
-rw-r--r--plugins/CoreUpdater/Test/Fixtures/FailUpdateHttpsFixture.php24
-rw-r--r--plugins/CoreUpdater/Test/Integration/UpdateCommunicationTest.php (renamed from plugins/CoreUpdater/tests/Integration/UpdateCommunicationTest.php)2
-rw-r--r--plugins/CoreUpdater/Test/Mock/UpdaterMock.php54
-rw-r--r--plugins/CoreUpdater/Test/Unit/ModelTest.php (renamed from plugins/CoreUpdater/tests/Unit/ModelTest.php)3
-rw-r--r--plugins/CoreUpdater/Updater.php272
-rw-r--r--plugins/CoreUpdater/UpdaterException.php37
-rw-r--r--plugins/CoreUpdater/config/config.php6
-rw-r--r--plugins/CoreUpdater/lang/en.json4
-rw-r--r--plugins/CoreUpdater/templates/newVersionAvailable.twig2
-rw-r--r--plugins/CoreUpdater/templates/oneClickResults.twig30
-rw-r--r--plugins/Goals/templates/_addEditGoal.twig27
-rw-r--r--plugins/Login/Controller.php1
17 files changed, 683 insertions, 248 deletions
diff --git a/plugins/CoreConsole/Commands/DevelopmentSyncUITestScreenshots.php b/plugins/CoreConsole/Commands/DevelopmentSyncUITestScreenshots.php
index be1bedd05d..a8fa9a7a6c 100644
--- a/plugins/CoreConsole/Commands/DevelopmentSyncUITestScreenshots.php
+++ b/plugins/CoreConsole/Commands/DevelopmentSyncUITestScreenshots.php
@@ -14,9 +14,13 @@ use Piwik\Http;
use Piwik\Plugin\ConsoleCommand;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\Output;
use Symfony\Component\Console\Output\OutputInterface;
/**
+ * Tool for core developers to help making UI screenshot builds green.
+ *
*/
class DevelopmentSyncUITestScreenshots extends ConsoleCommand
{
@@ -29,40 +33,44 @@ class DevelopmentSyncUITestScreenshots extends ConsoleCommand
{
$this->setName('development:sync-ui-test-screenshots');
$this->setDescription('For Piwik core devs. Copies screenshots '
- . 'from travis artifacts to tests/UI/expected-ui-screenshots/');
+ . 'from travis artifacts to the tests/UI/expected-ui-screenshots/ folder');
$this->addArgument('buildnumber', InputArgument::REQUIRED, 'Travis build number you want to sync.');
$this->addArgument('screenshotsRegex', InputArgument::OPTIONAL,
'A regex to use when selecting screenshots to copy. If not supplied all screenshots are copied.', '.*');
+ $this->addOption('plugin', 'p', InputOption::VALUE_OPTIONAL, 'Plugin name you want to sync screenshots for.');
+ $this->addOption('http-user', '', InputOption::VALUE_OPTIONAL, 'the HTTP AUTH username (for premium plugins where artifacts are protected)');
+ $this->addOption('http-password', '', InputOption::VALUE_OPTIONAL, 'the HTTP AUTH password (for premium plugins where artifacts are protected)');
}
protected function execute(InputInterface $input, OutputInterface $output)
{
$buildNumber = $input->getArgument('buildnumber');
- $screenshotsRegex = $input->getArgument('screenshotsRegex');
-
if (empty($buildNumber)) {
throw new \InvalidArgumentException('Missing build number.');
}
- $urlBase = sprintf('http://builds-artifacts.piwik.org/ui-tests.master/%s', $buildNumber);
- $diffviewer = Http::sendHttpRequest($urlBase . "/screenshot-diffs/diffviewer.html", $timeout = 60);
- $diffviewer = str_replace('&', '&amp;', $diffviewer);
+ $screenshotsRegex = $input->getArgument('screenshotsRegex');
+
+ $plugin = $input->getOption('plugin');
+
+ $httpUser = $input->getOption('http-user');
+ $httpPassword = $input->getOption('http-password');
+
+ $urlBase = $this->getUrlBase($plugin, $buildNumber);
+ $diffviewer = $this->getDiffviewerContent($output, $urlBase, $httpUser, $httpPassword);
+
+ if(empty($diffviewer)) {
+ throw new \Exception("Screenshot tests artifacts were not found for this build.");
+ }
+
$dom = new \DOMDocument();
$dom->loadHTML($diffviewer);
foreach ($dom->getElementsByTagName("tr") as $row) {
$columns = $row->getElementsByTagName("td");
- $nameColumn = $columns->item(0);
$processedColumn = $columns->item(3);
- $testPlugin = null;
- if ($nameColumn
- && preg_match("/\(for ([a-zA-Z_]+) plugin\)/", $dom->saveXml($nameColumn), $matches)
- ) {
- $testPlugin = $matches[1];
- }
-
$file = null;
if ($processedColumn
&& preg_match("/href=\".*\/(.*)\"/", $dom->saveXml($processedColumn), $matches)
@@ -73,42 +81,152 @@ class DevelopmentSyncUITestScreenshots extends ConsoleCommand
if ($file !== null
&& preg_match("/" . $screenshotsRegex . "/", $file)
) {
- if ($testPlugin == null) {
- $downloadTo = "tests/UI/expected-ui-screenshots/$file";
- } else {
- $downloadTo = "plugins/$testPlugin/tests/UI/expected-ui-screenshots/$file";
- }
-
- $output->write("<info>Downloading $file to $downloadTo...</info>\n");
- Http::sendHttpRequest("$urlBase/processed-ui-screenshots/$file", $timeout = 60, $userAgent = null,
- PIWIK_DOCUMENT_ROOT . "/" . $downloadTo);
+ $this->downloadProcessedScreenshot($output, $urlBase, $file, $plugin, $httpUser, $httpPassword);
}
}
- $this->displayGitInstructions($output);
+ $this->displayGitInstructions($output, $plugin);
}
- /**
- * @param OutputInterface $output
- */
- protected function displayGitInstructions(OutputInterface $output)
+ protected function displayGitInstructions(OutputInterface $output, $plugin)
{
$output->writeln('');
$output->writeln('--------------');
$output->writeln('');
$output->writeln("If all downloaded screenshots are valid you may push them with these commands:");
- $output->writeln('');
- $commands = "cd tests/UI/expected-ui-screenshots
+ $downloadToPath = $this->getDownloadToPath($plugin);
+ $commands = "
+cd $downloadToPath
git pull
git add .
-git commit -m '' # WRITE A COMMIT MESSAGE
-git push
+git commit -m '' # Write a good commit message, eg. 'Fixed UI test failure caused by change introduced in <core or plugin commit> which caused failure by <explanation of failure>'
+git push";
+
+ if(empty($plugin)) {
+ $commands .= "
cd ..
git pull
-git add expected-ui-screenshots
-git commit -m '' #WRITE A COMMIT MESSAGE
-git push";
+git add expected-ui-screenshots/
+git commit -m '' # Copy paste the good commit message
+git push
+cd ../../\n\n";
+ } else {
+ $commands .= "
+cd ../../../../../\n\n";
+ }
$output->writeln($commands);
}
+
+ protected function getUrlBase($plugin, $buildNumber)
+ {
+ if ($plugin) {
+ return sprintf('http://builds-artifacts.piwik.org/ui-tests.master.%s/%s', $plugin, $buildNumber);
+ }
+ return sprintf('http://builds-artifacts.piwik.org/ui-tests.master/%s', $buildNumber);
+ }
+
+ protected function getDownloadToPath($plugin)
+ {
+ if (empty($plugin)) {
+ return PIWIK_DOCUMENT_ROOT . "/tests/UI/expected-ui-screenshots/";
+ }
+
+ $downloadTo = PIWIK_DOCUMENT_ROOT . "/plugins/$plugin/tests/UI/expected-ui-screenshots/";
+ if(is_dir($downloadTo)) {
+ return $downloadTo;
+ }
+
+ // Maybe the plugin is using folder "Test/" instead of "tests/"
+ $downloadTo = str_replace("tests/", "Test/", $downloadTo);
+ if(is_dir($downloadTo)) {
+ return $downloadTo;
+ }
+ throw new \Exception("Download to path could not be found: $downloadTo");
+ }
+
+ protected function getDiffviewerContent(OutputInterface $output, $urlBase, $httpUser = false, $httpPassword = false)
+ {
+ $diffviewerUrl = $this->getDiffviewerUrl($urlBase);
+
+ try {
+ return $this->downloadDiffviewer($output, $diffviewerUrl);
+ } catch(\Exception $e) {
+
+ // Maybe this is a Premium Piwik PRO plugin...
+ return $this->getDiffviewContentForPrivatePlugin($output, $urlBase, $httpUser, $httpPassword);
+ }
+ }
+
+ protected function getDiffviewContentForPrivatePlugin(OutputInterface $output, $urlBase, $httpUser, $httpPassword)
+ {
+ if (empty($httpUser) || empty($httpPassword)) {
+ $output->writeln("<info>--http-user and --http-password was not specified, skip download of private plugins screenshots.</info>");
+ return;
+ }
+
+ // Attempt to download from protected/ artifacts...
+ $urlBase = str_replace("builds-artifacts.piwik.org/", "builds-artifacts.piwik.org/protected/", $urlBase);
+ $diffviewerUrl = $this->getDiffviewerUrl($urlBase);
+
+ return $this->downloadDiffviewer($output, $diffviewerUrl, $httpUser, $httpPassword);
+ }
+
+ /**
+ * @return string
+ */
+ protected function getDiffviewerUrl($urlBase)
+ {
+ return $urlBase . "/screenshot-diffs/diffviewer.html";
+ }
+
+ protected function downloadDiffviewer(OutputInterface $output, $urlDiffviewer, $httpUsername = false, $httpPassword = false)
+ {
+ $responseExtended = Http::sendHttpRequest(
+ $urlDiffviewer,
+ $timeout = 60,
+ $userAgent = null,
+ $destinationPath = null,
+ $followDepth = 0,
+ $acceptLanguage = false,
+ $byteRange = false,
+ $getExtendedInfo = true,
+ $httpMethod = 'GET',
+ $httpUsername,
+ $httpPassword
+ );
+ $httpStatus = $responseExtended['status'];
+ if ($httpStatus == '200') {
+ $output->writeln("Found diffviewer at: " . $urlDiffviewer);
+ $diffviewer = str_replace('&', '&amp;', $responseExtended['data']);
+ return $diffviewer;
+ }
+
+ if($httpStatus == '401') {
+ $output->writeln("<error>HTTP AUTH username and password are not valid.</error>");
+ }
+ throw new \Exception ("Failed downloading diffviewer from $urlDiffviewer - Got HTTP status " . $httpStatus);
+ }
+
+
+ protected function downloadProcessedScreenshot(OutputInterface $output, $urlBase, $file, $plugin, $httpUser, $httpPassword)
+ {
+ $downloadTo = $this->getDownloadToPath($plugin) . $file;
+
+ $output->write("<info>Downloading $file to $downloadTo...</info>\n");
+ $urlProcessedScreenshot = $urlBase . "/processed-ui-screenshots/$file";
+
+ Http::sendHttpRequest($urlProcessedScreenshot,
+ $timeout = 60,
+ $userAgent = null,
+ $downloadTo,
+ $followDepth = 0,
+ $acceptLanguage = false,
+ $byteRange = false,
+ $getExtendedInfo = true,
+ $httpMethod = 'GET',
+ $httpUser,
+ $httpPassword);
+ }
+
}
diff --git a/plugins/CoreHome/Widgets.php b/plugins/CoreHome/Widgets.php
index 68812f0749..17d888bd35 100644
--- a/plugins/CoreHome/Widgets.php
+++ b/plugins/CoreHome/Widgets.php
@@ -10,12 +10,23 @@ namespace Piwik\Plugins\CoreHome;
use Piwik\Common;
use Piwik\Piwik;
+use Piwik\Translation\Translator;
use Piwik\View;
class Widgets extends \Piwik\Plugin\Widgets
{
protected $category = 'Example Widgets';
+ /**
+ * @var Translator
+ */
+ private $translator;
+
+ public function __construct(Translator $translator)
+ {
+ $this->translator = $translator;
+ }
+
protected function init()
{
$this->addWidget('CoreHome_SupportPiwik', 'getDonateForm');
@@ -31,7 +42,7 @@ class Widgets extends \Piwik\Plugin\Widgets
if (Common::getRequestVar('widget', false)
&& Piwik::hasUserSuperUserAccess()) {
- $view->footerMessage = Piwik::translate('CoreHome_OnlyForSuperUserAccess');
+ $view->footerMessage = $this->translator->translate('CoreHome_OnlyForSuperUserAccess');
}
return $view->render();
@@ -43,8 +54,8 @@ class Widgets extends \Piwik\Plugin\Widgets
public function getPromoVideo()
{
$view = new View('@CoreHome/getPromoVideo');
- $view->shareText = Piwik::translate('CoreHome_SharePiwikShort');
- $view->shareTextLong = Piwik::translate('CoreHome_SharePiwikLong');
+ $view->shareText = $this->translator->translate('CoreHome_SharePiwikShort');
+ $view->shareTextLong = $this->translator->translate('CoreHome_SharePiwikLong');
$view->promoVideoUrl = 'https://www.youtube.com/watch?v=OslfF_EH81g';
return $view->render();
diff --git a/plugins/CoreUpdater/ArchiveDownloadException.php b/plugins/CoreUpdater/ArchiveDownloadException.php
new file mode 100644
index 0000000000..0b68f30c18
--- /dev/null
+++ b/plugins/CoreUpdater/ArchiveDownloadException.php
@@ -0,0 +1,22 @@
+<?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\CoreUpdater;
+
+use Exception;
+
+/**
+ * Error while downloading the archive.
+ */
+class ArchiveDownloadException extends UpdaterException
+{
+ public function __construct(Exception $exception)
+ {
+ parent::__construct($exception, array());
+ }
+}
diff --git a/plugins/CoreUpdater/Controller.php b/plugins/CoreUpdater/Controller.php
index 998ef3ece7..d15dc231e6 100644
--- a/plugins/CoreUpdater/Controller.php
+++ b/plugins/CoreUpdater/Controller.php
@@ -9,10 +9,8 @@
namespace Piwik\Plugins\CoreUpdater;
use Exception;
-use Piwik\ArchiveProcessor\Rules;
use Piwik\Common;
use Piwik\Config;
-use Piwik\Container\StaticContainer;
use Piwik\DbHelper;
use Piwik\Filechecks;
use Piwik\Filesystem;
@@ -24,51 +22,34 @@ use Piwik\Plugin;
use Piwik\Plugins\CorePluginsAdmin\Marketplace;
use Piwik\Plugins\LanguagesManager\LanguagesManager;
use Piwik\SettingsServer;
-use Piwik\Unzip;
-use Piwik\UpdateCheck;
-use Piwik\Updater;
+use Piwik\Updater as DbUpdater;
use Piwik\Version;
use Piwik\View\OneClickDone;
use Piwik\View;
-/**
- *
- */
class Controller extends \Piwik\Plugin\Controller
{
- const PATH_TO_EXTRACT_LATEST_VERSION = '/latest/';
- const LATEST_VERSION_URL = '://builds.piwik.org/piwik.zip';
- const LATEST_BETA_VERSION_URL = '://builds.piwik.org/piwik-%s.zip';
-
private $coreError = false;
private $warningMessages = array();
private $errorMessages = array();
private $deactivatedPlugins = array();
- private $pathPiwikZip = false;
- private $newVersion;
- protected static function getLatestZipUrl($newVersion)
- {
- if (@Config::getInstance()->Debug['allow_upgrades_to_beta']) {
- $url = sprintf(self::LATEST_BETA_VERSION_URL, $newVersion);
- } else {
- $url = self::LATEST_VERSION_URL;
- }
+ /**
+ * @var Updater
+ */
+ private $updater;
- if (self::isUpdatingOverHttps()) {
- $url = 'https' . $url;
- } else {
- $url = 'http' . $url;
- }
-
- return $url;
+ public function __construct(Updater $updater)
+ {
+ $this->updater = $updater;
}
public function newVersionAvailable()
{
Piwik::checkUserHasSuperUserAccess();
+ $this->checkNewVersionIsAvailableOrDie();
- $newVersion = $this->checkNewVersionIsAvailableOrDie();
+ $newVersion = $this->updater->getLatestVersion();
$view = new View('@CoreUpdater/newVersionAvailable');
$this->addCustomLogoInfo($view);
@@ -88,7 +69,7 @@ class Controller extends \Piwik\Plugin\Controller
$view->marketplacePlugins = $marketplacePlugins;
$view->incompatiblePlugins = $incompatiblePlugins;
- $view->piwik_latest_version_url = self::getLatestZipUrl($newVersion);
+ $view->piwik_latest_version_url = $this->updater->getArchiveUrl($newVersion);
$view->can_auto_update = Filechecks::canAutoUpdate();
$view->makeWritableCommands = Filechecks::getAutoUpdateMakeWritableMessage();
@@ -98,61 +79,38 @@ class Controller extends \Piwik\Plugin\Controller
public function oneClickUpdate()
{
Piwik::checkUserHasSuperUserAccess();
- $this->newVersion = $this->checkNewVersionIsAvailableOrDie();
-
- SettingsServer::setMaxExecutionTime(0);
- $url = self::getLatestZipUrl($this->newVersion);
- $steps = array(
- array('oneClick_Download', Piwik::translate('CoreUpdater_DownloadingUpdateFromX', $url)),
- array('oneClick_Unpack', Piwik::translate('CoreUpdater_UnpackingTheUpdate')),
- array('oneClick_Verify', Piwik::translate('CoreUpdater_VerifyingUnpackedFiles')),
- );
- $incompatiblePlugins = $this->getIncompatiblePlugins($this->newVersion);
- if (!empty($incompatiblePlugins)) {
- $namesToDisable = array();
- foreach ($incompatiblePlugins as $incompatiblePlugin) {
- $namesToDisable[] = $incompatiblePlugin->getPluginName();
- }
- $steps[] = array('oneClick_DisableIncompatiblePlugins', Piwik::translate('CoreUpdater_DisablingIncompatiblePlugins', implode(', ', $namesToDisable)));
- }
+ $view = new OneClickDone(Piwik::getCurrentUserTokenAuth());
- $steps[] = array('oneClick_Copy', Piwik::translate('CoreUpdater_InstallingTheLatestVersion'));
- $steps[] = array('oneClick_Finished', Piwik::translate('CoreUpdater_PiwikUpdatedSuccessfully'));
+ $useHttps = Common::getRequestVar('https', 1, 'int');
- $errorMessage = false;
- $messages = array();
- foreach ($steps as $step) {
- try {
- $method = $step[0];
- $message = $step[1];
- $this->$method();
- $messages[] = $message;
- } catch (Exception $e) {
- $errorMessage = $e->getMessage();
- break;
- }
+ try {
+ $messages = $this->updater->updatePiwik($useHttps);
+ } catch (ArchiveDownloadException $e) {
+ $view->httpsFail = $useHttps;
+ $view->error = $e->getMessage();
+ $messages = $e->getUpdateLogMessages();
+ } catch (UpdaterException $e) {
+ $view->error = $e->getMessage();
+ $messages = $e->getUpdateLogMessages();
}
- $view = new OneClickDone(Piwik::getCurrentUserTokenAuth());
- $view->coreError = $errorMessage;
$view->feedbackMessages = $messages;
-
$this->addCustomLogoInfo($view);
-
return $view->render();
}
public function oneClickResults()
{
$view = new View('@CoreUpdater/oneClickResults');
- $view->coreError = Common::getRequestVar('error', '', 'string', $_POST);
+ $view->error = Common::getRequestVar('error', '', 'string', $_POST);
$view->feedbackMessages = safe_unserialize(Common::unsanitizeInputValue(Common::getRequestVar('messages', '', 'string', $_POST)));
+ $view->httpsFail = (bool) Common::getRequestVar('httpsFail', 0, 'int', $_POST);
$this->addCustomLogoInfo($view);
return $view->render();
}
- protected function redirectToDashboardWhenNoError($updater)
+ protected function redirectToDashboardWhenNoError(DbUpdater $updater)
{
if (count($updater->getSqlQueriesToExecute()) == 1
&& !$this->coreError
@@ -166,130 +124,9 @@ class Controller extends \Piwik\Plugin\Controller
private function checkNewVersionIsAvailableOrDie()
{
- $newVersion = UpdateCheck::isNewestVersionAvailable();
- if (!$newVersion) {
+ if (!$this->updater->isNewVersionAvailable()) {
throw new Exception(Piwik::translate('CoreUpdater_ExceptionAlreadyLatestVersion', Version::VERSION));
}
- return $newVersion;
- }
-
- private function oneClick_Download()
- {
- $path = StaticContainer::get('path.tmp') . self::PATH_TO_EXTRACT_LATEST_VERSION;
- $this->pathPiwikZip = $path . 'latest.zip';
-
- Filechecks::dieIfDirectoriesNotWritable(array($path));
-
- // we catch exceptions in the caller (i.e., oneClickUpdate)
- $url = self::getLatestZipUrl($this->newVersion) . '?cb=' . $this->newVersion;
-
- Http::fetchRemoteFile($url, $this->pathPiwikZip, 0, 120);
- }
-
- private function oneClick_Unpack()
- {
- $pathExtracted = StaticContainer::get('path.tmp') . self::PATH_TO_EXTRACT_LATEST_VERSION;
-
- $this->pathRootExtractedPiwik = $pathExtracted . 'piwik';
-
- if (file_exists($this->pathRootExtractedPiwik)) {
- Filesystem::unlinkRecursive($this->pathRootExtractedPiwik, true);
- }
-
- $archive = Unzip::factory('PclZip', $this->pathPiwikZip);
-
- if (0 == ($archive_files = $archive->extract($pathExtracted))) {
- throw new Exception(Piwik::translate('CoreUpdater_ExceptionArchiveIncompatible', $archive->errorInfo()));
- }
-
- if (0 == count($archive_files)) {
- throw new Exception(Piwik::translate('CoreUpdater_ExceptionArchiveEmpty'));
- }
- unlink($this->pathPiwikZip);
- }
-
- private function oneClick_Verify()
- {
- $someExpectedFiles = array(
- '/config/global.ini.php',
- '/index.php',
- '/core/Piwik.php',
- '/piwik.php',
- '/plugins/API/API.php'
- );
- foreach ($someExpectedFiles as $file) {
- if (!is_file($this->pathRootExtractedPiwik . $file)) {
- throw new Exception(Piwik::translate('CoreUpdater_ExceptionArchiveIncomplete', $file));
- }
- }
- }
-
- private function oneClick_DisableIncompatiblePlugins()
- {
- $plugins = $this->getIncompatiblePlugins($this->newVersion);
-
- foreach ($plugins as $plugin) {
- PluginManager::getInstance()->deactivatePlugin($plugin->getPluginName());
- }
- }
-
- private function oneClick_Copy()
- {
- /*
- * Make sure the execute bit is set for this shell script
- */
- if (!Rules::isBrowserTriggerEnabled()) {
- @chmod($this->pathRootExtractedPiwik . '/misc/cron/archive.sh', 0755);
- }
-
- $model = new Model();
-
- /*
- * Copy all files to PIWIK_INCLUDE_PATH.
- * These files are accessed through the dispatcher.
- */
- Filesystem::copyRecursive($this->pathRootExtractedPiwik, PIWIK_INCLUDE_PATH);
- $model->removeGoneFiles($this->pathRootExtractedPiwik, PIWIK_INCLUDE_PATH);
-
- /*
- * These files are visible in the web root and are generally
- * served directly by the web server. May be shared.
- */
- if (PIWIK_INCLUDE_PATH !== PIWIK_DOCUMENT_ROOT) {
- /*
- * Copy PHP files that expect to be in the document root
- */
- $specialCases = array(
- '/index.php',
- '/piwik.php',
- '/js/index.php',
- );
-
- foreach ($specialCases as $file) {
- Filesystem::copy($this->pathRootExtractedPiwik . $file, PIWIK_DOCUMENT_ROOT . $file);
- }
-
- /*
- * Copy the non-PHP files (e.g., images, css, javascript)
- */
- Filesystem::copyRecursive($this->pathRootExtractedPiwik, PIWIK_DOCUMENT_ROOT, true);
- $model->removeGoneFiles($this->pathRootExtractedPiwik, PIWIK_DOCUMENT_ROOT);
- }
-
- /*
- * Config files may be user (account) specific
- */
- if (PIWIK_INCLUDE_PATH !== PIWIK_USER_PATH) {
- Filesystem::copyRecursive($this->pathRootExtractedPiwik . '/config', PIWIK_USER_PATH . '/config');
- }
-
- Filesystem::unlinkRecursive($this->pathRootExtractedPiwik, true);
-
- Filesystem::clearPhpCaches();
- }
-
- private function oneClick_Finished()
- {
}
public function index()
@@ -308,7 +145,7 @@ class Controller extends \Piwik\Plugin\Controller
public function runUpdaterAndExit($doDryRun = null)
{
- $updater = new Updater();
+ $updater = new DbUpdater();
$componentsWithUpdateFile = $updater->getComponentUpdates();
if (empty($componentsWithUpdateFile)) {
throw new NoUpdatesFoundException("Everything is already up to date.");
@@ -402,7 +239,7 @@ class Controller extends \Piwik\Plugin\Controller
$view->coreToUpdate = $coreToUpdate;
}
- private function doExecuteUpdates($view, Updater $updater, $componentsWithUpdateFile)
+ private function doExecuteUpdates($view, DbUpdater $updater, $componentsWithUpdateFile)
{
$result = $updater->updateComponents($componentsWithUpdateFile);
diff --git a/plugins/CoreUpdater/Test/Fixtures/DbUpdaterTestFixture.php b/plugins/CoreUpdater/Test/Fixtures/DbUpdaterTestFixture.php
new file mode 100644
index 0000000000..89a29126f2
--- /dev/null
+++ b/plugins/CoreUpdater/Test/Fixtures/DbUpdaterTestFixture.php
@@ -0,0 +1,23 @@
+<?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\CoreUpdater\Test\Fixtures;
+
+use Piwik\Tests\Fixtures\SqlDump;
+
+class DbUpdaterTestFixture extends SqlDump
+{
+ public function performSetUp($setupEnvironmentOnly = false)
+ {
+ $this->dumpUrl = PIWIK_INCLUDE_PATH . "/tests/UI/resources/piwik1.0.sql.gz";
+ $this->dropDatabaseInSetUp = true;
+ $this->resetPersistedFixture = true;
+
+ parent::performSetUp($setupEnvironmentOnly);
+ }
+}
diff --git a/plugins/CoreUpdater/Test/Fixtures/FailUpdateHttpsFixture.php b/plugins/CoreUpdater/Test/Fixtures/FailUpdateHttpsFixture.php
new file mode 100644
index 0000000000..5060c99320
--- /dev/null
+++ b/plugins/CoreUpdater/Test/Fixtures/FailUpdateHttpsFixture.php
@@ -0,0 +1,24 @@
+<?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\CoreUpdater\Test\Fixtures;
+
+use Piwik\Tests\Framework\Fixture;
+
+/**
+ * Fixture that makes the update over HTTPS fail to be able to test that users can still update over HTTP.
+ */
+class FailUpdateHttpsFixture extends Fixture
+{
+ public function provideContainerConfig()
+ {
+ return array(
+ 'Piwik\Plugins\CoreUpdater\Updater' => \DI\object('Piwik\Plugins\CoreUpdater\Test\Mock\UpdaterMock'),
+ );
+ }
+}
diff --git a/plugins/CoreUpdater/tests/Integration/UpdateCommunicationTest.php b/plugins/CoreUpdater/Test/Integration/UpdateCommunicationTest.php
index 91b6e2c2a1..6ec5fdaf83 100644
--- a/plugins/CoreUpdater/tests/Integration/UpdateCommunicationTest.php
+++ b/plugins/CoreUpdater/Test/Integration/UpdateCommunicationTest.php
@@ -6,7 +6,7 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
-namespace Piwik\Plugins\CoreUpdater\tests;
+namespace Piwik\Plugins\CoreUpdater\Test;
use Piwik\Config;
use Piwik\Option;
diff --git a/plugins/CoreUpdater/Test/Mock/UpdaterMock.php b/plugins/CoreUpdater/Test/Mock/UpdaterMock.php
new file mode 100644
index 0000000000..7a73129c5b
--- /dev/null
+++ b/plugins/CoreUpdater/Test/Mock/UpdaterMock.php
@@ -0,0 +1,54 @@
+<?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\CoreUpdater\Test\Mock;
+
+use Piwik\Plugins\CoreUpdater\ArchiveDownloadException;
+use Piwik\Plugins\CoreUpdater\Updater;
+use Piwik\Translation\Translator;
+
+class UpdaterMock extends Updater
+{
+ /**
+ * @var Translator
+ */
+ private $translator;
+
+ public function __construct(Translator $translator)
+ {
+ $this->translator = $translator;
+ }
+
+ public function getLatestVersion()
+ {
+ return '4.0.0';
+ }
+
+ public function isNewVersionAvailable()
+ {
+ return true;
+ }
+
+ public function updatePiwik($https = true)
+ {
+ // Simulate that the update over HTTPS fails
+ if ($https) {
+ // The actual error message depends on the OS, the HTTP method etc.
+ // This is what I get on my machine, but it doesn't really matter
+ throw new ArchiveDownloadException(new \Exception('curl_exec: SSL certificate problem: Invalid certificate chain. Hostname requested was: piwik.org'), array());
+ }
+
+ // Simulate that the update over HTTP succeeds
+ return array(
+ $this->translator->translate('CoreUpdater_DownloadingUpdateFromX', ''),
+ $this->translator->translate('CoreUpdater_UnpackingTheUpdate'),
+ $this->translator->translate('CoreUpdater_VerifyingUnpackedFiles'),
+ $this->translator->translate('CoreUpdater_InstallingTheLatestVersion'),
+ );
+ }
+}
diff --git a/plugins/CoreUpdater/tests/Unit/ModelTest.php b/plugins/CoreUpdater/Test/Unit/ModelTest.php
index 3098595b77..521aa8fc35 100644
--- a/plugins/CoreUpdater/tests/Unit/ModelTest.php
+++ b/plugins/CoreUpdater/Test/Unit/ModelTest.php
@@ -6,7 +6,8 @@
* @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
*/
-namespace Piwik\Plugins\CoreUpdater\tests;
+namespace Piwik\Plugins\CoreUpdater\Test\Unit;
+
use Piwik\Plugins\CoreUpdater\Model;
/**
diff --git a/plugins/CoreUpdater/Updater.php b/plugins/CoreUpdater/Updater.php
new file mode 100644
index 0000000000..1adcbc6cc0
--- /dev/null
+++ b/plugins/CoreUpdater/Updater.php
@@ -0,0 +1,272 @@
+<?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\CoreUpdater;
+
+use Exception;
+use Piwik\ArchiveProcessor\Rules;
+use Piwik\Config;
+use Piwik\Filechecks;
+use Piwik\Filesystem;
+use Piwik\Http;
+use Piwik\Option;
+use Piwik\Plugin\Manager as PluginManager;
+use Piwik\SettingsServer;
+use Piwik\Translation\Translator;
+use Piwik\Unzip;
+use Piwik\Version;
+
+class Updater
+{
+ const OPTION_LATEST_VERSION = 'UpdateCheck_LatestVersion';
+ const PATH_TO_EXTRACT_LATEST_VERSION = '/latest/';
+ const LATEST_VERSION_URL = '://builds.piwik.org/piwik.zip';
+ const LATEST_BETA_VERSION_URL = '://builds.piwik.org/piwik-%s.zip';
+ const DOWNLOAD_TIMEOUT = 120;
+
+ /**
+ * @var Translator
+ */
+ private $translator;
+
+ /**
+ * @var string
+ */
+ private $tmpPath;
+
+ public function __construct(Translator $translator, $tmpPath)
+ {
+ $this->translator = $translator;
+ $this->tmpPath = $tmpPath;
+ }
+
+ /**
+ * Returns the latest available version number. Does not perform a check whether a later version is available.
+ *
+ * @return false|string
+ */
+ public function getLatestVersion()
+ {
+ return Option::get(self::OPTION_LATEST_VERSION);
+ }
+
+ /**
+ * @return bool
+ */
+ public function isNewVersionAvailable()
+ {
+ $latestVersion = self::getLatestVersion();
+ return $latestVersion && version_compare(Version::VERSION, $latestVersion) === -1;
+ }
+
+ /**
+ * @return bool
+ */
+ public function isUpdatingOverHttps()
+ {
+ $openSslEnabled = extension_loaded('openssl');
+ $usingMethodSupportingHttps = (Http::getTransportMethod() !== 'socket');
+
+ return $openSslEnabled && $usingMethodSupportingHttps;
+ }
+
+ /**
+ * Update Piwik codebase by downloading and installing the latest version.
+ *
+ * @param bool $https Whether to use HTTPS if supported of not. If false, will use HTTP.
+ * @return string[] Return an array of messages for the user.
+ * @throws ArchiveDownloadException
+ * @throws UpdaterException
+ * @throws Exception
+ */
+ public function updatePiwik($https = true)
+ {
+ if (!$this->isNewVersionAvailable()) {
+ throw new Exception($this->translator->translate('CoreUpdater_ExceptionAlreadyLatestVersion', Version::VERSION));
+ }
+
+ SettingsServer::setMaxExecutionTime(0);
+
+ $newVersion = $this->getLatestVersion();
+ $url = $this->getArchiveUrl($newVersion, $https);
+ $messages = array();
+
+ try {
+ $archiveFile = $this->downloadArchive($newVersion, $url);
+ $messages[] = $this->translator->translate('CoreUpdater_DownloadingUpdateFromX', $url);
+
+ $extractedArchiveDirectory = $this->decompressArchive($archiveFile);
+ $messages[] = $this->translator->translate('CoreUpdater_UnpackingTheUpdate');
+
+ $this->verifyDecompressedArchive($extractedArchiveDirectory);
+ $messages[] = $this->translator->translate('CoreUpdater_VerifyingUnpackedFiles');
+
+ $disabledPluginNames = $this->disableIncompatiblePlugins($newVersion);
+ if (!empty($disabledPluginNames)) {
+ $messages[] = $this->translator->translate('CoreUpdater_DisablingIncompatiblePlugins', implode(', ', $disabledPluginNames));
+ }
+
+ $this->installNewFiles($extractedArchiveDirectory);
+ $messages[] = $this->translator->translate('CoreUpdater_InstallingTheLatestVersion');
+ } catch (Exception $e) {
+ throw new UpdaterException($e, $messages);
+ }
+
+ return $messages;
+ }
+
+ private function downloadArchive($version, $url)
+ {
+ $path = $this->tmpPath . self::PATH_TO_EXTRACT_LATEST_VERSION;
+ $archiveFile = $path . 'latest.zip';
+
+ Filechecks::dieIfDirectoriesNotWritable(array($path));
+
+ $url .= '?cb=' . $version;
+
+ try {
+ Http::fetchRemoteFile($url, $archiveFile, 0, self::DOWNLOAD_TIMEOUT);
+ } catch (Exception $e) {
+ // We throw a specific exception allowing to offer HTTP download if HTTPS failed
+ throw new ArchiveDownloadException($e);
+ }
+
+ return $archiveFile;
+ }
+
+ private function decompressArchive($archiveFile)
+ {
+ $extractionPath = $this->tmpPath . self::PATH_TO_EXTRACT_LATEST_VERSION;
+
+ $extractedArchiveDirectory = $extractionPath . 'piwik';
+
+ // Remove previous decompressed archive
+ if (file_exists($extractedArchiveDirectory)) {
+ Filesystem::unlinkRecursive($extractedArchiveDirectory, true);
+ }
+
+ $archive = Unzip::factory('PclZip', $archiveFile);
+ $archiveFiles = $archive->extract($extractionPath);
+
+ if (0 == $archiveFiles) {
+ throw new Exception($this->translator->translate('CoreUpdater_ExceptionArchiveIncompatible', $archive->errorInfo()));
+ }
+
+ if (0 == count($archiveFiles)) {
+ throw new Exception($this->translator->translate('CoreUpdater_ExceptionArchiveEmpty'));
+ }
+
+ unlink($archiveFile);
+
+ return $extractedArchiveDirectory;
+ }
+
+ private function verifyDecompressedArchive($extractedArchiveDirectory)
+ {
+ $someExpectedFiles = array(
+ '/config/global.ini.php',
+ '/index.php',
+ '/core/Piwik.php',
+ '/piwik.php',
+ '/plugins/API/API.php'
+ );
+ foreach ($someExpectedFiles as $file) {
+ if (!is_file($extractedArchiveDirectory . $file)) {
+ throw new Exception($this->translator->translate('CoreUpdater_ExceptionArchiveIncomplete', $file));
+ }
+ }
+ }
+
+ private function disableIncompatiblePlugins($version)
+ {
+ $incompatiblePlugins = $this->getIncompatiblePlugins($version);
+ $disabledPluginNames = array();
+
+ foreach ($incompatiblePlugins as $plugin) {
+ $name = $plugin->getPluginName();
+ PluginManager::getInstance()->deactivatePlugin($name);
+ $disabledPluginNames[] = $name;
+ }
+
+ return $disabledPluginNames;
+ }
+
+ private function installNewFiles($extractedArchiveDirectory)
+ {
+ // Make sure the execute bit is set for this shell script
+ if (!Rules::isBrowserTriggerEnabled()) {
+ @chmod($extractedArchiveDirectory . '/misc/cron/archive.sh', 0755);
+ }
+
+ $model = new Model();
+
+ /*
+ * Copy all files to PIWIK_INCLUDE_PATH.
+ * These files are accessed through the dispatcher.
+ */
+ Filesystem::copyRecursive($extractedArchiveDirectory, PIWIK_INCLUDE_PATH);
+ $model->removeGoneFiles($extractedArchiveDirectory, PIWIK_INCLUDE_PATH);
+
+ /*
+ * These files are visible in the web root and are generally
+ * served directly by the web server. May be shared.
+ */
+ if (PIWIK_INCLUDE_PATH !== PIWIK_DOCUMENT_ROOT) {
+ // Copy PHP files that expect to be in the document root
+ $specialCases = array(
+ '/index.php',
+ '/piwik.php',
+ '/js/index.php',
+ );
+
+ foreach ($specialCases as $file) {
+ Filesystem::copy($extractedArchiveDirectory . $file, PIWIK_DOCUMENT_ROOT . $file);
+ }
+
+ // Copy the non-PHP files (e.g., images, css, javascript)
+ Filesystem::copyRecursive($extractedArchiveDirectory, PIWIK_DOCUMENT_ROOT, true);
+ $model->removeGoneFiles($extractedArchiveDirectory, PIWIK_DOCUMENT_ROOT);
+ }
+
+ // Config files may be user (account) specific
+ if (PIWIK_INCLUDE_PATH !== PIWIK_USER_PATH) {
+ Filesystem::copyRecursive($extractedArchiveDirectory . '/config', PIWIK_USER_PATH . '/config');
+ }
+
+ Filesystem::unlinkRecursive($extractedArchiveDirectory, true);
+
+ Filesystem::clearPhpCaches();
+ }
+
+ /**
+ * @param string $version
+ * @param bool $https Whether to use HTTPS if supported of not. If false, will use HTTP.
+ * @return string
+ */
+ public function getArchiveUrl($version, $https = true)
+ {
+ if (@Config::getInstance()->Debug['allow_upgrades_to_beta']) {
+ $url = sprintf(self::LATEST_BETA_VERSION_URL, $version);
+ } else {
+ $url = self::LATEST_VERSION_URL;
+ }
+
+ if ($this->isUpdatingOverHttps() && $https) {
+ $url = 'https' . $url;
+ } else {
+ $url = 'http' . $url;
+ }
+
+ return $url;
+ }
+
+ private function getIncompatiblePlugins($piwikVersion)
+ {
+ return PluginManager::getInstance()->getIncompatiblePlugins($piwikVersion);
+ }
+}
diff --git a/plugins/CoreUpdater/UpdaterException.php b/plugins/CoreUpdater/UpdaterException.php
new file mode 100644
index 0000000000..bd4599b111
--- /dev/null
+++ b/plugins/CoreUpdater/UpdaterException.php
@@ -0,0 +1,37 @@
+<?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\CoreUpdater;
+
+use Exception;
+
+/**
+ * Exception during the updating of Piwik to a new version.
+ */
+class UpdaterException extends Exception
+{
+ /**
+ * @var string[]
+ */
+ private $updateLogMessages;
+
+ public function __construct(Exception $exception, array $updateLogMessages)
+ {
+ parent::__construct($exception->getMessage(), 0, $exception);
+
+ $this->updateLogMessages = $updateLogMessages;
+ }
+
+ /**
+ * @return string[]
+ */
+ public function getUpdateLogMessages()
+ {
+ return $this->updateLogMessages;
+ }
+}
diff --git a/plugins/CoreUpdater/config/config.php b/plugins/CoreUpdater/config/config.php
new file mode 100644
index 0000000000..419e43cc7b
--- /dev/null
+++ b/plugins/CoreUpdater/config/config.php
@@ -0,0 +1,6 @@
+<?php
+
+return array(
+ 'Piwik\Plugins\CoreUpdater\Updater' => DI\object()
+ ->constructorParameter('tmpPath', DI\link('path.tmp')),
+);
diff --git a/plugins/CoreUpdater/lang/en.json b/plugins/CoreUpdater/lang/en.json
index 67bc20f27b..2c3ffb9be2 100644
--- a/plugins/CoreUpdater/lang/en.json
+++ b/plugins/CoreUpdater/lang/en.json
@@ -47,6 +47,10 @@
"UpdateAutomatically": "Update Automatically",
"UpdateHasBeenCancelledExplanation": "Piwik One Click Update has been cancelled. If you can't fix the above error message, it is recommended that you manually update Piwik. %1$s Please check out the %2$sUpdate documentation%3$s to get started!",
"UpdateTitle": "Update",
+ "UpdateUsingHttpsFailed": "Downloading the latest Piwik version over secure HTTPS connection did not succeed, because of the following error:",
+ "UpdateUsingHttpsFailedHelp": "Please note that downloading the latest Piwik version (over secure HTTPS connection) can fail for various reasons, for example in case of network error, slow network speed, or wrong system configuration.",
+ "UpdateUsingHttpsFailedHelpWhatToDo": "You may continue the update via the non-secure standard HTTP connection by clicking on the button '%s'.",
+ "UpdateUsingHttpMessage": "Update Piwik automatically (over the non secure HTTP connection)",
"UpgradeComplete": "Upgrade complete!",
"UpgradePiwik": "Upgrade Piwik",
"VerifyingUnpackedFiles": "Verifying the unpacked files",
diff --git a/plugins/CoreUpdater/templates/newVersionAvailable.twig b/plugins/CoreUpdater/templates/newVersionAvailable.twig
index cf87a949e6..8691d97595 100644
--- a/plugins/CoreUpdater/templates/newVersionAvailable.twig
+++ b/plugins/CoreUpdater/templates/newVersionAvailable.twig
@@ -29,7 +29,7 @@
<form id="oneclickupdate" action="index.php">
<input type="hidden" name="module" value="CoreUpdater"/>
<input type="hidden" name="action" value="oneClickUpdate"/>
- <input type="submit" class="submit" value="{{ 'CoreUpdater_UpdateAutomatically'|translate }}"/>
+ <input id="updateAutomatically" type="submit" class="submit" value="{{ 'CoreUpdater_UpdateAutomatically'|translate }}"/>
{% endif %}
<a style="margin-left:50px;" class="submit button"
href="{{ piwik_latest_version_url }}?cb={{ piwik_new_version }}">{{ 'CoreUpdater_DownloadX'|translate(piwik_new_version) }}</a><br/>
diff --git a/plugins/CoreUpdater/templates/oneClickResults.twig b/plugins/CoreUpdater/templates/oneClickResults.twig
index d08378d6c3..8ded5fd604 100644
--- a/plugins/CoreUpdater/templates/oneClickResults.twig
+++ b/plugins/CoreUpdater/templates/oneClickResults.twig
@@ -3,13 +3,37 @@
{% block content %}
<br/>
{% for message in feedbackMessages %}
-<p>&#10003; {{ message }}</p>
+ <p>&#10003; {{ message }}</p>
{% endfor %}
-{% if coreError %}
+{% if httpsFail %}
<br/>
<br/>
- <div class="error"><img src="plugins/Morpheus/images/error_medium.png"/> {{ coreError }}</div>
+ <div class="warning">
+ <img src="plugins/Morpheus/images/warning_medium.png"/>
+ {{ 'CoreUpdater_UpdateUsingHttpsFailed'|translate }}<br/>
+ "{{ error }}"
+ </div>
+ <p>{{ 'CoreUpdater_UpdateUsingHttpsFailedHelp'|translate }}</p>
+ <p>{{ 'CoreUpdater_UpdateUsingHttpsFailedHelpWhatToDo'|translate('CoreUpdater_UpdateAutomatically'|translate) }}</p>
+ <div class="warning">
+ {{ 'CoreUpdater_UpdateUsingHttpMessage'|translate }}
+ <form id="oneclickupdate" action="index.php">
+ <input type="hidden" name="module" value="CoreUpdater"/>
+ <input type="hidden" name="action" value="oneClickUpdate"/>
+ <input type="hidden" name="https" value="0"/>
+ <input id="updateUsingHttp" type="submit" class="submit" value="{{ 'CoreUpdater_UpdateAutomatically'|translate }}"/>
+ </form>
+ </div>
+ <br/>
+ <br/>
+{% elseif error %}
+ <br/>
+ <br/>
+ <div class="error">
+ <img src="plugins/Morpheus/images/error_medium.png"/>
+ {{ error }}
+ </div>
<br/>
<br/>
<div class="warning">
diff --git a/plugins/Goals/templates/_addEditGoal.twig b/plugins/Goals/templates/_addEditGoal.twig
index 94db74df41..dc217c9a66 100644
--- a/plugins/Goals/templates/_addEditGoal.twig
+++ b/plugins/Goals/templates/_addEditGoal.twig
@@ -40,20 +40,21 @@
<br />{{ 'General_ForExampleShort'|translate }} {{ 'Goals_IsExactly'|translate("'click'") }} \
<br />{{ 'General_ForExampleShort'|translate }} {{ 'Goals_MatchesExpression'|translate("'(.*)_banner'") }}"
};
- bindGoalForm();
-
- {% if onlyShowAddNewGoal is not defined %}
- piwik.goals = {{ goalsJSON|raw }};
- bindListGoalEdit();
-
- {% if idGoal %}
- editGoal({{ idGoal|e('js') }});
+ $(document).ready(function () {
+ bindGoalForm();
+
+ {% if onlyShowAddNewGoal is not defined %}
+ piwik.goals = {{ goalsJSON|raw }};
+ bindListGoalEdit();
+
+ {% if idGoal %}
+ editGoal({{ idGoal|e('js') }});
+ {% else %}
+ showEditGoals();
+ {% endif %}
{% else %}
- showEditGoals();
+ initAndShowAddGoalForm();
{% endif %}
- {% else %}
- initAndShowAddGoalForm();
- {% endif %}
-
+ });
</script>
diff --git a/plugins/Login/Controller.php b/plugins/Login/Controller.php
index 270b788380..b9660a221d 100644
--- a/plugins/Login/Controller.php
+++ b/plugins/Login/Controller.php
@@ -93,6 +93,7 @@ class Controller extends \Piwik\Plugin\Controller
function login($messageNoAccess = null, $infoMessage = false)
{
$form = new FormLogin();
+ $form->removeAttribute('action'); // remove action attribute, otherwise hash part will be lost
if ($form->validate()) {
$nonce = $form->getSubmitValue('form_nonce');
if (Nonce::verifyNonce('Login.login', $nonce)) {