Completed
Push — master ( a85fc8...8e3ad0 )
by Daniel
05:24
created

ApiContextBuilder   A

Complexity

Total Complexity 15

Size/Duplication

Total Lines 91
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 11
Bugs 2 Features 0
Metric Value
wmc 15
eloc 38
dl 0
loc 91
ccs 23
cts 23
cp 1
rs 10
c 11
b 2
f 0

5 Methods

Rating   Name   Duplication   Size   Complexity  
A createFromRequest() 0 14 4
A getGroupVariants() 0 4 2
A __construct() 0 4 1
A getGroups() 0 18 6
A matchClass() 0 3 2
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Silverback\ApiComponentBundle\Serializer;
6
7
use ApiPlatform\Core\Exception\RuntimeException;
8
use ApiPlatform\Core\Serializer\SerializerContextBuilderInterface;
9
use Silverback\ApiComponentBundle\Entity\Component\AbstractComponent;
10
use Silverback\ApiComponentBundle\Entity\Component\ComponentLocation;
11
use Silverback\ApiComponentBundle\Entity\Component\Navigation\AbstractNavigation;
12
use Silverback\ApiComponentBundle\Entity\Content\AbstractContent;
13
use Silverback\ApiComponentBundle\Entity\Content\Page\Dynamic\DynamicContent;
14
use Silverback\ApiComponentBundle\Entity\Content\Page\DynamicPage;
15
use Silverback\ApiComponentBundle\Entity\Layout\Layout;
16
use Silverback\ApiComponentBundle\Entity\Route\Route;
17
use Silverback\ApiComponentBundle\Entity\SortableInterface;
18
use Symfony\Component\HttpFoundation\Request;
19
use Symfony\Component\Security\Core\Security;
20
21
class ApiContextBuilder implements SerializerContextBuilderInterface
22
{
23
    /**
24
     * @var string[][]
25
     */
26
    public const CLASS_GROUP_MAPPING = [
27
        AbstractComponent::class => ['component'],
28
        AbstractNavigation::class => ['component'],
29
        ComponentLocation::class => ['component'],
30
        AbstractContent::class => ['content'],
31
        DynamicContent::class => ['content'],
32
        Route::class => ['route'],
33
        Layout::class => ['layout'],
34
        DynamicPage::class => ['dynamic_content', 'content'],
35
        SortableInterface::class => ['sortable']
36
    ];
37
38
    /**
39 4
     * @var SerializerContextBuilderInterface
40
     */
41 4
    private $decorated;
42 4
43
    private $security;
44
45
    public function __construct(SerializerContextBuilderInterface $decorated, Security $security)
46
    {
47
        $this->decorated = $decorated;
48
        $this->security = $security;
49 3
    }
50
    /**
51 3
     * @param $className
52
     * @param $matchClassName
53
     * @return bool
54
     */
55
    private function matchClass($className, $matchClassName): bool
56
    {
57
        return $className === $matchClassName || is_subclass_of($className, $matchClassName);
58
    }
59 3
60
    private function getGroupVariants(string $group, bool $normalization): array
61 3
    {
62
        $rw = ($normalization ? 'read' : 'write');
63
        return [ $group, sprintf('%s_%s', $group, $rw) ];
64
    }
65
66
    /**
67
     * @param string $subject
68
     * @param bool $normalization
69 3
     * @return array
70
     */
71
    public function getGroups(string $subject, bool $normalization): array
72 3
    {
73 3
        /** @var string[] $groups */
74 3
        $groups = [$this->getGroupVariants('default', $normalization)];
75 3
        if ($this->security->isGranted('ROLE_ADMIN')) {
76 3
            $groups[] = $this->getGroupVariants('admin', $normalization);
77
        }
78
        if ($this->security->isGranted('ROLE_SUPER_ADMIN')) {
79
            $groups[] = $this->getGroupVariants('super_admin', $normalization);
80 3
        }
81
        foreach (self::CLASS_GROUP_MAPPING as $class => $groupMapping) {
82
            if ($this->matchClass($subject, $class)) {
83
                foreach ($groupMapping as $group) {
84
                    $groups[] = $this->getGroupVariants($group, $normalization);
85
                }
86
            }
87
        }
88
        return $groups;
89
    }
90 4
91
    /**
92 4
     * @param Request $request
93 4
     * @param bool $normalization
94 1
     * @param array|null $extractedAttributes
95
     * @return array
96 3
     * @throws RuntimeException
97 3
     */
98 3
    public function createFromRequest(Request $request, bool $normalization, array $extractedAttributes = null): array
99 3
    {
100
        $context = $this->decorated->createFromRequest($request, $normalization, $extractedAttributes);
101 3
        $ctxGroups = array_key_exists('groups', $context) ? (array) $context['groups'] : [];
102
        if (\in_array('none', $ctxGroups, true)) {
103
            return $context;
104
        }
105
        $subject = $request->attributes->get('_api_resource_class');
106
        $groups = $this->getGroups($subject, $normalization);
107
        if (\count($groups)) {
108
            $ctxGroups = array_merge($ctxGroups, ...$groups);
109
        }
110
        $context['groups'] = $ctxGroups;
111
        return $context;
112
    }
113
}
114