Completed
Push — master ( 82d1fc...6f9908 )
by Ivannis Suárez
02:50 queued 29s
created

DynamicDispatchVisitor::handlerMethod()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 1
Metric Value
c 2
b 1
f 1
dl 0
loc 12
rs 9.4285
cc 3
eloc 7
nc 3
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->name])) {
97
            return $this->handlerMethods[$class->name];
98
        }
99
        if ($this->visitorMethods === null) {
100
            $this->visitorMethods = $this->visitorMethods();
101
        }
102
103
        return $this->findHandlerMethod($class);
104
    }
105
106
    /**
107
     * @param \ReflectionClass $class
108
     *
109
     * @return \ReflectionMethod|null
110
     */
111
    private function findHandlerMethod(\ReflectionClass $class)
112
    {
113
        $current = $class;
114
        while ($current !== false) {
115
            if (isset($this->visitorMethods[$current->name])) {
116
                $this->handlerMethods[$class->name] = $this->visitorMethods[$current->name];
117
118
                return $this->handlerMethods[$class->name];
119
            }
120
121
            $current = $current->getParentClass();
122
        }
123
124
        return;
125
    }
126
127
    /**
128
     * @return \ReflectionMethod[]
129
     */
130
    private function visitorMethods()
131
    {
132
        $visitorMethods = array();
133
        $reflection = new \ReflectionClass(static::class);
134
        /** @var \ReflectionMethod $method */
135
        foreach ($reflection->getMethods() as $method) {
136
            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...
137
                $visiteeClass = $this->resolver->resolveVisiteeClass($method);
138
                if ($visiteeClass !== null) {
139
                    $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...
140
                }
141
            }
142
        }
143
144
        return $visitorMethods;
145
    }
146
}
147