[BUGFIX] Admin users should ignore user mounts
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Mvc / Cli / RequestBuilder.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Mvc\Cli;
3
4 /***************************************************************
5 * Copyright notice
6 * All rights reserved
7 *
8 * This class is a backport of the corresponding class of TYPO3 Flow.
9 * All credits go to the TYPO3 Flow team.
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 *
20 * This script is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * This copyright notice MUST APPEAR in all copies of the script!
26 ***************************************************************/
27 /**
28 * Builds a CLI request object from the raw command call
29 *
30 * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License, version 3 or later
31 */
32 class RequestBuilder {
33
34 /**
35 * @var \TYPO3\CMS\Extbase\Object\ObjectManagerInterface
36 * @inject
37 */
38 protected $objectManager;
39
40 /**
41 * @var \TYPO3\CMS\Extbase\Reflection\ReflectionService
42 * @inject
43 */
44 protected $reflectionService;
45
46 /**
47 * @var \TYPO3\CMS\Extbase\Mvc\Cli\CommandManager
48 * @inject
49 */
50 protected $commandManager;
51
52 /**
53 * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
54 * @inject
55 */
56 protected $configurationManager;
57
58 /**
59 * Builds a CLI request object from a command line.
60 *
61 * The given command line may be a string (e.g. "myextension:foo do-that-thing --force") or
62 * an array consisting of the individual parts. The array must not include the script
63 * name (like in $argv) but start with command right away.
64 *
65 * @param mixed $commandLine The command line, either as a string or as an array
66 * @return \TYPO3\CMS\Extbase\Mvc\Cli\Request The CLI request as an object
67 */
68 public function build($commandLine = '') {
69 $request = $this->objectManager->get('TYPO3\\CMS\\Extbase\\Mvc\\Cli\\Request');
70 $request->setControllerObjectName('TYPO3\\CMS\\Extbase\\Command\\HelpCommandController');
71 $rawCommandLineArguments = is_array($commandLine) ? $commandLine : explode(' ', $commandLine);
72 if (count($rawCommandLineArguments) === 0) {
73 $request->setControllerCommandName('helpStub');
74 return $request;
75 }
76 $commandIdentifier = trim(array_shift($rawCommandLineArguments));
77 try {
78 $command = $this->commandManager->getCommandByIdentifier($commandIdentifier);
79 $this->configurationManager->setConfiguration(array('extensionName' => $command->getExtensionName()));
80 } catch (\TYPO3\CMS\Extbase\Mvc\Exception\CommandException $exception) {
81 $request->setArgument('exception', $exception);
82 $request->setControllerCommandName('error');
83 return $request;
84 }
85 $controllerObjectName = $command->getControllerClassName();
86 $controllerCommandName = $command->getControllerCommandName();
87 $request->setControllerObjectName($controllerObjectName);
88 $request->setControllerCommandName($controllerCommandName);
89 list($commandLineArguments, $exceedingCommandLineArguments) = $this->parseRawCommandLineArguments($rawCommandLineArguments, $controllerObjectName, $controllerCommandName);
90 $request->setArguments($commandLineArguments);
91 $request->setExceedingArguments($exceedingCommandLineArguments);
92 return $request;
93 }
94
95 /**
96 * Takes an array of unparsed command line arguments and options and converts it separated
97 * by named arguments, options and unnamed arguments.
98 *
99 * @param array $rawCommandLineArguments The unparsed command parts (such as "--foo") as an array
100 * @param string $controllerObjectName Object name of the designated command controller
101 * @param string $controllerCommandName Command name of the recognized command (ie. method name without "Command" suffix)
102 * @throws \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentMixingException
103 * @return array All and exceeding command line arguments
104 */
105 protected function parseRawCommandLineArguments(array $rawCommandLineArguments, $controllerObjectName, $controllerCommandName) {
106 $commandLineArguments = array();
107 $exceedingArguments = array();
108 $commandMethodName = $controllerCommandName . 'Command';
109 $commandMethodParameters = $this->reflectionService->getMethodParameters($controllerObjectName, $commandMethodName);
110 $requiredArguments = array();
111 $optionalArguments = array();
112 $argumentNames = array();
113 foreach ($commandMethodParameters as $parameterName => $parameterInfo) {
114 $argumentNames[] = $parameterName;
115 if ($parameterInfo['optional'] === FALSE) {
116 $requiredArguments[strtolower($parameterName)] = array('parameterName' => $parameterName, 'type' => $parameterInfo['type']);
117 } else {
118 $optionalArguments[strtolower($parameterName)] = array('parameterName' => $parameterName, 'type' => $parameterInfo['type']);
119 }
120 }
121 $decidedToUseNamedArguments = FALSE;
122 $decidedToUseUnnamedArguments = FALSE;
123 $argumentIndex = 0;
124 while (count($rawCommandLineArguments) > 0) {
125 $rawArgument = array_shift($rawCommandLineArguments);
126 if ($rawArgument[0] === '-') {
127 if ($rawArgument[1] === '-') {
128 $rawArgument = substr($rawArgument, 2);
129 } else {
130 $rawArgument = substr($rawArgument, 1);
131 }
132 $argumentName = $this->extractArgumentNameFromCommandLinePart($rawArgument);
133 if (isset($optionalArguments[$argumentName])) {
134 $argumentValue = $this->getValueOfCurrentCommandLineOption($rawArgument, $rawCommandLineArguments, $optionalArguments[$argumentName]['type']);
135 $commandLineArguments[$optionalArguments[$argumentName]['parameterName']] = $argumentValue;
136 } elseif (isset($requiredArguments[$argumentName])) {
137 if ($decidedToUseUnnamedArguments) {
138 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentMixingException(sprintf('Unexpected named argument "%s". If you use unnamed arguments, all required arguments must be passed without a name.', $argumentName), 1309971821);
139 }
140 $decidedToUseNamedArguments = TRUE;
141 $argumentValue = $this->getValueOfCurrentCommandLineOption($rawArgument, $rawCommandLineArguments, $requiredArguments[$argumentName]['type']);
142 $commandLineArguments[$requiredArguments[$argumentName]['parameterName']] = $argumentValue;
143 unset($requiredArguments[$argumentName]);
144 }
145 } else {
146 if (count($requiredArguments) > 0) {
147 if ($decidedToUseNamedArguments) {
148 throw new \TYPO3\CMS\Extbase\Mvc\Exception\InvalidArgumentMixingException(sprintf('Unexpected unnamed argument "%s". If you use named arguments, all required arguments must be passed named.', $rawArgument), 1309971820);
149 }
150 $argument = array_shift($requiredArguments);
151 $commandLineArguments[$argument['parameterName']] = $rawArgument;
152 $decidedToUseUnnamedArguments = TRUE;
153 } else {
154 if ($argumentIndex < count($argumentNames)) {
155 $commandLineArguments[$argumentNames[$argumentIndex]] = $rawArgument;
156 } else {
157 $exceedingArguments[] = $rawArgument;
158 }
159 }
160 }
161 $argumentIndex++;
162 }
163 return array($commandLineArguments, $exceedingArguments);
164 }
165
166 /**
167 * Extracts the option or argument name from the name / value pair of a command line.
168 *
169 * @param string $commandLinePart Part of the command line, e.g. "my-important-option=SomeInterestingValue
170 * @return string The lowercased argument name, e.g. "myimportantoption
171 */
172 protected function extractArgumentNameFromCommandLinePart($commandLinePart) {
173 $nameAndValue = explode('=', $commandLinePart, 2);
174 return strtolower(str_replace('-', '', $nameAndValue[0]));
175 }
176
177 /**
178 * Returns the value of the first argument of the given input array. Shifts the parsed argument off the array.
179 *
180 * @param string $currentArgument The current argument
181 * @param array &$rawCommandLineArguments Array of the remaining command line arguments
182 * @param string $expectedArgumentType The expected type of the current argument, because booleans get special attention
183 * @return string The value of the first argument
184 */
185 protected function getValueOfCurrentCommandLineOption($currentArgument, array &$rawCommandLineArguments, $expectedArgumentType) {
186 if (!isset($rawCommandLineArguments[0]) && strpos($currentArgument, '=') === FALSE || isset($rawCommandLineArguments[0]) && $rawCommandLineArguments[0][0] === '-' && strpos($currentArgument, '=') === FALSE) {
187 return TRUE;
188 }
189 if (strpos($currentArgument, '=') === FALSE) {
190 $possibleValue = trim(array_shift($rawCommandLineArguments));
191 if (strpos($possibleValue, '=') === FALSE) {
192 if ($expectedArgumentType !== 'boolean') {
193 return $possibleValue;
194 }
195 if (array_search($possibleValue, array('on', '1', 'y', 'yes', 'true', 'TRUE')) !== FALSE) {
196 return TRUE;
197 }
198 if (array_search($possibleValue, array('off', '0', 'n', 'no', 'false', 'FALSE')) !== FALSE) {
199 return FALSE;
200 }
201 array_unshift($rawCommandLineArguments, $possibleValue);
202 return TRUE;
203 }
204 $currentArgument .= $possibleValue;
205 }
206 $splitArgument = explode('=', $currentArgument, 2);
207 while ((!isset($splitArgument[1]) || trim($splitArgument[1]) === '') && count($rawCommandLineArguments) > 0) {
208 $currentArgument .= array_shift($rawCommandLineArguments);
209 $splitArgument = explode('=', $currentArgument);
210 }
211 $value = isset($splitArgument[1]) ? $splitArgument[1] : '';
212 return $value;
213 }
214 }