MethodSelector::excludeNative()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %
Metric Value
dl 0
loc 8
rs 9.4285
cc 1
eloc 4
nc 1
nop 0
1
<?php
2
3
/**
4
 * This file is part of cloak.
5
 *
6
 * (c) Noritaka Horio <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace cloak\reflection;
13
14
15
use cloak\reflection\collection\ReflectionCollection;
16
use PhpCollection\Map;
17
use \ReflectionMethod;
18
use \ReflectionClass;
19
use PhpCollection\Sequence;
20
21
22
/**
23
 * Class MethodSelector
24
 * @package cloak\reflection
25
 */
26
class MethodSelector
27
{
28
29
    /**
30
     * @var ReflectionClass
31
     */
32
    private $reflection;
33
34
    /**
35
     * @var Sequence
36
     */
37
    private $reflections;
38
39
40
    /**
41
     * @param ReflectionMethod[] $reflections
42
     * @param ReflectionClass $reflection
43
     */
44
    public function __construct(array $reflections, ReflectionClass $reflection)
45
    {
46
        $this->reflections = new Sequence($reflections);
47
        $this->reflection = $reflection;
48
    }
49
50
    /**
51
     * @return MethodSelector
52
     */
53
    public function excludeNative()
54
    {
55
        $callback = function(ReflectionMethod $reflection) {
56
            return $reflection->isUserDefined();
57
        };
58
59
        return $this->applyFilter($callback);
60
    }
61
62
    /**
63
     * @return MethodSelector
64
     */
65
    public function excludeInherited()
66
    {
67
        $className = $this->reflection->name;
68
69
        $callback = function(ReflectionMethod $reflection) use ($className) {
70
            $declaringClass = $reflection->getDeclaringClass();
71
            return $declaringClass->name === $className;
72
        };
73
74
        return $this->applyFilter($callback);
75
    }
76
77
    /**
78
     * @return MethodSelector
79
     */
80
    public function excludeTraitMethods()
81
    {
82
        $dictionary = $this->getTraitMethods();
83
84
        $callback = function(ReflectionMethod $reflection) use ($dictionary) {
85
            $name = $reflection->name;
86
            return $dictionary->containsKey($name) === false;
87
        };
88
89
        return $this->applyFilter($callback);
90
    }
91
92
93
    /**
94
     * @return Map
95
     */
96
    private function getTraitMethods()
97
    {
98
        $traitMethods = $this->getTraitOriginalMethods();
99
        $traitAliasMethods = $this->reflection->getTraitAliases();
100
101
        foreach ($traitAliasMethods as $aliasName => $originalName) {
102
            $values = explode('::', $originalName);
103
            $methodName = array_pop($values);
104
            $traitMethods->remove($methodName);
105
            $traitMethods->set($aliasName, $this->reflection->getMethod($aliasName));
106
        }
107
108
        return $traitMethods;
109
    }
110
111
    /**
112
     * @return Map
113
     */
114
    private function getTraitOriginalMethods()
115
    {
116
        $result = new Map();
117
118
        foreach ($this->reflection->getTraits() as $trait) {
119
            $methods = $this->getMethodsFromTrait($trait);
120
            $result->addMap($methods);
121
        }
122
123
        return $result;
124
    }
125
126
    /**
127
     * @param ReflectionClass $trait
128
     * @return Map
129
     */
130
    private function getMethodsFromTrait($trait)
131
    {
132
        $result = new Map();
133
        $methods = $trait->getMethods(ReflectionMethod::IS_PUBLIC);
134
135
        foreach ($methods as $method) {
136
            $name = $method->name;
137
            $result->set($name, $method);
138
        }
139
140
        return $result;
141
    }
142
143
    /**
144
     * @return ReflectionCollection
145
     */
146
    public function toCollection()
147
    {
148
        $methods = $this->reflections->map(function(ReflectionMethod $method) {
149
            $className = $method->getDeclaringClass()->name;
150
            $methodName = $method->name;
151
152
            return new MethodReflection($className, $methodName);
153
        });
154
155
        return new ReflectionCollection( $methods->all() );
156
    }
157
158
    /**
159
     * @param callable $callback
160
     * @return MethodSelector
161
     */
162
    private function applyFilter(\Closure $callback)
163
    {
164
        $reflections = $this->reflections->filter($callback);
165
166
        return new self( $reflections->all(), $this->reflection );
167
    }
168
169
    /**
170
     * @return int
171
     */
172
    public function count()
173
    {
174
        return $this->reflections->count();
175
    }
176
177
    /**
178
     * @return bool
179
     */
180
    public function isEmpty()
181
    {
182
        return $this->reflections->isEmpty();
183
    }
184
185
    /**
186
     * @param string $className
187
     * @return MethodSelector
188
     */
189
    public static function fromClassName($className)
190
    {
191
        $reflection = new ReflectionClass($className);
192
        $reflectionMethods = $reflection->getMethods(ReflectionMethod::IS_PUBLIC);
193
194
        return new self($reflectionMethods, $reflection);
195
    }
196
197
}
198