Passed
Branch 3.0.0 (80e4da)
by Pieter
04:11
created

CorePlugin::getNormalizers()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 33
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 24
c 1
b 0
f 0
nc 1
nop 0
dl 0
loc 33
rs 9.536
1
<?php
2
3
4
namespace W2w\Lib\Apie\Plugins;
5
6
7
use Doctrine\Common\Annotations\AnnotationReader;
8
use Doctrine\Common\Annotations\AnnotationRegistry;
9
use Doctrine\Common\Annotations\CachedReader;
10
use Doctrine\Common\Annotations\Reader;
11
use Doctrine\Common\Cache\PhpFileCache;
12
use Psr\Cache\CacheItemPoolInterface;
13
use Symfony\Component\Cache\Adapter\ArrayAdapter;
14
use Symfony\Component\PropertyAccess\PropertyAccess;
15
use Symfony\Component\PropertyAccess\PropertyAccessor;
16
use Symfony\Component\PropertyInfo\Extractor\PhpDocExtractor;
17
use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor;
18
use Symfony\Component\PropertyInfo\Extractor\SerializerExtractor;
19
use Symfony\Component\PropertyInfo\PropertyInfoExtractor;
20
use Symfony\Component\PropertyInfo\PropertyTypeExtractorInterface;
21
use Symfony\Component\Serializer\Mapping\ClassDiscriminatorFromClassMetadata;
22
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactory;
23
use Symfony\Component\Serializer\Mapping\Factory\ClassMetadataFactoryInterface;
24
use Symfony\Component\Serializer\Mapping\Loader\AnnotationLoader;
25
use Symfony\Component\Serializer\Mapping\Loader\LoaderChain;
26
use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter;
27
use Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter;
28
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
29
use Symfony\Component\Serializer\Normalizer\ArrayDenormalizer;
30
use Symfony\Component\Serializer\Normalizer\DenormalizerInterface;
31
use Symfony\Component\Serializer\Normalizer\JsonSerializableNormalizer;
32
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
33
use Symfony\Component\Serializer\Serializer;
34
use W2w\Lib\Apie\ApiResources\ApplicationInfo;
35
use W2w\Lib\Apie\ApiResources\Status;
36
use W2w\Lib\Apie\BaseGroupLoader;
37
use W2w\Lib\Apie\ExtendReaderWithConfigReader;
38
use W2w\Lib\Apie\Normalizers\ApieObjectNormalizer;
39
use W2w\Lib\Apie\Normalizers\ContextualNormalizer;
40
use W2w\Lib\Apie\Normalizers\EvilReflectionPropertyNormalizer;
41
use W2w\Lib\Apie\Normalizers\ExceptionNormalizer;
42
use W2w\Lib\Apie\PluginInterfaces\AnnotationReaderProviderInterface;
43
use W2w\Lib\Apie\PluginInterfaces\ApieAwareInterface;
44
use W2w\Lib\Apie\PluginInterfaces\ApieAwareTrait;
45
use W2w\Lib\Apie\PluginInterfaces\CacheItemPoolProviderInterface;
46
use W2w\Lib\Apie\PluginInterfaces\NormalizerProviderInterface;
47
use W2w\Lib\Apie\PluginInterfaces\ResourceProviderInterface;
48
use W2w\Lib\Apie\PluginInterfaces\SerializerProviderInterface;
49
use W2w\Lib\Apie\PluginInterfaces\SymfonyComponentProviderInterface;
50
use W2w\Lib\Apie\Serializers\ResourceSerializerInterface;
51
use W2w\Lib\Apie\Serializers\SymfonySerializerAdapter;
52
53
class CorePlugin implements SerializerProviderInterface, ResourceProviderInterface, ApieAwareInterface, NormalizerProviderInterface, SymfonyComponentProviderInterface, CacheItemPoolProviderInterface, AnnotationReaderProviderInterface
54
{
55
    use ApieAwareTrait;
56
57
    private $classMetadataFactory;
58
59
    private $propertyConverter;
60
61
    private $propertyAccessor;
62
63
    private $propertyTypeExtractor;
64
65
    private $annotationReader;
66
67
    /**
68
     * Returns a list of Api resources.
69
     *
70
     * @param string $context
71
     * @return string[]
72
     */
73
    public function getResources(string $context): array
74
    {
75
        return [ApplicationInfo::class, Status::class];
76
    }
77
78
    public function getResourceSerializer(): ResourceSerializerInterface
79
    {
80
        $normalizers = $this->getApie()->getNormalizers();
81
        $encoders = $this->getApie()->getEncoders();
82
        $serializer = new Serializer($normalizers, $encoders);
83
        return new SymfonySerializerAdapter($serializer);
84
    }
85
86
    /**
87
     * @return NormalizerInterface[]|DenormalizerInterface[]
88
     */
89
    public function getNormalizers(): array
90
    {
91
        $classMetadataFactory = $this->getApie()->getClassMetadataFactory();
92
93
        $classDiscriminator = new ClassDiscriminatorFromClassMetadata($classMetadataFactory);
94
95
        $objectNormalizer = new ApieObjectNormalizer(
96
            $classMetadataFactory,
97
            $this->getApie()->getPropertyConverter(),
98
            $this->getApie()->getPropertyAccessor(),
99
            $this->getApie()->getPropertyTypeExtractor(),
100
            $classDiscriminator,
101
            null,
102
            []
103
        );
104
        $evilObjectNormalizer = new EvilReflectionPropertyNormalizer(
105
            $classMetadataFactory,
106
            $this->getApie()->getPropertyConverter(),
107
            $this->getApie()->getPropertyAccessor(),
108
            $this->getApie()->getPropertyTypeExtractor(),
109
            $classDiscriminator,
110
            null,
111
            []
112
        );
113
        ContextualNormalizer::disableDenormalizer(EvilReflectionPropertyNormalizer::class);
114
        ContextualNormalizer::disableNormalizer(EvilReflectionPropertyNormalizer::class);
115
116
        return [
0 ignored issues
show
introduced by
The expression return array(new W2w\Lib...r)), $objectNormalizer) returns an array which contains values of type W2w\Lib\Apie\Normalizers\ExceptionNormalizer which are incompatible with the return type Symfony\Component\Serial...r\DenormalizerInterface mandated by W2w\Lib\Apie\PluginInter...rface::getNormalizers().
Loading history...
117
            new ExceptionNormalizer($this->getApie()->isDebug()),
118
            new JsonSerializableNormalizer(),
119
            new ArrayDenormalizer(),
120
            new ContextualNormalizer([$evilObjectNormalizer]),
121
            $objectNormalizer
122
        ];
