DoctrineApplicationFactory::getCommands()   A
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 26
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 14
c 1
b 0
f 0
dl 0
loc 26
rs 9.4888
cc 5
nc 5
nop 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Arp\LaminasDoctrine\Factory\Console;
6
7
use Arp\LaminasDoctrine\Console\DoctrineApplication;
8
use Arp\LaminasDoctrine\Console\Module\CommandManager;
9
use Arp\LaminasDoctrine\Console\Module\HelperManager;
10
use Arp\LaminasFactory\AbstractFactory;
11
use Laminas\ServiceManager\Exception\ServiceNotCreatedException;
12
use Laminas\ServiceManager\Exception\ServiceNotFoundException;
13
use Psr\Container\ContainerExceptionInterface;
14
use Psr\Container\ContainerInterface;
15
use Psr\Container\NotFoundExceptionInterface;
16
use Symfony\Component\Console\Application;
17
use Symfony\Component\Console\Command\Command;
0 ignored issues
show
Bug introduced by
The type Symfony\Component\Console\Command\Command was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
18
use Symfony\Component\Console\CommandLoader\CommandLoaderInterface;
19
use Symfony\Component\Console\Helper\HelperInterface;
20
use Symfony\Component\Console\Helper\HelperSet;
21
use Symfony\Component\Console\Input\InputOption;
22
23
/**
24
 * @author  Alex Patterson <[email protected]>
25
 * @package Arp\LaminasDoctrine\Factory\Console
26
 */
