1<?php
2/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
3
4/**
5 * PHP Version 4
6 *
7 * Copyright (c) 2002-2005, Sebastian Bergmann <sb@sebastian-bergmann.de>.
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 *
14 *   * Redistributions of source code must retain the above copyright
15 *     notice, this list of conditions and the following disclaimer.
16 *
17 *   * Redistributions in binary form must reproduce the above copyright
18 *     notice, this list of conditions and the following disclaimer in
19 *     the documentation and/or other materials provided with the
20 *     distribution.
21 *
22 *   * Neither the name of Sebastian Bergmann nor the names of his
23 *     contributors may be used to endorse or promote products derived
24 *     from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRIC
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37 * POSSIBILITY OF SUCH DAMAGE.
38 *
39 * @category   Testing
40 * @package    PHPUnit
41 * @author     Wolfram Kriesing <wolfram@kriesing.de>
42 * @copyright  2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
43 * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
44 * @version    CVS: $Id: SetupDecorator.php,v 1.15 2005/11/10 09:47:15 sebastian Exp $
45 * @link       http://pear.php.net/package/PHPUnit
46 * @since      File available since Release 1.0.0
47 */
48
49/**
50 * This decorator actually just adds the functionality to read the
51 * test-suite classes from a given directory and instanciate them
52 * automatically, use it as given in the example below.
53 *
54 * <code>
55 * <?php
56 * $gui = new PHPUnit_GUI_SetupDecorator(new PHPUnit_GUI_HTML());
57 * $gui->getSuitesFromDir('/path/to/dir/tests','.*\.php$',array('index.php','sql.php'));
58 * $gui->show();
59 * ?>
60 * </code>
61 *
62 * The example calls this class and tells it to:
63 *
64 *   - find all file under the directory /path/to/dir/tests
65 *   - for files, which end with '.php' (this is a piece of a regexp, that's why the . is escaped)
66 *   - and to exclude the files 'index.php' and 'sql.php'
67 *   - and include all the files that are left in the tests.
68 *
69 * Given that the path (the first parameter) ends with 'tests' it will be assumed
70 * that the classes are named tests_* where * is the directory plus the filename,
71 * according to PEAR standards.
72 *
73 * So that:
74 *
75 *   - 'testMe.php' in the dir 'tests' bill be assumed to contain a class tests_testMe
76 *   - '/moretests/aTest.php' should contain a class 'tests_moretests_aTest'
77 *
78 * @category   Testing
79 * @package    PHPUnit
80 * @author     Wolfram Kriesing <wolfram@kriesing.de>
81 * @copyright  2002-2005 Sebastian Bergmann <sb@sebastian-bergmann.de>
82 * @license    http://www.opensource.org/licenses/bsd-license.php  BSD License
83 * @version    Release: 1.3.2
84 * @link       http://pear.php.net/package/PHPUnit
85 * @since      Class available since Release 1.0.0
86 */
87class PHPUnit_GUI_SetupDecorator
88{
89    /**
90    *
91    *
92    */
93    function PHPUnit_GUI_SetupDecorator(&$gui)
94    {
95        $this->_gui = &$gui;
96    }
97
98    /**
99    *   just forwarding the action to the decorated class.
100    *
101    */
102    function show($showPassed=TRUE)
103    {
104        $this->_gui->show($showPassed);
105    }
106
107    /**
108    * Setup test suites that can be found in the given directory
109    * Using the second parameter you can also choose a subsets of the files found
110    * in the given directory. I.e. only all the files that contain '_UnitTest_',
111    * in order to do this simply call it like this:
112    * <code>getSuitesFromDir($dir,'.*_UnitTest_.*')</code>.
113    * There you can already see that the pattern is built for the use within a regular expression.
114    *
115    * @param  string  the directory where to search for test-suite files
116    * @param  string  the pattern (a regexp) by which to find the files
117    * @param  array   an array of file names that shall be excluded
118    */
119    function getSuitesFromDir($dir, $filenamePattern = '', $exclude = array())
120    {
121        if ($dir{strlen($dir)-1} == DIRECTORY_SEPARATOR) {
122            $dir = substr($dir, 0, -1);
123        }
124
125        $files = $this->_getFiles(realpath($dir), $filenamePattern, $exclude, realpath($dir . '/..'));
126        asort($files);
127
128        foreach ($files as $className => $aFile) {
129            include_once($aFile);
130
131            if (class_exists($className)) {
132                $suites[] =& new PHPUnit_TestSuite($className);
133            } else {
134                trigger_error("$className could not be found in $dir$aFile!");
135            }
136        }
137
138        $this->_gui->addSuites($suites);
139    }
140
141    /**
142    * This method searches recursively through the directories
143    * to find all the files that shall be added to the be visible.
144    *
145    * @param  string  the path where find the files
146    * @param  srting  the string pattern by which to find the files
147    * @param  string  the file names to be excluded
148    * @param  string  the root directory, which serves as the prefix to the fully qualified filename
149    * @access private
150    */
151    function _getFiles($dir, $filenamePattern, $exclude, $rootDir)
152    {
153        $files = array();
154
155        if ($dp = opendir($dir)) {
156            while (FALSE !== ($file = readdir($dp))) {
157                $filename = $dir . DIRECTORY_SEPARATOR . $file;
158                $match    = TRUE;
159
160                if ($filenamePattern && !preg_match("~$filenamePattern~", $file)) {
161                    $match = FALSE;
162                }
163
164                if (sizeof($exclude)) {
165                    foreach ($exclude as $aExclude) {
166                        if (strpos($file, $aExclude) !== FALSE) {
167                            $match = FALSE;
168                            break;
169                        }
170                    }
171                }
172
173                if (is_file($filename) && $match) {
174                    $tmp = str_replace($rootDir, '', $filename);
175
176                    if (strpos($tmp, DIRECTORY_SEPARATOR) === 0) {
177                        $tmp = substr($tmp, 1);
178                    }
179
180                    if (strpos($tmp, '/') === 0) {
181                        $tmp = substr($tmp, 1);
182                    }
183
184                    $className = str_replace(DIRECTORY_SEPARATOR, '_', $tmp);
185                    $className = basename($className, '.php');
186
187                    $files[$className] = $filename;
188                }
189
190                if ($file != '.' && $file != '..' && is_dir($filename)) {
191                    $files = array_merge($files, $this->_getFiles($filename, $filenamePattern, $exclude, $rootDir));
192                }
193            }
194
195            closedir($dp);
196        }
197
198        return $files;
199    }
200}
201
202/*
203 * Local variables:
204 * tab-width: 4
205 * c-basic-offset: 4
206 * c-hanging-comment-ender-p: nil
207 * End:
208 */
209?>
210