WebAppCommand.php 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. <?php
  2. /**
  3. * WebAppCommand class file.
  4. *
  5. * @author Qiang Xue <qiang.xue@gmail.com>
  6. * @link http://www.yiiframework.com/
  7. * @copyright 2008-2013 Yii Software LLC
  8. * @license http://www.yiiframework.com/license/
  9. */
  10. /**
  11. * WebAppCommand creates an Yii Web application at the specified location.
  12. *
  13. * @author Qiang Xue <qiang.xue@gmail.com>
  14. * @package system.cli.commands
  15. * @since 1.0
  16. */
  17. class WebAppCommand extends CConsoleCommand
  18. {
  19. private $_rootPath;
  20. public function getHelp()
  21. {
  22. return <<<EOD
  23. USAGE
  24. yiic webapp <app-path> [<vcs>]
  25. DESCRIPTION
  26. This command generates an Yii Web Application at the specified location.
  27. PARAMETERS
  28. * app-path: required, the directory where the new application will be created.
  29. If the directory does not exist, it will be created. After the application
  30. is created, please make sure the directory can be accessed by Web users.
  31. * vcs: optional, version control system you're going to use in the new project.
  32. Application generator will create all needed files to the specified VCS
  33. (such as .gitignore, .gitkeep, etc.). Possible values: git, hg. Do not
  34. use this argument if you're going to create VCS files yourself.
  35. EOD;
  36. }
  37. /**
  38. * Execute the action.
  39. * @param array $args command line parameters specific for this command
  40. */
  41. public function run($args)
  42. {
  43. $vcs=false;
  44. if(isset($args[1]))
  45. {
  46. if($args[1]!='git' && $args[1]!='hg')
  47. $this->usageError('Unsupported VCS specified. Currently only git and hg supported.');
  48. $vcs=$args[1];
  49. }
  50. if(!isset($args[0]))
  51. $this->usageError('the Web application location is not specified.');
  52. $path=strtr($args[0],'/\\',DIRECTORY_SEPARATOR);
  53. if(strpos($path,DIRECTORY_SEPARATOR)===false)
  54. $path='.'.DIRECTORY_SEPARATOR.$path;
  55. if(basename($path)=='..')
  56. $path.=DIRECTORY_SEPARATOR.'.';
  57. $dir=rtrim(realpath(dirname($path)),'\\/');
  58. if($dir===false || !is_dir($dir))
  59. $this->usageError("The directory '$path' is not valid. Please make sure the parent directory exists.");
  60. if(basename($path)==='.')
  61. $this->_rootPath=$path=$dir;
  62. else
  63. $this->_rootPath=$path=$dir.DIRECTORY_SEPARATOR.basename($path);
  64. if($this->confirm("Create a Web application under '$path'?"))
  65. {
  66. $sourceDir=$this->getSourceDir();
  67. if($sourceDir===false)
  68. die("\nUnable to locate the source directory.\n");
  69. $ignoreFiles=array();
  70. $renameMap=array();
  71. switch($vcs)
  72. {
  73. case 'git':
  74. $renameMap=array('git-gitignore'=>'.gitignore','git-gitkeep'=>'.gitkeep'); // move with rename git files
  75. $ignoreFiles=array('hg-hgignore','hg-hgkeep'); // ignore only hg files
  76. break;
  77. case 'hg':
  78. $renameMap=array('hg-hgignore'=>'.hgignore','hg-hgkeep'=>'.hgkeep'); // move with rename hg files
  79. $ignoreFiles=array('git-gitignore','git-gitkeep'); // ignore only git files
  80. break;
  81. default:
  82. // no files for renaming
  83. $ignoreFiles=array('git-gitignore','git-gitkeep','hg-hgignore','hg-hgkeep'); // ignore both git and hg files
  84. break;
  85. }
  86. $list=$this->buildFileList($sourceDir,$path,'',$ignoreFiles,$renameMap);
  87. $this->addFileModificationCallbacks($list);
  88. $this->copyFiles($list);
  89. $this->setPermissions($path);
  90. echo "\nYour application has been created successfully under {$path}.\n";
  91. }
  92. }
  93. /**
  94. * Adjusts created application file and directory permissions
  95. *
  96. * @param string $targetDir path to created application
  97. */
  98. protected function setPermissions($targetDir)
  99. {
  100. @chmod($targetDir.'/assets',0777);
  101. @chmod($targetDir.'/protected/runtime',0777);
  102. @chmod($targetDir.'/protected/data',0777);
  103. @chmod($targetDir.'/protected/data/testdrive.db',0777);
  104. @chmod($targetDir.'/protected/yiic',0755);
  105. }
  106. /**
  107. * @return string path to application bootstrap source files
  108. */
  109. protected function getSourceDir()
  110. {
  111. return realpath(dirname(__FILE__).'/../views/webapp');
  112. }
  113. /**
  114. * Adds callbacks that will modify source files
  115. *
  116. * @param array $fileList
  117. */
  118. protected function addFileModificationCallbacks(&$fileList)
  119. {
  120. $fileList['index.php']['callback']=array($this,'generateIndex');
  121. $fileList['index-test.php']['callback']=array($this,'generateIndex');
  122. $fileList['protected/tests/bootstrap.php']['callback']=array($this,'generateTestBoostrap');
  123. $fileList['protected/yiic.php']['callback']=array($this,'generateYiic');
  124. }
  125. /**
  126. * Inserts path to framework's yii.php into application's index.php
  127. *
  128. * @param string $source source file path
  129. * @param array $params
  130. * @return string modified source file content
  131. */
  132. public function generateIndex($source,$params)
  133. {
  134. $content=file_get_contents($source);
  135. $yii=realpath(dirname(__FILE__).'/../../yii.php');
  136. $yii=$this->getRelativePath($yii,$this->_rootPath.DIRECTORY_SEPARATOR.'index.php');
  137. $yii=str_replace('\\','\\\\',$yii);
  138. return preg_replace('/\$yii\s*=(.*?);/',"\$yii=$yii;",$content);
  139. }
  140. /**
  141. * Inserts path to framework's yiit.php into application's index-test.php
  142. *
  143. * @param string $source source file path
  144. * @param array $params
  145. * @return string modified source file content
  146. */
  147. public function generateTestBoostrap($source,$params)
  148. {
  149. $content=file_get_contents($source);
  150. $yii=realpath(dirname(__FILE__).'/../../yiit.php');
  151. $yii=$this->getRelativePath($yii,$this->_rootPath.DIRECTORY_SEPARATOR.'protected'.DIRECTORY_SEPARATOR.'tests'.DIRECTORY_SEPARATOR.'bootstrap.php');
  152. $yii=str_replace('\\','\\\\',$yii);
  153. return preg_replace('/\$yiit\s*=(.*?);/',"\$yiit=$yii;",$content);
  154. }
  155. /**
  156. * Inserts path to framework's yiic.php into application's yiic.php
  157. *
  158. * @param string $source source file path
  159. * @param array $params
  160. * @return string modified source file content
  161. */
  162. public function generateYiic($source,$params)
  163. {
  164. $content=file_get_contents($source);
  165. $yiic=realpath(dirname(__FILE__).'/../../yiic.php');
  166. $yiic=$this->getRelativePath($yiic,$this->_rootPath.DIRECTORY_SEPARATOR.'protected'.DIRECTORY_SEPARATOR.'yiic.php');
  167. $yiic=str_replace('\\','\\\\',$yiic);
  168. return preg_replace('/\$yiic\s*=(.*?);/',"\$yiic=$yiic;",$content);
  169. }
  170. /**
  171. * Returns variant of $path1 relative to $path2
  172. *
  173. * @param string $path1
  174. * @param string $path2
  175. * @return string $path1 relative to $path2
  176. */
  177. protected function getRelativePath($path1,$path2)
  178. {
  179. $segs1=explode(DIRECTORY_SEPARATOR,$path1);
  180. $segs2=explode(DIRECTORY_SEPARATOR,$path2);
  181. $n1=count($segs1);
  182. $n2=count($segs2);
  183. for($i=0;$i<$n1 && $i<$n2;++$i)
  184. {
  185. if($segs1[$i]!==$segs2[$i])
  186. break;
  187. }
  188. if($i===0)
  189. return "'".$path1."'";
  190. $up='';
  191. for($j=$i;$j<$n2-1;++$j)
  192. $up.='/..';
  193. for(;$i<$n1-1;++$i)
  194. $up.='/'.$segs1[$i];
  195. return 'dirname(__FILE__).\''.$up.'/'.basename($path1).'\'';
  196. }
  197. }