CorePlugin   A
last analyzed

Complexity

Total Complexity 17

Size/Duplication

Total Lines 163
Duplicated Lines 0 %

Importance

Changes 3
Bugs 0 Features 1
Metric Value
eloc 70
c 3
b 0
f 1
dl 0
loc 163
rs 10
wmc 17

10 Methods

Rating   Name   Duplication   Size   Complexity  
A getClassMetadataFactory() 0 11 2
A getPropertyConverter() 0 10 2
A getResourceSerializer() 0 7 1
A getEncoders() 0 7 1
A getObjectAccesses() 0 5 1
A getFormatRetriever() 0 5 1
A getCacheItemPool() 0 6 2
A getAnnotationReader() 0 15 4
A getApiResourceFactory() 0 9 2
A getNormalizers() 0 13 1
1
<?php
2
3
namespace W2w\Lib\Apie\Plugins\Core;
4
5
use Doctrine\Common\Annotations\AnnotationReader;
6
use Doctrine\Common\Annotations\AnnotationRegistry;
7
use Doctrine\Common\Annotations\CachedReader;
8
use Doctrine\Common\Annotations\Reader;
9
use Doctrine\Common\Cache\PhpFileCache;
10
use Psr\Cache\CacheItemPoolInterface;
11
use Symfony\Component\Cache\Adapter\ArrayAdapter;
12
use Symfony\Component\Serializer\Encoder\JsonDecode;
13
use Symfony\Component\Serializer\Encoder\JsonEncode;
14
use Symfony\Component\Serializer\Encoder\JsonEncoder;
15
use Symfony\Component\Serializer\Encoder\XmlEncoder;
16
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
17
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
18
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
19
use Symfony\Component\Serializer\Mapping\Loader\LoaderChain;
20
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
21
use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter;
22
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
23
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
24
use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer;
25
use Symfony\Component\Serializer\Serializer;
26
use Throwable;
27
use W2w\Lib\Apie\Interfaces\ApiResourceFactoryInterface;
28
use W2w\Lib\Apie\Interfaces\FormatRetrieverInterface;
29
use W2w\Lib\Apie\Interfaces\ResourceSerializerInterface;
30
use W2w\Lib\Apie\PluginInterfaces\AnnotationReaderProviderInterface;
31
use W2w\Lib\Apie\PluginInterfaces\ApieAwareInterface;
32
use W2w\Lib\Apie\PluginInterfaces\ApieAwareTrait;
33
use W2w\Lib\Apie\PluginInterfaces\ApiResourceFactoryProviderInterface;
34
use W2w\Lib\Apie\PluginInterfaces\CacheItemPoolProviderInterface;
35
use W2w\Lib\Apie\PluginInterfaces\EncoderProviderInterface;
36
use W2w\Lib\Apie\PluginInterfaces\NormalizerProviderInterface;
37
use W2w\Lib\Apie\PluginInterfaces\ObjectAccessProviderInterface;
38
use W2w\Lib\Apie\PluginInterfaces\ResourceLifeCycleInterface;
39
use W2w\Lib\Apie\PluginInterfaces\SerializerProviderInterface;
40
use W2w\Lib\Apie\PluginInterfaces\SymfonyComponentProviderInterface;
41
use W2w\Lib\Apie\Plugins\Core\Encodings\FormatRetriever;
42
use W2w\Lib\Apie\Plugins\Core\ObjectAccess\ExceptionObjectAccess;
43
use W2w\Lib\Apie\Plugins\Core\ResourceFactories\FallbackFactory;
44
use W2w\Lib\Apie\Plugins\Core\Serializers\Mapping\BaseGroupLoader;
45
use W2w\Lib\Apie\Plugins\Core\Serializers\SymfonySerializerAdapter;
46
use W2w\Lib\ApieObjectAccessNormalizer\Normalizers\ApieObjectAccessNormalizer;
47
use W2w\Lib\ApieObjectAccessNormalizer\Normalizers\MethodCallDenormalizer;
48
use W2w\Lib\ApieObjectAccessNormalizer\ObjectAccess\ObjectAccessInterface;
49
use W2w\Lib\ApieObjectAccessNormalizer\ObjectAccess\SelfObjectAccess;
50
use W2w\Lib\ApieObjectAccessNormalizer\ObjectAccess\SelfObjectAccessInterface;
51
52
/**
53
 * Plugin with most default functionality.
54
 */
55
class CorePlugin implements SerializerProviderInterface,
56
    ApieAwareInterface,
57
    NormalizerProviderInterface,
58
    EncoderProviderInterface,
59
    SymfonyComponentProviderInterface,
60
    CacheItemPoolProviderInterface,
61
    AnnotationReaderProviderInterface,
62
    ApiResourceFactoryProviderInterface,
63
    ObjectAccessProviderInterface
