Completed
Branch master (ddb139)
by Yann
02:49
created

__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 9
ccs 7
cts 7
cp 1
rs 9.6666
cc 1
eloc 6
nc 1
nop 2
crap 1
1
<?php
2
3
namespace EnumBundle\DependencyInjection\CompilerPass;
4
5
use EnumBundle\Enum\AbstractTranslatedEnum;
6
use EnumBundle\Enum\EnumInterface;
7
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
8
use Symfony\Component\DependencyInjection\Container;
9
use Symfony\Component\DependencyInjection\ContainerBuilder;
10
use Symfony\Component\DependencyInjection\Definition;
11
use Symfony\Component\DependencyInjection\DefinitionDecorator;
12
use Symfony\Component\Finder\Finder;
13
use Symfony\Component\Finder\SplFileInfo;
14
15
/**
16
 * @author Yann Eugoné <[email protected]>
17
 */
18
class DeclarativeEnumCollectorCompilerPass implements CompilerPassInterface
19
{
20
    /**
21
     * @var string
22
     */
23
    private $bundleDir;
24
25
    /**
26
     * @var string
27
     */
28
    private $bundleNamespace;
29
30
    /**
31
     * @var string
32
     */
33
    private $bundleName;
34
35
    /**
36
     * @var string
37
     */
38
    private $transDomain;
39
40
    /**
41
     * @param string      $bundle
42
     * @param string|null $transDomain
43
     */
44 3
    public function __construct($bundle, $transDomain = null)
45
    {
46 3
        $reflection = new \ReflectionClass($bundle);
47 3
        $this->bundleDir = dirname($reflection->getFileName());
48 3
        $this->bundleNamespace = $reflection->getNamespaceName();
49 3
        $this->bundleName = $reflection->getShortName();
50
51 3
        $this->transDomain = $transDomain;
52 3
    }
53
54
    /**
55
     * {@inheritdoc}
56
     */
57 3
    public function process(ContainerBuilder $container)
58
    {
59 3
        if (!class_exists('Symfony\Component\Finder\Finder')) {
60
            throw new \RuntimeException('You need the symfony/finder component to register enums.');
61
        }
62
63 3
        $enumDir = $this->bundleDir . '/Enum';
64
65 3
        if (!is_dir($enumDir)) {
66
            return;
67
        }
68
69 3
        $finder = new Finder();
70 3
        $finder->files()->name('*Enum.php')->in($enumDir);
71
72 3
        foreach ($finder as $file) {
73
            /** @var SplFileInfo $file */
74 3
            $enumNamespace = $this->bundleNamespace . '\\Enum';
75 3
            if ($relativePath = $file->getRelativePath()) {
76 3
                $enumNamespace .= '\\' . strtr($relativePath, '/', '\\');
77 3
            }
78
79 3
            $enumClass = $enumNamespace . '\\' . $file->getBasename('.php');
80 3
            $enumReflection = new \ReflectionClass($enumClass);
81
82 3
            if (!$enumReflection->isSubclassOf(EnumInterface::class) || $enumReflection->isAbstract()) {
83
                continue; //Not an enum or abstract enum
84
            }
85
86 3
            $definition = null;
87 3
            $requiredParameters = $enumReflection->getConstructor() ? $enumReflection->getConstructor()->getNumberOfRequiredParameters() : 0;
88 3
            if ($requiredParameters === 0) {
89 3
                $definition = new Definition($enumClass);
90 3
            } elseif ($requiredParameters === 2 && $enumReflection->isSubclassOf(AbstractTranslatedEnum::class)) {
91 3
                $definition = new DefinitionDecorator('enum.abstract_translated');
92 3
                $definition->setClass($enumClass);
93 3
                $definition->addArgument(
94 3
                    $this->getTransPattern($enumClass)
95 3
                );
96
97 3
                if ($this->transDomain) {
98
                    $definition->addMethodCall(
99
                        'setTransDomain',
100
                        [
101
                            $this->transDomain
102
                        ]
103
                    );
104
                }
105 3
            }
106
107 3
            if (!$definition) {
108
                continue; //Could not determine how to create definition for the enum
109
            }
110
111 3
            $definition->addTag('enum');
112
113 3
            $container->setDefinition(
114 3
                $this->getServiceId($enumClass),
115
                $definition
116 3
            );
117 3
        }
118 3
    }
119
120
    /**
121
     * @param string $enumClass
122
     *
123
     * @return string
124
     */
125 3
    private function getServiceId($enumClass)
126
    {
127 3
        $enumNamespace = $this->bundleNamespace.'\\Enum\\';
128
129 3
        return sprintf('%s.enum.%s',
130 3
            Container::underscore(
131 3
                substr($this->bundleName, 0, -6)
132 3
            ),
133 3
            Container::underscore(
134 3
                str_replace(
135 3
                    '\\',
136 3
                    '',
137 3
                    str_replace(
138 3
                        $enumNamespace,
139 3
                        '',
140 3
                        substr($enumClass, 0, -4)
141 3
                    )
142 3
                )
143 3
            )
144 3
        );
145
    }
146
147
    /**
148
     * @param string $enumClass
149
     *
150
     * @return string
151
     */
152 3
    private function getTransPattern($enumClass)
153
    {
154 3
        $parts = array_filter(
155 3
            array_map(
156 3
                [$this, 'underscore'],
157 3
                explode(
158 3
                    '\\',
159 3
                    str_replace(
160 3
                        $this->bundleNamespace . '\\',
161 3
                        '',
162
                        $enumClass
163 3
                    )
164 3
                )
165 3
            )
166 3
        );
167
168 3
        $enum = array_pop($parts);
169
170 3
        return implode('_', $parts) . '.' . $enum . '.label_%s';
171
    }
172
173
    /**
174
     * @param string $input
175
     *
176
     * @return string
177
     */
178 3
    private function underscore($input)
179
    {
180 3
        return strtolower(
181 3
            preg_replace(
182 3
                '~(?<=\\w)([A-Z])~', '_$1',
183 3
                preg_replace(
184 3
                    '~(Enum|Bundle)~',
185 3
                    '',
186
                    $input
187 3
                )
188 3
            )
189 3
        );
190
    }
191
}
192