Generator.php 5.82 KB
Newer Older
Qiang Xue committed
1 2 3 4 5 6 7 8 9 10
<?php
/**
 * @link http://www.yiiframework.com/
 * @copyright Copyright (c) 2008 Yii Software LLC
 * @license http://www.yiiframework.com/license/
 */

namespace yii\gii\generators\controller;

use Yii;
Qiang Xue committed
11 12
use yii\gii\CodeFile;
use yii\helpers\Html;
13
use yii\helpers\Inflector;
Qiang Xue committed
14 15

/**
16
 * This generator will generate a controller and one or a few action view files.
Qiang Xue committed
17 18 19 20 21 22
 *
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class Generator extends \yii\gii\Generator
{
23 24 25
	/**
	 * @var string the controller ID
	 */
Qiang Xue committed
26
	public $controller;
27 28 29
	/**
	 * @var string the base class of the controller
	 */
Qiang Xue committed
30
	public $baseClass = 'yii\web\Controller';
31 32 33
	/**
	 * @var string the namespace of the controller class
	 */
Qiang Xue committed
34
	public $ns = 'app\controllers';
35 36 37
	/**
	 * @var string list of action IDs separated by commas or spaces
	 */
Qiang Xue committed
38 39
	public $actions = 'index';

40 41 42
	/**
	 * @inheritdoc
	 */
Qiang Xue committed
43 44 45 46 47
	public function getName()
	{
		return 'Controller Generator';
	}

48 49 50
	/**
	 * @inheritdoc
	 */
Qiang Xue committed
51 52 53 54 55 56
	public function getDescription()
	{
		return 'This generator helps you to quickly generate a new controller class,
			one or several controller actions and their corresponding views.';
	}

57 58 59
	/**
	 * @inheritdoc
	 */
Qiang Xue committed
60 61 62
	public function rules()
	{
		return array_merge(parent::rules(), array(
Qiang Xue committed
63
			array('controller, actions, baseClass, ns', 'filter', 'filter' => 'trim'),
Qiang Xue committed
64
			array('controller, baseClass', 'required'),
65 66 67
			array('controller', 'match', 'pattern' => '/^[a-z\\-\\/]*$/', 'message' => 'Only a-z, dashes (-) and slashes (/) are allowed.'),
			array('actions', 'match', 'pattern' => '/^[a-z\\-,\\s]*$/', 'message' => 'Only a-z, dashes (-), spaces and commas are allowed.'),
			array('baseClass', 'match', 'pattern' => '/^[\w\\\\]*$/', 'message' => 'Only word characters and backslashes are allowed.'),
Qiang Xue committed
68
			array('baseClass', 'validateReservedWord'),
69
			array('ns', 'match', 'pattern' => '/^[\w\\\\]*$/', 'message' => 'Only word characters and backslashes are allowed.'),
Qiang Xue committed
70 71 72
		));
	}

73 74 75
	/**
	 * @inheritdoc
	 */
Qiang Xue committed
76 77
	public function attributeLabels()
	{
Qiang Xue committed
78
		return array(
Qiang Xue committed
79 80 81
			'baseClass' => 'Base Class',
			'controller' => 'Controller ID',
			'actions' => 'Action IDs',
Qiang Xue committed
82
			'ns' => 'Namespace',
Qiang Xue committed
83
		);
Qiang Xue committed
84 85
	}

86 87 88
	/**
	 * @inheritdoc
	 */
Qiang Xue committed
89 90 91 92 93 94 95 96
	public function requiredTemplates()
	{
		return array(
			'controller.php',
			'view.php',
		);
	}

97 98 99
	/**
	 * @inheritdoc
	 */
Qiang Xue committed
100 101 102 103 104
	public function stickyAttributes()
	{
		return array('ns', 'baseClass');
	}

105 106 107
	/**
	 * @inheritdoc
	 */
Qiang Xue committed
108 109 110
	public function hints()
	{
		return array(
111
			'controller' => 'Controller ID should be in lower case and may contain module ID(s) separated by slashes. For example:
Qiang Xue committed
112 113 114 115 116
				<ul>
					<li><code>order</code> generates <code>OrderController.php</code></li>
					<li><code>order-item</code> generates <code>OrderItemController.php</code></li>
					<li><code>admin/user</code> generates <code>UserController.php</code> within the <code>admin</code> module.</li>
				</ul>',
117 118 119 120 121 122
			'actions' => 'Provide one or multiple action IDs to generate empty action method(s) in the controller. Separate multiple action IDs with commas or spaces.
				Action IDs should be in lower case. For example:
				<ul>
					<li><code>index</code> generates <code>actionIndex()</code></li>
					<li><code>create-order</code> generates <code>actionCreateOrder()</code></li>
				</ul>',
Qiang Xue committed
123
			'ns' => 'This is the namespace that the new controller class will use.',
Qiang Xue committed
124 125 126 127
			'baseClass' => 'This is the class that the new controller class will extend from. Please make sure the class exists and can be autoloaded.',
		);
	}

