Completed
Push — master ( a97424...f904c2 )
by Daniel
14:31
created

ApiNormalizer::rolesVote()   B

Complexity

Conditions 7
Paths 25

Size

Total Lines 17
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 56

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 12
c 3
b 0
f 0
dl 0
loc 17
ccs 0
cts 0
cp 0
rs 8.8333
nc 25
nop 1
cc 7
crap 56

1 Method

Rating   Name   Duplication   Size   Complexity  
A ApiNormalizer::hasCacheableSupportsMethod() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Silverback\ApiComponentBundle\Serializer;
6
7
use Silverback\ApiComponentBundle\DataTransformer\DataTransformerInterface;
8
use Silverback\ApiComponentBundle\Entity\Component\AbstractComponent;
9
use Silverback\ApiComponentBundle\Entity\Content\Page\Dynamic\DynamicContent;
10
use Silverback\ApiComponentBundle\Security\RestrictedResourceVoter;
11
use Symfony\Component\PropertyAccess\Exception\NoSuchPropertyException;
12
use Symfony\Component\PropertyAccess\PropertyAccess;
13
use Symfony\Component\Serializer\Normalizer\CacheableSupportsMethodInterface;
14
use Symfony\Component\Serializer\Normalizer\ContextAwareNormalizerInterface;
15
use Symfony\Component\Serializer\Normalizer\NormalizerAwareInterface;
16
use Symfony\Component\Serializer\Normalizer\NormalizerAwareTrait;
17
18
class ApiNormalizer implements ContextAwareNormalizerInterface, NormalizerAwareInterface, CacheableSupportsMethodInterface
19
{
20
    use NormalizerAwareTrait;
21
22
    private const ALREADY_CALLED = 'API_COMPONENT_BUNDLE_NORMALIZER_ALREADY_CALLED';
23
24
    /** @var iterable|DataTransformerInterface[] */
25
    private $dataTransformers;
26
27
    /** @var DataTransformerInterface[] */
28
    private $supportedTransformers = [];
29
30
    private $propertyAccessor;
31
    private $restrictedResourceVoter;
32
33
    public function __construct(iterable $dataTransformers = [], RestrictedResourceVoter $restrictedResourceVoter)
34
    {
35
        $this->dataTransformers = $dataTransformers;
36
        $this->propertyAccessor = PropertyAccess::createPropertyAccessor();
37
        $this->restrictedResourceVoter = $restrictedResourceVoter;
38
    }
39
40
    private function getId($object)
41
    {
42
        try {
43
            return $this->propertyAccessor->getValue($object, 'id');
44
        } catch (NoSuchPropertyException $e) {
45
            return true;
46
        }
47
    }
48
49
    public function supportsNormalization($data, $format = null, array $context = []): bool
50
    {
51
        if (!isset($context[self::ALREADY_CALLED])) {
52
            $context[self::ALREADY_CALLED] = [];
53
        }
54
        $this->supportedTransformers = [];
55
        if (!is_object($data) || in_array($this->getId($data), $context[self::ALREADY_CALLED], true)) {
56
            return false;
57
        }
58
59
        foreach ($this->dataTransformers as $transformer) {
60
            if ($transformer->supportsTransformation($data)) {
61
                $this->supportedTransformers[] = $transformer;
62
            }
63
        }
64
65
        if ($data instanceof AbstractComponent) {
66
            return true;
67
        }
68
69
        if ($this->restrictedResourceVoter->isSupported($data)) {
70
            return true;
71
        }
72
73
        return !empty($this->supportedTransformers);
74
    }
75
76
    public function normalize($object, $format = null, array $context = [])
77
    {
78
        if (!$this->restrictedResourceVoter->vote($object)) {
79
            return null;
80
        }
81
        $context[self::ALREADY_CALLED][] = $this->getId($object);
82
        if ($object instanceof AbstractComponent || $object instanceof DynamicContent) {
83
            $context['groups'] = array_map(static function($grp) {
84
                if (strpos($grp, 'route') === 0) {
85
                    return str_replace('route', 'component', $grp);
86
                }
87
                return $grp;
88
            }, $context['groups']);
89
        }
90
        foreach ($this->supportedTransformers as $transformer) {
91
            $transformer->transform($object, $context);
92
        }
93
        return $this->normalizer->normalize($object, $format, $context);
94
    }
95
96
    public function hasCacheableSupportsMethod(): bool
97
    {
98
        return false;
99
    }
100
}
101