Completed
Pull Request — master (#552)
by Greg
03:15
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\Config;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Robo\Config.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
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 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
        foreach ($paths as $path) {
109
            $loader->load($path);
110
        }
111
        $config->extend($loader->export());
112
    }
113
114
    /**
115
     * Create a container and initiailze it.  If you wish to *change*
116
     * anything defined in the container, then you should call
117
     * \Robo::configureContainer() instead of this function.
118
     *
119
     * @param null|\Symfony\Component\Console\Input\InputInterface $input
120
     * @param null|\Symfony\Component\Console\Output\OutputInterface $output
121
     * @param null|\Robo\Application $app
122
     * @param null|\Robo\Config\Config $config
123
     *
124
     * @return \League\Container\Container|\League\Container\ContainerInterface
125
     */
126
    public static function createDefaultContainer($input = null, $output = null, $app = null, $config = null)
127
    {
128
        // Do not allow this function to be called more than once.
129
        if (static::hasContainer()) {
130
            return static::getContainer();
131
        }
132
133
        if (!$app) {
134
            $app = static::createDefaultApplication();
135
        }
136
137
        if (!$config) {
138
            $config = new Config();
139
        }
140
141
        // Set up our dependency injection container.
142
        $container = new Container();
143
        static::configureContainer($container, $app, $config, $input, $output);
144
145
        // Set the application dispatcher
146
        $app->setDispatcher($container->get('eventDispatcher'));
147
148
        return $container;
149
    }
150
151
    /**
152
     * Initialize a container with all of the default Robo services.
153
     * IMPORTANT:  after calling this method, clients MUST call:
154
     *
155
     * $dispatcher = $container->get('eventDispatcher');
156
     * $app->setDispatcher($dispatcher);
157
     *
158
     * Any modification to the container should be done prior to fetching
159
     * objects from it.
160
     *
161
     * It is recommended to use \Robo::createDefaultContainer()
162
     * instead, which does all required setup for the caller, but has
163
     * the limitation that the container it creates can only be
164
     * extended, not modified.
165
     *
166
     * @param \League\Container\ContainerInterface $container
167
     * @param \Symfony\Component\Console\Application $app
168
     * @param \Robo\Config\Config $config
169
     * @param null|\Symfony\Component\Console\Input\InputInterface $input
170
     * @param null|\Symfony\Component\Console\Output\OutputInterface $output
171
     */
172
    public static function configureContainer(ContainerInterface $container, SymfonyApplication $app, Config $config, $input = null, $output = null)
173
    {
174
        // Self-referential container refernce for the inflector
175
        $container->add('container', $container);
176
        static::setContainer($container);
177
178
        // Create default input and output objects if they were not provided
179
        if (!$input) {
180
            $input = new StringInput('');
181
        }
182
        if (!$output) {
183
            $output = new \Symfony\Component\Console\Output\ConsoleOutput();
184
        }
185
        $config->setDecorated($output->isDecorated());
186
187
        $container->share('application', $app);
188
        $container->share('config', $config);
189
        $container->share('input', $input);
190
        $container->share('output', $output);
191
        $container->share('outputAdapter', \Robo\Common\OutputAdapter::class);
192
193
        // Register logging and related services.
194
        $container->share('logStyler', \Robo\Log\RoboLogStyle::class);
195
        $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...
196
            ->withArgument('output')
197
            ->withMethodCall('setLogOutputStyler', ['logStyler']);
198
        $container->add('progressBar', \Symfony\Component\Console\Helper\ProgressBar::class)
199
            ->withArgument('output');
200
        $container->share('progressIndicator', \Robo\Common\ProgressIndicator::class)
201
            ->withArgument('progressBar')
202
            ->withArgument('output');
203
        $container->share('resultPrinter', \Robo\Log\ResultPrinter::class);
204
        $container->add('simulator', \Robo\Task\Simulator::class);
205
        $container->share('globalOptionsEventListener', \Robo\GlobalOptionsEventListener::class);
206
        $container->share('injectConfigEventListener', \Robo\InjectConfigEventListener::class);
207
        $container->share('collectionProcessHook', \Robo\Collection\CollectionProcessHook::class);
208
        $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...
209
            ->withMethodCall('addResultProcessor', ['collectionProcessHook', '*']);
210
        $container->share('alterOptionsCommandEvent', \Consolidation\AnnotatedCommand\Options\AlterOptionsCommandEvent::class)
211
            ->withArgument('application');
212
        $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...
213
            ->withMethodCall('addSubscriber', ['injectConfigEventListener'])
214
            ->withMethodCall('addSubscriber', ['globalOptionsEventListener'])
215
            ->withMethodCall('addSubscriber', ['alterOptionsCommandEvent'])
216
            ->withMethodCall('addSubscriber', ['hookManager']);
217
        $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...
218
            ->withMethodCall('addDefaultFormatters', [])
219
            ->withMethodCall('addDefaultSimplifiers', []);
220
        $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...
221
            ->withMethodCall('setApplication', ['application']);
222
        $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...
223
            ->withArgument('hookManager')
224
            ->withMethodCall('setFormatterManager', ['formatterManager'])
225
            ->withMethodCall('addPrepareFormatter', ['prepareTerminalWidthOption'])
226
            ->withMethodCall(
227
                'setDisplayErrorFunction',
228
                [
229
                    function ($output, $message) use ($container) {
230
                        $logger = $container->get('logger');
231
                        $logger->error($message);
232
                    }
233
                ]
234
            );
235
        $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...
236
            ->withMethodCall('setCommandProcessor', ['commandProcessor']);
237
238
        // Deprecated: favor using collection builders to direct use of collections.
239
        $container->add('collection', \Robo\Collection\Collection::class);
240
        // Deprecated: use CollectionBuilder::create() instead -- or, better
241
        // 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...
242
        $container->add('collectionBuilder', \Robo\Collection\CollectionBuilder::class);
243
244
        static::addInflectors($container);
245
246
        // Make sure the application is appropriately initialized.
247
        $app->setAutoExit(false);
248
    }