128 129 130
	/**
	 * @inheritdoc
	 */
Qiang Xue committed
131 132
	public function successMessage()
	{
Qiang Xue committed
133 134 135 136 137 138 139
		$actions = $this->getActionIDs();
		if (in_array('index', $actions)) {
			$route = $this->controller . '/index';
		} else {
			$route = $this->controller . '/' . reset($actions);
		}
		$link = Html::a('try it now', Yii::$app->getUrlManager()->createUrl($route), array('target' => '_blank'));
Qiang Xue committed
140 141 142
		return "The controller has been generated successfully. You may $link.";
	}

143 144 145 146
	/**
	 * @inheritdoc
	 */
	public function generate()
Qiang Xue committed
147
	{
Qiang Xue committed
148
		$files = array();
Qiang Xue committed
149

Qiang Xue committed
150 151 152 153
		$templatePath = $this->getTemplatePath();

		$files[] = new CodeFile(
			$this->getControllerFile(),
154
			$this->render($templatePath . '/controller.php')
Qiang Xue committed
155 156 157
		);

		foreach ($this->getActionIDs() as $action) {
Qiang Xue committed
158
			$files[] = new CodeFile(
Qiang Xue committed
159
				$this->getViewFile($action),
160
				$this->render($templatePath . '/view.php', array('action' => $action))
Qiang Xue committed
161 162
			);
		}
Qiang Xue committed
163 164

		return $files;
Qiang Xue committed
165 166
	}

167 168 169 170
	/**
	 * Normalizes [[actions]] into an array of action IDs.
	 * @return array an array of action IDs entered by the user
	 */
Qiang Xue committed
171 172
	public function getActionIDs()
	{
Qiang Xue committed
173
		$actions = array_unique(preg_split('/[\s,]+/', $this->actions, -1, PREG_SPLIT_NO_EMPTY));
Qiang Xue committed
174 175 176 177
		sort($actions);
		return $actions;
	}

Qiang Xue committed
178 179 180
	/**
	 * @return string the controller class name without the namespace part.
	 */
Qiang Xue committed
181
	public function getControllerClass()
182 183 184 185
	{
		return Inflector::id2camel($this->getControllerID()) . 'Controller';
	}

Qiang Xue committed
186 187 188
	/**
	 * @return string the controller ID (without the module ID prefix)
	 */
189
	public function getControllerID()
Qiang Xue committed
190 191
	{
		if (($pos = strrpos($this->controller, '/')) !== false) {
192
			return substr($this->controller, $pos + 1);
Qiang Xue committed
193
		} else {
194
			return $this->controller;
Qiang Xue committed
195 196 197
		}
	}

Qiang Xue committed
198 199 200
	/**
	 * @return \yii\base\Module the module that the new controller belongs to
	 */
Qiang Xue committed
201 202 203 204
	public function getModule()
	{
		if (($pos = strpos($this->controller, '/')) !== false) {
			$id = substr($this->controller, 0, $pos);
Qiang Xue committed
205
			if (($module = Yii::$app->getModule($id)) !== null) {
Qiang Xue committed
206 207 208
				return $module;
			}
		}
Qiang Xue committed
209
		return Yii::$app;
Qiang Xue committed
210 211
	}

Qiang Xue committed
212 213 214
	/**
	 * @return string the controller class file path
	 */
Qiang Xue committed
215 216 217
	public function getControllerFile()
	{
		$module = $this->getModule();
218
		return $module->getControllerPath() . '/' . $this->getControllerClass() . '.php';
Qiang Xue committed
219
	}
Qiang Xue committed
220

Qiang Xue committed
221 222 223 224
	/**
	 * @param string $action the action ID
	 * @return string the action view file path
	 */
Qiang Xue committed
225 226
	public function getViewFile($action)
	{
227 228
		$module = $this->getModule();
		return $module->getViewPath() . '/' . $this->getControllerID() . '/' . $action . '.php';
Qiang Xue committed
229
	}
Qiang Xue committed
230
}