MappingPass   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 160
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 17
lcom 1
cbo 4
dl 0
loc 160
rs 10
c 0
b 0
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A process() 0 14 2
C handleDirectoryMapping() 0 87 10
A getNamespaces() 0 17 3
A getFullNamespace() 0 10 1
A getClassname() 0 9 1
1
<?php
2
3
/*
4
 * This file is part of the ONGR package.
5
 *
6
 * (c) NFQ Technologies UAB <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace ONGR\ElasticsearchBundle\DependencyInjection\Compiler;
13
14
use ONGR\ElasticsearchBundle\Annotation\Index;
15
use ONGR\ElasticsearchBundle\DependencyInjection\Configuration;
16
use ONGR\ElasticsearchBundle\Mapping\Converter;
17
use ONGR\ElasticsearchBundle\Mapping\DocumentParser;
18
use ONGR\ElasticsearchBundle\Mapping\IndexSettings;
19
use ONGR\ElasticsearchBundle\Service\IndexService;
20
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
21
use Symfony\Component\DependencyInjection\ContainerBuilder;
22
use Symfony\Component\DependencyInjection\Definition;
23
24
class MappingPass implements CompilerPassInterface
25
{
26
    /**
27
     * @var array
28
     */
29
    private $indexes = [];
30
31
    /**
32
     * @var string
33
     */
34
    private $defaultIndex = null;
35
36
    public function process(ContainerBuilder $container)
37
    {
38
        $kernelDir = $container->getParameter('kernel.project_dir');
39
40
        foreach ($container->getParameter(Configuration::ONGR_SOURCE_DIR) as $dir) {
41
            $this->handleDirectoryMapping($container, $kernelDir . $dir);
42
        }
43
44
        $container->setParameter(Configuration::ONGR_INDEXES, $this->indexes);
45
        $container->setParameter(
46
            Configuration::ONGR_DEFAULT_INDEX,
47
            $this->defaultIndex ?? current(array_keys($this->indexes))
48
        );
49
    }
50
51
    /**
52
     * @param ContainerBuilder $container
53
     * @param string $dir
54
     *
55
     * @throws \ReflectionException
56
     */
57
    private function handleDirectoryMapping(ContainerBuilder $container, string $dir): void
58
    {
59
        /** @var DocumentParser $parser */
60
        $parser = $container->get(DocumentParser::class);
61
        $indexesOverride = $container->getParameter(Configuration::ONGR_INDEXES_OVERRIDE);
62
        $converterDefinition = $container->getDefinition(Converter::class);
63
64
        foreach ($this->getNamespaces($dir) as $namespace) {
65
            $class = new \ReflectionClass($namespace);
66
67
            if (isset($indexesOverride[$namespace]['alias']) && $indexesOverride[$namespace]['alias']) {
68
                $indexAlias = $indexesOverride[$namespace]['alias'];
69
            } else {
70
                $indexAlias = $parser->getIndexAliasName($class);
71
            }
72
73
            /** @var Index $document */
74
            $document = $parser->getIndexAnnotation($class);
75
            $indexMetadata = $parser->getIndexMetadata($class);
76
77
            if (!empty($indexMetadata)) {
78
                $indexMetadata['settings'] = array_filter(
79
                    array_replace_recursive(
80
                        $indexMetadata['settings'] ?? [],
81
                        [
82
                            'number_of_replicas' => $document->numberOfReplicas,
83
                            'number_of_shards' => $document->numberOfShards,
84
                        ],
85
                        $indexesOverride[$namespace]['settings'] ?? []
86
                    ),
87
                    function ($value) {
88
                        if (0 === $value) {
89
                            return true;
90
                        }
91
92
                        return (bool)$value;
93
                    }
94
                );
95
96
                $indexSettings = new Definition(
97
                    IndexSettings::class,
98
                    [
99
                        $namespace,
100
                        $indexAlias,
101
                        $indexAlias,
102
                        $indexMetadata,
103
                        $indexesOverride[$namespace]['hosts'] ?? $document->hosts,
104
                        $indexesOverride[$namespace]['default'] ?? $document->default,
105
                    ]
106
                );
107
108
                $indexServiceDefinition = new Definition(IndexService::class, [
109
                    $namespace,
110
                    $converterDefinition,
111
                    $container->getDefinition('event_dispatcher'),
112
                    $indexSettings,
113
                    $container->getParameter(Configuration::ONGR_PROFILER_CONFIG)
114
                        ? $container->getDefinition('ongr.esb.tracer') : null
115
                ]);
116
                $indexServiceDefinition->setPublic(true);
117
                $converterDefinition->addMethodCall(
118
                    'addClassMetadata',
119
                    [
120
                        $namespace,
121
                        $parser->getPropertyMetadata($class)
122
                    ]
123
                );
124
125
                $container->setDefinition($namespace, $indexServiceDefinition);
126
                $this->indexes[$indexAlias] = $namespace;
127
                $isCurrentIndexDefault = $parser->isDefaultIndex($class);
128
                if ($this->defaultIndex && $isCurrentIndexDefault) {
129
                    throw new \RuntimeException(
130
                        sprintf(
131
                            'Only one index can be set as default. We found 2 indexes as default ones `%s` and `%s`',
132
                            $this->defaultIndex,
133
                            $indexAlias
134
                        )
135
                    );
136
                }
137
138
                if ($isCurrentIndexDefault) {
139
                    $this->defaultIndex = $indexAlias;
140
                }
141
            }
142
        }
143
    }
144
145
    private function getNamespaces($directory): array
146
    {
147
        if (!is_dir($directory)) {
148
            return [];
149
        }
150
151
        $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($directory));
152
        $files = new \RegexIterator($iterator, '/^.+\.php$/i', \RecursiveRegexIterator::GET_MATCH);
153
154
        $documents = [];
155
156
        foreach ($files as $file => $v) {
157
            $documents[] = $this->getFullNamespace($file) . '\\' . $this->getClassname($file);
158
        }
159
160
        return $documents;
161
    }
162
163
    private function getFullNamespace($filename)
164
    {
165
        $lines = preg_grep('/^namespace /', file($filename));
166
        $namespaceLine = array_shift($lines);
167
        $match = array();
168
        preg_match('/^namespace (.*);$/', $namespaceLine, $match);
169
        $fullNamespace = array_pop($match);
170
171
        return $fullNamespace;
172
    }
173
174
    private function getClassname($filename)
175
    {
176
        $directoriesAndFilename = explode('/', $filename);
177
        $filename = array_pop($directoriesAndFilename);
178
        $nameAndExtension = explode('.', $filename);
179
        $className = array_shift($nameAndExtension);
180
181
        return $className;
182
    }
183
}
184