249
250
    /**
251
     * @param null|string $appName
252
     * @param null|string $appVersion
253
     *
254
     * @return \Robo\Application
255
     */
256
    public static function createDefaultApplication($appName = null, $appVersion = null)
257
    {
258
        $appName = $appName ?: self::APPLICATION_NAME;
259
        $appVersion = $appVersion ?: self::VERSION;
260
261
        $app = new \Robo\Application($appName, $appVersion);
262
        $app->setAutoExit(false);
263
        return $app;
264
    }
265
266
    /**
267
     * Add the Robo League\Container inflectors to the container
268
     *
269
     * @param \League\Container\ContainerInterface $container
270
     */
271
    public static function addInflectors($container)
272
    {
273
        // Register our various inflectors.
274
        $container->inflector(\Robo\Contract\ConfigAwareInterface::class)
275
            ->invokeMethod('setConfig', ['config']);
276
        $container->inflector(\Psr\Log\LoggerAwareInterface::class)
277
            ->invokeMethod('setLogger', ['logger']);
278
        $container->inflector(\League\Container\ContainerAwareInterface::class)
279
            ->invokeMethod('setContainer', ['container']);
280
        $container->inflector(\Symfony\Component\Console\Input\InputAwareInterface::class)
281
            ->invokeMethod('setInput', ['input']);
282
        $container->inflector(\Robo\Contract\OutputAwareInterface::class)
283
            ->invokeMethod('setOutput', ['output']);
284
        $container->inflector(\Robo\Contract\ProgressIndicatorAwareInterface::class)
285
            ->invokeMethod('setProgressIndicator', ['progressIndicator']);
286
        $container->inflector(\Consolidation\AnnotatedCommand\Events\CustomEventAwareInterface::class)
287
            ->invokeMethod('setHookManager', ['hookManager']);
288
        $container->inflector(\Robo\Contract\VerbosityThresholdInterface::class)
289
            ->invokeMethod('setOutputAdapter', ['outputAdapter']);
290
    }
291
292
    /**
293
     * Retrieves a service from the container.
294
     *
295
     * Use this method if the desired service is not one of those with a dedicated
296
     * accessor method below. If it is listed below, those methods are preferred
297
     * as they can return useful type hints.
298
     *
299
     * @param string $id
300
     *   The ID of the service to retrieve.
301
     *
302
     * @return mixed
303
     *   The specified service.
304
     */
305
    public static function service($id)
306
    {
307
        return static::getContainer()->get($id);
308
    }
309
310
    /**
311
     * Indicates if a service is defined in the container.
312
     *
313
     * @param string $id
314
     *   The ID of the service to check.
315
     *
316
     * @return bool
317
     *   TRUE if the specified service exists, FALSE otherwise.
318
     */
319
    public static function hasService($id)
320
    {
321
        // Check hasContainer() first in order to always return a Boolean.
322
        return static::hasContainer() && static::getContainer()->has($id);
323
    }
324
325
    /**
326
     * Return the result printer object.
327
     *
328
     * @return \Robo\Log\ResultPrinter
329
     */
330
    public static function resultPrinter()
331
    {
332
        return static::service('resultPrinter');
333
    }
334
335
    /**
336
     * @return \Robo\Config\Config
337
     */
338
    public static function config()
339
    {
340
        return static::service('config');
341
    }
342
343
    /**
344
     * @return \Consolidation\Log\Logger
345
     */
346
    public static function logger()
347
    {
348
        return static::service('logger');
349
    }
350
351
    /**
352
     * @return \Robo\Application
353
     */
354
    public static function application()
355
    {
356
        return static::service('application');
357
    }
358
359
    /**
360
     * Return the output object.
361
     *
362
     * @return \Symfony\Component\Console\Output\OutputInterface
363
     */
364
    public static function output()
365
    {
366
        return static::service('output');
367
    }
368
369
    /**
370
     * Return the input object.
371
     *
372
     * @return \Symfony\Component\Console\Input\InputInterface
373
     */
374
    public static function input()
375
    {
376
        return static::service('input');
377
    }
378
379
    public static function process(Process $process)
380
    {
381
        return ProcessExecutor::create(static::getContainer(), $process);
382
    }
383
}
384