Completed
Pull Request — master (#552)
by Greg
02:57
created

Robo::createConfiguration()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 6
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
namespace Robo;
3
4
use League\Container\Container;
5
use League\Container\ContainerInterface;
6
use Robo\Common\ProcessExecutor;
7
use Robo\Config\ConfigProcessor;
8
use Robo\Config\YamlConfigLoader;
9
use Symfony\Component\Console\Input\StringInput;
10
use Symfony\Component\Console\Application as SymfonyApplication;
11
use Symfony\Component\Process\Process;
12
13
/**
14
 * Manages the container reference and other static data.  Favor
15
 * using dependency injection wherever possible.  Avoid using
16
 * this class directly, unless setting up a custom DI container.
17
 */
18
class Robo
19
{
20
    const APPLICATION_NAME = 'Robo';
21
    const VERSION = '1.0.6-dev';
22
23
    /**
24
     * The currently active container object, or NULL if not initialized yet.
25
     *
26
     * @var ContainerInterface|null
27
     */
28
    protected static $container;
29
30
    /**
31
     * Entrypoint for standalone Robo-based tools.  See docs/framework.md.
32
     *
33
     * @param string[] $argv
34
     * @param string $commandClasses
35
     * @param null|string $appName
36
     * @param null|string $appVersion
37
     * @param null|\Symfony\Component\Console\Output\OutputInterface $output
38
     *
39
     * @return int
40
     */
41
    public static function run($argv, $commandClasses, $appName = null, $appVersion = null, $output = null)
42
    {
43
        $runner = new \Robo\Runner($commandClasses);
44
        $statusCode = $runner->execute($argv, $appName, $appVersion, $output);
45
        return $statusCode;
46
    }
47
48
    /**
49
     * Sets a new global container.
50
     *
51
     * @param ContainerInterface $container
52
     *   A new container instance to replace the current.
53
     */
54
    public static function setContainer(ContainerInterface $container)
55
    {
56
        static::$container = $container;
57
    }
58
59
    /**
60
     * Unsets the global container.
61
     */
62
    public static function unsetContainer()
63
    {
64
        static::$container = null;
65
    }
66
67
    /**
68
     * Returns the currently active global container.
69
     *
70
     * @return \League\Container\ContainerInterface
71
     *
72
     * @throws \RuntimeException
73
     */
74
    public static function getContainer()
75
    {
76
        if (static::$container === null) {
77
            throw new \RuntimeException('container is not initialized yet. \Robo\Robo::setContainer() must be called with a real container.');
78
        }
79
        return static::$container;
80
    }
81
82
    /**
83
     * Returns TRUE if the container has been initialized, FALSE otherwise.
84
     *
85
     * @return bool
86
     */
87
    public static function hasContainer()
88
    {
89
        return static::$container !== null;
90
    }
91
92
    /**
93
     * Create a config object and load it from the provided paths.
94
     */
95
    public static function createConfiguration($paths)
96
    {
97
        $config = new \Robo\Config\Config();
98
        static::loadConfiguration($config, $paths);
99
        return $config;
100
    }
101
102
    /**
103
     * Use a simple config loader to load configuration values from specified paths
104
     */
105
    public static function loadConfiguration($config, $paths)
106
    {
107
        $loader = new YamlConfigLoader();
108
        $processor = new ConfigProcessor();
109
        foreach ($paths as $path) {
110
            $processor->extend($loader->load($path));
111
        }
112
        $config->import($loader->export());
113
    }
114
115
    /**
116
     * Create a container and initiailze it.  If you wish to *change*
117
     * anything defined in the container, then you should call
118
     * \Robo::configureContainer() instead of this function.
119
     *
120
     * @param null|\Symfony\Component\Console\Input\InputInterface $input
121
     * @param null|\Symfony\Component\Console\Output\OutputInterface $output
122
     * @param null|\Robo\Application $app
123
     * @param null|\Robo\Config\Config $config
124
     *
125
     * @return \League\Container\Container|\League\Container\ContainerInterface
126
     */
127
    public static function createDefaultContainer($input = null, $output = null, $app = null, $config = null)
128
    {
129
        // Do not allow this function to be called more than once.
130
        if (static::hasContainer()) {
131
            return static::getContainer();
132
        }
133
134
        if (!$app) {
135
            $app = static::createDefaultApplication();
136
        }
137
138
        if (!$config) {
139
            $config = new \Robo\Config\Config();
140
        }
141
142
        // Set up our dependency injection container.
143
        $container = new Container();
144
        static::configureContainer($container, $app, $config, $input, $output);
145
146
        // Set the application dispatcher
147
        $app->setDispatcher($container->get('eventDispatcher'));
148
149
        return $container;
150
    }
151
152
    /**
153
     * Initialize a container with all of the default Robo services.
154
     * IMPORTANT:  after calling this method, clients MUST call:
155
     *
156
     * $dispatcher = $container->get('eventDispatcher');
157
     * $app->setDispatcher($dispatcher);
158
     *
159
     * Any modification to the container should be done prior to fetching
160
     * objects from it.
161
     *
162
     * It is recommended to use \Robo::createDefaultContainer()
163
     * instead, which does all required setup for the caller, but has
164
     * the limitation that the container it creates can only be
165
     * extended, not modified.
166
     *
167
     * @param \League\Container\ContainerInterface $container
168
     * @param \Symfony\Component\Console\Application $app
169
     * @param \Robo\Config\Config $config
170
     * @param null|\Symfony\Component\Console\Input\InputInterface $input
171
     * @param null|\Symfony\Component\Console\Output\OutputInterface $output
172
     */
173
    public static function configureContainer(ContainerInterface $container, SymfonyApplication $app, \Robo\Config\Config $config, $input = null, $output = null)
174
    {
175
        // Self-referential container refernce for the inflector
176
        $container->add('container', $container);
177
        static::setContainer($container);
178
179
        // Create default input and output objects if they were not provided
180
        if (!$input) {
181
            $input = new StringInput('');
182
        }
183
        if (!$output) {
184
            $output = new \Symfony\Component\Console\Output\ConsoleOutput();
185
        }
186
        $config->setDecorated($output->isDecorated());
187
188
        $container->share('application', $app);
189
        $container->share('config', $config);
190
        $container->share('input', $input);
191
        $container->share('output', $output);
192
        $container->share('outputAdapter', \Robo\Common\OutputAdapter::class);
193
194
        // Register logging and related services.
195
        $container->share('logStyler', \Robo\Log\RoboLogStyle::class);
196
        $container->share('logger', \Robo\Log\RoboLogger::class)
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface League\Container\Definition\DefinitionInterface as the method withMethodCall() does only exist in the following implementations of said interface: League\Container\Definition\ClassDefinition.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
197
            ->withArgument('output')
198
            ->withMethodCall('setLogOutputStyler', ['logStyler']);
199
        $container->add('progressBar', \Symfony\Component\Console\Helper\ProgressBar::class)
200
            ->withArgument('output');
201
        $container->share('progressIndicator', \Robo\Common\ProgressIndicator::class)
202
            ->withArgument('progressBar')
203
            ->withArgument('output');
204
        $container->share('resultPrinter', \Robo\Log\ResultPrinter::class);
205
        $container->add('simulator', \Robo\Task\Simulator::class);
206
        $container->share('globalOptionsEventListener', \Robo\GlobalOptionsEventListener::class);
207
        $container->share('injectConfigEventListener', \Robo\InjectConfigEventListener::class);
208
        $container->share('collectionProcessHook', \Robo\Collection\CollectionProcessHook::class);
209
        $container->share('hookManager', \Consolidation\AnnotatedCommand\Hooks\HookManager::class)
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface League\Container\Definition\DefinitionInterface as the method withMethodCall() does only exist in the following implementations of said interface: League\Container\Definition\ClassDefinition.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
210
            ->withMethodCall('addResultProcessor', ['collectionProcessHook', '*']);
211
        $container->share('alterOptionsCommandEvent', \Consolidation\AnnotatedCommand\Options\AlterOptionsCommandEvent::class)
212
            ->withArgument('application');
213
        $container->share('eventDispatcher', \Symfony\Component\EventDispatcher\EventDispatcher::class)
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface League\Container\Definition\DefinitionInterface as the method withMethodCall() does only exist in the following implementations of said interface: League\Container\Definition\ClassDefinition.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
214
            ->withMethodCall('addSubscriber', ['injectConfigEventListener'])
215
            ->withMethodCall('addSubscriber', ['globalOptionsEventListener'])
216
            ->withMethodCall('addSubscriber', ['alterOptionsCommandEvent'])
217
            ->withMethodCall('addSubscriber', ['hookManager']);
218
        $container->share('formatterManager', \Consolidation\OutputFormatters\FormatterManager::class)
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface League\Container\Definition\DefinitionInterface as the method withMethodCall() does only exist in the following implementations of said interface: League\Container\Definition\ClassDefinition.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
219
            ->withMethodCall('addDefaultFormatters', [])
220
            ->withMethodCall('addDefaultSimplifiers', []);
221
        $container->share('prepareTerminalWidthOption', \Consolidation\AnnotatedCommand\Options\PrepareTerminalWidthOption::class)
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface League\Container\Definition\DefinitionInterface as the method withMethodCall() does only exist in the following implementations of said interface: League\Container\Definition\ClassDefinition.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
222
            ->withMethodCall('setApplication', ['application']);
223
        $container->share('commandProcessor', \Consolidation\AnnotatedCommand\CommandProcessor::class)
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface League\Container\Definition\DefinitionInterface as the method withMethodCall() does only exist in the following implementations of said interface: League\Container\Definition\ClassDefinition.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
224
            ->withArgument('hookManager')
225
            ->withMethodCall('setFormatterManager', ['formatterManager'])
226
            ->withMethodCall('addPrepareFormatter', ['prepareTerminalWidthOption'])
227
            ->withMethodCall(
228
                'setDisplayErrorFunction',
229
                [
230
                    function ($output, $message) use ($container) {
231
                        $logger = $container->get('logger');
232
                        $logger->error($message);
233
                    }
234
                ]
235
            );
236
        $container->share('commandFactory', \Consolidation\AnnotatedCommand\AnnotatedCommandFactory::class)
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface League\Container\Definition\DefinitionInterface as the method withMethodCall() does only exist in the following implementations of said interface: League\Container\Definition\ClassDefinition.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
237
            ->withMethodCall('setCommandProcessor', ['commandProcessor']);
238
239
        // Deprecated: favor using collection builders to direct use of collections.
240
        $container->add('collection', \Robo\Collection\Collection::class);
241
        // Deprecated: use CollectionBuilder::create() instead -- or, better
242
        // yet, BuilderAwareInterface::collectionBuilder() if available.
0 ignored issues
show
Unused Code Comprehensibility introduced by
36% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
243
        $container->add('collectionBuilder', \Robo\Collection\CollectionBuilder::class);
244
245
        static::addInflectors($container);
246
247
        // Make sure the application is appropriately initialized.
248
        $app->setAutoExit(false);
249
    }
250
251
    /**
252
     * @param null|string $appName
253
     * @param null|string $appVersion
254
     *
255
     * @return \Robo\Application
256
     */
257
    public static function createDefaultApplication($appName = null, $appVersion = null)
258
    {
259
        $appName = $appName ?: self::APPLICATION_NAME;
260
        $appVersion = $appVersion ?: self::VERSION;
261
262
        $app = new \Robo\Application($appName, $appVersion);
263
        $app->setAutoExit(false);
264
        return $app;
265
    }
266
267
    /**
268
     * Add the Robo League\Container inflectors to the container
269
     *
270
     * @param \League\Container\ContainerInterface $container
271
     */
272
    public static function addInflectors($container)
273
    {
274
        // Register our various inflectors.
275
        $container->inflector(\Robo\Contract\ConfigAwareInterface::class)
276
            ->invokeMethod('setConfig', ['config']);
277
        $container->inflector(\Psr\Log\LoggerAwareInterface::class)
278
            ->invokeMethod('setLogger', ['logger']);
279
        $container->inflector(\League\Container\ContainerAwareInterface::class)
280
            ->invokeMethod('setContainer', ['container']);
281
        $container->inflector(\Symfony\Component\Console\Input\InputAwareInterface::class)
282
            ->invokeMethod('setInput', ['input']);
283
        $container->inflector(\Robo\Contract\OutputAwareInterface::class)
284
            ->invokeMethod('setOutput', ['output']);
285
        $container->inflector(\Robo\Contract\ProgressIndicatorAwareInterface::class)
286
            ->invokeMethod('setProgressIndicator', ['progressIndicator']);
287
        $container->inflector(\Consolidation\AnnotatedCommand\Events\CustomEventAwareInterface::class)
288
            ->invokeMethod('setHookManager', ['hookManager']);
289
        $container->inflector(\Robo\Contract\VerbosityThresholdInterface::class)
290
            ->invokeMethod('setOutputAdapter', ['outputAdapter']);
291
    }
292
293
    /**
294
     * Retrieves a service from the container.
295
     *
296
     * Use this method if the desired service is not one of those with a dedicated
297
     * accessor method below. If it is listed below, those methods are preferred
298
     * as they can return useful type hints.
299
     *
300
     * @param string $id
301
     *   The ID of the service to retrieve.
302
     *
303
     * @return mixed
304
     *   The specified service.
305
     */
306
    public static function service($id)
307
    {
308
        return static::getContainer()->get($id);
309
    }
310
311
    /**
312
     * Indicates if a service is defined in the container.
313
     *
314
     * @param string $id
315
     *   The ID of the service to check.
316
     *
317
     * @return bool
318
     *   TRUE if the specified service exists, FALSE otherwise.
319
     */
320
    public static function hasService($id)
321
    {
322
        // Check hasContainer() first in order to always return a Boolean.
323
        return static::hasContainer() && static::getContainer()->has($id);
324
    }
325
326
    /**
327
     * Return the result printer object.
328
     *
329
     * @return \Robo\Log\ResultPrinter
330
     */
331
    public static function resultPrinter()
332
    {
333
        return static::service('resultPrinter');
334
    }
335
336
    /**
337
     * @return \Robo\Config\Config
338
     */
339
    public static function config()
340
    {
341
        return static::service('config');
342
    }
343
344
    /**
345
     * @return \Consolidation\Log\Logger
346
     */
347
    public static function logger()
348
    {
349
        return static::service('logger');
350
    }
351
352
    /**
353
     * @return \Robo\Application
354
     */
355
    public static function application()
356
    {
357
        return static::service('application');
358
    }
359
360
    /**
361
     * Return the output object.
362
     *
363
     * @return \Symfony\Component\Console\Output\OutputInterface
364
     */
365
    public static function output()
366
    {
367
        return static::service('output');
368
    }
369
370
    /**
371
     * Return the input object.
372
     *
373
     * @return \Symfony\Component\Console\Input\InputInterface
374
     */
375
    public static function input()
376
    {
377
        return static::service('input');
378
    }
379
380
    public static function process(Process $process)
381
    {
382
        return ProcessExecutor::create(static::getContainer(), $process);
383
    }
384
}
385