2007-03-09 23:15:03 +00:00
< ? php
2007-03-27 05:10:42 +00:00
/* SVN FILE: $Id$ */
/**
2007-05-13 20:17:27 +00:00
* Base class for Shells
2007-03-27 05:10:42 +00:00
*
* Long description for file
*
* PHP versions 4 and 5
*
* CakePHP ( tm ) : Rapid Development Framework < http :// www . cakephp . org />
* Copyright 2005 - 2007 , Cake Software Foundation , Inc .
* 1785 E . Sahara Avenue , Suite 490 - 204
* Las Vegas , Nevada 89104
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice .
*
* @ filesource
* @ copyright Copyright 2005 - 2007 , Cake Software Foundation , Inc .
* @ link http :// www . cakefoundation . org / projects / info / cakephp CakePHP ( tm ) Project
* @ package cake
2007-05-14 01:14:41 +00:00
* @ subpackage cake . cake . console . libs
* @ since CakePHP ( tm ) v 1.2 . 0.5012
2007-03-27 05:10:42 +00:00
* @ version $Revision $
* @ modifiedby $LastChangedBy $
* @ lastmodified $Date $
* @ license http :// www . opensource . org / licenses / mit - license . php The MIT License
*/
2007-05-14 12:23:25 +00:00
require_once CAKE . 'console' . DS . 'error.php' ;
2007-03-09 23:15:03 +00:00
/**
* Base class for command - line utilities for automating programmer chores .
*
* @ package cake
2007-05-13 20:17:27 +00:00
* @ subpackage cake . cake . console . libs
2007-03-09 23:15:03 +00:00
*/
2007-05-12 21:18:07 +00:00
class Shell extends Object {
2007-03-09 23:15:03 +00:00
/**
2007-05-12 21:18:07 +00:00
* ShellDispatcher object
2007-03-09 23:15:03 +00:00
*
2007-05-12 21:18:07 +00:00
* @ var object An instance of the ShellDispatcher object that loaded this script
2007-03-09 23:15:03 +00:00
*/
2007-05-04 19:32:05 +00:00
var $Dispatch = null ;
2007-03-09 23:15:03 +00:00
/**
* If true , the script will ask for permission to perform actions .
*
* @ var boolean
*/
var $interactive = true ;
/**
* Holds the DATABASE_CONFIG object for the app . Null if database . php could not be found ,
* or the app does not exist .
*
* @ var object
*/
var $dbConfig = null ;
/**
* Contains command switches parsed from the command line .
*
* @ var array
*/
var $params = array ();
/**
* Contains arguments parsed from the command line .
*
* @ var array
*/
var $args = array ();
2007-05-13 20:17:27 +00:00
/**
* The file name of the shell that was invoked .
*
* @ var string
*/
var $shell = null ;
/**
* The class name of the shell that was invoked .
*
* @ var string
*/
var $className = null ;
/**
* The command called if public methods are available .
*
* @ var string
*/
var $command = null ;
/**
* The name of the shell in camelized .
*
* @ var string
*/
var $name = null ;
/**
* Contains tasks to load and instantiate
*
* @ var array
*/
var $tasks = array ();
2007-05-13 22:03:03 +00:00
/**
2007-05-14 01:14:41 +00:00
* Contains the loaded tasks
2007-05-13 22:03:03 +00:00
*
* @ var array
*/
2007-05-14 01:14:41 +00:00
var $taskNames = array ();
2007-05-13 20:17:27 +00:00
/**
* Contains models to load and instantiate
*
* @ var array
*/
var $uses = array ();
2007-03-09 23:15:03 +00:00
/**
2007-05-12 21:18:07 +00:00
* Constructs this Shell instance .
2007-03-09 23:15:03 +00:00
*
*/
function __construct ( & $dispatch ) {
2007-05-04 03:49:53 +00:00
$this -> Dispatch = & $dispatch ;
2007-05-13 20:17:27 +00:00
$vars = array ( 'params' , 'args' , 'shell' , 'shellName' => 'name' , 'shellClass' => 'className' , 'shellCommand' => 'command' );
foreach ( $vars as $key => $var ) {
if ( is_string ( $key )){
$this -> { $var } = & $this -> Dispatch -> { $key };
} else {
$this -> { $var } = & $this -> Dispatch -> { $var };
}
2007-05-12 23:40:37 +00:00
}
2007-05-14 12:23:25 +00:00
$name = get_class ( $this );
if ( strpos ( $name , 'Task' ) === false && strpos ( $name , 'task' ) == false ) {
$this -> _loadTasks ();
}
2007-05-04 00:25:04 +00:00
}
/**
2007-05-12 21:18:07 +00:00
* Initializes the Shell
2007-05-04 00:25:04 +00:00
* can be overriden in subclasses
*
2007-05-13 20:49:37 +00:00
* @ return void
2007-05-04 03:49:53 +00:00
*/
2007-05-04 00:25:04 +00:00
function initialize () {
2007-05-13 20:17:27 +00:00
$this -> _loadModels ();
2007-05-13 20:49:37 +00:00
$this -> _welcome ();
}
/**
* Displays a header for the shell
*
* @ return void
*/
function _welcome () {
2007-05-12 19:47:14 +00:00
$this -> hr ();
2007-05-13 20:17:27 +00:00
$this -> out ( 'App : ' . APP_DIR );
2007-05-12 19:47:14 +00:00
$this -> out ( 'Path: ' . ROOT . DS . APP_DIR );
$this -> hr ();
2007-03-09 23:15:03 +00:00
}
2007-05-04 00:25:04 +00:00
/**
* Loads database file and constructs DATABASE_CONFIG class
* makes $this -> dbConfig available to subclasses
*
* @ return bool
*/
2007-05-03 21:14:46 +00:00
function _loadDbConfig () {
if ( config ( 'database' )) {
if ( class_exists ( 'DATABASE_CONFIG' )) {
$this -> dbConfig = new DATABASE_CONFIG ();
return true ;
}
}
2007-05-04 00:25:04 +00:00
$this -> err ( 'Database config could not be loaded' );
2007-05-13 01:36:56 +00:00
$this -> out ( 'Run \'bake\' to create the database configuration' );
2007-05-03 21:14:46 +00:00
return false ;
}
2007-05-04 00:25:04 +00:00
/**
2007-05-13 20:17:27 +00:00
* if var $uses = true
2007-05-04 00:25:04 +00:00
* Loads AppModel file and constructs AppModel class
* makes $this -> AppModel available to subclasses
2007-05-13 20:17:27 +00:00
* if var $uses is an array of models
2007-05-04 00:25:04 +00:00
*
* @ return bool
*/
2007-05-13 20:17:27 +00:00
function _loadModels () {
if ( $this -> uses === null || $this -> uses === false ) {
return ;
}
2007-05-03 21:14:46 +00:00
uses ( 'model' . DS . 'connection_manager' ,
'model' . DS . 'datasources' . DS . 'dbo_source' , 'model' . DS . 'model'
);
2007-05-13 20:17:27 +00:00
if ( $this -> uses === true && loadModel ()) {
2007-05-13 01:36:56 +00:00
$this -> AppModel = & new AppModel ( false , false , false );
2007-05-03 21:14:46 +00:00
return true ;
}
2007-05-13 20:17:27 +00:00
if ( $this -> uses !== true && ! empty ( $this -> uses )) {
$uses = is_array ( $this -> uses ) ? $this -> uses : array ( $this -> uses );
$this -> modelClass = $uses [ 0 ];
foreach ( $uses as $modelClass ) {
$modelKey = Inflector :: underscore ( $modelClass );
if ( ! class_exists ( $modelClass )){
loadModel ( $modelClass );
}
if ( class_exists ( $modelClass )) {
$model =& new $modelClass ();
$this -> modelNames [] = $modelClass ;
$this -> { $modelClass } =& $model ;
ClassRegistry :: addObject ( $modelKey , $model );
} else {
return $this -> cakeError ( 'missingModel' , array ( array ( 'className' => $modelClass )));
}
}
return true ;
}
2007-05-03 21:14:46 +00:00
return false ;
}
2007-05-13 20:17:27 +00:00
/**
* Loads tasks defined in var $tasks
*
* @ return bool
*/
function _loadTasks () {
if ( $this -> tasks === null || $this -> tasks === false ) {
return ;
}
2007-05-03 21:14:46 +00:00
2007-05-13 20:17:27 +00:00
if ( $this -> tasks !== true && ! empty ( $this -> tasks )) {
$tasks = $this -> tasks ;
if ( ! is_array ( $tasks )) {
$tasks = array ( $tasks );
}
$this -> taskClass = $tasks [ 0 ];
2007-05-14 12:23:25 +00:00
2007-05-13 20:17:27 +00:00
foreach ( $tasks as $taskName ) {
$taskKey = Inflector :: underscore ( $taskName );
$loaded = false ;
foreach ( $this -> Dispatch -> shellPaths as $path ) {
$taskPath = $path . 'tasks' . DS . Inflector :: underscore ( $taskName ) . '.php' ;
if ( file_exists ( $taskPath )) {
$loaded = true ;
break ;
}
}
2007-05-14 12:23:25 +00:00
2007-05-13 20:17:27 +00:00
if ( $loaded ) {
$taskClass = Inflector :: camelize ( $taskName . 'Task' );
2007-05-14 12:23:25 +00:00
if ( ! class_exists ( $taskClass )) {
require_once $taskPath ;
}
if ( class_exists ( $taskClass ) && ! isset ( $this -> { $taskName })) {
2007-05-13 20:17:27 +00:00
$task =& new $taskClass ( $this -> Dispatch );
$this -> taskNames [] = $taskName ;
$this -> { $taskName } =& $task ;
ClassRegistry :: addObject ( $taskKey , $task );
2007-05-14 12:23:25 +00:00
}
if ( ! isset ( $this -> { $taskName })) {
2007-05-13 20:17:27 +00:00
$this -> err ( " Task ' " . $taskName . " ' could not be loaded " );
exit ();
}
} else {
$this -> err ( " Task ' " . $taskName . " ' could not be found " );
exit ();
}
}
}
return false ;
}
2007-03-09 23:15:03 +00:00
/**
* Prompts the user for input , and returns it .
*
* @ param string $prompt Prompt text .
* @ param mixed $options Array or string of options .
* @ param string $default Default input value .
* @ return Either the default value , or the user - provided input .
*/
function in ( $prompt , $options = null , $default = null ) {
2007-05-14 12:23:25 +00:00
$in = $this -> Dispatch -> getInput ( $prompt , $options , $default );
if ( $options && is_string ( $options )) {
if ( strpos ( $options , ',' )) {
$options = explode ( ',' , $options );
} else if ( strpos ( $options , '/' )) {
$options = explode ( '/' , $options );
} else {
$options = array ( $options );
}
}
if ( is_array ( $options )) {
while ( $in == '' || ( $in && ( ! in_array ( low ( $in ), $options ) && ! in_array ( up ( $in ), $options )) && ! in_array ( $in , $options ))) {
$in = $this -> Dispatch -> getInput ( $prompt , $options , $default );
}
}
if ( $in ) {
return $in ;
}
2007-03-09 23:15:03 +00:00
}
/**
* Outputs to the stdout filehandle .
*
* @ param string $string String to output .
* @ param boolean $newline If true , the outputs gets an added newline .
*/
function out ( $string , $newline = true ) {
2007-05-04 03:49:53 +00:00
return $this -> Dispatch -> stdout ( $string , $newline );
2007-03-09 23:15:03 +00:00
}
/**
* Outputs to the stderr filehandle .
*
* @ param string $string Error text to output .
*/
function err ( $string ) {
2007-05-04 04:37:25 +00:00
return $this -> Dispatch -> stderr ( $string . " \n " );
2007-03-09 23:15:03 +00:00
}
/**
* Outputs a series of minus characters to the standard output , acts as a visual separator .
*
*/
2007-05-02 18:41:55 +00:00
function hr ( $newline = false ) {
if ( $newline ) {
$this -> out ( " \n " );
}
2007-03-09 23:15:03 +00:00
$this -> out ( '---------------------------------------------------------------' );
2007-05-02 18:41:55 +00:00
if ( $newline ) {
$this -> out ( " \n " );
}
2007-03-09 23:15:03 +00:00
}
2007-05-04 03:49:53 +00:00
/**
* Displays a formatted error message
*
* @ param unknown_type $title
* @ param unknown_type $msg
*/
2007-05-14 12:23:25 +00:00
function error ( $title , $msg ) {
$out .= " $title\n " ;
2007-05-04 03:49:53 +00:00
$out .= " $msg\n " ;
$out .= " \n " ;
2007-05-14 12:23:25 +00:00
$this -> err ( $out );
2007-05-04 03:49:53 +00:00
exit ();
}
/**
* Will check the number args matches otherwise throw an error
*
* @ param unknown_type $expectedNum
* @ param unknown_type $command
*/
2007-05-04 19:32:05 +00:00
function _checkArgs ( $expectedNum , $command = null ) {
2007-05-04 03:49:53 +00:00
if ( ! $command ) {
$command = $this -> command ;
}
if ( count ( $this -> args ) < $expectedNum ) {
2007-05-14 12:23:25 +00:00
$this -> error ( 'Wrong number of parameters: ' . count ( $this -> args ), 'Please type \'cake ' . $this -> shell . ' help\' for help on usage of the ' . $this -> name . ' ' . $command );
2007-05-04 03:49:53 +00:00
}
}
2007-03-09 23:15:03 +00:00
/**
* Creates a file at given path .
*
* @ param string $path Where to put the file .
* @ param string $contents Content to put in the file .
* @ return Success
*/
function createFile ( $path , $contents ) {
$path = str_replace ( DS . DS , DS , $path );
2007-05-14 12:23:25 +00:00
$this -> out ( " \n " . __ ( sprintf ( " Creating file %s " , $path ), true ));
2007-03-09 23:15:03 +00:00
if ( is_file ( $path ) && $this -> interactive === true ) {
2007-05-14 12:23:25 +00:00
$key = $this -> in ( __ ( " File exists, overwrite? " , true ) . " { $path } " , array ( 'y' , 'n' , 'q' ), 'n' );
if ( low ( $key ) == 'q' ) {
2007-05-03 21:14:46 +00:00
$this -> out ( __ ( " Quitting. " , true ) . " \n " );
2007-03-09 23:15:03 +00:00
exit ;
2007-05-14 12:23:25 +00:00
} else if ( low ( $key ) == 'a' ) {
2007-03-09 23:15:03 +00:00
$this -> dont_ask = true ;
2007-05-14 12:23:25 +00:00
} else if ( low ( $key ) != 'y' ) {
2007-05-03 21:14:46 +00:00
$this -> out ( __ ( " Skip " , true ) . " { $path } \n " );
2007-03-09 23:15:03 +00:00
return false ;
}
}
2007-05-14 12:23:25 +00:00
if ( ! class_exists ( 'File' )) {
uses ( 'file' );
}
2007-05-03 23:22:02 +00:00
if ( $File = new File ( $path , true )) {
$File -> write ( $contents );
2007-05-14 12:23:25 +00:00
$this -> out ( __ ( " Wrote " , true ) . " { $path } " );
2007-03-09 23:15:03 +00:00
return true ;
} else {
2007-05-03 21:14:46 +00:00
$this -> err ( __ ( " Error! Could not write to " , true ) . " { $path } . \n " );
2007-03-09 23:15:03 +00:00
return false ;
}
}
/**
2007-05-07 15:30:06 +00:00
* Outputs usage text on the standard output . Implement it in subclasses .
2007-03-09 23:15:03 +00:00
*
*/
function help () {
2007-05-13 20:17:27 +00:00
if ( $this -> command != null ) {
$this -> err ( " Unknown { $this -> name } command ' $this->command '. \n For usage, try 'cake { $this -> shell } help'. \n \n " );
} else {
$this -> Dispatch -> help ();
}
2007-03-09 23:15:03 +00:00
}
/**
2007-05-14 12:23:25 +00:00
* Action to create a Unit Test .
2007-03-09 23:15:03 +00:00
*
2007-05-14 12:23:25 +00:00
* @ return Success
2007-03-09 23:15:03 +00:00
*/
2007-05-14 12:23:25 +00:00
function _checkUnitTest () {
if ( is_dir ( VENDORS . 'simpletest' ) || is_dir ( ROOT . DS . APP_DIR . DS . 'vendors' . DS . 'simpletest' )) {
2007-03-09 23:15:03 +00:00
return true ;
}
2007-05-14 12:23:25 +00:00
$unitTest = $this -> in ( 'Cake test suite not installed. Do you want to bake unit test files anyway?' , array ( 'y' , 'n' ), 'y' );
$result = low ( $unitTest ) == 'y' || low ( $unitTest ) == 'yes' ;
if ( $result ) {
$this -> out ( " \n You can download the Cake test suite from http://cakeforge.org/projects/testsuite/ " , true );
}
return $result ;
2007-03-09 23:15:03 +00:00
}
2007-05-14 12:23:25 +00:00
2007-03-09 23:15:03 +00:00
/**
2007-05-14 12:23:25 +00:00
* creates the proper pluralize controller for the url
2007-03-09 23:15:03 +00:00
*
2007-05-14 12:23:25 +00:00
* @ param string $name
* @ return string $name
2007-03-09 23:15:03 +00:00
*/
2007-05-14 12:23:25 +00:00
function _controllerPath ( $name ) {
return low ( Inflector :: underscore ( $name ));
}
/**
* creates the proper pluralize controller class name .
*
* @ param string $name
* @ return string $name
*/
function _controllerName ( $name ) {
return Inflector :: pluralize ( Inflector :: camelize ( $name ));
}
/**
* creates the proper singular model name .
*
* @ param string $name
* @ return string $name
*/
function _modelName ( $name ) {
return Inflector :: camelize ( Inflector :: singularize ( $name ));
}
/**
* creates the proper singular model key for associations .
*
* @ param string $name
* @ return string $name
*/
function _modelKey ( $name ) {
return Inflector :: underscore ( Inflector :: singularize ( $name )) . '_id' ;
2007-03-09 23:15:03 +00:00
}
2007-05-14 12:23:25 +00:00
/**
* creates the proper model name from a foreign key .
*
* @ param string $key
* @ return string $name
*/
function _modelNameFromKey ( $key ) {
$name = str_replace ( '_id' , '' , $key );
return $this -> _modelName ( $name );
}
/**
* creates the singular name for use in views .
*
* @ param string $name
* @ return string $name
*/
function _singularName ( $name ) {
return Inflector :: variable ( Inflector :: singularize ( $name ));
}
/**
* creates the plural name for views .
*
* @ param string $name
* @ return string $name
*/
function _pluralName ( $name ) {
return Inflector :: variable ( Inflector :: pluralize ( $name ));
}
/**
* creates the singular human name used in views
*
* @ param string $name
* @ return string $name
*/
function _singularHumanName ( $name ) {
return Inflector :: humanize ( Inflector :: underscore ( Inflector :: singularize ( $name )));
}
/**
* creates the plural humna name used in views
*
* @ param string $name
* @ return string $name
*/
function _pluralHumanName ( $name ) {
return Inflector :: humanize ( Inflector :: underscore ( Inflector :: pluralize ( $name )));
}
2007-03-09 23:15:03 +00:00
}
?>