Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
1 lars 1
<?php
2
    /**
3
     *	base include file for SimpleTest
4
     *	@package	SimpleTest
5
     *	@subpackage	UnitTester
6
     *	@version	$Id: reflection_php5.php 1398 2006-09-08 19:31:03Z xue $
7
     */
8
 
9
    /**
10
     *    Version specific reflection API.
11
	 *    @package SimpleTest
12
	 *    @subpackage UnitTester
13
     */
14
    class SimpleReflection {
15
        protected $_interface;
16
 
17
        /**
18
         *    Stashes the class/interface.
19
         *    @param string $interface    Class or interface
20
         *                                to inspect.
21
         */
22
        function SimpleReflection($interface) {
23
            $this->_interface = $interface;
24
        }
25
 
26
        /**
27
         *    Checks that a class has been declared. Versions
28
         *    before PHP5.0.2 need a check that it's not really
29
         *    an interface.
30
         *    @return boolean            True if defined.
31
         *    @access public
32
         */
33
        function classExists() {
34
            if (! class_exists($this->_interface)) {
35
                return false;
36
            }
37
            $reflection = new ReflectionClass($this->_interface);
38
            return ! $reflection->isInterface();
39
        }
40
 
41
        /**
42
         *    Needed to kill the autoload feature in PHP5
43
         *    for classes created dynamically.
44
         *    @return boolean        True if defined.
45
         *    @access public
46
         */
47
        function classExistsSansAutoload() {
48
            return class_exists($this->_interface, false);
49
        }
50
 
51
        /**
52
         *    Checks that a class or interface has been
53
         *    declared.
54
         *    @return boolean            True if defined.
55
         *    @access public
56
         */
57
        function classOrInterfaceExists() {
58
            return $this->_classOrInterfaceExistsWithAutoload($this->_interface, true);
59
        }
60
 
61
        /**
62
         *    Needed to kill the autoload feature in PHP5
63
         *    for classes created dynamically.
64
         *    @return boolean        True if defined.
65
         *    @access public
66
         */
67
        function classOrInterfaceExistsSansAutoload() {
68
            return $this->_classOrInterfaceExistsWithAutoload($this->_interface, false);
69
        }
70
 
71
        /**
72
         *    Needed to select the autoload feature in PHP5
73
         *    for classes created dynamically.
74
         *    @param string $interface       Class or interface name.
75
         *    @param boolean $autoload       True totriggerautoload.
76
         *    @return boolean                True if interface defined.
77
         *    @access private
78
         */
79
        function _classOrInterfaceExistsWithAutoload($interface, $autoload) {
80
            if (function_exists('interface_exists')) {
81
                if (interface_exists($this->_interface, $autoload)) {
82
                    return true;
83
                }
84
            }
85
            return class_exists($this->_interface, $autoload);
86
        }
87
 
88
        /**
89
         *    Gets the list of methods on a class or
90
         *    interface. Needs to recursively look at all of
91
         *    the interfaces included.
92
         *    @returns array              List of method names.
93
         *    @access public
94
         */
95
        function getMethods() {
96
            return array_unique(get_class_methods($this->_interface));
97
        }
98
 
99
        /**
100
         *    Gets the list of interfaces from a class. If the
101
         *    class name is actually an interface then just that
102
         *    interface is returned.
103
         *    @returns array          List of interfaces.
104
         *    @access public
105
         */
106
        function getInterfaces() {
107
            $reflection = new ReflectionClass($this->_interface);
108
            if ($reflection->isInterface()) {
109
            	return array($this->_interface);
110
            }
111
            return $this->_onlyParents($reflection->getInterfaces());
112
        }
113
 
114
        /**
115
         *    Gets the list of methods for the implemented
116
         *    interfaces only.
117
         *    @returns array      List of enforced method signatures.
118
         *    @access public
119
         */
120
        function getInterfaceMethods() {
121
            $methods = array();
122
            foreach ($this->getInterfaces() as $interface) {
123
                $methods = array_merge($methods, get_class_methods($interface));
124
            }
125
            return array_unique($methods);
126
        }
127
 
128
        /**
129
         *    Checks to see if the method signature has to be tightly
130
         *    specified.
131
         *    @param string $method        Method name.
132
         *    @returns boolean             True if enforced.
133
         *    @access private
134
         */
135
        function _isInterfaceMethod($method) {
136
            return in_array($method, $this->getInterfaceMethods());
137
        }
138
 
139
        /**
140
         *    Finds the parent class name.
141
         *    @returns string      Parent class name.
142
         *    @access public
143
         */
144
        function getParent() {
145
            $reflection = new ReflectionClass($this->_interface);
146
            $parent = $reflection->getParentClass();
147
            if ($parent) {
148
                return $parent->getName();
149
            }
150
            return false;
151
        }
152
 
153
        /**
154
         *    Determines if the class is abstract.
155
         *    @returns boolean      True if abstract.
156
         *    @access public
157
         */
158
        function isAbstract() {
159
            $reflection = new ReflectionClass($this->_interface);
160
            return $reflection->isAbstract();
161
        }
162
 
163
        /**
164
         *    Wittles a list of interfaces down to only the top
165
         *    level parents.
166
         *    @param array $interfaces     Reflection API interfaces
167
         *                                 to reduce.
168
         *    @returns array               List of parent interface names.
169
         *    @access private
170
         */
171
        function _onlyParents($interfaces) {
172
            $parents = array();
173
            foreach ($interfaces as $interface) {
174
                foreach($interfaces as $possible_parent) {
175
                    if ($interface->getName() == $possible_parent->getName()) {
176
                        continue;
177
                    }
178
                    if ($interface->isSubClassOf($possible_parent)) {
179
                        break;
180
                    }
181
                }
182
                $parents[] = $interface->getName();
183
            }
184
            return $parents;
185
        }
186
 
187
        /**
188
         *    Gets the source code matching the declaration
189
         *    of a method.
190
         *    @param string $name    Method name.
191
         *    @return string         Method signature up to last
192
         *                           bracket.
193
         *    @access public
194
         */
195
        function getSignature($name) {
196
        	if ($name == '__get') {
197
        		return 'function __get($key)';
198
        	}
199
        	if ($name == '__set') {
200
        		return 'function __set($key, $value)';
201
        	}
202
        	if (! is_callable(array($this->_interface, $name))) {
203
        		return "function $name()";
204
        	}
205
        	if ($this->_isInterfaceMethod($name)) {
206
        	    return $this->_getFullSignature($name);
207
        	}
208
        	return "function $name()";
209
        }
210
 
211
        /**
212
         *    For a signature specified in an interface, full
213
         *    details must be replicated to be a valid implementation.
214
         *    @param string $name    Method name.
215
         *    @return string         Method signature up to last
216
         *                           bracket.
217
         *    @access private
218
         */
219
        function _getFullSignature($name) {
220
	        $interface = new ReflectionClass($this->_interface);
221
	        $method = $interface->getMethod($name);
222
	        $reference = $method->returnsReference() ? '&' : '';
223
        	return "function $reference$name(" .
224
            		implode(', ', $this->_getParameterSignatures($method)) .
225
            		")";
226
        }
227
 
228
        /**
229
         *    Gets the source code for each parameter.
230
         *    @param ReflectionMethod $method   Method object from
231
         *										reflection API
232
         *    @return array                     List of strings, each
233
         *                                      a snippet of code.
234
         *    @access private
235
         */
236
        function _getParameterSignatures($method) {
237
        	$signatures = array();
238
            foreach ($method->getParameters() as $parameter) {
239
                $type = $parameter->getClass();
240
            	$signatures[] =
241
					(! is_null($type) ? $type->getName() . ' ' : '') .
242
            			($parameter->isPassedByReference() ? '&' : '') .
243
            			'$' . $this->_suppressSpurious($parameter->getName()) .
244
            			($this->_isOptional($parameter) ? ' = null' : '');
245
            }
246
            return $signatures;
247
        }
248
 
249
        /**
250
         *    The SPL library has problems with the
251
         *    Reflection library. In particular, you can
252
         *    get extra characters in parameter names :(.
253
         *    @param string $name    Parameter name.
254
         *    @return string         Cleaner name.
255
         *    @access private
256
         */
257
        function _suppressSpurious($name) {
258
            return str_replace(array('[', ']', ' '), '', $name);
259
        }
260
 
261
        /**
262
         *    Test of a reflection parameter being optional
263
         *    that works with early versions of PHP5.
264
         *    @param reflectionParameter $parameter    Is this optional.
265
         *    @return boolean                          True if optional.
266
         *    @access private
267
         */
268
        function _isOptional($parameter) {
269
            if (method_exists($parameter, 'isOptional')) {
270
                return $parameter->isOptional();
271
            }
272
            return false;
273
        }
274
    }
275
?>