From 0cb1c514c1a8ebb0ae8a392f6deca26a0be9c900 Mon Sep 17 00:00:00 2001
From: Benni Mack <benni@typo3.org>
Date: Sun, 15 Jan 2017 14:22:44 +0100
Subject: [PATCH] [TASK] Throw exception when CLI command is added twice

If two extensions register the same command, the "last one"
wins currently.

The patch throws an exception if there is already a name
or alias with this command name.

Resolves: #79590
Releases: master
Change-Id: Iaafb97d88455077ab60689c32dda0580c47e0b47
Reviewed-on: https://review.typo3.org/51316
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Andreas Fernandez <typo3@scripting-base.de>
Reviewed-by: Wouter Wolters <typo3@wouterwolters.nl>
Tested-by: Wouter Wolters <typo3@wouterwolters.nl>
Reviewed-by: Georg Ringer <georg.ringer@gmail.com>
Tested-by: Georg Ringer <georg.ringer@gmail.com>
---
 .../CommandNameAlreadyInUseException.php      | 25 +++++++++++++
 .../Classes/Console/CommandRequestHandler.php | 36 ++++++-------------
 2 files changed, 35 insertions(+), 26 deletions(-)
 create mode 100644 typo3/sysext/core/Classes/Console/CommandNameAlreadyInUseException.php

diff --git a/typo3/sysext/core/Classes/Console/CommandNameAlreadyInUseException.php b/typo3/sysext/core/Classes/Console/CommandNameAlreadyInUseException.php
new file mode 100644
index 000000000000..fcc59c5b0a97
--- /dev/null
+++ b/typo3/sysext/core/Classes/Console/CommandNameAlreadyInUseException.php
@@ -0,0 +1,25 @@
+<?php
+namespace TYPO3\CMS\Core\Console;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use TYPO3\CMS\Core\Exception;
+
+/**
+ * Exception thrown when a command is registered with a name
+ * that is already taken
+ */
+class CommandNameAlreadyInUseException extends Exception
+{
+}
diff --git a/typo3/sysext/core/Classes/Console/CommandRequestHandler.php b/typo3/sysext/core/Classes/Console/CommandRequestHandler.php
index 20613d225019..1295db3ff531 100644
--- a/typo3/sysext/core/Classes/Console/CommandRequestHandler.php
+++ b/typo3/sysext/core/Classes/Console/CommandRequestHandler.php
@@ -40,11 +40,6 @@ class CommandRequestHandler implements RequestHandlerInterface
      */
     protected $application;
 
-    /**
-     * @var []
-     */
-    protected $availableCommands;
-
     /**
      * Constructor handing over the bootstrap
      *
@@ -131,40 +126,29 @@ class CommandRequestHandler implements RequestHandlerInterface
     }
 
     /**
-     * put all available commands inside the application
+     * Put all available commands inside the application
      */
     protected function populateAvailableCommands()
-    {
-        $this->availableCommands = $this->getAvailableCommands();
-        foreach ($this->availableCommands as $name => $data) {
-            /** @var Command $cmd */
-            $cmd = GeneralUtility::makeInstance($data['class'], $name);
-            $this->application->add($cmd);
-            $this->availableCommands[$name]['command'] = $cmd;
-        }
-    }
-
-    /**
-     * Fetches all commands registered via Commands.php of all active packages
-     *
-     * @return array
-     */
-    protected function getAvailableCommands()
     {
         /** @var PackageManager $packageManager */
         $packageManager = Bootstrap::getInstance()->getEarlyInstance(PackageManager::class);
-        $availableCommands = [];
 
         foreach ($packageManager->getActivePackages() as $package) {
             $commandsOfExtension = $package->getPackagePath() . 'Configuration/Commands.php';
             if (@is_file($commandsOfExtension)) {
                 $commands = require_once $commandsOfExtension;
                 if (is_array($commands)) {
-                    $availableCommands = array_merge($availableCommands, $commands);
+                    foreach ($commands as $commandName => $commandDescription) {
+                        /** @var Command $cmd */
+                        $cmd = GeneralUtility::makeInstance($commandDescription['class'], $commandName);
+                        // Check if the command name is already in use
+                        if ($this->application->has($commandName)) {
+                            throw new CommandNameAlreadyInUseException('Command "' . $commandName . '" registered by "' . $package->getPackageKey() . '" is already in use', 1484486383);
+                        }
+                        $this->application->add($cmd);
+                    }
                 }
             }
         }
-
-        return $availableCommands;
     }
 }
-- 
GitLab