ControllerMetadataFactory::__construct()   A
last analyzed

Complexity

Conditions 2
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 2
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 3
cts 3
cp 1
cc 2
nc 1
nop 2
crap 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 Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface;
14
use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
15
use Yarhon\RouteGuardBundle\DependencyInjection\Container\ClassMapInterface;
16
use Yarhon\RouteGuardBundle\Exception\InvalidArgumentException;
17
18
/**
19
 * To detect "controllers as a service" and retrieve class of those controllers we use ClassMapInterface container class map,
20
 * since \Symfony\Component\DependencyInjection\ContainerInterface doesn't allow to get actual service class
21
 * without instantiating it.
22
 *
23
 * @author Yaroslav Honcharuk <[email protected]>
24
 */
25
class ControllerMetadataFactory
26
{
27
    /**
28
     * @var ArgumentMetadataFactoryInterface
29
     */
30
    private $argumentMetadataFactory;
31
32
    /**
33
     * @var ClassMapInterface
34
     */
35
    private $containerClassMap;
36
37
    /**
38
     * @param ArgumentMetadataFactoryInterface|null $argumentMetadataFactory
39
     * @param ClassMapInterface|null                $containerClassMap
40
     */
41 23
    public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, ClassMapInterface $containerClassMap = null)
42
    {
43 23
        $this->argumentMetadataFactory = $argumentMetadataFactory ?: new ArgumentMetadataFactory();
44 23
        $this->containerClassMap = $containerClassMap;
45 23
    }
46
47
    /**
48
     * @param string $controllerName Controller name in class::method (service::method) notation
49
     *
50
     * @return ControllerMetadata
51
     *
52
     * @throws InvalidArgumentException
53
     */
54 23
    public function createMetadata($controllerName)
55
    {
56 23
        list($class, $method) = explode('::', $controllerName);
57
58 23
        if (null === $serviceClass = $this->detectContainerController($class)) {
59 20
            $serviceId = null;
60
        } else {
61 2
            $serviceId = $class;
62 2
            $class = $serviceClass;
63
        }
64
65 22
        $arguments = $this->argumentMetadataFactory->createArgumentMetadata([$class, $method]);
66
67 22
        $class = ltrim($class, '\\');
68
69 22
        return new ControllerMetadata($controllerName, $class, $method, $arguments, $serviceId);
70
    }
71
72
    /**
73
     * @param string $serviceId
74
     *
75
     * @return string|null
76
     */
77 23
    private function detectContainerController($serviceId)
78
    {
79 23
        if (!$this->containerClassMap || !$this->containerClassMap->has($serviceId)) {
80 20
            return null;
81
        }
82
83 3
        $serviceClass = $this->containerClassMap->get($serviceId);
84
85
        // Service class in container class map can be null is some cases (i.e., when service is instantiated by a factory method).
86 3
        if (null === $serviceClass) {
0 ignored issues
show
introduced by
The condition null === $serviceClass is always false.
Loading history...
87 1
            throw new InvalidArgumentException(sprintf('Unable to resolve class for service "%s".', $serviceId));
88
        }
89
90 2
        return $serviceClass;
91
    }
92
}
93