diff --git a/framework/console/controllers/CreateController.php b/framework/console/controllers/CreateController.php index 72f0611..df11ab5 100644 --- a/framework/console/controllers/CreateController.php +++ b/framework/console/controllers/CreateController.php @@ -11,6 +11,7 @@ namespace yii\console\controllers; use yii\console\Controller; +use yii\util\FileHelper; /** * This command creates an Yii Web application at the specified location. @@ -20,6 +21,8 @@ use yii\console\Controller; */ class CreateController extends Controller { + const EXIT_UNABLE_TO_LOCATE_SOURCE = 1; + private $_rootPath; /** @@ -34,83 +37,119 @@ class CreateController extends Controller */ public function actionIndex($path, $type = 'default') { - $path=strtr($path,'/\\',DIRECTORY_SEPARATOR); - if(strpos($path,DIRECTORY_SEPARATOR)===false) - $path='.'.DIRECTORY_SEPARATOR.$path; - $dir=rtrim(realpath(dirname($path)),'\\/'); - if($dir===false || !is_dir($dir)) + $path = strtr($path, '/\\', DIRECTORY_SEPARATOR); + if(strpos($path, DIRECTORY_SEPARATOR) === false) { + $path = '.'.DIRECTORY_SEPARATOR.$path; + } + $dir = rtrim(realpath(dirname($path)), '\\/'); + if($dir === false || !is_dir($dir)) { $this->usageError("The directory '$path' is not valid. Please make sure the parent directory exists."); - if(basename($path)==='.') - $this->_rootPath=$path=$dir; - else - $this->_rootPath=$path=$dir.DIRECTORY_SEPARATOR.basename($path); - if($this->confirm("Create \"$type\" application under '$path'?")) - { - $sourceDir=realpath(__DIR__.'/../create/'.$type); - if($sourceDir===false) - die("\nUnable to locate the source directory for \"$type\".\n"); - $list=$this->buildFileList($sourceDir,$path); - $list['index.php']['callback']=array($this,'generateIndex'); - $list['index-test.php']['callback']=array($this,'generateIndex'); - $list['protected/tests/bootstrap.php']['callback']=array($this,'generateTestBoostrap'); - $list['protected/yiic.php']['callback']=array($this,'generateYiic'); - $this->copyFiles($list); - @chmod($path.'/assets',0777); - @chmod($path.'/protected/runtime',0777); - @chmod($path.'/protected/data',0777); - @chmod($path.'/protected/data/testdrive.db',0777); - @chmod($path.'/protected/yiic',0755); + } + if(basename($path) === '.') { + $this->_rootPath = $path = $dir; + } + else { + $this->_rootPath = $path = $dir.DIRECTORY_SEPARATOR.basename($path); + } + if($this->confirm("Create \"$type\" application under '$path'?")) { + $sourceDir = realpath(__DIR__.'/../create/'.$type); + if($sourceDir === false) { + echo "\nUnable to locate the source directory for \"$type\".\n"; + return self::EXIT_UNABLE_TO_LOCATE_SOURCE; + } + $list = FileHelper::buildFileList($sourceDir, $path); + $list['index.php']['callback'] = array($this, 'generateIndex'); + $list['index-test.php']['callback'] = array($this, 'generateIndex'); + $list['protected/tests/bootstrap.php']['callback'] = array($this, 'generateTestBoostrap'); + $list['protected/yiic.php']['callback'] = array($this, 'generateYiic'); + FileHelper::copyFiles($list); + //@chmod($path.'/assets', 0777); + //@chmod($path.'/protected/runtime', 0777); + //@chmod($path.'/protected/yiic', 0755); echo "\nYour application has been created successfully under {$path}.\n"; } } - public function generateIndex($source,$params) + /** + * Generates index.php file contents + * + * @param string $source path to index.php template + * @param array $params + * + * @return string final index.php file contents + */ + public function generateIndex($source, $params) { - $content=file_get_contents($source); - $yii=realpath(dirname(__FILE__).'/../../yii.php'); - $yii=$this->getRelativePath($yii,$this->_rootPath.DIRECTORY_SEPARATOR.'index.php'); - $yii=str_replace('\\','\\\\',$yii); - return preg_replace('/\$yii\s*=(.*?);/',"\$yii=$yii;",$content); + $content = file_get_contents($source); + $yii = realpath(dirname(__FILE__).'/../../yii.php'); + $yii = $this->getRelativePath($yii, $this->_rootPath.DIRECTORY_SEPARATOR.'index.php'); + $yii = str_replace('\\', '\\\\', $yii); + return preg_replace('/\$yii\s*=(.*?);/', "\$yii=$yii;", $content); } - public function generateTestBoostrap($source,$params) + /** + * Generates index-test.php file contents + * + * @param string $source path to index-test.php template + * @param array $params + * + * @return string final index-test.php file contents + */ + public function generateTestBoostrap($source, $params) { - $content=file_get_contents($source); - $yii=realpath(dirname(__FILE__).'/../../yiit.php'); - $yii=$this->getRelativePath($yii,$this->_rootPath.DIRECTORY_SEPARATOR.'protected'.DIRECTORY_SEPARATOR.'tests'.DIRECTORY_SEPARATOR.'bootstrap.php'); - $yii=str_replace('\\','\\\\',$yii); - return preg_replace('/\$yiit\s*=(.*?);/',"\$yiit=$yii;",$content); + $content = file_get_contents($source); + $yii = realpath(dirname(__FILE__).'/../../yiit.php'); + $yii = $this->getRelativePath($yii, $this->_rootPath.DIRECTORY_SEPARATOR.'protected'.DIRECTORY_SEPARATOR.'tests'.DIRECTORY_SEPARATOR.'bootstrap.php'); + $yii = str_replace('\\', '\\\\', $yii); + return preg_replace('/\$yiit\s*=(.*?);/', "\$yiit=$yii;", $content); } - public function generateYiic($source,$params) + /** + * Generates yiic.php file contents + * + * @param string $source path to yiic.php template + * @param array $params + * + * @return string final yiic.php file contents + */ + public function generateYiic($source, $params) { - $content=file_get_contents($source); - $yiic=realpath(dirname(__FILE__).'/../../yiic.php'); - $yiic=$this->getRelativePath($yiic,$this->_rootPath.DIRECTORY_SEPARATOR.'protected'.DIRECTORY_SEPARATOR.'yiic.php'); - $yiic=str_replace('\\','\\\\',$yiic); - return preg_replace('/\$yiic\s*=(.*?);/',"\$yiic=$yiic;",$content); + $content = file_get_contents($source); + $yiic = realpath(dirname(__FILE__).'/../../yiic.php'); + $yiic = $this->getRelativePath($yiic, $this->_rootPath.DIRECTORY_SEPARATOR.'protected'.DIRECTORY_SEPARATOR.'yiic.php'); + $yiic = str_replace('\\', '\\\\', $yiic); + return preg_replace('/\$yiic\s*=(.*?);/', "\$yiic=$yiic;", $content); } - protected function getRelativePath($path1,$path2) + /** + * @param string $path1 abosolute path + * @param string $path2 abosolute path + * + * @return string relative path + */ + protected function getRelativePath($path1, $path2) { - $segs1=explode(DIRECTORY_SEPARATOR,$path1); - $segs2=explode(DIRECTORY_SEPARATOR,$path2); - $n1=count($segs1); - $n2=count($segs2); + $segs1 = explode(DIRECTORY_SEPARATOR, $path1); + $segs2 = explode(DIRECTORY_SEPARATOR, $path2); + $n1 = count($segs1); + $n2 = count($segs2); - for($i=0;$i<$n1 && $i<$n2;++$i) - { - if($segs1[$i]!==$segs2[$i]) + for($i=0; $i<$n1 && $i<$n2; ++$i) { + if($segs1[$i] !== $segs2[$i]) { break; + } } - if($i===0) + if($i===0) { return "'".$path1."'"; + } $up=''; - for($j=$i;$j<$n2-1;++$j) + for($j=$i;$j<$n2-1;++$j) { $up.='/..'; - for(;$i<$n1-1;++$i) + } + for(; $i<$n1-1; ++$i) { $up.='/'.$segs1[$i]; + } return 'dirname(__FILE__).\''.$up.'/'.basename($path1).'\''; } diff --git a/framework/console/create/default/index-test.php b/framework/console/create/default/index-test.php new file mode 100644 index 0000000..a814366 --- /dev/null +++ b/framework/console/create/default/index-test.php @@ -0,0 +1 @@ +spec). + * The array keys are names displayed during the copy process, and array values are specifications + * for files to be copied. Each array value must be an array of the following structure: + * + * @see buildFileList + */ + public static function copyFiles($fileList) + { + $overwriteAll = false; + foreach($fileList as $name=>$file) { + $source = strtr($file['source'], '/\\', DIRECTORY_SEPARATOR); + $target = strtr($file['target'], '/\\', DIRECTORY_SEPARATOR); + $callback = isset($file['callback']) ? $file['callback'] : null; + $params = isset($file['params']) ? $file['params'] : null; + + if(is_dir($source)) { + try { + self::ensureDirectory($target); + } + catch (Exception $e) { + mkdir($target, true, 0777); + } + continue; + } + + if($callback !== null) { + $content = call_user_func($callback, $source, $params); + } + else { + $content = file_get_contents($source); + } + if(is_file($target)) { + if($content === file_get_contents($target)) { + echo " unchanged $name\n"; + continue; + } + if($overwriteAll) { + echo " overwrite $name\n"; + } + else { + echo " exist $name\n"; + echo " ...overwrite? [Yes|No|All|Quit] "; + $answer = trim(fgets(STDIN)); + if(!strncasecmp($answer, 'q', 1)) { + return; + } + elseif(!strncasecmp($answer, 'y', 1)) { + echo " overwrite $name\n"; + } + elseif(!strncasecmp($answer, 'a', 1)) { + echo " overwrite $name\n"; + $overwriteAll = true; + } + else { + echo " skip $name\n"; + continue; + } + } + } + else { + try { + self::ensureDirectory(dirname($target)); + } + catch (Exception $e) { + mkdir(dirname($target), true, 0777); + } + echo " generate $name\n"; + } + file_put_contents($target, $content); + } + } + + /** + * Builds the file list of a directory. + * This method traverses through the specified directory and builds + * a list of files and subdirectories that the directory contains. + * The result of this function can be passed to {@link copyFiles}. + * @param string $sourceDir the source directory + * @param string $targetDir the target directory + * @param string $baseDir base directory + * @param array $ignoreFiles list of the names of files that should + * be ignored in list building process. Argument available since 1.1.11. + * @param array $renameMap hash array of file names that should be + * renamed. Example value: array('1.old.txt'=>'2.new.txt'). + * @return array the file list (see {@link copyFiles}) + */ + public static function buildFileList($sourceDir, $targetDir, $baseDir='', $ignoreFiles=array(), $renameMap=array()) + { + $list = array(); + $handle = opendir($sourceDir); + while(($file = readdir($handle)) !== false) { + if(in_array($file, array('.', '..', '.svn', '.gitignore')) || in_array($file, $ignoreFiles)) { + continue; + } + $sourcePath = $sourceDir.DIRECTORY_SEPARATOR.$file; + $targetPath = $targetDir.DIRECTORY_SEPARATOR.strtr($file, $renameMap); + $name = $baseDir === '' ? $file : $baseDir.'/'.$file; + $list[$name] = array( + 'source' => $sourcePath, + 'target' => $targetPath, + ); + if(is_dir($sourcePath)) { + $list = array_merge($list, self::buildFileList($sourcePath, $targetPath, $name, $ignoreFiles, $renameMap)); + } + } + closedir($handle); + return $list; + } +} \ No newline at end of file diff --git a/framework/yiic.php b/framework/yiic.php index 9b38690..9e087ba 100644 --- a/framework/yiic.php +++ b/framework/yiic.php @@ -1,4 +1,5 @@