27
final class DoctrineApplicationFactory extends AbstractFactory
28
{
29
    private const NAME_UNKNOWN = 'UNKNOWN';
30
    private const VERSION_UNKNOWN = 'UNKNOWN';
31
32
    /**
33
     * @var string
34
     */
35
    private string $defaultClassName = DoctrineApplication::class;
36
37
    /**
38
     * @param ContainerInterface $container
39
     * @param string             $requestedName
40
     * @param array<mixed>|null  $options
41
     *
42
     * @return DoctrineApplication
43
     *
44
     * @throws ServiceNotCreatedException
45
     * @throws ServiceNotFoundException
46
     * @throws ContainerExceptionInterface
47
     */
48
    public function __invoke(
49
        ContainerInterface $container,
50
        string $requestedName,
51
        array $options = null
52
    ): DoctrineApplication {
53
        $options = $options ?? $this->getServiceOptions($container, $requestedName);
54
55
        $name = $options['name'] ?? self::NAME_UNKNOWN;
56
        $version = $options['version'] ?? self::VERSION_UNKNOWN;
57
58
        /** @var DoctrineApplication $application */
59
        $application = new $this->defaultClassName($name, $version);
60
61
        if (!empty($options['command_loader'])) {
62
            $application->setCommandLoader(
63
                $this->getCommandLoader($container, $options['command_loader'], $requestedName)
64
            );
65
        }
66
67
        if (!empty($options['helper_set'])) {
68
            if (is_string($options['helper_set'])) {
69
                $options['helper_set'] = $this->getService($container, $options['helper_set'], $requestedName);
70
            }
71
            if ($options['helper_set'] instanceof HelperSet) {
72
                $application->setHelperSet($options['helper_set']);
73
            }
74
        }
75
76
        if (!empty($options['helpers'])) {
77
            $helperSet = $application->getHelperSet();
78
            foreach ($this->getHelpers($container, $options['helpers'], $requestedName) as $alias => $helper) {
79
                $helperSet->set($helper, $alias);
80
            }
81
        }
82
83
        if (!empty($options['commands'])) {
84
            $application->addCommands($this->getCommands($container, $options['commands'], $requestedName));
85
        }
86
87
        if (isset($options['auto_exit'])) {
88
            $application->setAutoExit((bool)$options['auto_exit']);
89
        }
90
91
        if (isset($options['catch_exceptions'])) {
92
            $application->setCatchExceptions((bool)$options['catch_exceptions']);
93
        }
94
95
        if (isset($options['default_command'])) {
96
            $application->setDefaultCommand($options['default_command']);
97
        }
98
99
        if (!empty($options['global_input_options'])) {
100
            $this->registerGlobalInputOptions(
101
                $container,
102
                $application,
103
                $options['global_input_options'],
104
                $requestedName
105
            );
106
        }
107
108
        return $application;
109
    }
110
111
    /**
112
     * @param ContainerInterface            $container
113
     * @param CommandLoaderInterface|string $commandLoader
114
     * @param string                        $serviceName
115
     *
116
     * @return CommandLoaderInterface
117
     *
118
     * @throws ServiceNotCreatedException
119
     * @throws ServiceNotFoundException
120
     * @throws ContainerExceptionInterface
121
     */
122
    private function getCommandLoader(
123
        ContainerInterface $container,
124
        $commandLoader,
125
        string $serviceName
126
    ): CommandLoaderInterface {
127
        if (is_string($commandLoader)) {
128
            $commandLoader = $this->getService($container, $commandLoader, $serviceName);
129
        }
130
131
        if (!$commandLoader instanceof CommandLoaderInterface) {
132
            throw new ServiceNotCreatedException(
133
                sprintf(
134
                    'The command loader must be an object of type \'%s\'; \'%s\' provided for service \'%s\'',
135
                    CommandLoaderInterface::class,
136
                    (is_object($commandLoader) ? get_class($commandLoader) : gettype($commandLoader)),
137
                    $serviceName
138
                )
139
            );
140
        }
141
142
        return $commandLoader;
143
    }
144
145
    /**
146
     * @param ContainerInterface $container
147
     * @param array<mixed>       $data
148
     * @param string             $serviceName
149
     *
150
     * @return array<mixed>
151
     *
152
     * @throws ContainerExceptionInterface
153
     * @throws ServiceNotCreatedException
154
     * @throws ServiceNotFoundException
155
     * @throws NotFoundExceptionInterface
156
     */
157
    private function getCommands(ContainerInterface $container, array $data, string $serviceName): array
158
    {
159
        /** @var CommandManager $commandManager */
160
        $commandManager = $container->get(CommandManager::class);
161
162
        $commands = [];
163
        foreach ($data as $command) {
164
            if (is_string($command)) {
165
                $command = $this->getService($commandManager, $command, $serviceName);
166
            }
167
168
            if (!$command instanceof Command) {
169
                throw new ServiceNotCreatedException(
170
                    sprintf(
171
                        'The command must be an object of type \'%s\'; \'%s\' provided for service \'%s\'',
172
                        Command::class,
173
                        (is_object($command) ? get_class($command) : gettype($command)),
174
                        $serviceName
175
                    )
176
                );
177
            }
178
179
            $commands[] = $command;
180
        }
181
182
        return $commands;
183
    }
184
185
    /**
186
     * @param ContainerInterface $container
187
     * @param array<mixed>       $helperConfig
188
     * @param string             $serviceName
189
     *
190
     * @return HelperInterface[]
191
     *
192
     * @throws ContainerExceptionInterface
193
     * @throws NotFoundExceptionInterface
194
     * @throws ServiceNotCreatedException
195
     * @throws ServiceNotFoundException
196
     */
197
    private function getHelpers(ContainerInterface $container, array $helperConfig, string $serviceName): array
198
    {
199
        /** @var HelperManager $helperManager */
200
        $helperManager = $container->get(HelperManager::class);
201
202
        $helpers = [];
203
        foreach ($helperConfig as $name => $helper) {
204
            if (is_string($helper)) {
205
                $helper = $this->getService($helperManager, $helper, $serviceName);
206
            }
207
208
            if (!$helper instanceof HelperInterface) {
209
                throw new ServiceNotCreatedException(
210
                    sprintf(
211
                        'The command must be an object of type \'%s\'; \'%s\' provided for service \'%s\'',
212
                        HelperInterface::class,
213
                        (is_object($helper) ? get_class($helper) : gettype($helper)),
214
                        $serviceName
215
                    )
216
                );
217
            }
218
219
            $name = is_string($name) ? $name : $helper->getName();
220
            $helpers[$name] = $helper;
221
        }
222
223
        return $helpers;
224
    }
225
226
    /**
227
     * Add a collection of options to all currently registered commands
228
     *
229
     * @param ContainerInterface $container
230
     * @param Application        $application
231
     * @param array<mixed>       $inputOptions
232
     * @param string             $serviceName
233
     *
234
     * @throws ServiceNotCreatedException
235
     * @throws ServiceNotFoundException
236
     * @throws ContainerExceptionInterface
237
     */
238
    private function registerGlobalInputOptions(
239
        ContainerInterface $container,
240
        Application $application,
241
        array $inputOptions,
242
        string $serviceName
243
    ): void {
244
        $options = [];
245
        foreach ($inputOptions as $inputOption) {
246
            if (is_string($inputOption)) {
247
                $inputOption = $this->getService($container, $inputOption, $serviceName);
248
            }
249
            if ($inputOption instanceof InputOption) {
250
                $options[$inputOption->getName()] = $inputOption;
251
            }
252
        }
253
254
        if (empty($options)) {
255
            return;
256
        }
257
258
        foreach ($application->all() as $command) {
259
            $command->getDefinition()->addOptions($options);
260
        }
261
    }
262
}
263