Completed
Branch 3.3 (d40063)
by Pieter
04:00
created

Apie::getOpenApiSpecGenerator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace W2w\Lib\Apie;
4
5
use Doctrine\Common\Annotations\Reader;
6
use erasys\OpenApi\Spec\v3\Document;
7
use erasys\OpenApi\Spec\v3\Info;
8
use Psr\Cache\CacheItemPoolInterface;
9
use Symfony\Component\PropertyAccess\PropertyAccessor;
10
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
11
use Symfony\Component\Serializer\Encoder\DecoderInterface;
12
use Symfony\Component\Serializer\Encoder\EncoderInterface;
13
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
14
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
15
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
16
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
17
use W2w\Lib\Apie\Core\ApieCore;
18
use W2w\Lib\Apie\Core\ApiResourceFacade;
19
use W2w\Lib\Apie\Core\ClassResourceConverter;
20
use W2w\Lib\Apie\Core\Encodings\ChainableFormatRetriever;
21
use W2w\Lib\Apie\Core\IdentifierExtractor;
22
use W2w\Lib\Apie\Core\PluginContainer;
23
use W2w\Lib\Apie\Core\ResourceFactories\ChainableFactory;
24
use W2w\Lib\Apie\Exceptions\BadConfigurationException;
25
use W2w\Lib\Apie\Exceptions\NotAnApiePluginException;
26
use W2w\Lib\Apie\Interfaces\ApiResourceFactoryInterface;
27
use W2w\Lib\Apie\Interfaces\FormatRetrieverInterface;
28
use W2w\Lib\Apie\Interfaces\ResourceSerializerInterface;
29
use W2w\Lib\Apie\OpenApiSchema\OpenApiSpecGenerator;
30
use W2w\Lib\Apie\OpenApiSchema\SchemaGenerator;
31
use W2w\Lib\Apie\PluginInterfaces\AnnotationReaderProviderInterface;
32
use W2w\Lib\Apie\PluginInterfaces\ApieAwareInterface;
33
use W2w\Lib\Apie\PluginInterfaces\ApieConfigInterface;
34
use W2w\Lib\Apie\PluginInterfaces\ApiResourceFactoryProviderInterface;
35
use W2w\Lib\Apie\PluginInterfaces\CacheItemPoolProviderInterface;
36
use W2w\Lib\Apie\PluginInterfaces\EncoderProviderInterface;
37
use W2w\Lib\Apie\PluginInterfaces\NormalizerProviderInterface;
38
use W2w\Lib\Apie\PluginInterfaces\ObjectAccessProviderInterface;
39
use W2w\Lib\Apie\PluginInterfaces\OpenApiEventProviderInterface;
40
use W2w\Lib\Apie\PluginInterfaces\OpenApiInfoProviderInterface;
41
use W2w\Lib\Apie\PluginInterfaces\PropertyInfoExtractorProviderInterface;
42
use W2w\Lib\Apie\PluginInterfaces\ResourceProviderInterface;
43
use W2w\Lib\Apie\PluginInterfaces\SchemaProviderInterface;
44
use W2w\Lib\Apie\PluginInterfaces\SerializerProviderInterface;
45
use W2w\Lib\Apie\PluginInterfaces\SymfonyComponentProviderInterface;
46
use W2w\Lib\Apie\Plugins\Core\CorePlugin;
47
use W2w\Lib\ApieObjectAccessNormalizer\ObjectAccess\CachedObjectAccess;
48
use W2w\Lib\ApieObjectAccessNormalizer\ObjectAccess\GroupedObjectAccess;
49
use W2w\Lib\ApieObjectAccessNormalizer\ObjectAccess\ObjectAccess;
50
use W2w\Lib\ApieObjectAccessNormalizer\ObjectAccess\ObjectAccessInterface;
51
52
final class Apie implements SerializerProviderInterface,
53
    ResourceProviderInterface,
54
    NormalizerProviderInterface,