64
{
65
    use ApieAwareTrait;
66
67
    private $classMetadataFactory;
68
69
    private $propertyConverter;
70
71
    private $annotationReader;
72
73
    private $arrayAdapter;
74
75
    private $apiResourceFactory;
76
77
    /**
78
     * {@inheritDoc}
79
     */
80
    public function getResourceSerializer(): ResourceSerializerInterface
81
    {
82
        $normalizers = $this->getApie()->getNormalizers();
83
        $encoders = $this->getApie()->getEncoders();
84
        $serializer = new Serializer($normalizers, $encoders);
85
        $lifecycles = $this->apie->getPluginsWithInterface(ResourceLifeCycleInterface::class);
86
        return new SymfonySerializerAdapter($serializer, $this->getApie()->getFormatRetriever(), $lifecycles);
87
    }
88
89
    /**
90
     * {@inheritDoc}
91
     */
92
    public function getNormalizers(): array
93
    {
94
        $apieObjectAccessNormalizer = new ApieObjectAccessNormalizer(
95
            $this->getApie()->getObjectAccess(),
96
            $this->getApie()->getPropertyConverter(),
97
            $this->getApie()->getClassMetadataFactory()
98
        );
99
100
        return [
101
            new JsonSerializableNormalizer(),
102
            new ArrayDenormalizer(),
103
            new MethodCallDenormalizer($this->getApie()->getObjectAccess(), $apieObjectAccessNormalizer, $this->getApie()->getPropertyConverter()),
104
            $apieObjectAccessNormalizer,
105
        ];
106
107
    }
108
109
    /**
110
     * {@inheritDoc}
111
     */
112
    public function getClassMetadataFactory(): ClassMetadataFactoryInterface
113
    {
114
        if (!$this->classMetadataFactory) {
115
            $this->classMetadataFactory = new ClassMetadataFactory(
116
                new LoaderChain([
117
                    new AnnotationLoader($this->getApie()->getAnnotationReader()),
118
                    new BaseGroupLoader(['read', 'write', 'get', 'post', 'put']),
119
                ])
120
            );
121
        }
122
        return $this->classMetadataFactory;
123
    }
124
125
    /**
126
     * {@inheritDoc}
127
     */
128
    public function getPropertyConverter(): NameConverterInterface
129
    {
130
        if (!$this->propertyConverter) {
131
            $classMetadataFactory = $this->getApie()->getClassMetadataFactory();
132
            $this->propertyConverter = new MetadataAwareNameConverter(
133
                $classMetadataFactory,
134
                new CamelCaseToSnakeCaseNameConverter()
135
            );
136
        }
137
        return $this->propertyConverter;
138
    }
139
140
    /**
141
     * {@inheritDoc}
142
     */
143
    public function getCacheItemPool(): CacheItemPoolInterface
144
    {
145
        if (!$this->arrayAdapter) {
146
            $this->arrayAdapter = new ArrayAdapter(0, true);
147
        }
148
        return $this->arrayAdapter;
149
    }
150
151
    /**
152
     * {@inheritDoc}
153
     */
154
    public function getAnnotationReader(): Reader
155
    {
156
        if (!$this->annotationReader) {
157
            /** @scrutinizer ignore-deprecated */AnnotationRegistry::registerLoader('class_exists');
158
            if (class_exists(PhpFileCache::class) && $this->getApie()->getCacheFolder()) {
159
                $this->annotationReader = new CachedReader(
160
                    new AnnotationReader(),
161
                    new PhpFileCache($this->getApie()->getCacheFolder() . DIRECTORY_SEPARATOR . '/doctrine-cache'),
162
                    $this->getApie()->isDebug()
163
                );
164
            } else {
165
                $this->annotationReader = new AnnotationReader();
166
            }
167
        }
168
        return $this->annotationReader;
169
    }
170
171
    /**
172
     * {@inheritDoc}
173
     */
174
    public function getEncoders(): array
175
    {
176
        return [
177
            new XmlEncoder([XmlEncoder::ROOT_NODE_NAME => 'item']),
178
            new JsonEncoder(
179
                new JsonEncode([JsonEncode::OPTIONS => JSON_UNESCAPED_SLASHES]),
180
                new JsonDecode([JsonDecode::ASSOCIATIVE => false])
181
            )
182
        ];
183
    }
184
185
    /**
186
     * {@inheritDoc}
187
     */
188
    public function getFormatRetriever(): FormatRetrieverInterface
189
    {
190
        return new FormatRetriever([
191
            'application/json' => 'json',
192
            'application/xml' => 'xml',
193
        ]);
194
    }
195
196
    /**
197
     * {@inheritDoc}
198
     */
199
    public function getApiResourceFactory(): ApiResourceFactoryInterface
200
    {
201
        if (!$this->apiResourceFactory) {
202
            $this->apiResourceFactory = new FallbackFactory(
203
                $this->getApie()->getObjectAccess(),
204
                $this->getApie()->getIdentifierExtractor()
205
            );
206
        }
207
        return $this->apiResourceFactory;
208
    }
209
210
    /**
211
     * @return ObjectAccessInterface[]
212
     */
213
    public function getObjectAccesses(): array
214
    {
215
        return [
216
            SelfObjectAccessInterface::class => new SelfObjectAccess(),
217
            Throwable::class => new ExceptionObjectAccess($this->getApie()->isDebug()),
218
        ];
219
    }
220
}
221