Passed
Branch 3.0.0 (98e096)
by Pieter
02:47
created

Apie::__construct()   B

Complexity

Conditions 8
Paths 18

Size

Total Lines 34
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 8
eloc 25
c 1
b 0
f 0
nc 18
nop 4
dl 0
loc 34
rs 8.4444
1
<?php
2
3
namespace W2w\Lib\Apie;
4
5
use Doctrine\Common\Annotations\Reader;
6
use Psr\Cache\CacheItemPoolInterface;
7
use Symfony\Component\PropertyAccess\PropertyAccessor;
8
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
9
use Symfony\Component\Serializer\Encoder\DecoderInterface;
10
use Symfony\Component\Serializer\Encoder\EncoderInterface;
11
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
12
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
13
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
14
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
15
use W2w\Lib\Apie\Encodings\ChainedFormatRetriever;
16
use W2w\Lib\Apie\Encodings\FormatRetrieverInterface;
17
use W2w\Lib\Apie\Exceptions\BadConfigurationException;
18
use W2w\Lib\Apie\Exceptions\NotAnApiePluginException;
19
use W2w\Lib\Apie\PluginInterfaces\AnnotationReaderProviderInterface;
20
use W2w\Lib\Apie\PluginInterfaces\ApieAwareInterface;
21
use W2w\Lib\Apie\PluginInterfaces\ApiResourceFactoryProviderInterface;
22
use W2w\Lib\Apie\PluginInterfaces\CacheItemPoolProviderInterface;
23
use W2w\Lib\Apie\PluginInterfaces\EncoderProviderInterface;
24
use W2w\Lib\Apie\PluginInterfaces\NormalizerProviderInterface;
25
use W2w\Lib\Apie\PluginInterfaces\ResourceProviderInterface;
26
use W2w\Lib\Apie\PluginInterfaces\SerializerProviderInterface;
27
use W2w\Lib\Apie\PluginInterfaces\SymfonyComponentProviderInterface;
28
use W2w\Lib\Apie\Plugins\CorePlugin;
29
use W2w\Lib\Apie\ResourceFactories\ApiResourceFactoryInterface;
30
use W2w\Lib\Apie\ResourceFactories\ChainableFactory;
31
use W2w\Lib\Apie\Serializers\ResourceSerializerInterface;
32
33
final class Apie implements SerializerProviderInterface, ResourceProviderInterface, NormalizerProviderInterface, EncoderProviderInterface, SymfonyComponentProviderInterface, CacheItemPoolProviderInterface, AnnotationReaderProviderInterface, ApiResourceFactoryProviderInterface
34
{
35
    /**
36
     * @var bool
37
     */
38
    private $debug;
39
40
    /**
41
     * @var string|null
42
     */
43
    private $cacheFolder;
44
45
    /**
46
     * @var SerializerProviderInterface[]
47
     */
48
    private $serializers = [];
49
50
    /**
51
     * @var ResourceProviderInterface[]
52
     */
53
    private $resources = [];
54
55
    /**
56
     * @var NormalizerProviderInterface[]
57
     */
58
    private $normalizers = [];
59
60
    /**
61
     * @var EncoderProviderInterface[]
62
     */
63
    private $encoders = [];
64
65
    /**
66
     * @var SymfonyComponentProviderInterface[]
67
     */
68
    private $symfonyComponents = [];
69
70
    /**
71
     * @var CacheItemPoolProviderInterface[]
72
     */
73
    private $cacheItemPools = [];
74
75
    /**
76
     * @var object[]
77
     */
78
    private $plugins = [];
79
80
    /**
81
     * @var AnnotationReaderProviderInterface[]
82
     */
83
    private $annotationReaders = [];
84
85
    /**
86
     * @var ApiResourceFactoryProviderInterface[]
87
     */
88
    private $apiResourceFactories = [];
89
90
    /**
91
     * @var ApieCore
92
     */
93
    private $apieCore;
94
95
    /**
96
97
     * @param object[] $plugins
98
     * @param bool $debug
99
     * @param string|null $cacheFolder
100
     * @param bool $addCorePlugin
101
     */
102
    public function __construct(array $plugins, bool $debug = false, ?string $cacheFolder = null, bool $addCorePlugin = true)
103
    {
104
        $this->debug = $debug;
105
        $this->cacheFolder = $cacheFolder;
106
        static $mapping = [
107
            SerializerProviderInterface::class => 'serializers',
108
            ResourceProviderInterface::class => 'resources',
109
            NormalizerProviderInterface::class => 'normalizers',
110
            EncoderProviderInterface::class => 'encoders',
111
            SymfonyComponentProviderInterface::class => 'symfonyComponents',
112
            CacheItemPoolProviderInterface::class => 'cacheItemPools',
113
            AnnotationReaderProviderInterface::class => 'annotationReaders',
114
            ApiResourceFactoryProviderInterface::class => 'apiResourceFactories',
115
        ];
116
        if ($addCorePlugin) {
117
            $plugins[] = new CorePlugin();
118
        }
119
        $this->plugins = $plugins;
120
        foreach ($plugins as $plugin) {
121
            $isUsed = false;
122
            foreach ($mapping as $className => $propertyName) {
123
                if ($plugin instanceof $className) {
124
                    $this->$propertyName[] = $plugin;
125
                    if (!$isUsed && $plugin instanceof ApieAwareInterface) {
126
                        $plugin->setApie($this);
127
                    }
128
                    $isUsed = true;
129
                }
130
            }
131
            if (!$isUsed) {
132
                throw new NotAnApiePluginException($plugin);
133
            }
134
        }
135
        $this->apieCore = new ApieCore($this);
136
    }
137
138
    /**
139
     * Creates a new instance of Apie reusing the services/instances of the current Apie instance.
140
     *
141
     * @param array $plugins
142
     * @return Apie
143
     */
144
    public function createContext(array $plugins = []): self
145
    {
146
        $plugins[] = $this;
147
        return new Apie($plugins, $this->debug, $this->cacheFolder, false);
148
    }
149
150
    /**
151
     * @return bool
152
     */
153
    public function isDebug(): bool
154
    {
155
        return $this->debug;
156
    }
157
158
    /**
159
     * @return string|null
160
     */
161
    public function getCacheFolder(): ?string
162
    {
163
        return $this->cacheFolder;
164
    }
165
166
    public function getPlugin(string $pluginClass): object
167
    {
168
        foreach ($this->plugins as $plugin) {
169
            if ($plugin instanceof $pluginClass) {
170
                return $plugin;
171
            }
172
        }
173
        throw new BadConfigurationException('Plugin ' . $pluginClass . ' not found!');
174
    }
175
176
    /**
177
     * @return ResourceSerializerInterface
178
     */
179
    public function getResourceSerializer(): ResourceSerializerInterface
180
    {
181
        if (empty($this->serializers)) {
182
            throw new BadConfigurationException('I have no resource serializer set up');
183
        }
184
        return reset($this->serializers)->getResourceSerializer();
185
    }
186
187
    /**
188
     * Returns a list of Api resources.
189
     *
190
     * @return string[]
191
     */
192
    public function getResources(): array
193
    {
194
        $resources = [];
195
        foreach ($this->resources as $resourceProvider) {
196
            $resources = array_merge($resources, $resourceProvider->getResources());
197
        }
198
        return array_values(array_unique($resources));
199
    }
200
201
    /**
202
     * @return NormalizerInterface[]|DenormalizerInterface[]
203
     */
204
    public function getNormalizers(): array
205
    {
206
        $normalizers = [];
207
        foreach ($this->normalizers as $normalizerProvider) {
208
            $normalizers = array_merge($normalizers, $normalizerProvider->getNormalizers());
209
        }
210
        return $normalizers;
211
    }
212
213
    /**
214
     * @return EncoderInterface[]|DecoderInterface[]
215
     */
216
    public function getEncoders(): array
217
    {
218
        $encoders = [];
219
        foreach ($this->encoders as $encoderProvider) {
220
            $encoders = array_merge($encoders, $encoderProvider->getEncoders());
221
        }
222
        return $encoders;
223
    }
224
225
    public function getClassMetadataFactory(): ClassMetadataFactoryInterface
226
    {
227
        if (empty($this->symfonyComponents)) {
228
            throw new BadConfigurationException('I have no symfony component provider set up');
229
        }
230
        return reset($this->symfonyComponents)->getClassMetadataFactory();
231
    }
232
233
    public function getPropertyConverter(): NameConverterInterface
234
    {
235
        if (empty($this->symfonyComponents)) {
236
            throw new BadConfigurationException('I have no symfony component provider set up');
237
        }
238
        return reset($this->symfonyComponents)->getPropertyConverter();
239
    }
240
241
    public function getPropertyAccessor(): PropertyAccessor
242
    {
243
        if (empty($this->symfonyComponents)) {
244
            throw new BadConfigurationException('I have no symfony component provider set up');
245
        }
246
        return reset($this->symfonyComponents)->getPropertyAccessor();
247
    }
248
249
    public function getPropertyTypeExtractor(): PropertyTypeExtractorInterface
250
    {
251
        if (empty($this->symfonyComponents)) {
252
            throw new BadConfigurationException('I have no symfony component provider set up');
253
        }
254
        return reset($this->symfonyComponents)->getPropertyTypeExtractor();
255
    }
256
257
    public function getCacheItemPool(): CacheItemPoolInterface
258
    {
259
        if (empty($this->cacheItemPools)) {
260
            throw new BadConfigurationException('I have no cache item pool provider set up');
261
        }
262
        return reset($this->cacheItemPools)->getCacheItemPool();
263
    }
264
265
    public function getAnnotationReader(): Reader
266
    {
267
        if (empty($this->annotationReaders)) {
268
            throw new BadConfigurationException('I have no annotation reader set up');
269
        }
270
        return reset($this->annotationReaders)->getAnnotationReader();
271
    }
272
273
    public function getFormatRetriever(): FormatRetrieverInterface
274
    {
275
        return new ChainedFormatRetriever(
276
            array_map(
277
                function (EncoderProviderInterface $encoderProvider) {
278
                    return $encoderProvider->getFormatRetriever();
279
                },
280
                $this->encoders
281
            )
282
        );
283
    }
284
285
    public function getIdentifierExtractor(): IdentifierExtractor
286
    {
287
        return $this->apieCore->getIdentifierExtractor();
288
    }
289
290
    public function getApiResourceFacade(): ApiResourceFacade
291
    {
292
        return $this->apieCore->getApiResourceFacade();
293
    }
294
295
    public function getApiResourceFactory(): ApiResourceFactoryInterface
296
    {
297
        return new ChainableFactory($this->apiResourceFactories);
298
    }
299
}
300