2008-05-30 11:40:08 +00:00
< ? php
/**
* The Project Task handles creating the base application
*
*
* PHP versions 4 and 5
*
2008-10-30 17:30:26 +00:00
* CakePHP ( tm ) : Rapid Development Framework ( http :// www . cakephp . org )
2009-06-17 03:05:48 +00:00
* Copyright 2005 - 2009 , Cake Software Foundation , Inc . ( http :// www . cakefoundation . org )
2008-05-30 11:40:08 +00:00
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice .
*
* @ filesource
2009-06-17 03:05:48 +00:00
* @ copyright Copyright 2005 - 2009 , Cake Software Foundation , Inc . ( http :// www . cakefoundation . org )
2008-10-30 17:30:26 +00:00
* @ link http :// www . cakefoundation . org / projects / info / cakephp CakePHP ( tm ) Project
* @ package cake
2009-06-17 03:05:48 +00:00
* @ subpackage cake . cake . console . bake
2008-10-30 17:30:26 +00:00
* @ since CakePHP ( tm ) v 1.2
* @ license http :// www . opensource . org / licenses / mit - license . php The MIT License
2008-05-30 11:40:08 +00:00
*/
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Task class for creating new project apps and plugins
*
2008-10-30 17:30:26 +00:00
* @ package cake
* @ subpackage cake . cake . console . libs . tasks
2008-05-30 11:40:08 +00:00
*/
class ProjectTask extends Shell {
2009-07-24 19:18:37 +00:00
2009-07-01 00:44:09 +00:00
/**
* configs path ( used in testing ) .
*
* @ var string
**/
var $configPath = null ;
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Checks that given project path does not already exist , and
* finds the app directory in it . Then it calls bake () with that information .
*
* @ param string $project Project path
* @ access public
*/
function execute ( $project = null ) {
if ( $project === null ) {
if ( isset ( $this -> args [ 0 ])) {
$project = $this -> args [ 0 ];
$this -> Dispatch -> shiftArgs ();
}
}
if ( $project ) {
$this -> Dispatch -> parseParams ( array ( '-app' , $project ));
$project = $this -> params [ 'working' ];
}
if ( empty ( $this -> params [ 'skel' ])) {
$this -> params [ 'skel' ] = '' ;
2009-07-26 05:52:05 +00:00
if ( is_dir ( CAKE_CORE_INCLUDE_PATH . DS . CAKE . 'console' . DS . 'templates' . DS . 'skel' ) === true ) {
$this -> params [ 'skel' ] = CAKE_CORE_INCLUDE_PATH . DS . CAKE . 'console' . DS . 'templates' . DS . 'skel' ;
2008-05-30 11:40:08 +00:00
}
}
while ( ! $project ) {
$project = $this -> in ( " What is the full path for this app including the app directory name? \n Example: " . $this -> params [ 'working' ] . DS . " myapp " , null , $this -> params [ 'working' ] . DS . 'myapp' );
}
if ( $project ) {
$response = false ;
while ( $response == false && is_dir ( $project ) === true && file_exists ( $project . 'config' . 'core.php' )) {
2009-06-30 22:30:39 +00:00
$response = $this -> in ( 'A project already exists in this location: ' . $project . ' Overwrite?' , array ( 'y' , 'n' ), 'n' );
2008-05-30 11:40:08 +00:00
if ( strtolower ( $response ) === 'n' ) {
$response = $project = false ;
}
}
}
2008-10-23 00:10:44 +00:00
if ( $this -> bake ( $project )) {
2008-05-30 11:40:08 +00:00
$path = Folder :: slashTerm ( $project );
if ( $this -> createHome ( $path )) {
$this -> out ( __ ( 'Welcome page created' , true ));
} else {
$this -> out ( __ ( 'The Welcome page was NOT created' , true ));
}
if ( $this -> securitySalt ( $path ) === true ) {
$this -> out ( __ ( 'Random hash key created for \'Security.salt\'' , true ));
} else {
$this -> err ( sprintf ( __ ( 'Unable to generate random hash for \'Security.salt\', you should change it in %s' , true ), CONFIGS . 'core.php' ));
}
$corePath = $this -> corePath ( $path );
if ( $corePath === true ) {
$this -> out ( sprintf ( __ ( 'CAKE_CORE_INCLUDE_PATH set to %s in webroot/index.php' , true ), CAKE_CORE_INCLUDE_PATH ));
$this -> out ( sprintf ( __ ( 'CAKE_CORE_INCLUDE_PATH set to %s in webroot/test.php' , true ), CAKE_CORE_INCLUDE_PATH ));
$this -> out ( __ ( 'Remember to check these value after moving to production server' , true ));
} elseif ( $corePath === false ) {
$this -> err ( sprintf ( __ ( 'Unable to set CAKE_CORE_INCLUDE_PATH, you should change it in %s' , true ), $path . 'webroot' . DS . 'index.php' ));
}
$Folder = new Folder ( $path );
if ( ! $Folder -> chmod ( $path . 'tmp' , 0777 )) {
$this -> err ( sprintf ( __ ( 'Could not set permissions on %s' , true ), $path . DS . 'tmp' ));
$this -> out ( sprintf ( __ ( 'chmod -R 0777 %s' , true ), $path . DS . 'tmp' ));
}
2008-08-25 18:52:50 +00:00
$this -> params [ 'working' ] = $path ;
$this -> params [ 'app' ] = basename ( $path );
2008-05-30 11:40:08 +00:00
return true ;
}
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Looks for a skeleton template of a Cake application ,
* and if not found asks the user for a path . When there is a path
* this method will make a deep copy of the skeleton to the project directory .
* A default home page will be added , and the tmp file storage will be chmod ' ed to 0777.
*
* @ param string $path Project path
* @ param string $skel Path to copy from
* @ param string $skip array of directories to skip when copying
* @ access private
*/
function bake ( $path , $skel = null , $skip = array ( 'empty' )) {
2008-10-23 00:10:44 +00:00
if ( ! $skel ) {
2008-05-30 11:40:08 +00:00
$skel = $this -> params [ 'skel' ];
}
while ( ! $skel ) {
$skel = $this -> in ( sprintf ( __ ( " What is the path to the directory layout you wish to copy? \n Example: %s " ), APP , null , ROOT . DS . 'myapp' . DS ));
if ( $skel == '' ) {
$this -> out ( __ ( 'The directory path you supplied was empty. Please try again.' , true ));
} else {
while ( is_dir ( $skel ) === false ) {
$skel = $this -> in ( __ ( 'Directory path does not exist please choose another:' , true ));
}
}
}
$app = basename ( $path );
$this -> out ( 'Bake Project' );
$this -> out ( " Skel Directory: $skel " );
$this -> out ( " Will be copied to: { $path } " );
$this -> hr ();
$looksGood = $this -> in ( 'Look okay?' , array ( 'y' , 'n' , 'q' ), 'y' );
2009-06-17 03:05:48 +00:00
if ( strtolower ( $looksGood ) == 'y' ) {
2008-05-30 11:40:08 +00:00
$verbose = $this -> in ( __ ( 'Do you want verbose output?' , true ), array ( 'y' , 'n' ), 'n' );
$Folder = new Folder ( $skel );
if ( $Folder -> copy ( array ( 'to' => $path , 'skip' => $skip ))) {
$this -> hr ();
$this -> out ( sprintf ( __ ( " Created: %s in %s " , true ), $app , $path ));
$this -> hr ();
} else {
2009-07-28 20:01:42 +00:00
$this -> err ( " ' " . $app . " ' could not be created properly " );
2008-05-30 11:40:08 +00:00
return false ;
}
2009-06-17 03:05:48 +00:00
if ( strtolower ( $verbose ) == 'y' ) {
2008-05-30 11:40:08 +00:00
foreach ( $Folder -> messages () as $message ) {
$this -> out ( $message );
}
}
return true ;
2009-06-17 03:05:48 +00:00
} elseif ( strtolower ( $looksGood ) == 'q' ) {
2008-05-30 11:40:08 +00:00
$this -> out ( 'Bake Aborted.' );
} else {
$this -> execute ( false );
return false ;
}
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Writes a file with a default home page to the project .
*
* @ param string $dir Path to project
* @ return boolean Success
* @ access public
*/
function createHome ( $dir ) {
$app = basename ( $dir );
$path = $dir . 'views' . DS . 'pages' . DS ;
2009-07-26 05:52:05 +00:00
$source = CAKE_CORE_INCLUDE_PATH . DS . CAKE . 'console' . DS . 'templates' . DS . 'default' . DS . 'views' . DS . 'home.ctp' ;
include ( $source );
2008-05-30 11:40:08 +00:00
return $this -> createFile ( $path . 'home.ctp' , $output );
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Generates and writes 'Security.salt'
*
* @ param string $path Project path
* @ return boolean Success
* @ access public
*/
function securitySalt ( $path ) {
$File =& new File ( $path . 'config' . DS . 'core.php' );
$contents = $File -> read ();
if ( preg_match ( '/([\\t\\x20]*Configure::write\\(\\\'Security.salt\\\',[\\t\\x20\'A-z0-9]*\\);)/' , $contents , $match )) {
2008-06-11 15:46:31 +00:00
if ( ! class_exists ( 'Security' )) {
2009-07-23 20:53:37 +00:00
require LIBS . 'security.php' ;
2008-06-11 15:46:31 +00:00
}
2008-05-30 11:40:08 +00:00
$string = Security :: generateAuthKey ();
$result = str_replace ( $match [ 0 ], " \t " . 'Configure::write(\'Security.salt\', \'' . $string . '\');' , $contents );
if ( $File -> write ( $result )) {
return true ;
}
return false ;
}
2008-09-08 20:33:48 +00:00
return false ;
2008-05-30 11:40:08 +00:00
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Generates and writes CAKE_CORE_INCLUDE_PATH
*
* @ param string $path Project path
* @ return boolean Success
* @ access public
*/
function corePath ( $path ) {
if ( dirname ( $path ) !== CAKE_CORE_INCLUDE_PATH ) {
$File =& new File ( $path . 'webroot' . DS . 'index.php' );
$contents = $File -> read ();
if ( preg_match ( '/([\\t\\x20]*define\\(\\\'CAKE_CORE_INCLUDE_PATH\\\',[\\t\\x20\'A-z0-9]*\\);)/' , $contents , $match )) {
2009-07-28 20:01:42 +00:00
$result = str_replace ( $match [ 0 ], " \t \t define('CAKE_CORE_INCLUDE_PATH', ' " . CAKE_CORE_INCLUDE_PATH . " '); " , $contents );
2008-05-30 11:40:08 +00:00
if ( ! $File -> write ( $result )) {
return false ;
}
} else {
return false ;
}
$File =& new File ( $path . 'webroot' . DS . 'test.php' );
$contents = $File -> read ();
if ( preg_match ( '/([\\t\\x20]*define\\(\\\'CAKE_CORE_INCLUDE_PATH\\\',[\\t\\x20\'A-z0-9]*\\);)/' , $contents , $match )) {
2009-07-28 20:01:42 +00:00
$result = str_replace ( $match [ 0 ], " \t \t define('CAKE_CORE_INCLUDE_PATH', ' " . CAKE_CORE_INCLUDE_PATH . " '); " , $contents );
2008-05-30 11:40:08 +00:00
if ( ! $File -> write ( $result )) {
return false ;
}
} else {
return false ;
}
return true ;
}
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Enables Configure :: read ( 'Routing.admin' ) in / app / config / core . php
*
* @ param string $name Name to use as admin routing
* @ return boolean Success
* @ access public
*/
function cakeAdmin ( $name ) {
2009-07-01 00:44:09 +00:00
$path = ( empty ( $this -> configPath )) ? CONFIGS : $this -> configPath ;
$File =& new File ( $path . 'core.php' );
2008-05-30 11:40:08 +00:00
$contents = $File -> read ();
if ( preg_match ( '%([/\\t\\x20]*Configure::write\(\'Routing.admin\',[\\t\\x20\'a-z]*\\);)%' , $contents , $match )) {
$result = str_replace ( $match [ 0 ], " \t " . 'Configure::write(\'Routing.admin\', \'' . $name . '\');' , $contents );
if ( $File -> write ( $result )) {
Configure :: write ( 'Routing.admin' , $name );
return true ;
} else {
return false ;
}
} else {
return false ;
}
}
2009-07-24 19:18:37 +00:00
2009-07-01 00:44:09 +00:00
/**
* Checks for Configure :: read ( 'Routing.admin' ) and forces user to input it if not enabled
*
* @ return string Admin route to use
* @ access public
*/
function getAdmin () {
$admin = '' ;
$cakeAdmin = null ;
$adminRoute = Configure :: read ( 'Routing.admin' );
if ( ! empty ( $adminRoute )) {
return $adminRoute . '_' ;
}
$this -> out ( 'You need to enable Configure::write(\'Routing.admin\',\'admin\') in /app/config/core.php to use admin routing.' );
$this -> out ( 'What would you like the admin route to be?' );
$this -> out ( 'Example: www.example.com/admin/controller' );
while ( $admin == '' ) {
$admin = $this -> in ( " What would you like the admin route to be? " , null , 'admin' );
}
if ( $this -> cakeAdmin ( $admin ) !== true ) {
$this -> out ( 'Unable to write to /app/config/core.php.' );
$this -> out ( 'You need to enable Configure::write(\'Routing.admin\',\'admin\') in /app/config/core.php to use admin routing.' );
$this -> _stop ();
}
return $admin . '_' ;
}
2009-07-24 19:18:37 +00:00
2008-05-30 11:40:08 +00:00
/**
* Help
*
* @ return void
* @ access public
*/
function help () {
$this -> hr ();
$this -> out ( " Usage: cake bake project <arg1> " );
$this -> hr ();
$this -> out ( 'Commands:' );
2009-05-30 04:55:44 +00:00
$this -> out ( '' );
$this -> out ( " project <name> " );
$this -> out ( " \t bakes app directory structure. " );
$this -> out ( " \t if <name> begins with '/' path is absolute. " );
2008-05-30 11:40:08 +00:00
$this -> out ( " " );
2008-06-04 19:04:58 +00:00
$this -> _stop ();
2008-05-30 11:40:08 +00:00
}
}
?>