123
124
    }
125
126
    public function getClassMetadataFactory(): ClassMetadataFactoryInterface
127
    {
128
        if (!$this->classMetadataFactory) {
129
            $this->classMetadataFactory = new ClassMetadataFactory(
130
                new LoaderChain([
131
                    new AnnotationLoader($this->getApie()->getAnnotationReader()),
132
                    new BaseGroupLoader(['read', 'write', 'get', 'post', 'put']),
133
                ])
134
            );
135
        }
136
        return $this->classMetadataFactory;
137
    }
138
139
    public function getPropertyConverter(): NameConverterInterface
140
    {
141
        if (!$this->propertyConverter) {
142
            $classMetadataFactory = $this->getApie()->getClassMetadataFactory();
143
            $this->propertyConverter = new MetadataAwareNameConverter(
144
                $classMetadataFactory,
145
                new CamelCaseToSnakeCaseNameConverter()
146
            );
147
        }
148
        return $this->propertyConverter;
149
    }
150
151
    public function getPropertyAccessor(): PropertyAccessor
152
    {
153
        if (!$this->propertyAccessor) {
154
            $this->propertyAccessor = PropertyAccess::createPropertyAccessorBuilder()
155
                ->setCacheItemPool($this->getApie()->getCacheItemPool())
156
                ->getPropertyAccessor();
157
        }
158
        return $this->propertyAccessor;
159
    }
160
161
    public function getPropertyTypeExtractor(): PropertyTypeExtractorInterface
162
    {
163
        if (!$this->propertyTypeExtractor) {
164
            $factory = $this->getApie()->getClassMetadataFactory();
165
            $reflectionExtractor = new ReflectionExtractor();
166
            $phpDocExtractor = new PhpDocExtractor();
167
168
            $this->propertyTypeExtractor = new PropertyInfoExtractor(
169
                [
170
                    new SerializerExtractor($factory),
171
                    $reflectionExtractor,
172
                ],
173
                [
174
                    $phpDocExtractor,
175
                    $reflectionExtractor,
176
                ],
177
                [
178
                    $phpDocExtractor,
179
                ],
180
                [
181
                    $reflectionExtractor,
182
                ],
183
                [
184
                    $reflectionExtractor,
185
                ]
186
            );
187
        }
188
        return $this->propertyTypeExtractor;
189
    }
190
191
    public function getCacheItemPool(): CacheItemPoolInterface
192
    {
193
        return new ArrayAdapter(0, true);
194
    }
195
196
    /**
197
     * @return Reader
198
     */
199
    public function getAnnotationReader(): Reader
200
    {
201
        if (!$this->annotationReader) {
202
            /** @scrutinizer ignore-deprecated */AnnotationRegistry::registerLoader('class_exists');
203
            if (class_exists(PhpFileCache::class) && $this->getApie()->getCacheFolder()) {
204
                $this->annotationReader = new CachedReader(
205
                    new AnnotationReader(),
206
                    new PhpFileCache($this->getCacheFolder() . DIRECTORY_SEPARATOR . '/doctrine-cache'),
0 ignored issues
show
Bug introduced by
The method getCacheFolder() does not exist on W2w\Lib\Apie\Plugins\CorePlugin. ( Ignorable by Annotation )

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

206
                    new PhpFileCache($this->/** @scrutinizer ignore-call */ getCacheFolder() . DIRECTORY_SEPARATOR . '/doctrine-cache'),

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
207
                    $this->isDebug()
0 ignored issues
show
Bug introduced by
The method isDebug() does not exist on W2w\Lib\Apie\Plugins\CorePlugin. ( Ignorable by Annotation )

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

207
                    $this->/** @scrutinizer ignore-call */ 
208
                           isDebug()

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
208
                );
209
            } else {
210
                $this->annotationReader = new AnnotationReader();
211
            }
212
        }
213
        return $this->annotationReader;
214
    }
215
}
216