From 6f6a2a9bbe9c48232db4d097ffe6607d0d562d1d Mon Sep 17 00:00:00 2001
From: Thomas Steur <thomas.steur@gmail.com>
Date: Thu, 30 Jul 2015 09:31:49 +0000
Subject: [PATCH] When Piwik DB needs to be upgraded, the API should return a
 valid response

---
 plugins/CoreUpdater/CoreUpdater.php           | 10 ++++++++++
 tests/UI/specs/CoreUpdaterDb_spec.js          | 12 ++++++++++++
 .../support/page-renderer.js                  | 19 +++++++++++++++----
 3 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/plugins/CoreUpdater/CoreUpdater.php b/plugins/CoreUpdater/CoreUpdater.php
index 584a465130..8fc3f0d92f 100644
--- a/plugins/CoreUpdater/CoreUpdater.php
+++ b/plugins/CoreUpdater/CoreUpdater.php
@@ -10,6 +10,7 @@ namespace Piwik\Plugins\CoreUpdater;
 
 use Exception;
 use Piwik\Access;
+use Piwik\API\ResponseBuilder;
 use Piwik\Common;
 use Piwik\Filesystem;
 use Piwik\FrontController;
@@ -73,6 +74,15 @@ class CoreUpdater extends \Piwik\Plugin
             if (FrontController::shouldRethrowException()) {
                 throw new Exception("Piwik and/or some plugins have been upgraded to a new version. \n" .
                     "--> Please run the update process first. See documentation: http://piwik.org/docs/update/ \n");
+            } elseif ($module === 'API')  {
+
+                $outputFormat = strtolower(Common::getRequestVar('format', 'xml', 'string', $_GET + $_POST));
+                $response = new ResponseBuilder($outputFormat);
+                $e = new Exception('Database Upgrade Required. Your Piwik database is out-of-date, and must be upgraded before you can continue.');
+                echo $response->getResponseException($e);
+                Common::sendResponseCode(503);
+                exit;
+
             } else {
                 Piwik::redirectToModule('CoreUpdater');
             }
diff --git a/tests/UI/specs/CoreUpdaterDb_spec.js b/tests/UI/specs/CoreUpdaterDb_spec.js
index f77776a4ca..98586a7ca5 100644
--- a/tests/UI/specs/CoreUpdaterDb_spec.js
+++ b/tests/UI/specs/CoreUpdaterDb_spec.js
@@ -17,6 +17,18 @@ describe("CoreUpdaterDb", function () {
         testEnvironment.save();
     });
 
+    function apiUpgradeTest(format) {
+        it("should start the updater when an old version of Piwik is detected in the DB", function (done) {
+            expect.file('CoreUpdater.API.ErrorMessage' + format + '.txt').to.be.pageContents(function (page) {
+                page.load('');
+                page.downloadUrl('?module=API&method=API.getPiwikVersion&format=' + format);
+            }, done);
+        });
+    }
+
+    var formats = ['CSV', 'TSV', 'XML', 'JSON', 'PHP'];
+    formats.forEach(apiUpgradeTest);
+
     it("should start the updater when an old version of Piwik is detected in the DB", function (done) {
         expect.screenshot("main").to.be.capture(function (page) {
             page.load("");
diff --git a/tests/lib/screenshot-testing/support/page-renderer.js b/tests/lib/screenshot-testing/support/page-renderer.js
index 16db97d7f1..3a0ef301d0 100644
--- a/tests/lib/screenshot-testing/support/page-renderer.js
+++ b/tests/lib/screenshot-testing/support/page-renderer.js
@@ -114,6 +114,10 @@ PageRenderer.prototype.downloadLink = function (selector, waitTime) {
     this.queuedEvents.push([this._downloadLink, waitTime, selector]);
 };
 
+PageRenderer.prototype.downloadUrl = function (url, waitTime) {
+    this.queuedEvents.push([this._downloadUrl, waitTime, url]);
+};
+
 PageRenderer.prototype.dragDrop = function (startSelector, endSelector, waitTime) {
     this.mousedown(startSelector, waitTime);
     this.mouseMove(endSelector, waitTime);
@@ -220,16 +224,23 @@ PageRenderer.prototype._evaluate = function (impl, callback) {
 };
 
 PageRenderer.prototype._downloadLink = function (str, callback) {
-    var response = this.webpage.evaluate(function (selector) {
-        var $ = window.jQuery,
-            url = $(selector).attr('href');
+    var url = this.webpage.evaluate(function (selector) {
+        return $(selector).attr('href');
+    }, str);
+
+    this._downloadUrl(url, callback);
+};
+
+PageRenderer.prototype._downloadUrl = function (url, callback) {
+    var response = this.webpage.evaluate(function (url) {
+        var $ = window.jQuery;
 
         return $.ajax({
             type: "GET",
             url: url,
             async: false
         }).responseText;
-    }, str);
+    }, url);
 
     this.downloadedContents = response;
 
-- 
GitLab