From a5467e842316daf6a8a4345740f05a9731167ce1 Mon Sep 17 00:00:00 2001 From: xue <> Date: Sat, 23 Sep 2006 01:51:57 +0000 Subject: merge from 3.0 branch till 1435. --- framework/prado-cli.php | 814 +++++++++++++++++++++++++----------------------- 1 file changed, 419 insertions(+), 395 deletions(-) (limited to 'framework/prado-cli.php') diff --git a/framework/prado-cli.php b/framework/prado-cli.php index 7dd197f3..341ddb36 100755 --- a/framework/prado-cli.php +++ b/framework/prado-cli.php @@ -1,155 +1,267 @@ -#!/usr/bin/php +#!/usr/bin/env php + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2006 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id$ */ -if(!isset($_SERVER['argv'])) +if(!isset($_SERVER['argv']) || php_sapi_name()!=='cli') die('Must be run from the command line'); -//command line options. -$options['create'] = array('c:', 'create=', '', 'create a new project '); -$options['tests'] = array('t', 'create-tests', '', 'create unit and function test fixtures'); +require_once(dirname(__FILE__).'/prado.php'); -$console = new ConsoleOptions($options, $_SERVER['argv']); - -if($console->hasOptions()) +//stub application class +class PradoShellApplication extends TApplication { - if($dir = $console->getOption('create')) - create_new_prado_project($dir); - if($console->getOption('tests')) - create_test_fixtures($dir); + public function run() + { + $this->initApplication(); + } } -else -{ - $details = $console->renderOptions(); -echo << -Options: -$details -Example: php prado-cli.php -c ./example1 -EOD; -} - -/** - * Functions to create new prado project. - */ +restore_exception_handler(); -function create_new_prado_project($dir) -{ - if(strlen(trim($dir)) == 0) - return; - - $rootPath = realpath(dirname(trim($dir))); - - $basePath = $rootPath.'/'.basename($dir); - $assetPath = $basePath.'/assets'; - $protectedPath = $basePath.'/protected'; - $runtimePath = $basePath.'/protected/runtime'; - $pagesPath = $protectedPath.'/pages'; - - $indexFile = $basePath.'/index.php'; - $htaccessFile = $protectedPath.'/.htaccess'; - $defaultPageFile = $pagesPath.'/Home.page'; - - $tests = $basePath.'/tests'; - $unit_tests = $tests.'/unit'; - $functional_tests = $tests.'/functional'; - - create_directory($basePath, 0755); - create_directory($assetPath,0777); - create_directory($protectedPath,0755); - create_directory($runtimePath,0777); - create_directory($pagesPath,0755); - - create_file($indexFile, render_index_file()); - create_file($htaccessFile, render_htaccess_file()); - create_file($defaultPageFile, render_default_page()); -} +//register action classes +PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLineCreateProject'); +PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLineCreateTests'); +PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLinePhpShell'); +PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLineUnitTest'); + +//run it; +PradoCommandLineInterpreter::getInstance()->run($_SERVER['argv']); -function create_test_fixtures($dir) +//run PHP shell +if(count($_SERVER['argv']) > 1 && strtolower($_SERVER['argv'][1])==='shell') { - if(strlen(trim($dir)) == 0) - return; - - $rootPath = realpath(dirname(trim($dir))); - $basePath = $rootPath.'/'.basename($dir); - - $tests = $basePath.'/tests'; - $unit_tests = $tests.'/unit'; - $functional_tests = $tests.'/functional'; - - create_directory($tests,0755); - create_directory($unit_tests,0755); - create_directory($functional_tests,0755); - - $unit_test_index = $tests.'/unit.php'; - $functional_test_index = $tests.'/functional.php'; - - create_file($unit_test_index, render_unit_test_fixture()); - create_file($functional_test_index, render_functional_test_fixture()); + function __shell_print_var($shell,$var) + { + if(!$shell->has_semicolon) echo Prado::varDump($var); + } + include_once(dirname(__FILE__).'/3rdParty/PhpShell/php-shell-cmd.php'); } -function render_unit_test_fixture() + +/**************** END CONFIGURATION **********************/ + +/** + * PradoCommandLineInterpreter Class + * + * Command line interface, configures the action classes and dispatches the command actions. + * + * @author Wei Zhuo + * @version $Id$ + * @since 3.0.5 + */ +class PradoCommandLineInterpreter { - $tester = realpath(dirname(__FILE__).'/../tests/test_tools/unit_tests.php'); -return '_actions[$class] = new $class; + } -$app_directory = "../protected"; -$test_cases = dirname(__FILE__)."/unit"; + /** + * @return PradoCommandLineInterpreter static instance + */ + public static function getInstance() + { + static $instance; + if(is_null($instance)) + $instance = new self; + return $instance; + } -$tester = new PradoUnitTester($test_cases, $app_directory); -$tester->run(new HtmlReporter()); + /** + * Dispatch the command line actions. + * @param array command line arguments + */ + public function run($args) + { + echo "Command line tools for Prado ".Prado::getVersion().".\n"; -?>'; + if(count($args) > 1) + array_shift($args); + $valid = false; + foreach($this->_actions as $class => $action) + { + if($action->isValidAction($args)) + { + $valid |= $action->performAction($args); + break; + } + else + { + $valid = false; + } + } + if(!$valid) + $this->printHelp(); + } + + /** + * Print command line help, default action. + */ + public function printHelp() + { + echo "usage: php prado-cli.php action [optional]\n"; + echo "example: php prado-cli.php -c mysite\n\n"; + echo "actions:\n"; + foreach($this->_actions as $action) + echo $action->renderHelp(); + } } -function render_functional_test_fixture() +/** + * Base class for command line actions. + * + * @author Wei Zhuo + * @version $Id$ + * @since 3.0.5 + */ +abstract class PradoCommandLineAction { - $tester = realpath(dirname(__FILE__).'/../tests/test_tools/functional_tests.php'); -return 'run(new SimpleReporter()); + public function isValidAction($args) + { + return strtolower($args[0]) === $this->action && + count($args)-1 >= count($this->parameters); + } + + public function renderHelp() + { + $params = array(); + foreach($this->parameters as $v) + $params[] = '<'.$v.'>'; + $parameters = join($params, ' '); + $options = array(); + foreach($this->optional as $v) + $options[] = '['.$v.']'; + $optional = (strlen($parameters) ? ' ' : ''). join($options, ' '); + $description=''; + foreach(explode("\n", wordwrap($this->description,65)) as $line) + $description .= ' '.$line."\n"; + return <<action} {$parameters}{$optional} +{$description} + +EOD; + } + + protected function initializePradoApplication($directory) + { + $app_dir = realpath($directory.'/protected/'); + if($app_dir !== false) + { + $app = new PradoShellApplication($app_dir); + $app->run(); + $dir = substr(str_replace(realpath('./'),'',$app_dir),1); + + echo '** Loaded Prado appplication in directory "'.$dir."\".\n"; + } + else + echo '** Unable to load Prado application in directory "'.$directory."\".\n"; + } -?>'; } -function create_directory($dir, $mask) +/** + * Create a Prado project skeleton, including directories and files. + * + * @author Wei Zhuo + * @version $Id$ + * @since 3.0.5 + */ +class PradoCommandLineCreateProject extends PradoCommandLineAction { - if(!is_dir($dir)) + protected $action = '-c'; + protected $parameters = array('directory'); + protected $optional = array(); + protected $description = 'Creates a Prado project skeleton for the given .'; + + public function performAction($args) { - mkdir($dir); - echo "creating $dir\n"; - } - if(is_dir($dir)) - chmod($dir, $mask); -} - -function create_file($filename, $content) -{ - if(!is_file($filename)) + $this->createNewPradoProject($args[1]); + return true; + } + + /** + * Functions to create new prado project. + */ + protected function createNewPradoProject($dir) { - file_put_contents($filename, $content); - echo "creating $filename\n"; + if(strlen(trim($dir)) == 0) + return; + + $rootPath = realpath(dirname(trim($dir))); + + $basePath = $rootPath.'/'.basename($dir); + $assetPath = $basePath.'/assets'; + $protectedPath = $basePath.'/protected'; + $runtimePath = $basePath.'/protected/runtime'; + $pagesPath = $protectedPath.'/pages'; + + $indexFile = $basePath.'/index.php'; + $htaccessFile = $protectedPath.'/.htaccess'; + $defaultPageFile = $pagesPath.'/Home.page'; + + $this->createDirectory($basePath, 0755); + $this->createDirectory($assetPath,0777); + $this->createDirectory($protectedPath,0755); + $this->createDirectory($runtimePath,0777); + $this->createDirectory($pagesPath,0755); + + $this->createFile($indexFile, $this->renderIndexFile()); + $this->createFile($htaccessFile, $this->renderHtaccessFile()); + $this->createFile($defaultPageFile, $this->renderDefaultPage()); } -} -function render_index_file() -{ - $framework = realpath(dirname(__FILE__)).'/prado.php'; + protected function renderIndexFile() + { + $framework = realpath(dirname(__FILE__)).'/prado.php'; return 'run(); ?>'; -} + } -function render_htaccess_file() -{ - return 'deny from all'; -} + protected function renderHtaccessFile() + { + return 'deny from all'; + } -function render_default_page() -{ + protected function renderDefaultPage() + { return <<Welcome to Prado! EOD; + } } -/* vim: set expandtab tabstop=4 shiftwidth=4: */ -// +----------------------------------------------------------------------+ -// | PHP Version 4 | -// +----------------------------------------------------------------------+ -// | Copyright (c) 1997-2003 The PHP Group | -// +----------------------------------------------------------------------+ -// | This source file is subject to version 3.0 of the PHP license, | -// | that is bundled with this package in the file LICENSE, and is | -// | available through the world-wide-web at the following url: | -// | http://www.php.net/license/3_0.txt. | -// | If you did not receive a copy of the PHP license and are unable to | -// | obtain it through the world-wide-web, please send a note to | -// | license@php.net so we can mail you a copy immediately. | -// +----------------------------------------------------------------------+ -// | Author: Andrei Zmievski | -// +----------------------------------------------------------------------+ -// -// $Id$ - /** - * Command-line options parsing class. + * Creates test fixtures for a Prado application. * - * @author Andrei Zmievski * @author Wei Zhuo + * @version $Id$ + * @since 3.0.5 */ -class ConsoleOptions -{ - private $_short_options; - private $_long_options; - private $_options; - private $_args; - private $_values; - - /** - * @param array list of options with the following format - * option['name'] = array('short', 'long', 'parameter', 'description') - * see @link setOptions} for details on 'short' and 'long' string details. - */ - public function __construct($options, $args) +class PradoCommandLineCreateTests extends PradoCommandLineAction +{ + protected $action = '-t'; + protected $parameters = array('directory'); + protected $optional = array(); + protected $description = 'Create test fixtures in the given .'; + + public function performAction($args) { - $short = ''; - $long = array(); - foreach($options as $option) - { - $short .= $option[0]; - $long[] = $option[1]; - } - $this->setOptions($short,$long); - $this->_options = $options; - $this->_args = $args; + $this->createTestFixtures($args[1]); + return true; } - - /** - * The second parameter is a string of allowed short options. Each of the - * option letters can be followed by a colon ':' to specify that the option - * requires an argument, or a double colon '::' to specify that the option - * takes an optional argument. - * - * The third argument is an optional array of allowed long options. The - * leading '--' should not be included in the option name. Options that - * require an argument should be followed by '=', and options that take an - * option argument should be followed by '=='. - * - * @param string $short_options specifies the list of allowed short options - * @param array $long_options specifies the list of allowed long options - */ - protected function setOptions($short_options, $long_options=null) + + protected function createTestFixtures($dir) { - $this->_short_options = $short_options; - $this->_long_options = $long_options; + if(strlen(trim($dir)) == 0) + return; + + $rootPath = realpath(dirname(trim($dir))); + $basePath = $rootPath.'/'.basename($dir); + + $tests = $basePath.'/tests'; + $unit_tests = $tests.'/unit'; + $functional_tests = $tests.'/functional'; + + $this->createDirectory($tests,0755); + $this->createDirectory($unit_tests,0755); + $this->createDirectory($functional_tests,0755); + + $unit_test_index = $tests.'/unit.php'; + $functional_test_index = $tests.'/functional.php'; + + $this->createFile($unit_test_index, $this->renderUnitTestFixture()); + $this->createFile($functional_test_index, $this->renderFunctionalTestFixture()); } - - /** - * @return string list of options and its descriptions - */ - public function renderOptions() + + protected function renderUnitTestFixture() { - $options = array(); - $descriptions = array(); - $max = 0; - foreach($this->_options as $option) - { - $short = str_replace(':','',$option[0]); - $long = str_replace('=','',$option[1]); - $desc = $option[2]; - $details = " -{$short}, --{$long} {$desc}"; - if(($len = strlen($details)) > $max) - $max = $len; - $options[] = $details; - $descriptions[] = $option[3]; - } - - $content = ''; - for($i = 0, $k = count($options); $i < $k; $i++) - $content .= str_pad($options[$i],$max+3).$descriptions[$i]."\n"; - return $content; + $tester = realpath(dirname(__FILE__).'/../tests/test_tools/unit_tests.php'); +return 'run(new HtmlReporter()); + +?>'; } - - /** - * @param string argument name - * @return string argument value - */ - public function getOption($name) + + protected function renderFunctionalTestFixture() { - if(is_null($this->_values)) - $this->_values = $this->getNamedOptions(); - - return isset($this->_values[$name]) ? $this->_values[$name] : null; + $tester = realpath(dirname(__FILE__).'/../tests/test_tools/functional_tests.php'); +return 'run(new SimpleReporter()); + +?>'; } - - /** - * @return array list of all options given. - */ - public function getOptions() + +} + +/** + * Creates and run a Prado application in a PHP Shell. + * + * @author Wei Zhuo + * @version $Id$ + * @since 3.0.5 + */ +class PradoCommandLinePhpShell extends PradoCommandLineAction +{ + protected $action = 'shell'; + protected $parameters = array(); + protected $optional = array('directory'); + protected $description = 'Runs a PHP interactive interpreter. Initializes the Prado application in the given [directory].'; + + public function performAction($args) { - if(is_null($this->_values)) - $this->_values = $this->getNamedOptions(); - return $this->_values; + if(count($args) > 1) + $this->initializePradoApplication($args[1]); + return true; } - - /** - * @return boolean true if one or more options are given. - */ - public function hasOptions() +} + +/** + * Runs unit test cases. + * + * @author Wei Zhuo + * @version $Id$ + * @since 3.0.5 + */ +class PradoCommandLineUnitTest extends PradoCommandLineAction +{ + protected $action = 'test'; + protected $parameters = array('directory'); + protected $optional = array('testcase ...'); + protected $description = 'Runs all unit test cases in the given . Use [testcase] option to run specific test cases.'; + + protected $matches = array(); + + public function performAction($args) { - if(is_null($this->_values)) - $this->_values = $this->getNamedOptions(); - return count($this->_values) > 0; + $dir = realpath($args[1]); + if($dir !== false) + $this->runUnitTests($dir,$args); + else + echo '** Unable to find directory "'.$args[1]."\".\n"; + return true; } - - /** - * Parse the options from args into named arguements. - */ - protected function getNamedOptions() + + protected function initializeTestRunner() { - $options = array(); - $values = $this->parseOptions($this->_args); - foreach($values[0] as $value) - { - foreach($this->_options as $name => $option) - { - $short = str_replace(':', '', $option[0]); - $long = str_replace('=', '', $option[1]); - if($short == $value[0] || $long == $value[0]) - $options[$name] = is_null($value[1]) ? true : $value[1]; - } - } - return $options; - } - - /** - * Gets the command-line options. - * - * The parameter to this function should be the list of command-line - * arguments without the leading reference to the running program. - * - * The return value is an array of two elements: the list of parsed - * options and the list of non-option command-line arguments. Each entry in - * the list of parsed options is a pair of elements - the first one - * specifies the option, and the second one specifies the option argument, - * if there was one. - * - * Long and short options can be mixed. - * - * @param array $args an array of command-line arguments - * @return array two-element array containing the list of parsed options and - * the non-option arguments - */ - public function parseOptions($args) - { - if (empty($args)) - return array(array(), array()); - - $short_options = $this->_short_options; - $long_options = $this->_long_options; - - $opts = array(); - $non_opts = array(); - - settype($args, 'array'); - - if ($long_options) - sort($long_options); - - if (isset($args[0]{0}) && $args[0]{0} != '-') - array_shift($args); + $TEST_TOOLS = realpath(dirname(__FILE__).'/../tests/test_tools/'); - reset($args); - - while (list($i, $arg) = each($args)) - { + require_once($TEST_TOOLS.'/simpletest/unit_tester.php'); + require_once($TEST_TOOLS.'/simpletest/web_tester.php'); + require_once($TEST_TOOLS.'/simpletest/mock_objects.php'); + require_once($TEST_TOOLS.'/simpletest/reporter.php'); + } - /* The special element '--' means explicit end of - options. Treat the rest of the arguments as non-options - and end the loop. */ - if ($arg == '--') { - $non_opts = array_merge($non_opts, array_slice($args, $i + 1)); - break; - } + protected function runUnitTests($dir, $args) + { + $app_dir = $this->getAppDir($dir); + if($app_dir !== false) + $this->initializePradoApplication($app_dir.'/../'); - if ($arg{0} != '-' || (strlen($arg) > 1 && $arg{1} == '-' && !$long_options)) - { - $non_opts = array_merge($non_opts, array_slice($args, $i)); - break; - } - elseif (strlen($arg) > 1 && $arg{1} == '-') - $this->parseLongOption(substr($arg, 2), $long_options, $opts, $args); - else - $this->parseShortOption(substr($arg, 1), $short_options, $opts, $args); - } - - return array($opts, $non_opts); - } - - private function parseShortOption($arg, $short_options, &$opts, &$args) - { - for ($i = 0; $i < strlen($arg); $i++) + $this->initializeTestRunner(); + $test_dir = $this->getTestDir($dir); + if($test_dir !== false) { - $opt = $arg{$i}; - $opt_arg = null; - - /* Try to find the short option in the specifier string. */ - if (($spec = strstr($short_options, $opt)) === false || $arg{$i} == ':') - throw new Exception("Console_Getopt: unrecognized option -- $opt"); - - if (strlen($spec) > 1 && $spec{1} == ':') - { - if (strlen($spec) > 2 && $spec{2} == ':') - { - if ($i + 1 < strlen($arg)) - { - /* Option takes an optional argument. Use the remainder of - the arg string if there is anything left. */ - $opts[] = array($opt, substr($arg, $i + 1)); - break; - } - } - else - { - /* Option requires an argument. Use the remainder of the arg - string if there is anything left. */ - if ($i + 1 < strlen($arg)) - { - $opts[] = array($opt, substr($arg, $i + 1)); - break; - } - else if (list(, $opt_arg) = each($args)) - /* Else use the next argument. */; - else - throw new Exception("Console_Getopt: option requires an argument -- $opt"); - } - } - - $opts[] = array($opt, $opt_arg); - } - } - - private function parseLongOption($arg, $long_options, &$opts, &$args) - { - @list($opt, $opt_arg) = explode('=', $arg); - $opt_len = strlen($opt); - - for ($i = 0; $i < count($long_options); $i++) + $test =$this->getUnitTestCases($test_dir,$args); + $running_dir = substr(str_replace(realpath('./'),'',$test_dir),1); + echo 'Running unit tests in directory "'.$running_dir."\":\n"; + $test->run(new TextReporter()); + } + else { - $long_opt = $long_options[$i]; - $opt_start = substr($long_opt, 0, $opt_len); + $running_dir = substr(str_replace(realpath('./'),'',$dir),1); + echo '** Unable to find test directory "'.$running_dir.'/unit" or "'.$running_dir.'/tests/unit".'."\n"; + } + } - /* Option doesn't match. Go on to the next one. */ - if ($opt_start != $opt) - continue; + protected function getAppDir($dir) + { + $app_dir = realpath($dir.'/protected'); + if($app_dir !== false) + return $app_dir; + return realpath($dir.'/../protected'); + } - $opt_rest = substr($long_opt, $opt_len); + protected function getTestDir($dir) + { + $test_dir = realpath($dir.'/unit'); + if($test_dir !== false) + return $test_dir; + return realpath($dir.'/tests/unit/'); + } - /* Check that the options uniquely matches one of the allowed - options. */ - if ($opt_rest != '' && $opt{0} != '=' && - $i + 1 < count($long_options) && - $opt == substr($long_options[$i+1], 0, $opt_len)) + protected function getUnitTestCases($dir,$args) + { + $matches = null; + if(count($args) > 2) + $matches = array_slice($args,2); + $test=new GroupTest(' '); + $this->addTests($test,$dir,true,$matches); + $test->setLabel(implode(' ',$this->matches)); + return $test; + } + + protected function addTests($test,$path,$recursive=true,$match=null) + { + $dir=opendir($path); + while(($entry=readdir($dir))!==false) + { + if(is_file($path.'/'.$entry) && (preg_match('/[^\s]*test[^\s]*\.php/', strtolower($entry)))) { - throw new Exception("Console_Getopt: option --$opt is ambiguous"); - } + if($match==null||($match!=null && $this->hasMatch($match,$entry))) + $test->addTestFile($path.'/'.$entry); + } + if($entry!=='.' && $entry!=='..' && $entry!=='.svn' && is_dir($path.'/'.$entry) && $recursive) + $this->addTests($test,$path.'/'.$entry,$recursive,$match); + } + closedir($dir); + } - if (substr($long_opt, -1) == '=') + protected function hasMatch($match,$entry) + { + $file = strtolower(substr($entry,0,strrpos($entry,'.'))); + foreach($match as $m) + { + if(strtolower($m) === $file) { - if (substr($long_opt, -2) != '==') - { - /* Long option requires an argument. - Take the next argument if one wasn't specified. */; - if (!strlen($opt_arg) && !(list(, $opt_arg) = each($args))) - throw new Exception("Console_Getopt: option --$opt requires an argument"); - } - } - else if ($opt_arg) - throw new Exception("Console_Getopt: option --$opt doesn't allow an argument"); - - $opts[] = array($opt, $opt_arg); - return; - } - - throw new Exception("Console_Getopt: unrecognized option --$opt"); - } + $this->matches[] = $m; + return true; + } + } + return false; + } } - ?> \ No newline at end of file -- cgit v1.2.3