3 * base include file for SimpleTest
5 * @subpackage UnitTester
10 * Version specific reflection API.
12 * @subpackage UnitTester
14 class SimpleReflection
{
18 * Stashes the class/interface.
19 * @param string $interface Class or interface
22 function SimpleReflection($interface) {
23 $this->_interface
= $interface;
27 * Checks that a class has been declared. Versions
28 * before PHP5.0.2 need a check that it's not really
30 * @return boolean True if defined.
33 function classExists() {
34 if (! class_exists($this->_interface
)) {
37 $reflection = new ReflectionClass($this->_interface
);
38 return ! $reflection->isInterface();
42 * Needed to kill the autoload feature in PHP5
43 * for classes created dynamically.
44 * @return boolean True if defined.
47 function classExistsSansAutoload() {
48 return class_exists($this->_interface
, false);
52 * Checks that a class or interface has been
54 * @return boolean True if defined.
57 function classOrInterfaceExists() {
58 return $this->_classOrInterfaceExistsWithAutoload($this->_interface
, true);
62 * Needed to kill the autoload feature in PHP5
63 * for classes created dynamically.
64 * @return boolean True if defined.
67 function classOrInterfaceExistsSansAutoload() {
68 return $this->_classOrInterfaceExistsWithAutoload($this->_interface
, false);
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.
79 function _classOrInterfaceExistsWithAutoload($interface, $autoload) {
80 if (function_exists('interface_exists')) {
81 if (interface_exists($this->_interface
, $autoload)) {
85 return class_exists($this->_interface
, $autoload);
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.
95 function getMethods() {
96 return array_unique(get_class_methods($this->_interface
));
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.
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
117 * @returns array List of enforced method signatures.
120 function getInterfaceMethods() {
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
131 * @param string $method Method name.
132 * @returns boolean True if enforced.
135 function _isInterfaceMethod($method) {
136 return in_array($method, $this->getInterfaceMethods());
140 * Finds the parent class name.
141 * @returns string Parent class name.
144 function getParent() {
145 $reflection = new ReflectionClass($this->_interface
);
146 $parent = $reflection->getParentClass();
148 return $parent->getName();
154 * Determines if the class is abstract.
155 * @returns boolean True if abstract.
158 function isAbstract() {
159 $reflection = new ReflectionClass($this->_interface
);
160 return $reflection->isAbstract();
164 * Wittles a list of interfaces down to only the top
166 * @param array $interfaces Reflection API interfaces
168 * @returns array List of parent interface names.
171 function _onlyParents($interfaces) {
173 foreach ($interfaces as $interface) {
174 foreach($interfaces as $possible_parent) {
175 if ($interface->getName() == $possible_parent->getName()) {
178 if ($interface->isSubClassOf($possible_parent)) {
182 $parents[] = $interface->getName();
188 * Gets the source code matching the declaration
190 * @param string $name Method name.
191 * @return string Method signature up to last
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
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)) .
234 * Gets the source code for each parameter.
235 * @param ReflectionMethod $method Method object from
237 * @return array List of strings, each
241 function _getParameterSignatures($method) {
242 $signatures = array();
243 foreach ($method->getParameters() as $parameter) {
244 $type = $parameter->getClass();
246 (! is_null($type) ?
$type->getName() . ' ' : '') .
247 ($parameter->isPassedByReference() ?
'&' : '') .
248 '$' . $this->_suppressSpurious($parameter->getName()) .
249 ($this->_isOptional($parameter) ?
' = null' : '');
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.
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.
273 function _isOptional($parameter) {
274 if (method_exists($parameter, 'isOptional')) {
275 return $parameter->isOptional();