CreateController.php 5.07 KB
Newer Older
Qiang Xue committed
1 2
<?php
/**
Alexander Makarov committed
3
 * CreateController class file.
Qiang Xue committed
4 5
 *
 * @link http://www.yiiframework.com/
Qiang Xue committed
6
 * @copyright Copyright &copy; 2008 Yii Software LLC
Qiang Xue committed
7 8 9
 * @license http://www.yiiframework.com/license/
 */

10 11 12
namespace yii\console\controllers;

use yii\console\Controller;
13
use yii\util\FileHelper;
14
use yii\base\Exception;
15

Qiang Xue committed
16
/**
17
 * This command creates an Yii Web application at the specified location.
Qiang Xue committed
18 19
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
20
 * @author Alexander Makarov <sam@rmcreative.ru>
21
 * @since 2.0
Qiang Xue committed
22
 */
Alexander Makarov committed
23
class CreateController extends Controller
Qiang Xue committed
24 25
{
	private $_rootPath;
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
	private $_config;

	/**
	 * @var string custom template path. If specified, templates will be
	 * searched there additionally to `framework/console/create`.
	 */
	public $templatesPath;

	/**
	 * @var string application type. If not specified default application
	 * skeleton will be used.
	 */
	public $type = 'default';

	public function init()
	{
		parent::init();

		if($this->templatesPath && !is_dir($this->templatesPath)) {
			throw new Exception('--templatesPath "'.$this->templatesPath.'" does not exist or can not be read.');
		}
	}
Qiang Xue committed
48 49

	/**
50 51
	 * Generates Yii application at the path specified via appPath parameter.
	 *
Alexander Makarov committed
52
	 * @param string $path the directory where the new application will be created.
53 54
	 * If the directory does not exist, it will be created. After the application
	 * is created, please make sure the directory has enough permissions.
55 56
	 *
	 * @throws \yii\base\Exception if path specified is not valid
57
	 * @return integer the exit status
Qiang Xue committed
58
	 */
59
	public function actionIndex($path)
Qiang Xue committed
60
	{
61 62 63 64 65 66
		$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)) {
67
			throw new Exception("The directory '$path' is not valid. Please make sure the parent directory exists.");
68
		}
69

70 71 72 73 74 75
		if(basename($path) === '.') {
			$this->_rootPath = $path = $dir;
		}
		else {
			$this->_rootPath = $path = $dir.DIRECTORY_SEPARATOR.basename($path);
		}
76 77 78 79 80

		if($this->confirm("Create \"$this->type\" application under '$path'?")) {
			$sourceDir = $this->getSourceDir();
			$config = $this->getConfig();

81
			$list = FileHelper::buildFileList($sourceDir, $path);
82 83 84 85 86 87 88 89 90

			if(is_array($config)) {
				foreach($config as $file => $settings) {
					if(isset($settings['handler'])) {
						$list[$file]['callback'] = $settings['handler'];
					}
				}
			}

91
			FileHelper::copyFiles($list);
92 93 94 95 96 97 98 99 100

			if(is_array($config)) {
				foreach($config as $file => $settings) {
					if(isset($settings['permissions'])) {
						@chmod($path.'/'.$file, $settings['permissions']);
					}
				}
			}

Qiang Xue committed
101 102 103 104
			echo "\nYour application has been created successfully under {$path}.\n";
		}
	}

105
	/**
106 107
	 * @throws \yii\base\Exception if source directory wasn't located
	 * @return string
108
	 */
109
	protected function getSourceDir()
Qiang Xue committed
110
	{
111 112 113 114 115 116 117 118 119 120 121 122
		$customSource = realpath($this->templatesPath.'/'.$this->type);
		$defaultSource = realpath($this->getDefaultTemplatesPath().'/'.$this->type);

		if($customSource) {
			return $customSource;
		}
		elseif($defaultSource) {
			return $defaultSource;
		}
		else {
			throw new Exception('Unable to locate the source directory for "'.$this->type.'".');
		}
Qiang Xue committed
123 124
	}

125
	/**
126
	 * @return string default templates path
127
	 */
128
	protected function getDefaultTemplatesPath()
Qiang Xue committed
129
	{
130
		return realpath(__DIR__.'/../create');
Qiang Xue committed
131 132
	}

133
	/**
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152
	 * @return array|null template configuration
	 */
	protected function getConfig()
	{
		if($this->_config===null) {
			$this->_config = require $this->getDefaultTemplatesPath().'/config.php';
			if($this->templatesPath && file_exists($this->templatesPath)) {
				$this->_config = array_merge($this->_config, require $this->templatesPath.'/config.php');
			}
		}
		if(isset($this->_config[$this->type])) {
			return $this->_config[$this->type];
		}
	}

	/**
	 * @param string $source path to source file
	 * @param string $pathTo path to file we want to get relative path for
	 * @param string $varName variable name w/o $ to replace value with relative path for
153
	 *
154
	 * @return string target file contetns
155
	 */
156
	public function replaceRelativePath($source, $pathTo, $varName)
Qiang Xue committed
157
	{
158
		$content = file_get_contents($source);
159 160 161 162 163 164
		$relativeFile = str_replace($this->getSourceDir(), '', $source);

		$relativePath = $this->getRelativePath($pathTo, $this->_rootPath.$relativeFile);
		$relativePath = str_replace('\\', '\\\\', $relativePath);

		return preg_replace('/\$'.$varName.'\s*=(.*?);/', "\$".$varName."=$relativePath;", $content);
Qiang Xue committed
165 166
	}

167
	/**
Qiang Xue committed
168 169
	 * @param string $path1 absolute path
	 * @param string $path2 absolute path
170 171 172 173
	 *
	 * @return string relative path
	 */
	protected function getRelativePath($path1, $path2)
Qiang Xue committed
174
	{
175 176 177 178
		$segs1 = explode(DIRECTORY_SEPARATOR, $path1);
		$segs2 = explode(DIRECTORY_SEPARATOR, $path2);
		$n1 = count($segs1);
		$n2 = count($segs2);
Qiang Xue committed
179

180 181
		for($i=0; $i<$n1 && $i<$n2; ++$i) {
			if($segs1[$i] !== $segs2[$i]) {
Qiang Xue committed
182
				break;
183
			}
Qiang Xue committed
184 185
		}

186
		if($i===0) {
Qiang Xue committed
187
			return "'".$path1."'";
188
		}
Qiang Xue committed
189
		$up='';
190
		for($j=$i;$j<$n2-1;++$j) {
Qiang Xue committed
191
			$up.='/..';
192 193
		}
		for(; $i<$n1-1; ++$i) {
Qiang Xue committed
194
			$up.='/'.$segs1[$i];
195
		}
Qiang Xue committed
196

197
		return '__DIR__.\''.$up.'/'.basename($path1).'\'';
Qiang Xue committed
198 199
	}
}