premier commit
[bazdig.git] / test / simpletest / reflection_php5.php
blobb30a2a138de372f8c523b513cd404538e6bc111e
1 <?php
2 /**
3 * base include file for SimpleTest
4 * @package SimpleTest
5 * @subpackage UnitTester
6 * @version $Id: reflection_php5.php,v 1.24 2006/11/08 19:07:59 lastcraft Exp $
7 */
9 /**
10 * Version specific reflection API.
11 * @package SimpleTest
12 * @subpackage UnitTester
14 class SimpleReflection {
15 var $_interface;
17 /**
18 * Stashes the class/interface.
19 * @param string $interface Class or interface
20 * to inspect.
22 function SimpleReflection($interface) {
23 $this->_interface = $interface;
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
33 function classExists() {
34 if (! class_exists($this->_interface)) {
35 return false;
37 $reflection = new ReflectionClass($this->_interface);
38 return ! $reflection->isInterface();
41 /**
42 * Needed to kill the autoload feature in PHP5
43 * for classes created dynamically.
44 * @return boolean True if defined.
45 * @access public
47 function classExistsSansAutoload() {
48 return class_exists($this->_interface, false);
51 /**
52 * Checks that a class or interface has been
53 * declared.
54 * @return boolean True if defined.
55 * @access public
57 function classOrInterfaceExists() {
58 return $this->_classOrInterfaceExistsWithAutoload($this->_interface, true);
61 /**
62 * Needed to kill the autoload feature in PHP5
63 * for classes created dynamically.
64 * @return boolean True if defined.
65 * @access public
67 function classOrInterfaceExistsSansAutoload() {
68 return $this->_classOrInterfaceExistsWithAutoload($this->_interface, false);
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
79 function _classOrInterfaceExistsWithAutoload($interface, $autoload) {
80 if (function_exists('interface_exists')) {
81 if (interface_exists($this->_interface, $autoload)) {
82 return true;
85 return class_exists($this->_interface, $autoload);
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
95 function getMethods() {
96 return array_unique(get_class_methods($this->_interface));
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
106 function getInterfaces() {
107 $reflection = new ReflectionClass($this->_interface);
108 if ($reflection->isInterface()) {
109 return array($this->_interface);
111 return $this->_onlyParents($reflection->getInterfaces());
115 * Gets the list of methods for the implemented
116 * interfaces only.
117 * @returns array List of enforced method signatures.
118 * @access public
120 function getInterfaceMethods() {
121 $methods = array();
122 foreach ($this->getInterfaces() as $interface) {
123 $methods = array_merge($methods, get_class_methods($interface));
125 return array_unique($methods);
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
135 function _isInterfaceMethod($method) {
136 return in_array($method, $this->getInterfaceMethods());
140 * Finds the parent class name.
141 * @returns string Parent class name.
142 * @access public
144 function getParent() {
145 $reflection = new ReflectionClass($this->_interface);
146 $parent = $reflection->getParentClass();
147 if ($parent) {
148 return $parent->getName();
150 return false;
154 * Determines if the class is abstract.
155 * @returns boolean True if abstract.
156 * @access public
158 function isAbstract() {
159 $reflection = new ReflectionClass($this->_interface);
160 return $reflection->isAbstract();
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
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;
178 if ($interface->isSubClassOf($possible_parent)) {
179 break;
182 $parents[] = $interface->getName();
184 return $parents;
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
195 function getSignature($name) {
196 if ($name == '__set') {
197 return 'function __set($key, $value)';
199 if ($name == '__call') {
200 return 'function __call($method, $arguments)';
202 if (version_compare(phpversion(), '5.1.0', '>=')) {
203 if (in_array($name, array('__get', '__isset', $name == '__unset'))) {
204 return "function {$name}(\$key)";
207 if (! is_callable(array($this->_interface, $name))) {
208 return "function $name()";
210 if ($this->_isInterfaceMethod($name)) {
211 return $this->_getFullSignature($name);
213 return "function $name()";
217 * For a signature specified in an interface, full
218 * details must be replicated to be a valid implementation.
219 * @param string $name Method name.
220 * @return string Method signature up to last
221 * bracket.
222 * @access private
224 function _getFullSignature($name) {
225 $interface = new ReflectionClass($this->_interface);
226 $method = $interface->getMethod($name);
227 $reference = $method->returnsReference() ? '&' : '';
228 return "function $reference$name(" .
229 implode(', ', $this->_getParameterSignatures($method)) .
230 ")";
234 * Gets the source code for each parameter.
235 * @param ReflectionMethod $method Method object from
236 * reflection API
237 * @return array List of strings, each
238 * a snippet of code.
239 * @access private
241 function _getParameterSignatures($method) {
242 $signatures = array();
243 foreach ($method->getParameters() as $parameter) {
244 $type = $parameter->getClass();
245 $signatures[] =
246 (! is_null($type) ? $type->getName() . ' ' : '') .
247 ($parameter->isPassedByReference() ? '&' : '') .
248 '$' . $this->_suppressSpurious($parameter->getName()) .
249 ($this->_isOptional($parameter) ? ' = null' : '');
251 return $signatures;
255 * The SPL library has problems with the
256 * Reflection library. In particular, you can
257 * get extra characters in parameter names :(.
258 * @param string $name Parameter name.
259 * @return string Cleaner name.
260 * @access private
262 function _suppressSpurious($name) {
263 return str_replace(array('[', ']', ' '), '', $name);
267 * Test of a reflection parameter being optional
268 * that works with early versions of PHP5.
269 * @param reflectionParameter $parameter Is this optional.
270 * @return boolean True if optional.
271 * @access private
273 function _isOptional($parameter) {
274 if (method_exists($parameter, 'isOptional')) {
275 return $parameter->isOptional();
277 return false;