Completed
Push — master ( 236a45...b262d2 )
by Yaroslav
09:39
created

ArgumentResolver   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 99
Duplicated Lines 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 9
eloc 34
dl 0
loc 99
rs 10
c 0
b 0
f 0
ccs 32
cts 32
cp 1

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A getArgument() 0 36 6
A getControllerMetadata() 0 10 2
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\Controller;
12
13
use Psr\Cache\CacheItemPoolInterface;
14
use Symfony\Component\HttpFoundation\RequestStack;
15
use Yarhon\RouteGuardBundle\Cache\CacheFactory;
16
use Yarhon\RouteGuardBundle\Routing\RequestAttributesFactoryInterface;
17
use Yarhon\RouteGuardBundle\Routing\RouteContextInterface;
18
use Yarhon\RouteGuardBundle\Controller\ArgumentResolver\ArgumentResolverContext;
19
use Yarhon\RouteGuardBundle\Controller\ArgumentResolver\ArgumentValueResolverInterface;
20
use Yarhon\RouteGuardBundle\Exception\RuntimeException;
21
22
/**
23
 * Responsible for resolving the argument passed to an action.
24
 *
25
 * @author Yaroslav Honcharuk <[email protected]>
26
 */
27
class ArgumentResolver implements ArgumentResolverInterface
28
{
29
    /**
30
     * @var CacheItemPoolInterface
31
     */
32
    private $controllerMetadataCache;
33
34
    /**
35
     * @var RequestAttributesFactoryInterface
36
     */
37
    private $requestAttributesFactory;
38
39
    /**
40
     * @var RequestStack
41
     */
42
    private $requestStack;
43
44
    /**
45
     * @var \Traversable|ArgumentValueResolverInterface[]
46
     */
47
    private $argumentValueResolvers;
48
49
    /**
50
     * @var array
51
     */
52
    private $internalCache = [];
53
54
    /**
55
     * @param CacheItemPoolInterface                        $controllerMetadataCache
56
     * @param RequestAttributesFactoryInterface             $requestAttributesFactory
57
     * @param RequestStack                                  $requestStack
58
     * @param \Traversable|ArgumentValueResolverInterface[] $argumentValueResolvers
59
     */
60 16
    public function __construct(CacheItemPoolInterface $controllerMetadataCache, RequestAttributesFactoryInterface $requestAttributesFactory, RequestStack $requestStack, $argumentValueResolvers = [])
61
    {
62 16
        $this->controllerMetadataCache = $controllerMetadataCache;
63 16
        $this->requestAttributesFactory = $requestAttributesFactory;
64 16
        $this->requestStack = $requestStack;
65 16
        $this->argumentValueResolvers = $argumentValueResolvers;
66 16
    }
67
68
    /**
69
     * {@inheritdoc}
70
     */
71 11
    public function getArgument(RouteContextInterface $routeContext, $name)
72
    {
73 11
        $cacheKey = spl_object_hash($routeContext).'#'.$name;
74
75 11
        if (array_key_exists($cacheKey, $this->internalCache)) {
76 1
            return $this->internalCache[$cacheKey];
77
        }
78
79 11
        $controllerMetadata = $this->getControllerMetadata($routeContext->getName());
80
81 10
        if (null === $controllerMetadata) {
82 1
            $message = 'Route "%s" does not have controller or controller name is unresolvable.';
83 1
            throw new RuntimeException(sprintf($message, $routeContext->getName()));
84
        }
85
86 9
        if (!$controllerMetadata->hasArgument($name)) {
87 1
            $message = 'Route "%s" controller "%s" does not have argument "$%s".';
88 1
            throw new RuntimeException(sprintf($message, $routeContext->getName(), $controllerMetadata->getName(), $name));
89
        }
90
91 8
        $requestAttributes = $this->requestAttributesFactory->createAttributes($routeContext);
92
93 8
        $resolverContext = new ArgumentResolverContext($requestAttributes, $controllerMetadata->getName(), $this->requestStack->getCurrentRequest());
94
95 8
        $argumentMetadata = $controllerMetadata->getArgument($name);
96
97 8
        foreach ($this->argumentValueResolvers as $resolver) {
98 8
            if (!$resolver->supports($resolverContext, $argumentMetadata)) {
99 5
                continue;
100
            }
101
102 7
            return $this->internalCache[$cacheKey] = $resolver->resolve($resolverContext, $argumentMetadata);
103
        }
104
105 1
        $message = 'Route "%s" controller "%s" requires that you provide a value for the "$%s" argument.';
106 1
        throw new RuntimeException(sprintf($message, $routeContext->getName(), $controllerMetadata->getName(), $name));
107
    }
108
109
    /**
110
     * @param string $routeName
111
     *
112
     * @return ControllerMetadata
113
     *
114
     * @throws RuntimeException
115
     */
116 11
    private function getControllerMetadata($routeName)
117
    {
118 11
        $cacheKey = CacheFactory::getValidCacheKey($routeName);
119 11
        $cacheItem = $this->controllerMetadataCache->getItem($cacheKey);
120
121 11
        if (!$cacheItem->isHit()) {
122 1
            throw new RuntimeException(sprintf('Cannot get ControllerMetadata for route "%s".', $routeName));
123
        }
124
125 10
        return $cacheItem->get();
126
    }
127
}
128