Completed
Push — master ( ad7fd3...b10ab8 )
by Théo
03:40
created

DefinitionsParser   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 244
Duplicated Lines 11.48 %

Coupling/Cohesion

Components 1
Dependencies 6

Importance

Changes 2
Bugs 1 Features 1
Metric Value
wmc 30
c 2
b 1
f 1
lcom 1
cbo 6
dl 28
loc 244
rs 10

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 2
A parse() 0 19 4
C parseDefinition() 10 48 7
B getClass() 0 24 3
C getTags() 9 60 9
B getAutowiringTypes() 9 33 5

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

1
<?php
2
3
/*
4
 * This file is part of the LaravelYaml package.
5
 *
6
 * (c) Théo FIDRY <[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 Fidry\LaravelYaml\FileLoader\Parser\Yaml;
13
14
use Fidry\LaravelYaml\DependencyInjection\Builder\ContainerBuilder;
15
use Fidry\LaravelYaml\DependencyInjection\Definition\Alias;
16
use Fidry\LaravelYaml\DependencyInjection\Definition\Service;
17
use Fidry\LaravelYaml\Exception\FileLoader\InvalidArgumentException;
18
use Fidry\LaravelYaml\FileLoader\Parser\Resolver\ResolverInterface;
19
use Fidry\LaravelYaml\FileLoader\Parser\Resolver\ServiceResolver;
20
21
/**
22
 * @author Théo FIDRY <[email protected]>
23
 */
