AccessCompilerPass   A
last analyzed

Complexity

Total Complexity 8

Size/Duplication

Total Lines 86
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 8
eloc 29
dl 0
loc 86
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A process() 0 22 3
A getRoles() 0 30 4
A getRolePrefix() 0 3 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Neimheadh\SonataAnnotationBundle\DependencyInjection\Compiler;
6
7
use Doctrine\Common\Annotations\AnnotationReader;
8
use Neimheadh\SonataAnnotationBundle\Annotation\Access;
9
use Neimheadh\SonataAnnotationBundle\Exception\MissingAnnotationArgumentException;
10
use ReflectionClass;
11
use ReflectionException;
12
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
13
use Symfony\Component\DependencyInjection\ContainerBuilder;
14
15
/**
16
 * Bundle compiler pass.
17
 *
18
 * @author Marko Kunic <[email protected]>
19
 * @author Mathieu Wambre <[email protected]>
20
 */
21
final class AccessCompilerPass implements CompilerPassInterface
22
{
23
24
    use FindClassTrait;
25
26
    /**
27
     * {@inheritDoc}
28
     *
29
     * @throws ReflectionException
30
     */
31
    public function process(ContainerBuilder $container): void
32
    {
33
        /**
34
         * @var AnnotationReader $annotationReader
35
         */
36
        $annotationReader = $container->get('annotation_reader');
37
        $roles = $container->getParameter('security.role_hierarchy.roles');
38
        $services = $container->findTaggedServiceIds('sonata.admin');
39
40
        foreach ($services as $id => $tag) {
41
            $class = $this->getClass($container, $id);
42
43
            if ($permissions = $this->getRoles(
44
                $annotationReader,
45
                new ReflectionClass($class),
46
                $this->getRolePrefix($id)
47
            )) {
48
                $roles = array_merge_recursive($roles, $permissions);
49
            }
50
        }
51
52
        $container->setParameter('security.role_hierarchy.roles', $roles);
53
    }
54
55
    /**
56
     * Get service role name.
57
     *
58
     * @param string $serviceId Service name.
59
     *
60
     * @return string
61
     */
62
    private function getRolePrefix(string $serviceId): string
63
    {
64
        return 'ROLE_' . str_replace('.', '_', strtoupper($serviceId)) . '_';
65
    }
66
67
    /**
68
     * Get the list of permissions associated roles.
69
     *
70
     * @param AnnotationReader $annotationReader Doctrine annotation reader.
71
     * @param ReflectionClass  $class            Service class.
72
     * @param string           $prefix           Service role name (permission
73
     *                                           roles prefix).
74
     *
75
     * @return array
76
     */
77
    private function getRoles(
78
        AnnotationReader $annotationReader,
79
        ReflectionClass $class,
80
        string $prefix
81
    ): array {
82
        $roles = [];
83
        $annotations = $annotationReader->getClassAnnotations($class);
84
85
        foreach ($annotations as $annotation) {
86
            if (!$annotation instanceof Access) {
87
                continue;
88
            }
89
90
            if (!isset($annotation->role)) {
91
                throw new MissingAnnotationArgumentException(
92
                    $annotation,
93
                    'role',
94
                    $class
95
                );
96
            }
97
98
            $roles[$annotation->role] = array_map(
99
                function (string $permission) use ($prefix) {
100
                    return $prefix . strtoupper($permission);
101
                },
102
                $annotation->permissions
103
            );
104
        }
105
106
        return $roles;
107
    }
108
109
}
110