Passed
Push — master ( 63f785...e28c78 )
by Michael
02:34
created

YamlDefinitionProvider   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 150
Duplicated Lines 5.33 %

Coupling/Cohesion

Components 1
Dependencies 8

Test Coverage

Coverage 93.94%

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 8
dl 8
loc 150
ccs 31
cts 33
cp 0.9394
rs 10
c 0
b 0
f 0

6 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 7 1
A registerProcessor() 0 4 1
A getDefinition() 8 8 2
A createDefinition() 0 18 3
A readConfig() 0 12 2
A getSchema() 0 8 2

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
declare(strict_types = 1);
3
4
namespace Mikemirten\Component\JsonApi\Mapper\Definition;
5
6
use Mikemirten\Component\JsonApi\Mapper\Definition\ConfigurationProcessor\ConfigurationProcessorInterface;
7
use Mikemirten\Component\JsonApi\Mapper\Definition\Exception\DefinitionNotFoundException;
8
use Mikemirten\Component\JsonApi\Mapper\Definition\Exception\DefinitionProviderException;
9
use Symfony\Component\Config\Definition\ConfigurationInterface as Configuration;
10
use Symfony\Component\Config\Definition\NodeInterface;
11
use Symfony\Component\Config\Definition\Processor;
12
use Symfony\Component\Yaml\Parser;
13
14
/**
15
 * YAML-config based definition provider
16
 *
17
 *                  +--------+                +-------------+
18
 *                  | Schema |->-+        +-->| Processor A |--+
19
 *                  +--------+   |        |   +-------------+  |
20
 *                               |        |                    |
21
 * +------+   +--------+   +-----------+  |   +-------------+  |   +------------+
22
 * | File |-->| Parser |-->| Config    |--+-->| Processor B |--+-->| Definition |
23
 * +------+   +--------+   | processor |      +-------------+      +------------+
24
 *                         +-----------+
25
 *
26
 * @package Mikemirten\Component\JsonApi\Mapper\Definition
27
 */
28
class YamlDefinitionProvider implements DefinitionProviderInterface
29
{
30
    /**
31
     * Path to directory with mapping definitions
32
     *
33
     * @var string
34
     */
35
    protected $basePath;
36
37
    /**
38
     * YAML-parser
39
     *
40
     * @var Parser
41
     */
42
    protected $parser;
43
44
    /**
45
     * Configuration processor
46
     * Handles schema, normalization and default values
47
     *
48
     * @var Processor
49
     */
50
    protected $processor;
51
52
    /**
53
     * Configuration
54
     * Provides schema of mapping definition
55
     *
56
     * @var Configuration
57
     */
58
    protected $config;
59
60
    /**
61
     * Lazy initialized schema of mapping definition
62
     *
63
     * @var NodeInterface
64
     */
65
    private $schema;
66
67
    /**
68
     * Registered configuration processors
69
     * Each processor handles certain part of definition
70
     *
71
     * @var ConfigurationProcessorInterface[]
72
     */
73
    private $processors = [];
74
75
    /**
76
     * Cache of created definitions
77
     *
78
     * @var array
79
     */
80
    private $definitionCache = [];
81
82
    /**
83
     * YamlDefinitionProvider constructor.
84
     *
85
     * @param string        $basePath
86
     * @param Parser        $parser
87
     * @param Processor     $processor
88
     * @param Configuration $config
89
     */
90 1
    public function __construct(string $basePath, Parser $parser, Processor $processor, Configuration $config)
91
    {
92 1
        $this->basePath  = $basePath;
93 1
        $this->parser    = $parser;
94 1
        $this->processor = $processor;
95 1
        $this->config    = $config;
96 1
    }
97
98
    /**
99
     * Register configuration processor
100
     *
101
     * @param ConfigurationProcessorInterface $processor
102
     */
103 1
    public function registerProcessor(ConfigurationProcessorInterface $processor)
104
    {
105 1
        $this->processors[] = $processor;
106 1
    }
107
108
    /**
109
     * {@inheritdoc}
110
     */
111 1 View Code Duplication
    public function getDefinition(string $class): Definition
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
112
    {
113 1
        if (! isset($this->definitionCache[$class])) {
114 1
            $this->definitionCache[$class] = $this->createDefinition($class);
115
        }
116
117 1
        return $this->definitionCache[$class];
118
    }
119
120
    /**
121
     * Create definition
122
     *
123
     * @param  string $class
124
     * @return Definition
125
     */
126 1
    protected function createDefinition(string $class): Definition
127
    {
128 1
        $path = $this->basePath . DIRECTORY_SEPARATOR . str_replace('\\', '.', $class) . '.yml';
129
130 1
        if (! is_file($path)) {
131
            throw new DefinitionNotFoundException($class);
132
        }
133
134 1
        $config = $this->readConfig($path);
135 1
        $definition = new Definition($class);
136
137 1
        foreach ($this->processors as $processor)
138
        {
139 1
            $processor->process($config, $definition);
140
        }
141
142 1
        return $definition;
143
    }
144
145
    /**
146
     * Read configuration of mapping definition
147
     *
148
     * @param  string $path
149
     * @return array
150
     */
151 1
    protected function readConfig(string $path): array
152
    {
153 1
        if (! is_readable($path)) {
154
            throw new DefinitionProviderException(sprintf('File "%s" with definition is not readable.', $path));
155
        }
156
157 1
        $content = file_get_contents($path);
158 1
        $config  = $this->parser->parse($content);
159 1
        $schema  = $this->getSchema();
160
161 1
        return $this->processor->process($schema, [$config]);
162
    }
163
164
    /**
165
     * Get schema of mapping definition
166
     *
167
     * @return NodeInterface
168
     */
169 1
    protected function getSchema(): NodeInterface
170
    {
171 1
        if ($this->schema === null) {
172 1
            $this->schema = $this->config->getConfigTreeBuilder()->buildTree();
173
        }
174
175 1
        return $this->schema;
176
    }
177
}