24
final class DefinitionsParser
25
{
26
    /**
27
     * @var ResolverInterface
28
     */
29
    private $serviceResolver;
30
31
    public function __construct(ResolverInterface $serviceResolver = null)
32
    {
33
        $this->serviceResolver = (null === $serviceResolver)? new ServiceResolver(): $serviceResolver;
34
    }
35
36
    /**
37
     * Parses service definitions and register them to the container.
38
     *
39
     * @param ContainerBuilder $container
40
     * @param array            $content  YAML file content
41
     * @param string           $fileName file name
42
     *
43
     * @throws InvalidArgumentException
44
     */
45
    public function parse(ContainerBuilder $container, $content, $fileName)
46
    {
47
        if (!isset($content['services'])) {
48
            return;
49
        }
50
51
        if (!is_array($content['services'])) {
52
            throw new InvalidArgumentException(
53
                sprintf(
54
                    'The "services" key should contain an array in %s. Check your YAML syntax.',
55
                    $fileName
56
                )
57
            );
58
        }
59
60
        foreach ($content['services'] as $id => $service) {
61
            $this->parseDefinition($container, strtolower($id), $service, $fileName);
62
        }
63
    }
64
65
    /**
66
     * Parses a service definition and register it to the container.
67
     *
68
     * @param ContainerBuilder $container
69
     * @param string           $id
70
     * @param array|string     $service
71
     * @param string           $fileName file name
72
     *
73
     * @throws InvalidArgumentException
74
     */
75
    private function parseDefinition(ContainerBuilder $container, $id, $service, $fileName)
76
    {
77
        if (is_string($service) && 0 === strpos($service, '@')) {
78
            $aliasName = new Alias($id, substr($service, 1));
79
            $container->addAlias($aliasName);
80
81
            return;
82
        }
83
84 View Code Duplication
        if (false === is_array($service)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
85
            throw new InvalidArgumentException(
86
                sprintf(
87
                    'A service definition must be an array or a string starting with "@" but %s found for service "%s" in %s. Check your YAML syntax.',
88
                    gettype($service),
89
                    $id,
90
                    $fileName
91
                )
92
            );
93
        }
94
95
        if (isset($service['alias'])) {
96
            $aliasName = $service['alias'];
97
            if (false === is_string($aliasName)) {
98
                throw new InvalidArgumentException(
99
                    sprintf(
100
                        'Parameter "alias" must be a plain name for service "%s", but found "%s" instead in %s. Check your YAML syntax.',
101
                        $id,
102
                        gettype($aliasName),
103
                        $fileName
104
                    )
105
                );
106
            }
107
108
            $alias = new Alias($id, $aliasName);
109
            $container->addAlias($alias);
110
        }
111
112
        $class = $this->getClass($id, $service, $fileName);
113
        $arguments = (isset($service['arguments']))
114
            ? $this->serviceResolver->resolve($service['arguments'])
115
            : null
116
        ;
117
        $tags = $this->getTags($id, $service, $fileName);
118
        $autowiringTypes = $this->getAutowiringTypes($id, $service, $fileName);
119
120
        $service = new Service($id, $class, $arguments, $autowiringTypes, $tags);
121
        $container->addService($service);
122
    }
123
124
    /**
125
     * @param string $id
126
     * @param array  $service
127
     * @param string $fileName
128
     *
129
     * @return string
130
     * @throws InvalidArgumentException
131
     */
132
    private function getClass($id, $service, $fileName)
133
    {
134
        if (false === isset($service['class'])) {
135
            throw new InvalidArgumentException(
136
                sprintf(
137
                    'Parameter "class" missing for service "%s" in %s. Check your YAML syntax.',
138
                    $id,
139
                    $fileName
140
                )
141
            );
142
        }
143
        if (false === is_string($service['class'])) {
144
            throw new InvalidArgumentException(
145
                sprintf(
146
                    'Parameter "class" must be a FQCN for service "%s", but found "%s" instead in %s. Check your YAML syntax.',
147
                    $id,
148
                    gettype($service['class']),
149
                    $fileName
150
                )
151
            );
152
        }
153
154
        return $service['class'];
155
    }
156
157
    /**
158
     * @param string $id
159
     * @param array  $service
160
     * @param string $fileName
161
     *
162
     * @return array
163
     * @throws InvalidArgumentException
164
     */
165
    private function getTags($id, $service, $fileName)
166
    {
167
        if (false === isset($service['tags'])) {
168
            return [];
169
        }
170
171
        $tags = [];
172 View Code Duplication
        if (false === is_array($service['tags'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
173
            throw new InvalidArgumentException(
174
                sprintf(
175
                    'Parameter "tags" must be an array for service "%s" in %s. Check your YAML syntax.',
176
                    $id,
177
                    $fileName
178
                )
179
            );
180
        }
181
182
        foreach ($service['tags'] as $tag) {
183
            if (false === is_array($tag)) {
184
                throw new InvalidArgumentException(
185
                    sprintf(
186
                        'A "tags" entry must be an array for service "%s" in %s. Check your YAML syntax.',
187
                        $id,
188
                        $fileName
189
                    )
190
                );
191
            }
192
193
            if (false === isset($tag['name'])) {
194
                throw new InvalidArgumentException(
195
                    sprintf(
196
                        'A "tags" entry is missing a "name" key for service "%s" in %s.',
197
                        $id,
198
                        $fileName
199
                    )
200
                );
201
            }
202
203
            $name = strtolower($tag['name']);
204
            unset($tag['name']);
205
206
            foreach ($tag as $attribute => $value) {
207
                if (false === is_scalar($value) && null !== $value) {
208
                    throw new InvalidArgumentException(
209
                        sprintf(
210
                            'A "tags" attribute must be of a scalar-type for service "%s", tag "%s", attribute "%s" in %s. Check your YAML syntax.',
211
                            $id,
212
                            $name,
213
                            $attribute,
214
                            $fileName
215
                        )
216
                    );
217
                }
218
            }
219
220
            $tags[$name] = $tag;
221
        }
222
223
        return $tags;
224
    }
225
226
    /**
227
     * @param string $id
228
     * @param array  $service
229
     * @param string $fileName
230
     *
231
     * @return array
232
     * @throws InvalidArgumentException
233
     */
234
    private function getAutowiringTypes($id, $service, $fileName)
235
    {
236
        if (false === isset($service['autowiringTypes'])) {
237
            return [];
238
        }
239
240 View Code Duplication
        if (false === is_array($service['autowiringTypes'])) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
241
            throw new InvalidArgumentException(
242
                sprintf(
243
                    'Parameter "autowiringTypes" must be an array for service "%s" in %s. Check your YAML syntax.',
244
                    $id,
245
                    $fileName
246
                )
247
            );
248
        }
249
250
        $autowiringTypes = [];
251
        foreach ($service['autowiringTypes'] as $autowiringType) {
252
            if (false === is_string($autowiringType)) {
253
                throw new InvalidArgumentException(
254
                    sprintf(
255
                        'A "autowiringType" entry must be a FQCN for service "%s" in %s. Check your YAML syntax.',
256
                        $id,
257
                        $fileName
258
                    )
259
                );
260
            }
261
262
            $autowiringTypes[$autowiringType] = true;
263
        }
264
265
        return $autowiringTypes;
266
    }
267
}
268