dd48b7a8544f6ca6d90d245cfa8c0e0185fc6694
[yaffs-website] / vendor / consolidation / robo / src / Robo.php
1 <?php
2 namespace Robo;
3
4 use Composer\Autoload\ClassLoader;
5 use League\Container\Container;
6 use League\Container\ContainerInterface;
7 use Robo\Common\ProcessExecutor;
8 use Consolidation\Config\ConfigInterface;
9 use Consolidation\Config\Loader\ConfigProcessor;
10 use Consolidation\Config\Loader\YamlConfigLoader;
11 use Symfony\Component\Console\Input\StringInput;
12 use Symfony\Component\Console\Application as SymfonyApplication;
13 use Symfony\Component\Process\Process;
14
15 /**
16  * Manages the container reference and other static data.  Favor
17  * using dependency injection wherever possible.  Avoid using
18  * this class directly, unless setting up a custom DI container.
19  */
20 class Robo
21 {
22     const APPLICATION_NAME = 'Robo';
23     const VERSION = '1.2.3';
24
25     /**
26      * The currently active container object, or NULL if not initialized yet.
27      *
28      * @var ContainerInterface|null
29      */
30     protected static $container;
31
32     /**
33      * Entrypoint for standalone Robo-based tools.  See docs/framework.md.
34      *
35      * @param string[] $argv
36      * @param string $commandClasses
37      * @param null|string $appName
38      * @param null|string $appVersion
39      * @param null|\Symfony\Component\Console\Output\OutputInterface $output
40      *
41      * @return int
42      */
43     public static function run($argv, $commandClasses, $appName = null, $appVersion = null, $output = null, $repository = null)
44     {
45         $runner = new \Robo\Runner($commandClasses);
46         $runner->setSelfUpdateRepository($repository);
47         $statusCode = $runner->execute($argv, $appName, $appVersion, $output);
48         return $statusCode;
49     }
50
51     /**
52      * Sets a new global container.
53      *
54      * @param ContainerInterface $container
55      *   A new container instance to replace the current.
56      */
57     public static function setContainer(ContainerInterface $container)
58     {
59         static::$container = $container;
60     }
61
62     /**
63      * Unsets the global container.
64      */
65     public static function unsetContainer()
66     {
67         static::$container = null;
68     }
69
70     /**
71      * Returns the currently active global container.
72      *
73      * @return \League\Container\ContainerInterface
74      *
75      * @throws \RuntimeException
76      */
77     public static function getContainer()
78     {
79         if (static::$container === null) {
80             throw new \RuntimeException('container is not initialized yet. \Robo\Robo::setContainer() must be called with a real container.');
81         }
82         return static::$container;
83     }
84
85     /**
86      * Returns TRUE if the container has been initialized, FALSE otherwise.
87      *
88      * @return bool
89      */
90     public static function hasContainer()
91     {
92         return static::$container !== null;
93     }
94
95     /**
96      * Create a config object and load it from the provided paths.
97      */
98     public static function createConfiguration($paths)
99     {
100         $config = new \Robo\Config\Config();
101         static::loadConfiguration($paths, $config);
102         return $config;
103     }
104
105     /**
106      * Use a simple config loader to load configuration values from specified paths
107      */
108     public static function loadConfiguration($paths, $config = null)
109     {
110         if ($config == null) {
111             $config = static::config();
112         }
113         $loader = new YamlConfigLoader();
114         $processor = new ConfigProcessor();
115         $processor->add($config->export());
116         foreach ($paths as $path) {
117             $processor->extend($loader->load($path));
118         }
119         $config->import($processor->export());
120     }
121
122     /**
123      * Create a container and initiailze it.  If you wish to *change*
124      * anything defined in the container, then you should call
125      * \Robo::configureContainer() instead of this function.
126      *
127      * @param null|\Symfony\Component\Console\Input\InputInterface $input
128      * @param null|\Symfony\Component\Console\Output\OutputInterface $output
129      * @param null|\Robo\Application $app
130      * @param null|ConfigInterface $config
131      * @param null|\Composer\Autoload\ClassLoader $classLoader
132      *
133      * @return \League\Container\Container|\League\Container\ContainerInterface
134      */
135     public static function createDefaultContainer($input = null, $output = null, $app = null, $config = null, $classLoader = null)
136     {
137         // Do not allow this function to be called more than once.
138         if (static::hasContainer()) {
139             return static::getContainer();
140         }
141
142         if (!$app) {
143             $app = static::createDefaultApplication();
144         }
145
146         if (!$config) {
147             $config = new \Robo\Config\Config();
148         }
149
150         // Set up our dependency injection container.
151         $container = new Container();
152         static::configureContainer($container, $app, $config, $input, $output, $classLoader);
153
154         // Set the application dispatcher
155         $app->setDispatcher($container->get('eventDispatcher'));
156
157         return $container;
158     }
159
160     /**
161      * Initialize a container with all of the default Robo services.
162      * IMPORTANT:  after calling this method, clients MUST call:
163      *
164      * $dispatcher = $container->get('eventDispatcher');
165      * $app->setDispatcher($dispatcher);
166      *
167      * Any modification to the container should be done prior to fetching
168      * objects from it.
169      *
170      * It is recommended to use \Robo::createDefaultContainer()
171      * instead, which does all required setup for the caller, but has
172      * the limitation that the container it creates can only be
173      * extended, not modified.
174      *
175      * @param \League\Container\ContainerInterface $container
176      * @param \Symfony\Component\Console\Application $app
177      * @param ConfigInterface $config
178      * @param null|\Symfony\Component\Console\Input\InputInterface $input
179      * @param null|\Symfony\Component\Console\Output\OutputInterface $output
180      * @param null|\Composer\Autoload\ClassLoader $classLoader
181      */
182     public static function configureContainer(ContainerInterface $container, SymfonyApplication $app, ConfigInterface $config, $input = null, $output = null, $classLoader = null)
183     {
184         // Self-referential container refernce for the inflector
185         $container->add('container', $container);
186         static::setContainer($container);
187
188         // Create default input and output objects if they were not provided
189         if (!$input) {
190             $input = new StringInput('');
191         }
192         if (!$output) {
193             $output = new \Symfony\Component\Console\Output\ConsoleOutput();
194         }
195         if (!$classLoader) {
196             $classLoader = new ClassLoader();
197         }
198         $config->set(Config::DECORATED, $output->isDecorated());
199         $config->set(Config::INTERACTIVE, $input->isInteractive());
200
201         $container->share('application', $app);
202         $container->share('config', $config);
203         $container->share('input', $input);
204         $container->share('output', $output);
205         $container->share('outputAdapter', \Robo\Common\OutputAdapter::class);
206         $container->share('classLoader', $classLoader);
207
208         // Register logging and related services.
209         $container->share('logStyler', \Robo\Log\RoboLogStyle::class);
210         $container->share('logger', \Robo\Log\RoboLogger::class)
211             ->withArgument('output')
212             ->withMethodCall('setLogOutputStyler', ['logStyler']);
213         $container->add('progressBar', \Symfony\Component\Console\Helper\ProgressBar::class)
214             ->withArgument('output');
215         $container->share('progressIndicator', \Robo\Common\ProgressIndicator::class)
216             ->withArgument('progressBar')
217             ->withArgument('output');
218         $container->share('resultPrinter', \Robo\Log\ResultPrinter::class);
219         $container->add('simulator', \Robo\Task\Simulator::class);
220         $container->share('globalOptionsEventListener', \Robo\GlobalOptionsEventListener::class)
221             ->withMethodCall('setApplication', ['application']);
222         $container->share('injectConfigEventListener', \Consolidation\Config\Inject\ConfigForCommand::class)
223             ->withArgument('config')
224             ->withMethodCall('setApplication', ['application']);
225         $container->share('collectionProcessHook', \Robo\Collection\CollectionProcessHook::class);
226         $container->share('alterOptionsCommandEvent', \Consolidation\AnnotatedCommand\Options\AlterOptionsCommandEvent::class)
227             ->withArgument('application');
228         $container->share('hookManager', \Consolidation\AnnotatedCommand\Hooks\HookManager::class)
229             ->withMethodCall('addCommandEvent', ['alterOptionsCommandEvent'])
230             ->withMethodCall('addCommandEvent', ['injectConfigEventListener'])
231             ->withMethodCall('addCommandEvent', ['globalOptionsEventListener'])
232             ->withMethodCall('addResultProcessor', ['collectionProcessHook', '*']);
233         $container->share('eventDispatcher', \Symfony\Component\EventDispatcher\EventDispatcher::class)
234             ->withMethodCall('addSubscriber', ['hookManager']);
235         $container->share('formatterManager', \Consolidation\OutputFormatters\FormatterManager::class)
236             ->withMethodCall('addDefaultFormatters', [])
237             ->withMethodCall('addDefaultSimplifiers', []);
238         $container->share('prepareTerminalWidthOption', \Consolidation\AnnotatedCommand\Options\PrepareTerminalWidthOption::class)
239             ->withMethodCall('setApplication', ['application']);
240         $container->share('commandProcessor', \Consolidation\AnnotatedCommand\CommandProcessor::class)
241             ->withArgument('hookManager')
242             ->withMethodCall('setFormatterManager', ['formatterManager'])
243             ->withMethodCall('addPrepareFormatter', ['prepareTerminalWidthOption'])
244             ->withMethodCall(
245                 'setDisplayErrorFunction',
246                 [
247                     function ($output, $message) use ($container) {
248                         $logger = $container->get('logger');
249                         $logger->error($message);
250                     }
251                 ]
252             );
253         $container->share('commandFactory', \Consolidation\AnnotatedCommand\AnnotatedCommandFactory::class)
254             ->withMethodCall('setCommandProcessor', ['commandProcessor']);
255         $container->share('relativeNamespaceDiscovery', \Robo\ClassDiscovery\RelativeNamespaceDiscovery::class)
256             ->withArgument('classLoader');
257
258         // Deprecated: favor using collection builders to direct use of collections.
259         $container->add('collection', \Robo\Collection\Collection::class);
260         // Deprecated: use CollectionBuilder::create() instead -- or, better
261         // yet, BuilderAwareInterface::collectionBuilder() if available.
262         $container->add('collectionBuilder', \Robo\Collection\CollectionBuilder::class);
263
264         static::addInflectors($container);
265
266         // Make sure the application is appropriately initialized.
267         $app->setAutoExit(false);
268     }
269
270     /**
271      * @param null|string $appName
272      * @param null|string $appVersion
273      *
274      * @return \Robo\Application
275      */
276     public static function createDefaultApplication($appName = null, $appVersion = null)
277     {
278         $appName = $appName ?: self::APPLICATION_NAME;
279         $appVersion = $appVersion ?: self::VERSION;
280
281         $app = new \Robo\Application($appName, $appVersion);
282         $app->setAutoExit(false);
283         return $app;
284     }
285
286     /**
287      * Add the Robo League\Container inflectors to the container
288      *
289      * @param \League\Container\ContainerInterface $container
290      */
291     public static function addInflectors($container)
292     {
293         // Register our various inflectors.
294         $container->inflector(\Robo\Contract\ConfigAwareInterface::class)
295             ->invokeMethod('setConfig', ['config']);
296         $container->inflector(\Psr\Log\LoggerAwareInterface::class)
297             ->invokeMethod('setLogger', ['logger']);
298         $container->inflector(\League\Container\ContainerAwareInterface::class)
299             ->invokeMethod('setContainer', ['container']);
300         $container->inflector(\Symfony\Component\Console\Input\InputAwareInterface::class)
301             ->invokeMethod('setInput', ['input']);
302         $container->inflector(\Robo\Contract\OutputAwareInterface::class)
303             ->invokeMethod('setOutput', ['output']);
304         $container->inflector(\Robo\Contract\ProgressIndicatorAwareInterface::class)
305             ->invokeMethod('setProgressIndicator', ['progressIndicator']);
306         $container->inflector(\Consolidation\AnnotatedCommand\Events\CustomEventAwareInterface::class)
307             ->invokeMethod('setHookManager', ['hookManager']);
308         $container->inflector(\Robo\Contract\VerbosityThresholdInterface::class)
309             ->invokeMethod('setOutputAdapter', ['outputAdapter']);
310     }
311
312     /**
313      * Retrieves a service from the container.
314      *
315      * Use this method if the desired service is not one of those with a dedicated
316      * accessor method below. If it is listed below, those methods are preferred
317      * as they can return useful type hints.
318      *
319      * @param string $id
320      *   The ID of the service to retrieve.
321      *
322      * @return mixed
323      *   The specified service.
324      */
325     public static function service($id)
326     {
327         return static::getContainer()->get($id);
328     }
329
330     /**
331      * Indicates if a service is defined in the container.
332      *
333      * @param string $id
334      *   The ID of the service to check.
335      *
336      * @return bool
337      *   TRUE if the specified service exists, FALSE otherwise.
338      */
339     public static function hasService($id)
340     {
341         // Check hasContainer() first in order to always return a Boolean.
342         return static::hasContainer() && static::getContainer()->has($id);
343     }
344
345     /**
346      * Return the result printer object.
347      *
348      * @return \Robo\Log\ResultPrinter
349      */
350     public static function resultPrinter()
351     {
352         return static::service('resultPrinter');
353     }
354
355     /**
356      * @return ConfigInterface
357      */
358     public static function config()
359     {
360         return static::service('config');
361     }
362
363     /**
364      * @return \Consolidation\Log\Logger
365      */
366     public static function logger()
367     {
368         return static::service('logger');
369     }
370
371     /**
372      * @return \Robo\Application
373      */
374     public static function application()
375     {
376         return static::service('application');
377     }
378
379     /**
380      * Return the output object.
381      *
382      * @return \Symfony\Component\Console\Output\OutputInterface
383      */
384     public static function output()
385     {
386         return static::service('output');
387     }
388
389     /**
390      * Return the input object.
391      *
392      * @return \Symfony\Component\Console\Input\InputInterface
393      */
394     public static function input()
395     {
396         return static::service('input');
397     }
398
399     public static function process(Process $process)
400     {
401         return ProcessExecutor::create(static::getContainer(), $process);
402     }
403 }