Passed
Push — master ( d72858...0074fd )
by Alex
02:03
created

Extension   A

Complexity

Total Complexity 17

Size/Duplication

Total Lines 94
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 5
dl 0
loc 94
ccs 51
cts 51
cp 1
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A loadInternal() 0 7 1
A registerTags() 0 11 2
A registerCommands() 0 7 1
A registerConfig() 0 15 2
B registerConfigurationTags() 0 18 5
A registerShell() 0 14 2
A scopeVariables() 0 10 4
1
<?php
2
declare(strict_types=1);
3
4
namespace AlexMasterov\PsyshBundle\DependencyInjection;
5
6
use AlexMasterov\PsyshBundle\Command\ShellCommand;
7
use Psy\{
8
    Command\Command,
9
    Configuration,
1 ignored issue
show
Bug introduced by
This use statement conflicts with another class in this namespace, AlexMasterov\PsyshBundle...Injection\Configuration.

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...
10
    Matcher\AbstractMatcher,
11
    Shell
12
};
13
use Symfony\Component\DependencyInjection\{
14
    ContainerBuilder,
15
    Definition,
16
    Reference
17
};
18
use Symfony\Component\HttpKernel\DependencyInjection\ConfigurableExtension;
19
20
class Extension extends ConfigurableExtension
21
{
22
    /**
23
     * @inheritDoc
24
     */
25 1
    protected function loadInternal(array $mergedConfig, ContainerBuilder $container)
26
    {
27 1
        $this->registerTags($container);
28 1
        $this->registerCommands($container);
29 1
        $this->registerConfig($mergedConfig, $container);
30 1
        $this->registerShell($mergedConfig, $container);
31 1
    }
32
33 1
    private function registerTags(ContainerBuilder $container): void
34
    {
35 1
        static $tags = [
36
            'psysh.command' => Command::class,
37
            'psysh.matcher' => AbstractMatcher::class,
38
        ];
39
40 1
        foreach ($tags as $tag => $spec) {
41 1
            $container->registerForAutoconfiguration($spec)->addTag($tag);
42
        }
43 1
    }
44
45 1
    private function registerCommands(ContainerBuilder $container): void
46
    {
47 1
        $container->register('psysh.command.shell_command', ShellCommand::class)
48 1
            ->setPublic(false)
49 1
            ->addArgument(new Reference('psysh.shell'))
50 1
            ->setAutoconfigured(true);
51 1
    }
52
53 1
    private function registerConfig(array $config, ContainerBuilder $container): void
54
    {
55 1
        $config = $this->registerConfigurationTags($config, $container);
56
57 1
        $definition = (new Definition(Configuration::class))
58 1
            ->setShared(false)
59 1
            ->setPublic(false)
60 1
            ->addArgument($config);
61
62 1
        if (isset($config['historyFile'])) {
63 1
            $definition->addMethodCall('setHistoryFile', [$config['historyFile']]);
64
        }
65
66 1
        $container->setDefinition('psysh.config', $definition);
67 1
    }
68
69
    private function registerConfigurationTags(array $config, ContainerBuilder $container): array
70
    {
71 1
        $configurator = function (array $services, ContainerBuilder $container): void {
1 ignored issue
show
Coding Style introduced by
Expected 1 space after closing parenthesis; found 0
Loading history...
72 1
            foreach ($services as $service) {
73 1
                $container->hasDefinition($service) ?: $container->register($service)->setPublic(false);
74 1
                $container->getDefinition($service)->setAutoconfigured(true);
75
            }
76 1
        };
77
78 1
        foreach (['commands', 'tabCompletionMatchers'] as $option) {
79 1
            if (isset($config[$option])) {
80 1
                $configurator($config[$option], $container);
81 1
                unset($config[$option]);
82
            }
83
        }
84
85 1
        return $config;
86
    }
87
88 1
    private function registerShell(array $config, ContainerBuilder $container): void
89
    {
90 1
        $definition = (new Definition(Shell::class))
91 1
            ->setPublic(false)
92 1
            ->addArgument(new Reference('psysh.config'));
93
94 1
        if (isset($config['variables'])) {
95 1
            $definition->addMethodCall('setScopeVariables', [
96 1
                $this->scopeVariables($config['variables']),
97
            ]);
98
        }
99
100 1
        $container->setDefinition('psysh.shell', $definition);
101 1
    }
102
103 1
    private function scopeVariables(array $variables): array
104
    {
105 1
        foreach ($variables as &$spec) {
106 1
            if (\is_string($spec) && 0 === \strpos($spec, '@')) {
107 1
                $spec = new Reference(\substr($spec, 1));
108
            }
109
        }
110
111 1
        return $variables;
112
    }
113
}
114