Completed
Push — master ( 8b8afe...5f2bbe )
by Greg
02:21
created

src/Robo.php (9 issues)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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.3.3-dev';
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)
0 ignored issues
show
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...
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)
0 ignored issues
show
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('injectConfigEventListener', \Consolidation\Config\Inject\ConfigForCommand::class)
0 ignored issues
show
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('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)
0 ignored issues
show
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...
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)
0 ignored issues
show
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...
234
            ->withMethodCall('addSubscriber', ['hookManager']);
235
        $container->share('formatterManager', \Consolidation\OutputFormatters\FormatterManager::class)
0 ignored issues
show
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('addDefaultFormatters', [])
237
            ->withMethodCall('addDefaultSimplifiers', []);
238
        $container->share('prepareTerminalWidthOption', \Consolidation\AnnotatedCommand\Options\PrepareTerminalWidthOption::class)
0 ignored issues
show
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...
239
            ->withMethodCall('setApplication', ['application']);
240
        $container->share('commandProcessor', \Consolidation\AnnotatedCommand\CommandProcessor::class)
0 ignored issues
show
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...
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('stdinHandler', \Consolidation\AnnotatedCommand\Input\StdinHandler::class);
254
        $container->share('commandFactory', \Consolidation\AnnotatedCommand\AnnotatedCommandFactory::class)
0 ignored issues
show
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...
255
            ->withMethodCall('setCommandProcessor', ['commandProcessor']);
256
        $container->share('relativeNamespaceDiscovery', \Robo\ClassDiscovery\RelativeNamespaceDiscovery::class)
257
            ->withArgument('classLoader');
258
259
        // Deprecated: favor using collection builders to direct use of collections.
260
        $container->add('collection', \Robo\Collection\Collection::class);
261
        // Deprecated: use CollectionBuilder::create() instead -- or, better
262
        // yet, BuilderAwareInterface::collectionBuilder() if available.
263
        $container->add('collectionBuilder', \Robo\Collection\CollectionBuilder::class);
264
265
        static::addInflectors($container);
266
267
        // Make sure the application is appropriately initialized.
268
        $app->setAutoExit(false);
269
    }
270
271
    /**
272
     * @param null|string $appName
273
     * @param null|string $appVersion
274
     *
275
     * @return \Robo\Application
276
     */
277
    public static function createDefaultApplication($appName = null, $appVersion = null)
278
    {
279
        $appName = $appName ?: self::APPLICATION_NAME;
280
        $appVersion = $appVersion ?: self::VERSION;
281
282
        $app = new \Robo\Application($appName, $appVersion);
283
        $app->setAutoExit(false);
284
        return $app;
285
    }
286
287
    /**
288
     * Add the Robo League\Container inflectors to the container
289
     *
290
     * @param \League\Container\ContainerInterface $container
291
     */
292
    public static function addInflectors($container)
293
    {
294
        // Register our various inflectors.
295
        $container->inflector(\Robo\Contract\ConfigAwareInterface::class)
296
            ->invokeMethod('setConfig', ['config']);
297
        $container->inflector(\Psr\Log\LoggerAwareInterface::class)
298
            ->invokeMethod('setLogger', ['logger']);
299
        $container->inflector(\League\Container\ContainerAwareInterface::class)
300
            ->invokeMethod('setContainer', ['container']);
301
        $container->inflector(\Symfony\Component\Console\Input\InputAwareInterface::class)
302
            ->invokeMethod('setInput', ['input']);
303
        $container->inflector(\Robo\Contract\OutputAwareInterface::class)
304
            ->invokeMethod('setOutput', ['output']);
305
        $container->inflector(\Robo\Contract\ProgressIndicatorAwareInterface::class)
306
            ->invokeMethod('setProgressIndicator', ['progressIndicator']);
307
        $container->inflector(\Consolidation\AnnotatedCommand\Events\CustomEventAwareInterface::class)
308
            ->invokeMethod('setHookManager', ['hookManager']);
309
        $container->inflector(\Robo\Contract\VerbosityThresholdInterface::class)
310
            ->invokeMethod('setOutputAdapter', ['outputAdapter']);
311
        $container->inflector(\Consolidation\AnnotatedCommand\Input\StdinAwareInterface::class)
312
            ->invokeMethod('setStdinHandler', ['stdinHandler']);
313
    }
314
315
    /**
316
     * Retrieves a service from the container.
317
     *
318
     * Use this method if the desired service is not one of those with a dedicated
319
     * accessor method below. If it is listed below, those methods are preferred
320
     * as they can return useful type hints.
321
     *
322
     * @param string $id
323
     *   The ID of the service to retrieve.
324
     *
325
     * @return mixed
326
     *   The specified service.
327
     */
328
    public static function service($id)
329
    {
330
        return static::getContainer()->get($id);
331
    }
332
333
    /**
334
     * Indicates if a service is defined in the container.
335
     *
336
     * @param string $id
337
     *   The ID of the service to check.
338
     *
339
     * @return bool
340
     *   TRUE if the specified service exists, FALSE otherwise.
341
     */
342
    public static function hasService($id)
343
    {
344
        // Check hasContainer() first in order to always return a Boolean.
345
        return static::hasContainer() && static::getContainer()->has($id);
346
    }
347
348
    /**
349
     * Return the result printer object.
350
     *
351
     * @return \Robo\Log\ResultPrinter
352
     */
353
    public static function resultPrinter()
354
    {
355
        return static::service('resultPrinter');
356
    }
357
358
    /**
359
     * @return ConfigInterface
360
     */
361
    public static function config()
362
    {
363
        return static::service('config');
364
    }
365
366
    /**
367
     * @return \Consolidation\Log\Logger
368
     */
369
    public static function logger()
370
    {
371
        return static::service('logger');
372
    }
373
374
    /**
375
     * @return \Robo\Application
376
     */
377
    public static function application()
378
    {
379
        return static::service('application');
380
    }
381
382
    /**
383
     * Return the output object.
384
     *
385
     * @return \Symfony\Component\Console\Output\OutputInterface
386
     */
387
    public static function output()
388
    {
389
        return static::service('output');
390
    }
391
392
    /**
393
     * Return the input object.
394
     *
395
     * @return \Symfony\Component\Console\Input\InputInterface
396
     */
397
    public static function input()
398
    {
399
        return static::service('input');
400
    }
401
402
    public static function process(Process $process)
403
    {
404
        return ProcessExecutor::create(static::getContainer(), $process);
405
    }
406
}
407