-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrepository.php
121 lines (105 loc) · 3.77 KB
/
repository.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
<?php
class ClassRepository {
private static $reflection = false;
function __construct() {
if (! self::$reflection) {
self::$reflection = new ReflectionCache();
}
self::$reflection->refresh();
}
function candidatesFor($interface) {
return array_merge(
self::$reflection->concreteSubgraphOf($interface),
self::$reflection->implementationsOf($interface));
}
function isSupertype($class, $type) {
$supertypes = array_merge(
array($class),
self::$reflection->interfacesOf($class),
self::$reflection->parentsOf($class));
return in_array($type, $supertypes);
}
function getConstructorParameters($class) {
$reflection = self::$reflection->reflection($class);
if ($constructor = $reflection->getConstructor()) {
return $constructor->getParameters();
}
return array();
}
function getParameters($class, $method) {
$reflection = self::$reflection->reflection($class);
if (! $reflection->hasMethod($method)) {
throw new SetterDoesNotExist();
}
return $reflection->getMethod($method)->getParameters();
}
}
class ReflectionCache {
private $implementations_of = array();
private $interfaces_of = array();
private $reflections = array();
private $subclasses = array();
private $parents = array();
function refresh() {
$this->buildIndex(array_diff(get_declared_classes(), $this->indexed()));
$this->subclasses = array();
}
function implementationsOf($interface) {
return isset($this->implementations_of[$interface]) ?
$this->implementations_of[$interface] : array();
}
function interfacesOf($class) {
return isset($this->interfaces_of[$class]) ?
$this->interfaces_of[$class] : array();
}
function concreteSubgraphOf($class) {
if (! class_exists($class)) {
return array();
}
if (! isset($this->subclasses[$class])) {
$this->subclasses[$class] = $this->isConcrete($class) ? array($class) : array();
foreach ($this->indexed() as $candidate) {
if (is_subclass_of($candidate, $class) && $this->isConcrete($candidate)) {
$this->subclasses[$class][] = $candidate;
}
}
}
return $this->subclasses[$class];
}
function parentsOf($class) {
if (! isset($this->parents[$class])) {
$this->parents[$class] = class_parents($class);
}
return $this->parents[$class];
}
function reflection($class) {
if (! isset($this->reflections[$class])) {
$this->reflections[$class] = new ReflectionClass($class);
}
return $this->reflections[$class];
}
private function isConcrete($class) {
return ! $this->reflection($class)->isAbstract();
}
private function indexed() {
return array_keys($this->interfaces_of);
}
private function buildIndex($classes) {
foreach ($classes as $class) {
$interfaces = array_values(class_implements($class));
$this->interfaces_of[$class] = $interfaces;
foreach ($interfaces as $interface) {
$this->crossReference($interface, $class);
}
}
}
private function crossReference($interface, $class) {
if (! isset($this->implementations_of[$interface])) {
$this->implementations_of[$interface] = array();
}
$this->implementations_of[$interface][] = $class;
$this->implementations_of[$interface] =
array_values(array_unique($this->implementations_of[$interface]));
}
}
?>