Completed
Push — master ( 59818d...80b14f )
by Ivannis Suárez
02:22
created

DynamicDispatchVisitor::handlerMethod()   B

Complexity

Conditions 5
Paths 7

Size

Total Lines 22
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 22
rs 8.6737
cc 5
eloc 13
nc 7
nop 1
1
<?php
2
3
/**
4
 * This file is part of the Cubiche package.
5
 *
6
 * Copyright (c) Cubiche
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
namespace Cubiche\Core\Visitor;
12
13
/**
14
 * Abstract Dynamic Dispatch Visitor Class.
15
 *
16
 * @author Karel Osorio Ramírez <[email protected]>
17
 */
18
abstract class DynamicDispatchVisitor implements DynamicDispatchVisitorInterface
19
{
20
    /**
21
     * @var \ReflectionMethod[]
22
     */
23
    private $visitorMethods = null;
24
25
    /**
26
     * @var \ReflectionMethod[]
27
     */
28
    private $handlerMethods = array();
29
30
    /**
31
     * @var ResolverVisitorMethodInterface
32
     */
33
    protected $resolver;
34
35
    /**
36
     * @param ResolverVisitorMethodInterface $resolver
37
     */
38
    public function __construct(ResolverVisitorMethodInterface $resolver = null)
39
    {
40
        $this->resolver = $resolver === null ? new ResolverVisitorMethod() : $resolver;
41
    }
42
43
    /**
44
     * {@inheritdoc}
45
     */
46
    public function canHandlerVisitee(VisiteeInterface $visitee)
47
    {
48
        return $this->handlerMethod($visitee) !== null;
49
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54
    public function visit(VisiteeInterface $visitee)
55
    {
56
        return $this->visitWith($visitee, \func_get_args());
57
    }
58
59
    /**
60
     * @param VisiteeInterface $visitee
61
     * @param array            $args
62
     *
63
     * @return mixed
64
     */
65
    protected function visitWith(VisiteeInterface $visitee, array $args)
66
    {
67
        $method = $this->handlerMethod($visitee);
68
69
        if ($method !== null) {
70
            return $method->invokeArgs($this, $args);
71
        }
72
73
        throw $this->notSupportedVisiteeException($visitee);
74
    }
75
76
    /**
77
     * @param VisiteeInterface $visitee
78
     *
79
     * @return \LogicException
80
     */
81
    protected function notSupportedVisiteeException(VisiteeInterface $visitee)
82
    {
83
        return new \LogicException(
84
            \sprintf('The %s visitee is not supported by %s visitor', \get_class($visitee), static::class)
85
        );
86
    }
87
88
    /**
89
     * @param VisiteeInterface $visitee
90
     *
91
     * @return \ReflectionMethod|null
92
     */
93
    private function handlerMethod(VisiteeInterface $visitee)
94
    {
95
        $class = new \ReflectionClass(\get_class($visitee));
96
        if (isset($this->handlerMethods[$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...
97
            return $this->handlerMethods[$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...
98
        }
99
        if ($this->visitorMethods === null) {
100
            $this->visitorMethods = $this->visitorMethods();
0 ignored issues
show
Documentation Bug introduced by
It seems like $this->visitorMethods() of type array<integer,object<Cub...itor\ReflectionMethod>> is incompatible with the declared type array<integer,object<ReflectionMethod>> of property $visitorMethods.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
101
        }
102
        $current = $class;
103
        while ($current !== false) {
104
            if (isset($this->visitorMethods[$current->getName()])) {
105
                $this->handlerMethods[$class->getName()] = $this->visitorMethods[$current->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...
106
107
                return $this->handlerMethods[$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...
108
            }
109
110
            $current = $current->getParentClass();
111
        }
112
113
        return;
114
    }
115
116
    /**
117
     * @return ReflectionMethod[]
118
     */
119
    private function visitorMethods()
120
    {
121
        $visitorMethods = array();
122
        $reflection = new \ReflectionClass(static::class);
123
        /** @var \ReflectionMethod $method */
124
        foreach ($reflection->getMethods() as $method) {
125
            if ($method->getName() !== 'visit') {
0 ignored issues
show
Bug introduced by
Consider using $method->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
126
                $visiteeClass = $this->resolver->resolveVisiteeClass($method);
127
                if ($visiteeClass !== null) {
128
                    $visitorMethods[$visiteeClass->getName()] = $method;
0 ignored issues
show
Bug introduced by
Consider using $visiteeClass->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
129
                }
130
            }
131
        }
132
133
        return $visitorMethods;
134
    }
135
}
136