From 3069eaf35e833ffe4a1c1c7829dd7e168ae27420 Mon Sep 17 00:00:00 2001 From: Ciro Mattia Gonano Date: Wed, 11 Sep 2013 15:56:48 +0200 Subject: Merge up to r3319 --- bin/prado-cli.php | 883 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 883 insertions(+) create mode 100755 bin/prado-cli.php (limited to 'bin/prado-cli.php') diff --git a/bin/prado-cli.php b/bin/prado-cli.php new file mode 100755 index 00000000..4fa70c08 --- /dev/null +++ b/bin/prado-cli.php @@ -0,0 +1,883 @@ + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2005-2013 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Id: prado-cli.php 3316 2013-08-20 13:51:25Z ctrlaltca $ + */ + +if(!isset($_SERVER['argv']) || php_sapi_name()!=='cli') + die('Must be run from the command line'); + +$frameworkPath = realpath(dirname(dirname(__FILE__))).DIRECTORY_SEPARATOR.'framework'.DIRECTORY_SEPARATOR; + +require_once($frameworkPath.'prado.php'); + +//stub application class +class PradoShellApplication extends TApplication +{ + public function run() + { + $this->initApplication(); + } +} + +restore_exception_handler(); + +//config PHP shell +if(count($_SERVER['argv']) > 1 && strtolower($_SERVER['argv'][1])==='shell') +{ + function __shell_print_var($shell,$var) + { + if(!$shell->has_semicolon) echo Prado::varDump($var); + } + include_once($frameworkPath.'/3rdParty/PhpShell/php-shell-init.php'); +} + + +//register action classes +PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLineCreateProject'); +PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLineCreateTests'); +PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLinePhpShell'); +PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLineUnitTest'); +PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLineActiveRecordGen'); +PradoCommandLineInterpreter::getInstance()->addActionClass('PradoCommandLineActiveRecordGenAll'); + +//run it; +PradoCommandLineInterpreter::getInstance()->run($_SERVER['argv']); + +/**************** END CONFIGURATION **********************/ + +/** + * PradoCommandLineInterpreter Class + * + * Command line interface, configures the action classes and dispatches the command actions. + * + * @author Wei Zhuo + * @version $Id: prado-cli.php 3316 2013-08-20 13:51:25Z ctrlaltca $ + * @since 3.0.5 + */ +class PradoCommandLineInterpreter +{ + /** + * @var array command action classes + */ + protected $_actions=array(); + + /** + * @param string action class name + */ + public function addActionClass($class) + { + $this->_actions[$class] = new $class; + } + + /** + * @return PradoCommandLineInterpreter static instance + */ + public static function getInstance() + { + static $instance; + if($instance === null) + $instance = new self; + return $instance; + } + + public static function printGreeting() + { + echo "Command line tools for Prado ".Prado::getVersion().".\n"; + } + + /** + * Dispatch the command line actions. + * @param array command line arguments + */ + public function run($args) + { + 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() + { + PradoCommandLineInterpreter::printGreeting(); + + 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(); + } +} + +/** + * Base class for command line actions. + * + * @author Wei Zhuo + * @version $Id: prado-cli.php 3316 2013-08-20 13:51:25Z ctrlaltca $ + * @since 3.0.5 + */ +abstract class PradoCommandLineAction +{ + /** + * Execute the action. + * @param array command line parameters + * @return boolean true if action was handled + */ + public abstract function performAction($args); + + protected function createDirectory($dir, $mask) + { + if(!is_dir($dir)) + { + mkdir($dir); + echo "creating $dir\n"; + } + if(is_dir($dir)) + chmod($dir, $mask); + } + + protected function createFile($filename, $content) + { + if(!is_file($filename)) + { + file_put_contents($filename, $content); + echo "creating $filename\n"; + } + } + + 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 && is_dir($app_dir)) + { + if(Prado::getApplication()===null) + { + $app = new PradoShellApplication($app_dir); + $app->run(); + $dir = substr(str_replace(realpath('./'),'',$app_dir),1); + $initialized=true; + PradoCommandLineInterpreter::printGreeting(); + echo '** Loaded PRADO appplication in directory "'.$dir."\".\n"; + } + + return Prado::getApplication(); + } + else + { + PradoCommandLineInterpreter::printGreeting(); + echo '+'.str_repeat('-',77)."+\n"; + echo '** Unable to load PRADO application in directory "'.$directory."\".\n"; + echo '+'.str_repeat('-',77)."+\n"; + } + return false; + } + +} + +/** + * Create a Prado project skeleton, including directories and files. + * + * @author Wei Zhuo + * @version $Id: prado-cli.php 3316 2013-08-20 13:51:25Z ctrlaltca $ + * @since 3.0.5 + */ +class PradoCommandLineCreateProject extends PradoCommandLineAction +{ + protected $action = '-c'; + protected $parameters = array('directory'); + protected $optional = array(); + protected $description = 'Creates a Prado project skeleton for the given .'; + + public function performAction($args) + { + PradoCommandLineInterpreter::printGreeting(); + $this->createNewPradoProject($args[1]); + return true; + } + + /** + * Functions to create new prado project. + */ + protected function createNewPradoProject($dir) + { + if(strlen(trim($dir)) == 0) + return; + + $rootPath = realpath(dirname(trim($dir))); + + if(basename($dir)!=='.') + $basePath = $rootPath.DIRECTORY_SEPARATOR.basename($dir); + else + $basePath = $rootPath; + $appName = basename($basePath); + $assetPath = $basePath.DIRECTORY_SEPARATOR.'assets'; + $protectedPath = $basePath.DIRECTORY_SEPARATOR.'protected'; + $runtimePath = $basePath.DIRECTORY_SEPARATOR.'protected'.DIRECTORY_SEPARATOR.'runtime'; + $pagesPath = $protectedPath.DIRECTORY_SEPARATOR.'pages'; + + $indexFile = $basePath.DIRECTORY_SEPARATOR.'index.php'; + $htaccessFile = $protectedPath.DIRECTORY_SEPARATOR.'.htaccess'; + $configFile = $protectedPath.DIRECTORY_SEPARATOR.'application.xml'; + $defaultPageFile = $pagesPath.DIRECTORY_SEPARATOR.'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($configFile, $this->renderConfigFile($appName)); + $this->createFile($htaccessFile, $this->renderHtaccessFile()); + $this->createFile($defaultPageFile, $this->renderDefaultPage()); + } + + protected function renderIndexFile() + { + $framework = realpath(dirname(dirname(__FILE__))).DIRECTORY_SEPARATOR.'framework'.DIRECTORY_SEPARATOR.'prado.php'; +return 'run(); + +?>'; + } + + protected function renderConfigFile($appName) + { + return << + + + + + + + + + + + + + + + + + + + + +EOD; + } + + protected function renderHtaccessFile() + { + return 'deny from all'; + } + + + protected function renderDefaultPage() + { +return << + + Welcome to PRADO + + +

