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