]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - tests/PHPUnit/Util/Class.php
Added unit tests.
[Github/sugarcrm.git] / tests / PHPUnit / Util / Class.php
1 <?php
2 /**
3  * PHPUnit
4  *
5  * Copyright (c) 2002-2009, Sebastian Bergmann <sb@sebastian-bergmann.de>.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  *   * Redistributions of source code must retain the above copyright
13  *     notice, this list of conditions and the following disclaimer.
14  *
15  *   * Redistributions in binary form must reproduce the above copyright
16  *     notice, this list of conditions and the following disclaimer in
17  *     the documentation and/or other materials provided with the
18  *     distribution.
19  *
20  *   * Neither the name of Sebastian Bergmann nor the names of his
21  *     contributors may be used to endorse or promote products derived
22  *     from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35  * POSSIBILITY OF SUCH DAMAGE.
36  *
37  * @category   Testing
38  * @package    PHPUnit
39  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
40  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
41  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
42
43  * @link       http://www.phpunit.de/
44  * @since      File available since Release 3.1.0
45  */
46
47 require_once 'PHPUnit/Util/Filter.php';
48
49 PHPUnit_Util_Filter::addFileToFilter(__FILE__, 'PHPUNIT');
50
51 /**
52  * Class helpers.
53  *
54  * @category   Testing
55  * @package    PHPUnit
56  * @author     Sebastian Bergmann <sb@sebastian-bergmann.de>
57  * @copyright  2002-2009 Sebastian Bergmann <sb@sebastian-bergmann.de>
58  * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
59  * @version    Release: 3.3.17
60  * @link       http://www.phpunit.de/
61  * @since      Class available since Release 3.1.0
62  */
63 class PHPUnit_Util_Class
64 {
65     protected static $buffer = array();
66     protected static $fileClassMap = array();
67     protected static $fileFunctionMap = array();
68
69     /**
70      * Starts the collection of loaded classes.
71      *
72      */
73     public static function collectStart()
74     {
75         self::$buffer = get_declared_classes();
76     }
77
78     /**
79      * Stops the collection of loaded classes and
80      * returns the names of the loaded classes.
81      *
82      * @return array
83      */
84     public static function collectEnd()
85     {
86         return array_values(
87           array_diff(get_declared_classes(), self::$buffer)
88         );
89     }
90
91     /**
92      * Stops the collection of loaded classes and
93      * returns the names of the files that declare the loaded classes.
94      *
95      * @return array
96      */
97     public static function collectEndAsFiles()
98     {
99         $result = self::collectEnd();
100         $count  = count($result);
101
102         for ($i = 0; $i < $count; $i++) {
103             $class = new ReflectionClass($result[$i]);
104
105             if ($class->isUserDefined()) {
106                 $file = $class->getFileName();
107
108                 if (file_exists($file)) {
109                     $result[$i] = $file;
110                 } else {
111                     unset($result[$i]);
112                 }
113             }
114         }
115
116         return $result;
117     }
118
119     /**
120      * Returns the names of the classes declared in a sourcefile.
121      *
122      * @param  string  $filename
123      * @param  string  $commonPath
124      * @param  boolean $clearCache
125      * @return array
126      */
127     public static function getClassesInFile($filename, $commonPath = '', $clearCache = FALSE)
128     {
129         if ($commonPath != '') {
130             $filename = str_replace($commonPath, '', $filename);
131         }
132
133         if ($clearCache) {
134             self::$fileClassMap = array();
135         }
136
137         if (empty(self::$fileClassMap)) {
138             $classes = array_merge(get_declared_classes(), get_declared_interfaces());
139
140             foreach ($classes as $className) {
141                 $class = new ReflectionClass($className);
142
143                 if ($class->isUserDefined()) {
144                     $file = $class->getFileName();
145
146                     if ($commonPath != '') {
147                         $file = str_replace($commonPath, '', $file);
148                     }
149
150                     if (!isset(self::$fileClassMap[$file])) {
151                         self::$fileClassMap[$file] = array($class);
152                     } else {
153                         self::$fileClassMap[$file][] = $class;
154                     }
155                 }
156             }
157         }
158
159         return isset(self::$fileClassMap[$filename]) ? self::$fileClassMap[$filename] : array();
160     }
161
162     /**
163      * Returns the names of the classes declared in a sourcefile.
164      *
165      * @param  string  $filename
166      * @param  string  $commonPath
167      * @param  boolean $clearCache
168      * @return array
169      * @since  Method available since Release 3.2.0
170      * @todo   Find a better place for this method.
171      */
172     public static function getFunctionsInFile($filename, $commonPath = '', $clearCache = FALSE)
173     {
174         if ($commonPath != '') {
175             $filename = str_replace($commonPath, '', $filename);
176         }
177
178         if ($clearCache) {
179             self::$fileFunctionMap = array();
180         }
181
182         if (empty(self::$fileFunctionMap)) {
183             $functions = get_defined_functions();
184
185             foreach ($functions['user'] as $functionName) {
186                 $function = new ReflectionFunction($functionName);
187
188                 $file = $function->getFileName();
189
190                 if ($commonPath != '') {
191                     $file = str_replace($commonPath, '', $file);
192                 }
193
194                 if (!isset(self::$fileFunctionMap[$file])) {
195                     self::$fileFunctionMap[$file] = array($function);
196                 } else {
197                     self::$fileFunctionMap[$file][] = $function;
198                 }
199             }
200         }
201
202         return isset(self::$fileFunctionMap[$filename]) ? self::$fileFunctionMap[$filename] : array();
203     }
204
205     /**
206      * Returns the class hierarchy for a given class.
207      *
208      * @param  string  $className
209      * @param  boolean $asReflectionObjects
210      * @return array
211      */
212     public static function getHierarchy($className, $asReflectionObjects = FALSE)
213     {
214         if ($asReflectionObjects) {
215             $classes = array(new ReflectionClass($className));
216         } else {
217             $classes = array($className);
218         }
219
220         $done    = FALSE;
221
222         while (!$done) {
223             if ($asReflectionObjects) {
224                 $class = new ReflectionClass($classes[count($classes)-1]->getName());
225             } else {
226                 $class = new ReflectionClass($classes[count($classes)-1]);
227             }
228
229             $parent = $class->getParentClass();
230
231             if ($parent !== FALSE) {
232                 if ($asReflectionObjects) {
233                     $classes[] = $parent;
234                 } else {
235                     $classes[] = $parent->getName();
236                 }
237             } else {
238                 $done = TRUE;
239             }
240         }
241
242         return $classes;
243     }
244
245     /**
246      * Returns the signature of a function.
247      *
248      * @param  ReflectionFunction $function
249      * @return string
250      * @since  Method available since Release 3.3.2
251      * @todo   Find a better place for this method.
252      */
253     public static function getFunctionSignature(ReflectionFunction $function)
254     {
255         if ($function->returnsReference()) {
256             $reference = '&';
257         } else {
258             $reference = '';
259         }
260
261         return sprintf(
262           'function %s%s(%s)',
263
264           $reference,
265           $function->getName(),
266           self::getMethodParameters($function)
267         );
268     }
269
270     /**
271      * Returns the signature of a method.
272      *
273      * @param  ReflectionMethod $method
274      * @return string
275      * @since  Method available since Release 3.2.0
276      */
277     public static function getMethodSignature(ReflectionMethod $method)
278     {
279         if ($method->isPrivate()) {
280             $modifier = 'private';
281         }
282
283         else if ($method->isProtected()) {
284             $modifier = 'protected';
285         }
286
287         else {
288             $modifier = 'public';
289         }
290
291         if ($method->isStatic()) {
292             $modifier .= ' static';
293         }
294
295         if ($method->returnsReference()) {
296             $reference = '&';
297         } else {
298             $reference = '';
299         }
300
301         return sprintf(
302           '%s function %s%s(%s)',
303
304           $modifier,
305           $reference,
306           $method->getName(),
307           self::getMethodParameters($method)
308         );
309     }
310
311     /**
312      * Returns the parameters of a function or method.
313      *
314      * @param  ReflectionFunction|ReflectionMethod $method
315      * @return string
316      * @since  Method available since Release 3.2.0
317      */
318     public static function getMethodParameters($method)
319     {
320         $parameters = array();
321
322         foreach ($method->getParameters() as $i => $parameter) {
323             $name = '$' . $parameter->getName();
324
325             if ($name === '$') {
326                 $name .= 'arg' . $i;
327             }
328
329             $typeHint = '';
330
331             if ($parameter->isArray()) {
332                 $typeHint = 'array ';
333             } else {
334                 try {
335                     $class = $parameter->getClass();
336                 }
337
338                 catch (ReflectionException $e) {
339                     $class = FALSE;
340                 }
341
342                 if ($class) {
343                     $typeHint = $class->getName() . ' ';
344                 }
345             }
346
347             $default = '';
348
349             if ($parameter->isDefaultValueAvailable()) {
350                 $value   = $parameter->getDefaultValue();
351                 $default = ' = ' . var_export($value, TRUE);
352             }
353
354             else if ($parameter->isOptional()) {
355                 $default = ' = null';
356             }
357
358             $ref = '';
359
360             if ($parameter->isPassedByReference()) {
361                 $ref = '&';
362             }
363
364             $parameters[] = $typeHint . $ref . $name . $default;
365         }
366
367         return join(', ', $parameters);
368     }
369
370     /**
371      * Returns the sourcecode of a user-defined class.
372      *
373      * @param  string  $className
374      * @param  string  $methodName
375      * @return mixed
376      */
377     public static function getMethodSource($className, $methodName)
378     {
379         if ($className != 'global') {
380             $function = new ReflectionMethod($className, $methodName);
381         } else {
382             $function = new ReflectionFunction($methodName);
383         }
384
385         $filename = $function->getFileName();
386
387         if (file_exists($filename)) {
388             $file   = file($filename);
389             $result = '';
390             $start  = $function->getStartLine() - 1;
391             $end    = $function->getEndLine() - 1;
392
393             for ($line = $start; $line <= $end; $line++) {
394                 $result .= $file[$line];
395             }
396
397             return $result;
398         } else {
399             return FALSE;
400         }
401     }
402
403     /**
404      * Returns the package information of a user-defined class.
405      *
406      * @param  string $className
407      * @return array
408      */
409     public static function getPackageInformation($className)
410     {
411         $result = array(
412           'namespace'   => '',
413           'fullPackage' => '',
414           'category'    => '',
415           'package'     => '',
416           'subpackage'  => ''
417         );
418
419         if (strpos($className, ':') !== FALSE) {
420             $result['namespace'] = self::arrayToName(
421               explode('\\', $className), '\\'
422             );
423         }
424
425         $class      = new ReflectionClass($className);
426         $docComment = $class->getDocComment();
427
428         if (preg_match('/@category[\s]+([\.\w]+)/', $docComment, $matches)) {
429             $result['category'] = $matches[1];
430         }
431
432         if (preg_match('/@package[\s]+([\.\w]+)/', $docComment, $matches)) {
433             $result['package']     = $matches[1];
434             $result['fullPackage'] = $matches[1];
435         }
436
437         if (preg_match('/@subpackage[\s]+([\.\w]+)/', $docComment, $matches)) {
438             $result['subpackage'] = $matches[1];
439             $result['fullPackage'] .= '.' . $matches[1];
440         }
441
442         if (empty($result['fullPackage'])) {
443             $result['fullPackage'] = self::arrayToName(
444               explode('_', str_replace('\\', '_', $className)), '.'
445             );
446         }
447
448         return $result;
449     }
450
451     /**
452      * Returns the package information of a user-defined class.
453      *
454      * @param  array $parts
455      * @param  string $join
456      * @return string
457      * @since  Method available since Release 3.2.12
458      */
459     protected static function arrayToName(array $parts, $join)
460     {
461         $result = '';
462
463         if (count($parts) > 1) {
464             array_pop($parts);
465
466             $result = join($join, $parts);
467         }
468
469         return $result;
470     }
471 }
472 ?>