55
    EncoderProviderInterface,
56
    SymfonyComponentProviderInterface,
57
    CacheItemPoolProviderInterface,
58
    AnnotationReaderProviderInterface,
59
    ApiResourceFactoryProviderInterface,
60
    OpenApiInfoProviderInterface,
61
    ApieConfigInterface,
62
    SchemaProviderInterface,
63
    OpenApiEventProviderInterface,
64
    PropertyInfoExtractorProviderInterface
0 ignored issues
show
Deprecated Code introduced by
The interface W2w\Lib\Apie\PluginInter...ractorProviderInterface has been deprecated: use ObjectAccessProviderInterface instead ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-deprecated  annotation

64
    /** @scrutinizer ignore-deprecated */ PropertyInfoExtractorProviderInterface

This interface has been deprecated. The supplier of the interface has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the interface will be removed and what other interface to use instead.

Loading history...
65
{
66
    const VERSION = "3.0";
67
68
    /**
69
     * @var bool
70
     */
71
    private $debug;
72
73
    /**
74
     * @var string|null
75
     */
76
    private $cacheFolder;
77
78
    /**
79
     * @var PluginContainer
80
     */
81
    private $pluginContainer;
82
83
    /**
84
     * @var ApieCore
85
     */
86
    private $apieCore;
87
88
    /**
89
     * @var ChainableFactory|null
90
     */
91
    private $chainableFactory;
92
93
    /**
94
     * @var ChainableFormatRetriever|null
95
     */
96
    private $chainableFormatRetriever;
97
98
    /**
99
100
     * @param object[] $plugins
101
     * @param bool $debug
102
     * @param string|null $cacheFolder
103
     * @param bool $addCorePlugin
104
     */
105
    public function __construct(array $plugins, bool $debug = false, ?string $cacheFolder = null, bool $addCorePlugin = true)
106
    {
107
        $this->debug = $debug;
108
        $this->cacheFolder = $cacheFolder;
109
        if ($addCorePlugin) {
110
            $plugins[] = new CorePlugin();
111
        }
112
        $this->pluginContainer = new PluginContainer($plugins);
113
        $this->pluginContainer->each(
114
            ApieAwareInterface::class,
115
            function (ApieAwareInterface $plugin) {
116
                $plugin->setApie($this);
117
            }
118
        );
119
        $this->apieCore = new ApieCore($this, $this->pluginContainer);
120
    }
121
122
    /**
123
     * Creates a new instance of Apie reusing the services/instances of the current Apie instance.
124
     *
125
     * @param array $plugins
126
     * @return Apie
127
     */
128
    public function createContext(array $plugins = []): self
129
    {
130
        $plugins[] = $this;
131
        return new Apie($plugins, $this->debug, $this->cacheFolder, false);
132
    }
133
134
    /**
135
     * @return bool
136
     */
137
    public function isDebug(): bool
138
    {
139
        return $this->debug;
140
    }
141
142
    /**
143
     * @return string|null
144
     */
145
    public function getCacheFolder(): ?string
146
    {
147
        return $this->cacheFolder;
148
    }
149
150
    public function getPlugin(string $pluginClass): object
151
    {
152
        return $this->pluginContainer->getPlugin($pluginClass);
153
    }
154
155
    /**
156
     * @return ResourceSerializerInterface
157
     */
158
    public function getResourceSerializer(): ResourceSerializerInterface
159
    {
160
        return $this->pluginContainer->first(
161
            SerializerProviderInterface::class,
162
            new BadConfigurationException('I have no resource serializer set up')
163
        )->getResourceSerializer();
164
    }
165
166
    /**
167
     * Returns a list of Api resources.
168
     *
169
     * @return string[]
170
     */
171
    public function getResources(): array
172
    {
173
        return array_values(array_unique($this->pluginContainer->merge(ResourceProviderInterface::class, 'getResources')));
174
    }
175
176
    /**
177
     * @return NormalizerInterface[]|DenormalizerInterface[]
178
     */
179
    public function getNormalizers(): array
180
    {
181
        return $this->pluginContainer->merge(NormalizerProviderInterface::class, 'getNormalizers');
182
    }
183
184
    /**
185
     * @return EncoderInterface[]|DecoderInterface[]
186
     */
187
    public function getEncoders(): array
188
    {
189
        return $this->pluginContainer->merge(EncoderProviderInterface::class, 'getEncoders');
190
    }
191
192
    public function getClassMetadataFactory(): ClassMetadataFactoryInterface
193
    {
194
        return $this->pluginContainer->first(
195
            SymfonyComponentProviderInterface::class,
196
            new BadConfigurationException('I have no symfony component provider set up')
197
        )->getClassMetadataFactory();
198
    }
199
200
    public function getPropertyConverter(): NameConverterInterface
201
    {
202
        return $this->pluginContainer->first(
203
            SymfonyComponentProviderInterface::class,
204
            new BadConfigurationException('I have no symfony component provider set up')
205
        )->getPropertyConverter();
206
    }
207
208
    public function getPropertyAccessor(): PropertyAccessor
209
    {
210
        return $this->pluginContainer->first(
211
            SymfonyComponentProviderInterface::class,
212
            new BadConfigurationException('I have no symfony component provider set up')
213
        )->getPropertyAccessor();
214
    }
215
216
    public function getPropertyTypeExtractor(): PropertyTypeExtractorInterface
217
    {
218
        return $this->pluginContainer->first(
219
            SymfonyComponentProviderInterface::class,
220
            new BadConfigurationException('I have no symfony component provider set up')
221
        )->getPropertyTypeExtractor();
222
    }
223
224
    public function getCacheItemPool(): CacheItemPoolInterface
225
    {
226
        return $this->pluginContainer->first(
227
            CacheItemPoolProviderInterface::class,
228
            new BadConfigurationException('I have no cache item pool provider set up')
229
        )->getCacheItemPool();
230
    }
231
232
    public function getAnnotationReader(): Reader
233
    {
234
        return $this->pluginContainer->first(
235
            AnnotationReaderProviderInterface::class,
236
            new BadConfigurationException('I have no annotation reader set up')
237
        )->getAnnotationReader();
238
    }
239
240
    public function getFormatRetriever(): FormatRetrieverInterface
241
    {
242
        if (!$this->chainableFormatRetriever) {
243
            $this->chainableFormatRetriever = new ChainableFormatRetriever(
244
                iterator_to_array($this->pluginContainer->combine(EncoderProviderInterface::class, 'getFormatRetriever'))
245
            );
246
        }
247
        return $this->chainableFormatRetriever;
248
    }
249
250
    public function getIdentifierExtractor(): IdentifierExtractor
251
    {
252
        return $this->apieCore->getIdentifierExtractor();
253
    }
254
255
    public function getApiResourceFacade(): ApiResourceFacade
256
    {
257
        return $this->apieCore->getApiResourceFacade();
258
    }
259
260
    public function getOpenApiSpecGenerator(): OpenApiSpecGenerator
261
    {
262
        return $this->apieCore->getOpenApiSpecGenerator();
263
    }
264
265
    public function getSchemaGenerator(): SchemaGenerator
266
    {
267
        return $this->apieCore->getSchemaGenerator();
268
    }
269
270
    public function getApiResourceFactory(): ApiResourceFactoryInterface
271
    {
272
        if (!$this->chainableFactory) {
273
            $this->chainableFactory = new ChainableFactory(
274
                iterator_to_array($this->pluginContainer->combine(ApiResourceFactoryProviderInterface::class, 'getApiResourceFactory'))
275
            );
276
        }
277
        return $this->chainableFactory;
278
    }
279
280
    public function createInfo(): Info
281
    {
282
        $res = $this->pluginContainer->first(OpenApiInfoProviderInterface::class, null);
283
284
        if (empty($res)) {
285
            return new Info('Apie', Apie::VERSION);
286
        }
287
        return $res->createInfo();
288
    }
289
290
    public function getBaseUrl(): string
291
    {
292
        return $this->pluginContainer->first(ApieConfigInterface::class, new BadConfigurationException('I have no config set up'))->getBaseUrl();
293
    }
294
295
    public function getDefinedStaticData(): array
296
    {
297
        $result = [];
298
        foreach (array_reverse($this->pluginContainer->getPluginsWithInterface(SchemaProviderInterface::class)) as $schemaDefinition) {
299
            foreach ($schemaDefinition->getDefinedStaticData() as $className => $schema) {
300
                $result[$className] = $schema;
301
            }
302
        }
303
        return $result;
304
    }
305
306
    public function getDynamicSchemaLogic(): array
307
    {
308
        $result = [];
309
        foreach (array_reverse($this->pluginContainer->getPluginsWithInterface(SchemaProviderInterface::class)) as $schemaDefinition) {
310
            foreach ($schemaDefinition->getDynamicSchemaLogic() as $className => $callable) {
311
                $result[$className] = $callable;
312
            }
313
        }
314
        return $result;
315
    }
316
317
    public function getClassResourceConverter(): ClassResourceConverter
318
    {
319
        return $this->apieCore->getClassResourceConverter();
320
    }
321
322
    public function onOpenApiDocGenerated(Document $document): Document
323
    {
324
        $this->pluginContainer->each(OpenApiEventProviderInterface::class, function (OpenApiEventProviderInterface $plugin) use (&$document) {
325
            $document = $plugin->onOpenApiDocGenerated($document);
326
        });
327
        return $document;
328
    }
329
330
    /**
331
     * @deprecated  use getObjectAccess instead
332
     */
333
    public function getListExtractors(): array
334
    {
335
        return $this->pluginContainer->merge(PropertyInfoExtractorProviderInterface::class, 'getListExtractors');
336
    }
337
338
    /**
339
     * @deprecated  use getObjectAccess instead
340
     */
341
    public function getTypeExtractors(): array
342
    {
343
        return $this->pluginContainer->merge(PropertyInfoExtractorProviderInterface::class, 'getTypeExtractors');
344
    }
345
346
    /**
347
     * @deprecated  use getObjectAccess instead
348
     */
349
    public function getDescriptionExtractors(): array
350
    {
351
        return $this->pluginContainer->merge(PropertyInfoExtractorProviderInterface::class, 'getDescriptionExtractors');
352
    }
353
354
    /**
355
     * @deprecated  use getObjectAccess instead
356
     */
357
    public function getAccessExtractors(): array
358
    {
359
        return $this->pluginContainer->merge(PropertyInfoExtractorProviderInterface::class, 'getAccessExtractors');
360
    }
361
362
    /**
363
     * @deprecated  use getObjectAccess instead
364
     */
365
    public function getInitializableExtractors(): array
366
    {
367
        return $this->pluginContainer->merge(PropertyInfoExtractorProviderInterface::class, 'getInitializableExtractors');
368
    }
369
370
    public function getObjectAccess(): ObjectAccessInterface
371
    {
372
        $objectAccess = new ObjectAccess();
373
        $objectAccesses = $this->pluginContainer->getPluginsWithInterface(ObjectAccessProviderInterface::class);
374
        if (!empty($objectAccesses)) {
375
            $list = [];
376
            foreach ($objectAccesses as $objectAccess) {
377
                $list = array_merge($list, $objectAccess->getObjectAccesses());
378
            }
379
            $objectAccess = new GroupedObjectAccess($objectAccess, $list);
380
        }
381
        if (!$this->debug && $this->cacheFolder) {
382
            return new CachedObjectAccess($objectAccess, $this->getCacheItemPool());
383
        }
384
        return $objectAccess;
385
    }
386
}
387