[TASK] Improve duplicate exception code check
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Console / CommandRequestHandler.php
1 <?php
2 namespace TYPO3\CMS\Core\Console;
3
4 /*
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16
17 use Symfony\Component\Console\Application;
18 use Symfony\Component\Console\Command\Command;
19 use Symfony\Component\Console\Input\InputInterface;
20 use Symfony\Component\Console\Output\ConsoleOutput;
21 use TYPO3\CMS\Core\Core\Bootstrap;
22 use TYPO3\CMS\Core\Package\PackageManager;
23 use TYPO3\CMS\Core\Utility\GeneralUtility;
24
25 /**
26 * Command Line Interface Request Handler dealing with registered commands.
27 */
28 class CommandRequestHandler implements RequestHandlerInterface
29 {
30 /**
31 * Instance of the current TYPO3 bootstrap
32 * @var Bootstrap
33 */
34 protected $bootstrap;
35
36 /**
37 * Instance of the symfony application
38 * @var Application
39 */
40 protected $application;
41
42 /**
43 * @var []
44 */
45 protected $availableCommands;
46
47 /**
48 * Constructor handing over the bootstrap
49 *
50 * @param Bootstrap $bootstrap
51 */
52 public function __construct(Bootstrap $bootstrap)
53 {
54 $this->bootstrap = $bootstrap;
55 $this->application = new Application('TYPO3 CMS', TYPO3_version);
56 }
57
58 /**
59 * Handles any commandline request
60 *
61 * @param InputInterface $input
62 * @return void
63 */
64 public function handleRequest(InputInterface $input)
65 {
66 $output = new ConsoleOutput();
67
68 $this->bootstrap->loadExtensionTables();
69
70 // Check if the command to run needs a backend user to be loaded
71 $command = $this->getCommandToRun($input);
72 foreach ($this->availableCommands as $data) {
73 if ($data['command'] !== $command) {
74 continue;
75 }
76 if (isset($data['user'])) {
77 $this->initializeBackendUser($data['user']);
78 }
79 }
80
81 // Make sure output is not buffered, so command-line output and interaction can take place
82 $this->bootstrap->endOutputBufferingAndCleanPreviousOutput();
83 $exitCode = $this->application->run($input, $output);
84 exit($exitCode);
85 }
86
87 /**
88 * If the backend script is in CLI mode, it will try to load a backend user named by the CLI module name (in lowercase)
89 *
90 * @param string $userName the name of the module registered inside $TYPO3_CONF_VARS[SC_OPTIONS][GLOBAL][cliKeys] as second parameter
91 * @throws \RuntimeException if a non-admin Backend user could not be loaded
92 */
93 protected function initializeBackendUser($userName)
94 {
95 $this->bootstrap->initializeBackendUser();
96
97 $GLOBALS['BE_USER']->setBeUserByName($userName);
98 if (!$GLOBALS['BE_USER']->user['uid']) {
99 throw new \RuntimeException('No backend user named "' . $userName . '" was found!', 1476107260);
100 }
101
102 $this->bootstrap
103 ->initializeBackendAuthentication()
104 ->initializeLanguageObject();
105 }
106
107 /**
108 * This request handler can handle any CLI request, but checks for
109 *
110 * @param InputInterface $input
111 * @return bool Always TRUE
112 */
113 public function canHandleRequest(InputInterface $input)
114 {
115 $this->populateAvailableCommands();
116 return $this->getCommandToRun($input) !== false;
117 }
118
119 /**
120 * Returns the priority - how eager the handler is to actually handle the request.
121 *
122 * @return int The priority of the request handler.
123 */
124 public function getPriority()
125 {
126 return 50;
127 }
128
129 /**
130 *
131 * @param InputInterface $input
132 * @return bool|Command
133 */
134 protected function getCommandToRun(InputInterface $input)
135 {
136 $firstArgument = $input->getFirstArgument();
137 try {
138 return $this->application->find($firstArgument);
139 } catch (\InvalidArgumentException $e) {
140 return false;
141 }
142 }
143
144 /**
145 * put all available commands inside the application
146 */
147 protected function populateAvailableCommands()
148 {
149 $this->availableCommands = $this->getAvailableCommands();
150 foreach ($this->availableCommands as $name => $data) {
151 /** @var Command $cmd */
152 $cmd = GeneralUtility::makeInstance($data['class'], $name);
153 $this->application->add($cmd);
154 $this->availableCommands[$name]['command'] = $cmd;
155 }
156 }
157
158 /**
159 * Fetches all commands registered via Commands.php of all active packages
160 *
161 * @return array
162 */
163 protected function getAvailableCommands()
164 {
165 /** @var PackageManager $packageManager */
166 $packageManager = Bootstrap::getInstance()->getEarlyInstance(PackageManager::class);
167 $availableCommands = [];
168
169 foreach ($packageManager->getActivePackages() as $package) {
170 $commandsOfExtension = $package->getPackagePath() . 'Configuration/Commands.php';
171 if (@is_file($commandsOfExtension)) {
172 $commands = require_once $commandsOfExtension;
173 if (is_array($commands)) {
174 $availableCommands = array_merge($availableCommands, $commands);
175 }
176 }
177 }
178
179 return $availableCommands;
180 }
181 }