Welcome to PRADO!

+ + +EOD; + } +} + +/** + * Creates test fixtures for a Prado application. + * + * @author Wei Zhuo + * @version $Id: prado-cli.php 3316 2013-08-20 13:51:25Z ctrlaltca $ + * @since 3.0.5 + */ +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) + { + PradoCommandLineInterpreter::printGreeting(); + $this->createTestFixtures($args[1]); + return true; + } + + protected function createTestFixtures($dir) + { + 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()); + } + + protected function renderUnitTestFixture() + { + $tester = realpath(dirname(dirname(__FILE__))).'/tests/test_tools/unit_tests.php'; +return 'run(new HtmlReporter()); + +?>'; + } + + protected function renderFunctionalTestFixture() + { + $tester = realpath(dirname(dirname(__FILE__))).'/tests/test_tools/functional_tests.php'; +return 'run(new SimpleReporter()); + +?>'; + } + +} + +/** + * Creates and run a Prado application in a PHP Shell. + * + * @author Wei Zhuo + * @version $Id: prado-cli.php 3316 2013-08-20 13:51:25Z ctrlaltca $ + * @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(count($args) > 1) + $app = $this->initializePradoApplication($args[1]); + return true; + } +} + +/** + * Runs unit test cases. + * + * @author Wei Zhuo + * @version $Id: prado-cli.php 3316 2013-08-20 13:51:25Z ctrlaltca $ + * @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) + { + $dir = realpath($args[1]); + if($dir !== false && is_dir($dir)) + $this->runUnitTests($dir,$args); + else + echo '** Unable to find directory "'.$args[1]."\".\n"; + return true; + } + + protected function initializeTestRunner() + { + $TEST_TOOLS = realpath(dirname(dirname(__FILE__))).'/tests/test_tools/'; + + 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'); + } + + protected function runUnitTests($dir, $args) + { + $app_dir = $this->getAppDir($dir); + if($app_dir !== false) + $this->initializePradoApplication($app_dir.'/../'); + + $this->initializeTestRunner(); + $test_dir = $this->getTestDir($dir); + if($test_dir !== false) + { + $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 + { + $running_dir = substr(str_replace(realpath('./'),'',$dir),1); + echo '** Unable to find test directory "'.$running_dir.'/unit" or "'.$running_dir.'/tests/unit".'."\n"; + } + } + + protected function getAppDir($dir) + { + $app_dir = realpath($dir.'/protected'); + if($app_dir !== false && is_dir($app_dir)) + return $app_dir; + return realpath($dir.'/../protected'); + } + + protected function getTestDir($dir) + { + $test_dir = realpath($dir.'/unit'); + if($test_dir !== false && is_dir($test_dir)) + return $test_dir; + return realpath($dir.'/tests/unit/'); + } + + 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)))) + { + 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); + } + + protected function hasMatch($match,$entry) + { + $file = strtolower(substr($entry,0,strrpos($entry,'.'))); + foreach($match as $m) + { + if(strtolower($m) === $file) + { + $this->matches[] = $m; + return true; + } + } + return false; + } +} + +/** + * Create active record skeleton + * + * @author Wei Zhuo + * @version $Id: prado-cli.php 3316 2013-08-20 13:51:25Z ctrlaltca $ + * @since 3.1 + */ +class PradoCommandLineActiveRecordGen extends PradoCommandLineAction +{ + protected $action = 'generate'; + protected $parameters = array('table', 'output'); + protected $optional = array('directory', 'soap'); + protected $description = 'Generate Active Record skeleton for to file using application.xml in [directory]. May also generate [soap] properties.'; + private $_soap=false; + + public function performAction($args) + { + $app_dir = count($args) > 3 ? $this->getAppDir($args[3]) : $this->getAppDir(); + $this->_soap = count($args) > 4; + if($app_dir !== false) + { + $config = $this->getActiveRecordConfig($app_dir); + $output = $this->getOutputFile($app_dir, $args[2]); + if(is_file($output)) + echo "** File $output already exists, skiping. \n"; + else if($config !== false && $output !== false) + $this->generateActiveRecord($config, $args[1], $output); + } + return true; + } + + protected function getAppDir($dir=".") + { + if(is_dir($dir)) + return realpath($dir); + if(false !== ($app_dir = realpath($dir.'/protected/')) && is_dir($app_dir)) + return $app_dir; + echo '** Unable to find directory "'.$dir."\".\n"; + return false; + } + + protected function getXmlFile($app_dir) + { + if(false !== ($xml = realpath($app_dir.'/application.xml')) && is_file($xml)) + return $xml; + if(false !== ($xml = realpath($app_dir.'/protected/application.xml')) && is_file($xml)) + return $xml; + echo '** Unable to find application.xml in '.$app_dir."\n"; + return false; + } + + protected function getActiveRecordConfig($app_dir) + { + if(false === ($xml=$this->getXmlFile($app_dir))) + return false; + if(false !== ($app=$this->initializePradoApplication($app_dir))) + { + Prado::using('System.Data.ActiveRecord.TActiveRecordConfig'); + foreach($app->getModules() as $module) + if($module instanceof TActiveRecordConfig) + return $module; + echo '** Unable to find TActiveRecordConfig module in '.$xml."\n"; + } + return false; + } + + protected function getOutputFile($app_dir, $namespace) + { + if(is_file($namespace) && strpos($namespace, $app_dir)===0) + return $namespace; + $file = Prado::getPathOfNamespace($namespace, ".php"); + if($file !== null && false !== ($path = realpath(dirname($file))) && is_dir($path)) + { + if(strpos($path, $app_dir)===0) + return $file; + } + echo '** Output file '.$file.' must be within directory '.$app_dir."\n"; + return false; + } + + protected function generateActiveRecord($config, $tablename, $output) + { + $manager = TActiveRecordManager::getInstance(); + if($connection = $manager->getDbConnection()) { + $gateway = $manager->getRecordGateway(); + $tableInfo = $gateway->getTableInfo($manager->getDbConnection(), $tablename); + if(count($tableInfo->getColumns()) === 0) + { + echo '** Unable to find table or view "'.$tablename.'" in "'.$manager->getDbConnection()->getConnectionString()."\".\n"; + return false; + } + else + { + $properties = array(); + foreach($tableInfo->getColumns() as $field=>$column) + $properties[] = $this->generateProperty($field,$column); + } + + $classname = basename($output, '.php'); + $class = $this->generateClass($properties, $tablename, $classname); + echo " Writing class $classname to file $output\n"; + file_put_contents($output, $class); + } else { + echo '** Unable to connect to database with ConnectionID=\''.$config->getConnectionID()."'. Please check your settings in application.xml and ensure your database connection is set up first.\n"; + } + } + + protected function generateProperty($field,$column) + { + $prop = ''; + $name = '$'.$field; + $type = $column->getPHPType(); + if($this->_soap) + { + $prop .= << +EOD; + } +} + +/** + * Create active record skeleton for all tables in DB and its relations + * + * @author Matthias Endres + * @author Daniel Sampedro Bello + * @version $Id: prado-cli.php 3316 2013-08-20 13:51:25Z ctrlaltca $ + * @since 3.2 + */ +class PradoCommandLineActiveRecordGenAll extends PradoCommandLineAction { + + protected $action = 'generateAll'; + protected $parameters = array('output'); + protected $optional = array('directory', 'soap', 'overwrite', 'prefix', 'postfix'); + protected $description = "Generate Active Record skeleton for all Tables to file using application.xml in [directory]. May also generate [soap] properties.\nGenerated Classes are named like the Table with optional [Prefix] and/or [Postfix]. [Overwrite] is used to overwrite existing Files."; + private $_soap = false; + private $_prefix = ''; + private $_postfix = ''; + private $_overwrite = false; + + public function performAction($args) { + $app_dir = count($args) > 2 ? $this->getAppDir($args[2]) : $this->getAppDir(); + $this->_soap = count($args) > 3 ? ($args[3] == "soap" || $args[3] == "true" ? true : false) : false; + $this->_overwrite = count($args) > 4 ? ($args[4] == "overwrite" || $args[4] == "true" ? true : false) : false; + $this->_prefix = count($args) > 5 ? $args[5] : ''; + $this->_postfix = count($args) > 6 ? $args[6] : ''; + + if ($app_dir !== false) { + $config = $this->getActiveRecordConfig($app_dir); + + $manager = TActiveRecordManager::getInstance(); + $con = $manager->getDbConnection(); + $con->Active = true; + $command = $con->createCommand("Show Tables"); + $dataReader = $command->query(); + $dataReader->bindColumn(1, $table); + $generator = new PHP_Shell_Extensions_ActiveRecord(); + $tables = array(); + while ($dataReader->read() !== false) { + $tables[] = $table; + } + $con->Active = False; + foreach ($tables as $key => $table) { + $output = $args[1] . "." . $this->_prefix . ucfirst($table) . $this->_postfix; + if ($config !== false && $output !== false) { + $generator->generate("generate " . $table . " " . $output . " " . $this->_soap . " " . $this->_overwrite); + } + } + } + return true; + } + + protected function getAppDir($dir=".") { + if (is_dir($dir)) + return realpath($dir); + if (false !== ($app_dir = realpath($dir . '/protected/')) && is_dir($app_dir)) + return $app_dir; + echo '** Unable to find directory "' . $dir . "\".\n"; + return false; + } + + protected function getXmlFile($app_dir) { + if (false !== ($xml = realpath($app_dir . '/application.xml')) && is_file($xml)) + return $xml; + if (false !== ($xml = realpath($app_dir . '/protected/application.xml')) && is_file($xml)) + return $xml; + echo '** Unable to find application.xml in ' . $app_dir . "\n"; + return false; + } + + protected function getActiveRecordConfig($app_dir) { + if (false === ($xml = $this->getXmlFile($app_dir))) + return false; + if (false !== ($app = $this->initializePradoApplication($app_dir))) { + Prado::using('System.Data.ActiveRecord.TActiveRecordConfig'); + foreach ($app->getModules() as $module) + if ($module instanceof TActiveRecordConfig) + return $module; + echo '** Unable to find TActiveRecordConfig module in ' . $xml . "\n"; + } + return false; + } + + protected function getOutputFile($app_dir, $namespace) { + if (is_file($namespace) && strpos($namespace, $app_dir) === 0) + return $namespace; + $file = Prado::getPathOfNamespace($namespace, ""); + if ($file !== null && false !== ($path = realpath(dirname($file))) && is_dir($path)) { + if (strpos($path, $app_dir) === 0) + return $file; + } + echo '** Output file ' . $file . ' must be within directory ' . $app_dir . "\n"; + return false; + } + +} + +//run PHP shell +if(class_exists('PHP_Shell_Commands', false)) +{ + class PHP_Shell_Extensions_ActiveRecord implements PHP_Shell_Extension { + public function register() + { + + $cmd = PHP_Shell_Commands::getInstance(); + if(Prado::getApplication() !== null) + { + $cmd->registerCommand('#^generate#', $this, 'generate', 'generate
[soap]', + 'Generate Active Record skeleton for
to file using'.PHP_EOL. + ' application.xml in [directory]. May also generate [soap] properties.'); + } + } + + public function generate($l) + { + $input = explode(" ", trim($l)); + if(count($input) > 2) + { + $app_dir = '.'; + if(Prado::getApplication()!==null) + $app_dir = dirname(Prado::getApplication()->getBasePath()); + $args = array($input[0],$input[1], $input[2],$app_dir); + if(count($input)>3) + $args = array($input[0],$input[1], $input[2],$app_dir,'soap'); + $cmd = new PradoCommandLineActiveRecordGen; + $cmd->performAction($args); + } + else + { + echo "\n Usage: generate table_name Application.pages.RecordClassName\n"; + } + } + } + + $__shell_exts = PHP_Shell_Extensions::getInstance(); + $__shell_exts->registerExtensions(array( + "active-record" => new PHP_Shell_Extensions_ActiveRecord)); /* the :set command */ + + include_once(realpath(dirname(dirname(__FILE__))).'/framework/3rdParty/PhpShell/php-shell-cmd.php'); +} -- cgit v1.2.3