From a2a586a0bf38c41fbd998bcb00cb7f081cd06555 Mon Sep 17 00:00:00 2001
From: Thomas Steur <thomas.steur@googlemail.com>
Date: Tue, 11 Feb 2014 02:16:56 +0100
Subject: [PATCH] refs #4610 make sure the fallback mode works in case async is
 not supported

---
 core/CliMulti.php                             | 51 ++++++++++++++-----
 core/CliMulti/run.php                         |  4 +-
 .../PHPUnit/Integration/Core/CliMultiTest.php |  9 ++++
 3 files changed, 48 insertions(+), 16 deletions(-)

diff --git a/core/CliMulti.php b/core/CliMulti.php
index 0c9af59475..3688c254d2 100644
--- a/core/CliMulti.php
+++ b/core/CliMulti.php
@@ -12,16 +12,32 @@ use Piwik\CliMulti\Output;
 
 class CliMulti {
 
+    /**
+     * If set to true or false it will overwrite whether async is supported or not.
+     *
+     * @var null|bool
+     */
+    public $supportsAsync = null;
+
     /**
      * @var \Piwik\CliMulti\Process[]
      */
-    private $pids = array();
+    private $processes = array();
 
     /**
      * @var \Piwik\CliMulti\Output[]
      */
     private $outputs = array();
 
+    /**
+     * It will request all given URLs in parallel (async) using the CLI and wait until all requests are finished.
+     *
+     *
+     * @param string[]  $piwikUrls   An array of urls, for instance:
+     *                               array('/index.php?module=API', '/?module=API', 'http://www.example.com?module=API')
+     * @return array The response of each URL in the same order as the URLs. The array can contain null values in case
+     *               there was a problem with a request, for instance if the process died unexpected.
+     */
     public function request(array $piwikUrls)
     {
         $this->start($piwikUrls);
@@ -39,18 +55,21 @@ class CliMulti {
     private function start($piwikUrls)
     {
         foreach ($piwikUrls as $index => $url) {
-            $cmdId  = $this->generateCmdId($url);
-            $pid    = $cmdId . $index . '_cli_multi_pid';
-            $output = $cmdId . $index . '_cli_multi_output';
+            $cmdId    = $this->generateCmdId($url);
+            $pid      = $cmdId . $index . '_cli_multi_pid';
+            $outputId = $cmdId . $index . '_cli_multi_output';
 
-            $params   = array('output' => $output, 'pid' => $pid);
-            $command  = $this->buildCommand($url, $params);
+            $this->processes[] = new Process($pid);
+            $this->outputs[]   = new Output($outputId);
+
+            $command  = $this->buildCommand($url, array('outputId' => $outputId, 'pid' => $pid));
             $appendix = $this->supportsAsync() ? ' > /dev/null 2>&1 &' : '';
 
             shell_exec($command . $appendix);
 
-            $this->pids[]    = new Process($pid);
-            $this->outputs[] = new Output($output);
+            if (!$this->supportsAsync()) {
+                end($this->processes)->finishProcess();
+            }
         }
     }
 
@@ -88,12 +107,12 @@ class CliMulti {
 
     private function isFinished()
     {
-        foreach ($this->pids as $index => $pid) {
-            if (!$pid->hasStarted()) {
+        foreach ($this->processes as $index => $process) {
+            if (!$process->hasStarted()) {
                 return false;
             }
 
-            if ($pid->isRunning() && !$this->outputs[$index]->exists()) {
+            if ($process->isRunning() && !$this->outputs[$index]->exists()) {
                 return false;
             }
         }
@@ -112,12 +131,16 @@ class CliMulti {
      */
     private function supportsAsync()
     {
+        if (is_bool($this->supportsAsync)) {
+            return $this->supportsAsync;
+        }
+
         return !SettingsServer::isWindows();
     }
 
     private function cleanup()
     {
-        foreach ($this->pids as $pid) {
+        foreach ($this->processes as $pid) {
             $pid->finishProcess();
         }
 
@@ -125,8 +148,8 @@ class CliMulti {
             $output->destroy();
         }
 
-        $this->pids    = array();
-        $this->outputs = array();
+        $this->processes = array();
+        $this->outputs   = array();
     }
 
 }
diff --git a/core/CliMulti/run.php b/core/CliMulti/run.php
index a06608f993..1accd71669 100644
--- a/core/CliMulti/run.php
+++ b/core/CliMulti/run.php
@@ -43,8 +43,8 @@ require_once PIWIK_INCLUDE_PATH . "/index.php";
 $content = ob_get_contents();
 ob_clean();
 
-if (!empty($_GET['output']) && \Piwik\Filesystem::isValidFilename($_GET['output'])) {
-    $cliMulti = new \Piwik\CliMulti\Output($_GET['output']);
+if (!empty($_GET['outputId']) && \Piwik\Filesystem::isValidFilename($_GET['outputId'])) {
+    $cliMulti = new \Piwik\CliMulti\Output($_GET['outputId']);
     $cliMulti->write($content);
 } else {
     echo $content;
diff --git a/tests/PHPUnit/Integration/Core/CliMultiTest.php b/tests/PHPUnit/Integration/Core/CliMultiTest.php
index 1771467980..ac8d0f6c05 100644
--- a/tests/PHPUnit/Integration/Core/CliMultiTest.php
+++ b/tests/PHPUnit/Integration/Core/CliMultiTest.php
@@ -137,6 +137,15 @@ class Core_CliMultiTest extends IntegrationTestCase
         $this->assertTrue(false !== strpos($response[0], 'Widgetize the full dashboard'));
     }
 
+    public function test_shouldFallback_IfAsyncIsNotSupported()
+    {
+        $this->cliMulti->supportsAsync = false;
+
+        $urls = $this->buildUrls('getPiwikVersion', 'getAnswerToLife', 'getPiwikVersion');
+
+        $this->assertRequestReturnsValidResponses($urls, array('getPiwikVersion', 'getAnswerToLife', 'getPiwikVersion'));
+    }
+
     private function assertRequestReturnsValidResponses($urls, $expectedResponseIds)
     {
         $actualResponse = $this->cliMulti->request($urls);
-- 
GitLab