Completed
Push — master ( 18bc97...e7bdcd )
by Yaroslav
09:10
created

SensioExtraResolver::supports()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
eloc 1
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 1
crap 1
1
<?php
2
3
/*
4
 *
5
 * (c) Yaroslav Honcharuk <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
11
namespace Yarhon\RouteGuardBundle\Security\TestResolver;
12
13
use Yarhon\RouteGuardBundle\Security\Test\TestInterface;
14
use Yarhon\RouteGuardBundle\Security\Test\SensioExtraTest;
15
use Yarhon\RouteGuardBundle\Controller\ControllerArgumentResolverInterface;
16
use Yarhon\RouteGuardBundle\Routing\RequestAttributesFactoryInterface;
17
use Yarhon\RouteGuardBundle\Routing\RouteContextInterface;
18
use Yarhon\RouteGuardBundle\ExpressionLanguage\ExpressionDecorator;
19
use Yarhon\RouteGuardBundle\Exception\RuntimeException;
20
21
/**
22
 * Sensio FrameworkExtraBundle allows to use Request attributes, in addition to the controller arguments, as variables
23
 * in "@Security" annotation expressions and in "@IsGranted" annotation "subject" arguments.
24
 * SensioExtraResolver allows to fallback to the Request attribute, if controller doesn't have requested argument.
25
 *
26
 * @see \Sensio\Bundle\FrameworkExtraBundle\Request\ArgumentNameConverter::getControllerArguments
27
 *
28
 * @author Yaroslav Honcharuk <[email protected]>
29
 */
30
class SensioExtraResolver implements TestResolverInterface
31
{
32
    /**
33
     * @var ControllerArgumentResolverInterface
34
     */
35
    private $controllerArgumentResolver;
36
37
    /**
38
     * @var RequestAttributesFactoryInterface
39
     */
40
    private $requestAttributesFactory;
41
42
    /**
43
     * @param ControllerArgumentResolverInterface $controllerArgumentResolver
44
     * @param RequestAttributesFactoryInterface   $requestAttributesFactory
45
     */
46 18
    public function __construct(ControllerArgumentResolverInterface $controllerArgumentResolver, RequestAttributesFactoryInterface $requestAttributesFactory)
47
    {
48 18
        $this->controllerArgumentResolver = $controllerArgumentResolver;
49 18
        $this->requestAttributesFactory = $requestAttributesFactory;
50 18
    }
51
52
    /**
53
     * {@inheritdoc}
54
     */
55 9
    public function supports(TestInterface $test)
56
    {
57 9
        return $test instanceof SensioExtraTest;
58
    }
59
60
    /**
61
     * {@inheritdoc}
62
     */
63 15
    public function resolve(TestInterface $test, RouteContextInterface $routeContext)
64
    {
65
        /* @var SensioExtraTest $test */
66
67 15
        $requestAttributes = $test->getMetadata('request_attributes') ?: [];
68
69 15
        $attributes = $test->getAttributes();
70 15
        $subject = $test->getSubject();
71
72 15
        if ($subject) {
73 7
            $variableDescription = sprintf('subject variable "%s"', $subject);
74 7
            $subject = $this->resolveVariable($routeContext, $subject, $requestAttributes, $variableDescription);
75
        }
76
77 13
        foreach ($attributes as $attribute) {
78 13
            if ($attribute instanceof ExpressionDecorator) {
79 7
                $values = [];
80 7
                foreach ($attribute->getVariableNames() as $name) {
81 4
                    $variableDescription = sprintf('expression variable "%s" of expression "%s"', $name, (string) $attribute->getExpression());
82 4
                    $value = $this->resolveVariable($routeContext, $name, $requestAttributes, $variableDescription);
83 3
                    $values[$name] = $value;
84
                }
85 12
                $attribute->setVariables($values);
86
            }
87
        }
88
89 12
        return [$attributes, $subject];
90
    }
91
92 11
    private function resolveVariable(RouteContextInterface $routeContext, $name, $requestAttributes, $variableDescription)
93
    {
94 11
        if (in_array($name, $requestAttributes, true)) {
95 2
            $requestAttributes = $this->requestAttributesFactory->createAttributes($routeContext);
96 2
            if (!$requestAttributes->has($name)) {
97 1
                $message = sprintf('Cannot resolve %s directly from Request attributes.', $variableDescription);
98 1
                throw new RuntimeException(sprintf($message, $routeContext->getName(), $name));
99
            }
100
101 1
            return $requestAttributes->get($name);
102
        }
103
104
        try {
105 9
            $value = $this->controllerArgumentResolver->getArgument($routeContext, $name);
106 2
        } catch (RuntimeException $e) {
107 2
            $message = sprintf('Cannot resolve %s. %s', $variableDescription, $e->getMessage());
108 2
            throw new RuntimeException($message, 0, $e);
109
        }
110
111 7
        return $value;
112
    }
113
}
114