Generator.php 5.71 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 68
			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.'),
			array('ns', 'match', 'pattern' => '/^[\w\\\\]*$/', 'message' => 'Only word characters and backslashes are allowed.'),
Qiang Xue committed
69 70 71
		));
	}

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

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

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

104 105 106
	/**
	 * @inheritdoc
	 */
Qiang Xue committed
107 108 109
	public function hints()
	{
		return array(
110
			'controller' => 'Controller ID should be in lower case and may contain module ID(s) separated by slashes. For example:
Qiang Xue committed
111 112 113 114 115
				<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>',
116 117 118 119 120 121
			'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
122
			'ns' => 'This is the namespace that the new controller class will use.',
Qiang Xue committed
123 124 125 126
			'baseClass' => 'This is the class that the new controller class will extend from. Please make sure the class exists and can be autoloaded.',
		);
	}

127 128 129
	/**
	 * @inheritdoc
	 */
Qiang Xue committed
130 131
	public function successMessage()
	{
Qiang Xue committed
132 133 134 135 136 137 138
		$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
139 140 141
		return "The controller has been generated successfully. You may $link.";
	}

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

Qiang Xue committed
149 150
		$files[] = new CodeFile(
			$this->getControllerFile(),
Qiang Xue committed
151
			$this->render('controller.php')
Qiang Xue committed
152 153 154
		);

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

		return $files;
Qiang Xue committed
162 163
	}

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

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

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

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

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

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