Passed
Pull Request — master (#9)
by Pavel
11:27
created

AnnotationClassLoader   A

Complexity

Total Complexity 20

Size/Duplication

Total Lines 110
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 5

Test Coverage

Coverage 86.44%

Importance

Changes 0
Metric Value
wmc 20
lcom 1
cbo 5
dl 0
loc 110
ccs 51
cts 59
cp 0.8644
rs 10
c 0
b 0
f 0

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 4 1
C load() 0 34 7
A supports() 0 6 4
A getResolver() 0 3 1
A setResolver() 0 3 1
A getParentAnnotations() 0 21 4
A addRoute() 0 18 2
1
<?php
2
3
namespace Bankiru\Api\Rpc\Routing\Loader;
4
5
use Bankiru\Api\Rpc\Routing\Annotation\Method;
6
use Bankiru\Api\Rpc\Routing\LoaderInterface;
7
use Bankiru\Api\Rpc\Routing\MethodCollection;
8
use Bankiru\Api\Rpc\Routing\Route;
9
use Doctrine\Common\Annotations\Reader;
10
use Symfony\Component\Config\Resource\FileResource;
11
12
class AnnotationClassLoader implements LoaderInterface
13
{
14
    /** @var  Reader */
15
    private $reader;
16
17
    /**
18
     * Constructor.
19
     *
20
     * @param Reader $reader
21
     */
22 11
    public function __construct(Reader $reader)
23
    {
24 11
        $this->reader = $reader;
25 11
    }
26
27
    /** {@inheritdoc} */
28 2
    public function load($class, $type = null)
29
    {
30 2
        if (!class_exists($class)) {
31
            throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
32
        }
33
34 2
        $class = new \ReflectionClass($class);
35 2
        if ($class->isAbstract()) {
36
            throw new \InvalidArgumentException(
37
                sprintf('Annotations from class "%s" cannot be read as it is abstract.', $class->getName())
0 ignored issues
show
Bug introduced by
Consider using $class->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
38
            );
39
        }
40
41 2
        $parents = $this->getParentAnnotations($class);
42
43 2
        $collection = new MethodCollection();
44 2
        $collection->addResource(new FileResource($class->getFileName()));
45
46 2
        foreach ($class->getMethods() as $method) {
47 2
            if (!$method->isPublic()) {
48 2
                continue;
49
            }
50
51 2
            foreach ($this->reader->getMethodAnnotations($method) as $annot) {
52 2
                if ($annot instanceof Method) {
53 2
                    $this->addRoute($collection, $annot, $parents, $class, $method);
54 2
                }
55 2
            }
56 2
        }
57
58 2
        $collection->addPrefix($parents['method']);
59
60 2
        return $collection;
61
    }
62
63
    /** {@inheritdoc} */
64 2
    public function supports($resource, $type = null)
65
    {
66 2
        return is_string($resource) &&
67 2
               preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) &&
68 2
               (!$type || 'annotation' === $type);
0 ignored issues
show
Bug Best Practice introduced by
The expression $type of type string|null is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === null instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
69
    }
70
71
    /** {@inheritdoc} */
72
    public function getResolver()
73
    {
74
    }
75
76
    /** {@inheritdoc} */
77
    public function setResolver($resolver)
78
    {
79
    }
80
81 2
    protected function getParentAnnotations(\ReflectionClass $class)
82
    {
83
        $parents = [
84 2
            'method'          => '',
85 2
            'context'         => [],
86 2
            'default_context' => true,
87 2
        ];
88
89
        /** @var Method $annot */
90 2
        if ($annot = $this->reader->getClassAnnotation($class, Method::class)) {
91 2
            if (null !== $annot->getMethod()) {
92 2
                $parents['method'] = $annot->getMethod();
93 2
            }
94
95 2
            if (null !== $annot->getContext()) {
96 2
                $parents['context'] = $annot->getContext();
97 2
            }
98 2
        }
99
100 2
        return $parents;
101
    }
102
103 2
    protected function addRoute(
104
        MethodCollection $collection,
105
        Method $annot,
106
        array $parents,
107
        \ReflectionClass $class,
108
        \ReflectionMethod $method
109
    ) {
110 2
        $collection->add(
111 2
            $annot->getMethod(),
112 2
            new Route(
113 2
                $annot->getMethod(),
114 2
                $class->getName() . '::' . $method->getName(),
0 ignored issues
show
Bug introduced by
Consider using $class->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
115 2
                array_merge($parents['context'], $annot->getContext()),
116 2
                $parents['default_context'] && $annot->isDefaultContext(),
117 2
                $annot->isInherit()
118 2
            )
119 2
        );
120 2
    }
121
}
122