Chris@0
|
1 <?php
|
Chris@0
|
2 namespace Consolidation\AnnotatedCommand;
|
Chris@0
|
3
|
Chris@0
|
4 use Consolidation\AnnotatedCommand\Cache\CacheWrapper;
|
Chris@0
|
5 use Consolidation\AnnotatedCommand\Cache\NullCache;
|
Chris@0
|
6 use Consolidation\AnnotatedCommand\Cache\SimpleCacheInterface;
|
Chris@0
|
7 use Consolidation\AnnotatedCommand\Hooks\HookManager;
|
Chris@0
|
8 use Consolidation\AnnotatedCommand\Options\AutomaticOptionsProviderInterface;
|
Chris@0
|
9 use Consolidation\AnnotatedCommand\Parser\CommandInfo;
|
Chris@0
|
10 use Consolidation\AnnotatedCommand\Parser\CommandInfoDeserializer;
|
Chris@0
|
11 use Consolidation\AnnotatedCommand\Parser\CommandInfoSerializer;
|
Chris@0
|
12 use Consolidation\OutputFormatters\Options\FormatterOptions;
|
Chris@0
|
13 use Symfony\Component\Console\Command\Command;
|
Chris@0
|
14 use Symfony\Component\Console\Input\InputInterface;
|
Chris@0
|
15 use Symfony\Component\Console\Output\OutputInterface;
|
Chris@0
|
16
|
Chris@0
|
17 /**
|
Chris@0
|
18 * The AnnotatedCommandFactory creates commands for your application.
|
Chris@0
|
19 * Use with a Dependency Injection Container and the CommandFactory.
|
Chris@0
|
20 * Alternately, use the CommandFileDiscovery to find commandfiles, and
|
Chris@0
|
21 * then use AnnotatedCommandFactory::createCommandsFromClass() to create
|
Chris@0
|
22 * commands. See the README for more information.
|
Chris@0
|
23 *
|
Chris@0
|
24 * @package Consolidation\AnnotatedCommand
|
Chris@0
|
25 */
|
Chris@0
|
26 class AnnotatedCommandFactory implements AutomaticOptionsProviderInterface
|
Chris@0
|
27 {
|
Chris@0
|
28 /** var CommandProcessor */
|
Chris@0
|
29 protected $commandProcessor;
|
Chris@0
|
30
|
Chris@0
|
31 /** var CommandCreationListenerInterface[] */
|
Chris@0
|
32 protected $listeners = [];
|
Chris@0
|
33
|
Chris@0
|
34 /** var AutomaticOptionsProvider[] */
|
Chris@0
|
35 protected $automaticOptionsProviderList = [];
|
Chris@0
|
36
|
Chris@0
|
37 /** var boolean */
|
Chris@0
|
38 protected $includeAllPublicMethods = true;
|
Chris@0
|
39
|
Chris@0
|
40 /** var CommandInfoAltererInterface */
|
Chris@0
|
41 protected $commandInfoAlterers = [];
|
Chris@0
|
42
|
Chris@0
|
43 /** var SimpleCacheInterface */
|
Chris@0
|
44 protected $dataStore;
|
Chris@0
|
45
|
Chris@0
|
46 public function __construct()
|
Chris@0
|
47 {
|
Chris@0
|
48 $this->dataStore = new NullCache();
|
Chris@0
|
49 $this->commandProcessor = new CommandProcessor(new HookManager());
|
Chris@0
|
50 $this->addAutomaticOptionProvider($this);
|
Chris@0
|
51 }
|
Chris@0
|
52
|
Chris@0
|
53 public function setCommandProcessor(CommandProcessor $commandProcessor)
|
Chris@0
|
54 {
|
Chris@0
|
55 $this->commandProcessor = $commandProcessor;
|
Chris@0
|
56 return $this;
|
Chris@0
|
57 }
|
Chris@0
|
58
|
Chris@0
|
59 /**
|
Chris@0
|
60 * @return CommandProcessor
|
Chris@0
|
61 */
|
Chris@0
|
62 public function commandProcessor()
|
Chris@0
|
63 {
|
Chris@0
|
64 return $this->commandProcessor;
|
Chris@0
|
65 }
|
Chris@0
|
66
|
Chris@0
|
67 /**
|
Chris@0
|
68 * Set the 'include all public methods flag'. If true (the default), then
|
Chris@0
|
69 * every public method of each commandFile will be used to create commands.
|
Chris@0
|
70 * If it is false, then only those public methods annotated with @command
|
Chris@0
|
71 * or @name (deprecated) will be used to create commands.
|
Chris@0
|
72 */
|
Chris@0
|
73 public function setIncludeAllPublicMethods($includeAllPublicMethods)
|
Chris@0
|
74 {
|
Chris@0
|
75 $this->includeAllPublicMethods = $includeAllPublicMethods;
|
Chris@0
|
76 return $this;
|
Chris@0
|
77 }
|
Chris@0
|
78
|
Chris@0
|
79 public function getIncludeAllPublicMethods()
|
Chris@0
|
80 {
|
Chris@0
|
81 return $this->includeAllPublicMethods;
|
Chris@0
|
82 }
|
Chris@0
|
83
|
Chris@0
|
84 /**
|
Chris@0
|
85 * @return HookManager
|
Chris@0
|
86 */
|
Chris@0
|
87 public function hookManager()
|
Chris@0
|
88 {
|
Chris@0
|
89 return $this->commandProcessor()->hookManager();
|
Chris@0
|
90 }
|
Chris@0
|
91
|
Chris@0
|
92 /**
|
Chris@0
|
93 * Add a listener that is notified immediately before the command
|
Chris@0
|
94 * factory creates commands from a commandFile instance. This
|
Chris@0
|
95 * listener can use this opportunity to do more setup for the commandFile,
|
Chris@0
|
96 * and so on.
|
Chris@0
|
97 *
|
Chris@0
|
98 * @param CommandCreationListenerInterface $listener
|
Chris@0
|
99 */
|
Chris@0
|
100 public function addListener(CommandCreationListenerInterface $listener)
|
Chris@0
|
101 {
|
Chris@0
|
102 $this->listeners[] = $listener;
|
Chris@0
|
103 return $this;
|
Chris@0
|
104 }
|
Chris@0
|
105
|
Chris@0
|
106 /**
|
Chris@0
|
107 * Add a listener that's just a simple 'callable'.
|
Chris@0
|
108 * @param callable $listener
|
Chris@0
|
109 */
|
Chris@0
|
110 public function addListernerCallback(callable $listener)
|
Chris@0
|
111 {
|
Chris@0
|
112 $this->addListener(new CommandCreationListener($listener));
|
Chris@0
|
113 return $this;
|
Chris@0
|
114 }
|
Chris@0
|
115
|
Chris@0
|
116 /**
|
Chris@0
|
117 * Call all command creation listeners
|
Chris@0
|
118 *
|
Chris@0
|
119 * @param object $commandFileInstance
|
Chris@0
|
120 */
|
Chris@0
|
121 protected function notify($commandFileInstance)
|
Chris@0
|
122 {
|
Chris@0
|
123 foreach ($this->listeners as $listener) {
|
Chris@0
|
124 $listener->notifyCommandFileAdded($commandFileInstance);
|
Chris@0
|
125 }
|
Chris@0
|
126 }
|
Chris@0
|
127
|
Chris@0
|
128 public function addAutomaticOptionProvider(AutomaticOptionsProviderInterface $optionsProvider)
|
Chris@0
|
129 {
|
Chris@0
|
130 $this->automaticOptionsProviderList[] = $optionsProvider;
|
Chris@0
|
131 }
|
Chris@0
|
132
|
Chris@0
|
133 public function addCommandInfoAlterer(CommandInfoAltererInterface $alterer)
|
Chris@0
|
134 {
|
Chris@0
|
135 $this->commandInfoAlterers[] = $alterer;
|
Chris@0
|
136 }
|
Chris@0
|
137
|
Chris@0
|
138 /**
|
Chris@0
|
139 * n.b. This registers all hooks from the commandfile instance as a side-effect.
|
Chris@0
|
140 */
|
Chris@0
|
141 public function createCommandsFromClass($commandFileInstance, $includeAllPublicMethods = null)
|
Chris@0
|
142 {
|
Chris@0
|
143 // Deprecated: avoid using the $includeAllPublicMethods in favor of the setIncludeAllPublicMethods() accessor.
|
Chris@0
|
144 if (!isset($includeAllPublicMethods)) {
|
Chris@0
|
145 $includeAllPublicMethods = $this->getIncludeAllPublicMethods();
|
Chris@0
|
146 }
|
Chris@0
|
147 $this->notify($commandFileInstance);
|
Chris@0
|
148 $commandInfoList = $this->getCommandInfoListFromClass($commandFileInstance);
|
Chris@0
|
149 $this->registerCommandHooksFromClassInfo($commandInfoList, $commandFileInstance);
|
Chris@0
|
150 return $this->createCommandsFromClassInfo($commandInfoList, $commandFileInstance, $includeAllPublicMethods);
|
Chris@0
|
151 }
|
Chris@0
|
152
|
Chris@0
|
153 public function getCommandInfoListFromClass($commandFileInstance)
|
Chris@0
|
154 {
|
Chris@0
|
155 $cachedCommandInfoList = $this->getCommandInfoListFromCache($commandFileInstance);
|
Chris@0
|
156 $commandInfoList = $this->createCommandInfoListFromClass($commandFileInstance, $cachedCommandInfoList);
|
Chris@0
|
157 if (!empty($commandInfoList)) {
|
Chris@0
|
158 $cachedCommandInfoList = array_merge($commandInfoList, $cachedCommandInfoList);
|
Chris@0
|
159 $this->storeCommandInfoListInCache($commandFileInstance, $cachedCommandInfoList);
|
Chris@0
|
160 }
|
Chris@0
|
161 return $cachedCommandInfoList;
|
Chris@0
|
162 }
|
Chris@0
|
163
|
Chris@0
|
164 protected function storeCommandInfoListInCache($commandFileInstance, $commandInfoList)
|
Chris@0
|
165 {
|
Chris@0
|
166 if (!$this->hasDataStore()) {
|
Chris@0
|
167 return;
|
Chris@0
|
168 }
|
Chris@0
|
169 $cache_data = [];
|
Chris@0
|
170 $serializer = new CommandInfoSerializer();
|
Chris@0
|
171 foreach ($commandInfoList as $i => $commandInfo) {
|
Chris@0
|
172 $cache_data[$i] = $serializer->serialize($commandInfo);
|
Chris@0
|
173 }
|
Chris@0
|
174 $className = get_class($commandFileInstance);
|
Chris@0
|
175 $this->getDataStore()->set($className, $cache_data);
|
Chris@0
|
176 }
|
Chris@0
|
177
|
Chris@0
|
178 /**
|
Chris@0
|
179 * Get the command info list from the cache
|
Chris@0
|
180 *
|
Chris@0
|
181 * @param mixed $commandFileInstance
|
Chris@0
|
182 * @return array
|
Chris@0
|
183 */
|
Chris@0
|
184 protected function getCommandInfoListFromCache($commandFileInstance)
|
Chris@0
|
185 {
|
Chris@0
|
186 $commandInfoList = [];
|
Chris@0
|
187 $className = get_class($commandFileInstance);
|
Chris@0
|
188 if (!$this->getDataStore()->has($className)) {
|
Chris@0
|
189 return [];
|
Chris@0
|
190 }
|
Chris@0
|
191 $deserializer = new CommandInfoDeserializer();
|
Chris@0
|
192
|
Chris@0
|
193 $cache_data = $this->getDataStore()->get($className);
|
Chris@0
|
194 foreach ($cache_data as $i => $data) {
|
Chris@0
|
195 if (CommandInfoDeserializer::isValidSerializedData((array)$data)) {
|
Chris@0
|
196 $commandInfoList[$i] = $deserializer->deserialize((array)$data);
|
Chris@0
|
197 }
|
Chris@0
|
198 }
|
Chris@0
|
199 return $commandInfoList;
|
Chris@0
|
200 }
|
Chris@0
|
201
|
Chris@0
|
202 /**
|
Chris@0
|
203 * Check to see if this factory has a cache datastore.
|
Chris@0
|
204 * @return boolean
|
Chris@0
|
205 */
|
Chris@0
|
206 public function hasDataStore()
|
Chris@0
|
207 {
|
Chris@0
|
208 return !($this->dataStore instanceof NullCache);
|
Chris@0
|
209 }
|
Chris@0
|
210
|
Chris@0
|
211 /**
|
Chris@0
|
212 * Set a cache datastore for this factory. Any object with 'set' and
|
Chris@0
|
213 * 'get' methods is acceptable. The key is the classname being cached,
|
Chris@0
|
214 * and the value is a nested associative array of strings.
|
Chris@0
|
215 *
|
Chris@0
|
216 * TODO: Typehint this to SimpleCacheInterface
|
Chris@0
|
217 *
|
Chris@0
|
218 * This is not done currently to allow clients to use a generic cache
|
Chris@0
|
219 * store that does not itself depend on the annotated-command library.
|
Chris@0
|
220 *
|
Chris@0
|
221 * @param Mixed $dataStore
|
Chris@0
|
222 * @return type
|
Chris@0
|
223 */
|
Chris@0
|
224 public function setDataStore($dataStore)
|
Chris@0
|
225 {
|
Chris@0
|
226 if (!($dataStore instanceof SimpleCacheInterface)) {
|
Chris@0
|
227 $dataStore = new CacheWrapper($dataStore);
|
Chris@0
|
228 }
|
Chris@0
|
229 $this->dataStore = $dataStore;
|
Chris@0
|
230 return $this;
|
Chris@0
|
231 }
|
Chris@0
|
232
|
Chris@0
|
233 /**
|
Chris@0
|
234 * Get the data store attached to this factory.
|
Chris@0
|
235 */
|
Chris@0
|
236 public function getDataStore()
|
Chris@0
|
237 {
|
Chris@0
|
238 return $this->dataStore;
|
Chris@0
|
239 }
|
Chris@0
|
240
|
Chris@0
|
241 protected function createCommandInfoListFromClass($classNameOrInstance, $cachedCommandInfoList)
|
Chris@0
|
242 {
|
Chris@0
|
243 $commandInfoList = [];
|
Chris@0
|
244
|
Chris@0
|
245 // Ignore special functions, such as __construct and __call, which
|
Chris@0
|
246 // can never be commands.
|
Chris@0
|
247 $commandMethodNames = array_filter(
|
Chris@0
|
248 get_class_methods($classNameOrInstance) ?: [],
|
Chris@0
|
249 function ($m) use ($classNameOrInstance) {
|
Chris@0
|
250 $reflectionMethod = new \ReflectionMethod($classNameOrInstance, $m);
|
Chris@0
|
251 return !$reflectionMethod->isStatic() && !preg_match('#^_#', $m);
|
Chris@0
|
252 }
|
Chris@0
|
253 );
|
Chris@0
|
254
|
Chris@0
|
255 foreach ($commandMethodNames as $commandMethodName) {
|
Chris@0
|
256 if (!array_key_exists($commandMethodName, $cachedCommandInfoList)) {
|
Chris@0
|
257 $commandInfo = CommandInfo::create($classNameOrInstance, $commandMethodName);
|
Chris@0
|
258 if (!static::isCommandOrHookMethod($commandInfo, $this->getIncludeAllPublicMethods())) {
|
Chris@0
|
259 $commandInfo->invalidate();
|
Chris@0
|
260 }
|
Chris@0
|
261 $commandInfoList[$commandMethodName] = $commandInfo;
|
Chris@0
|
262 }
|
Chris@0
|
263 }
|
Chris@0
|
264
|
Chris@0
|
265 return $commandInfoList;
|
Chris@0
|
266 }
|
Chris@0
|
267
|
Chris@0
|
268 public function createCommandInfo($classNameOrInstance, $commandMethodName)
|
Chris@0
|
269 {
|
Chris@0
|
270 return CommandInfo::create($classNameOrInstance, $commandMethodName);
|
Chris@0
|
271 }
|
Chris@0
|
272
|
Chris@0
|
273 public function createCommandsFromClassInfo($commandInfoList, $commandFileInstance, $includeAllPublicMethods = null)
|
Chris@0
|
274 {
|
Chris@0
|
275 // Deprecated: avoid using the $includeAllPublicMethods in favor of the setIncludeAllPublicMethods() accessor.
|
Chris@0
|
276 if (!isset($includeAllPublicMethods)) {
|
Chris@0
|
277 $includeAllPublicMethods = $this->getIncludeAllPublicMethods();
|
Chris@0
|
278 }
|
Chris@0
|
279 return $this->createSelectedCommandsFromClassInfo(
|
Chris@0
|
280 $commandInfoList,
|
Chris@0
|
281 $commandFileInstance,
|
Chris@0
|
282 function ($commandInfo) use ($includeAllPublicMethods) {
|
Chris@0
|
283 return static::isCommandMethod($commandInfo, $includeAllPublicMethods);
|
Chris@0
|
284 }
|
Chris@0
|
285 );
|
Chris@0
|
286 }
|
Chris@0
|
287
|
Chris@0
|
288 public function createSelectedCommandsFromClassInfo($commandInfoList, $commandFileInstance, callable $commandSelector)
|
Chris@0
|
289 {
|
Chris@0
|
290 $commandInfoList = $this->filterCommandInfoList($commandInfoList, $commandSelector);
|
Chris@0
|
291 return array_map(
|
Chris@0
|
292 function ($commandInfo) use ($commandFileInstance) {
|
Chris@0
|
293 return $this->createCommand($commandInfo, $commandFileInstance);
|
Chris@0
|
294 },
|
Chris@0
|
295 $commandInfoList
|
Chris@0
|
296 );
|
Chris@0
|
297 }
|
Chris@0
|
298
|
Chris@0
|
299 protected function filterCommandInfoList($commandInfoList, callable $commandSelector)
|
Chris@0
|
300 {
|
Chris@0
|
301 return array_filter($commandInfoList, $commandSelector);
|
Chris@0
|
302 }
|
Chris@0
|
303
|
Chris@0
|
304 public static function isCommandOrHookMethod($commandInfo, $includeAllPublicMethods)
|
Chris@0
|
305 {
|
Chris@0
|
306 return static::isHookMethod($commandInfo) || static::isCommandMethod($commandInfo, $includeAllPublicMethods);
|
Chris@0
|
307 }
|
Chris@0
|
308
|
Chris@0
|
309 public static function isHookMethod($commandInfo)
|
Chris@0
|
310 {
|
Chris@0
|
311 return $commandInfo->hasAnnotation('hook');
|
Chris@0
|
312 }
|
Chris@0
|
313
|
Chris@0
|
314 public static function isCommandMethod($commandInfo, $includeAllPublicMethods)
|
Chris@0
|
315 {
|
Chris@0
|
316 // Ignore everything labeled @hook
|
Chris@0
|
317 if (static::isHookMethod($commandInfo)) {
|
Chris@0
|
318 return false;
|
Chris@0
|
319 }
|
Chris@0
|
320 // Include everything labeled @command
|
Chris@0
|
321 if ($commandInfo->hasAnnotation('command')) {
|
Chris@0
|
322 return true;
|
Chris@0
|
323 }
|
Chris@0
|
324 // Skip anything that has a missing or invalid name.
|
Chris@0
|
325 $commandName = $commandInfo->getName();
|
Chris@0
|
326 if (empty($commandName) || preg_match('#[^a-zA-Z0-9:_-]#', $commandName)) {
|
Chris@0
|
327 return false;
|
Chris@0
|
328 }
|
Chris@0
|
329 // Skip anything named like an accessor ('get' or 'set')
|
Chris@0
|
330 if (preg_match('#^(get[A-Z]|set[A-Z])#', $commandInfo->getMethodName())) {
|
Chris@0
|
331 return false;
|
Chris@0
|
332 }
|
Chris@0
|
333
|
Chris@0
|
334 // Default to the setting of 'include all public methods'.
|
Chris@0
|
335 return $includeAllPublicMethods;
|
Chris@0
|
336 }
|
Chris@0
|
337
|
Chris@0
|
338 public function registerCommandHooksFromClassInfo($commandInfoList, $commandFileInstance)
|
Chris@0
|
339 {
|
Chris@0
|
340 foreach ($commandInfoList as $commandInfo) {
|
Chris@0
|
341 if (static::isHookMethod($commandInfo)) {
|
Chris@0
|
342 $this->registerCommandHook($commandInfo, $commandFileInstance);
|
Chris@0
|
343 }
|
Chris@0
|
344 }
|
Chris@0
|
345 }
|
Chris@0
|
346
|
Chris@0
|
347 /**
|
Chris@0
|
348 * Register a command hook given the CommandInfo for a method.
|
Chris@0
|
349 *
|
Chris@0
|
350 * The hook format is:
|
Chris@0
|
351 *
|
Chris@0
|
352 * @hook type name type
|
Chris@0
|
353 *
|
Chris@0
|
354 * For example, the pre-validate hook for the core:init command is:
|
Chris@0
|
355 *
|
Chris@0
|
356 * @hook pre-validate core:init
|
Chris@0
|
357 *
|
Chris@0
|
358 * If no command name is provided, then this hook will affect every
|
Chris@0
|
359 * command that is defined in the same file.
|
Chris@0
|
360 *
|
Chris@0
|
361 * If no hook is provided, then we will presume that ALTER_RESULT
|
Chris@0
|
362 * is intended.
|
Chris@0
|
363 *
|
Chris@0
|
364 * @param CommandInfo $commandInfo Information about the command hook method.
|
Chris@0
|
365 * @param object $commandFileInstance An instance of the CommandFile class.
|
Chris@0
|
366 */
|
Chris@0
|
367 public function registerCommandHook(CommandInfo $commandInfo, $commandFileInstance)
|
Chris@0
|
368 {
|
Chris@0
|
369 // Ignore if the command info has no @hook
|
Chris@0
|
370 if (!static::isHookMethod($commandInfo)) {
|
Chris@0
|
371 return;
|
Chris@0
|
372 }
|
Chris@0
|
373 $hookData = $commandInfo->getAnnotation('hook');
|
Chris@0
|
374 $hook = $this->getNthWord($hookData, 0, HookManager::ALTER_RESULT);
|
Chris@0
|
375 $commandName = $this->getNthWord($hookData, 1);
|
Chris@0
|
376
|
Chris@0
|
377 // Register the hook
|
Chris@0
|
378 $callback = [$commandFileInstance, $commandInfo->getMethodName()];
|
Chris@0
|
379 $this->commandProcessor()->hookManager()->add($callback, $hook, $commandName);
|
Chris@0
|
380
|
Chris@0
|
381 // If the hook has options, then also register the commandInfo
|
Chris@0
|
382 // with the hook manager, so that we can add options and such to
|
Chris@0
|
383 // the commands they hook.
|
Chris@0
|
384 if (!$commandInfo->options()->isEmpty()) {
|
Chris@0
|
385 $this->commandProcessor()->hookManager()->recordHookOptions($commandInfo, $commandName);
|
Chris@0
|
386 }
|
Chris@0
|
387 }
|
Chris@0
|
388
|
Chris@0
|
389 protected function getNthWord($string, $n, $default = '', $delimiter = ' ')
|
Chris@0
|
390 {
|
Chris@0
|
391 $words = explode($delimiter, $string);
|
Chris@0
|
392 if (!empty($words[$n])) {
|
Chris@0
|
393 return $words[$n];
|
Chris@0
|
394 }
|
Chris@0
|
395 return $default;
|
Chris@0
|
396 }
|
Chris@0
|
397
|
Chris@0
|
398 public function createCommand(CommandInfo $commandInfo, $commandFileInstance)
|
Chris@0
|
399 {
|
Chris@0
|
400 $this->alterCommandInfo($commandInfo, $commandFileInstance);
|
Chris@0
|
401 $command = new AnnotatedCommand($commandInfo->getName());
|
Chris@0
|
402 $commandCallback = [$commandFileInstance, $commandInfo->getMethodName()];
|
Chris@0
|
403 $command->setCommandCallback($commandCallback);
|
Chris@0
|
404 $command->setCommandProcessor($this->commandProcessor);
|
Chris@0
|
405 $command->setCommandInfo($commandInfo);
|
Chris@0
|
406 $automaticOptions = $this->callAutomaticOptionsProviders($commandInfo);
|
Chris@0
|
407 $command->setCommandOptions($commandInfo, $automaticOptions);
|
Chris@0
|
408 // Annotation commands are never bootstrap-aware, but for completeness
|
Chris@0
|
409 // we will notify on every created command, as some clients may wish to
|
Chris@0
|
410 // use this notification for some other purpose.
|
Chris@0
|
411 $this->notify($command);
|
Chris@0
|
412 return $command;
|
Chris@0
|
413 }
|
Chris@0
|
414
|
Chris@0
|
415 /**
|
Chris@0
|
416 * Give plugins an opportunity to update the commandInfo
|
Chris@0
|
417 */
|
Chris@0
|
418 public function alterCommandInfo(CommandInfo $commandInfo, $commandFileInstance)
|
Chris@0
|
419 {
|
Chris@0
|
420 foreach ($this->commandInfoAlterers as $alterer) {
|
Chris@0
|
421 $alterer->alterCommandInfo($commandInfo, $commandFileInstance);
|
Chris@0
|
422 }
|
Chris@0
|
423 }
|
Chris@0
|
424
|
Chris@0
|
425 /**
|
Chris@0
|
426 * Get the options that are implied by annotations, e.g. @fields implies
|
Chris@0
|
427 * that there should be a --fields and a --format option.
|
Chris@0
|
428 *
|
Chris@0
|
429 * @return InputOption[]
|
Chris@0
|
430 */
|
Chris@0
|
431 public function callAutomaticOptionsProviders(CommandInfo $commandInfo)
|
Chris@0
|
432 {
|
Chris@0
|
433 $automaticOptions = [];
|
Chris@0
|
434 foreach ($this->automaticOptionsProviderList as $automaticOptionsProvider) {
|
Chris@0
|
435 $automaticOptions += $automaticOptionsProvider->automaticOptions($commandInfo);
|
Chris@0
|
436 }
|
Chris@0
|
437 return $automaticOptions;
|
Chris@0
|
438 }
|
Chris@0
|
439
|
Chris@0
|
440 /**
|
Chris@0
|
441 * Get the options that are implied by annotations, e.g. @fields implies
|
Chris@0
|
442 * that there should be a --fields and a --format option.
|
Chris@0
|
443 *
|
Chris@0
|
444 * @return InputOption[]
|
Chris@0
|
445 */
|
Chris@0
|
446 public function automaticOptions(CommandInfo $commandInfo)
|
Chris@0
|
447 {
|
Chris@0
|
448 $automaticOptions = [];
|
Chris@0
|
449 $formatManager = $this->commandProcessor()->formatterManager();
|
Chris@0
|
450 if ($formatManager) {
|
Chris@0
|
451 $annotationData = $commandInfo->getAnnotations()->getArrayCopy();
|
Chris@0
|
452 $formatterOptions = new FormatterOptions($annotationData);
|
Chris@0
|
453 $dataType = $commandInfo->getReturnType();
|
Chris@0
|
454 $automaticOptions = $formatManager->automaticOptions($formatterOptions, $dataType);
|
Chris@0
|
455 }
|
Chris@0
|
456 return $automaticOptions;
|
Chris@0
|
457 }
|
Chris@0
|
458 }
|