You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

224 lines
6.9KB

  1. <?php
  2. /**
  3. * @link http://www.yiiframework.com/
  4. * @copyright Copyright (c) 2008 Yii Software LLC
  5. * @license http://www.yiiframework.com/license/
  6. */
  7. namespace yii\gii\generators\controller;
  8. use Yii;
  9. use yii\gii\CodeFile;
  10. use yii\helpers\Html;
  11. use yii\helpers\Inflector;
  12. use yii\helpers\StringHelper;
  13. /**
  14. * This generator will generate a controller and one or a few action view files.
  15. *
  16. * @property array $actionIDs An array of action IDs entered by the user. This property is read-only.
  17. * @property string $controllerFile The controller class file path. This property is read-only.
  18. * @property string $controllerID The controller ID. This property is read-only.
  19. * @property string $controllerNamespace The namespace of the controller class. This property is read-only.
  20. *
  21. * @author Qiang Xue <qiang.xue@gmail.com>
  22. * @since 2.0
  23. */
  24. class Generator extends \yii\gii\Generator
  25. {
  26. /**
  27. * @var string the controller class name
  28. */
  29. public $controllerClass;
  30. /**
  31. * @var string the controller's view path
  32. */
  33. public $viewPath;
  34. /**
  35. * @var string the base class of the controller
  36. */
  37. public $baseClass = 'yii\web\Controller';
  38. /**
  39. * @var string list of action IDs separated by commas or spaces
  40. */
  41. public $actions = 'index';
  42. /**
  43. * @inheritdoc
  44. */
  45. public function getName()
  46. {
  47. return 'Controller Generator';
  48. }
  49. /**
  50. * @inheritdoc
  51. */
  52. public function getDescription()
  53. {
  54. return 'This generator helps you to quickly generate a new controller class with
  55. one or several controller actions and their corresponding views.';
  56. }
  57. /**
  58. * @inheritdoc
  59. */
  60. public function rules()
  61. {
  62. return array_merge(parent::rules(), [
  63. [['controllerClass', 'actions', 'baseClass'], 'filter', 'filter' => 'trim'],
  64. [['controllerClass', 'baseClass'], 'required'],
  65. ['controllerClass', 'match', 'pattern' => '/^[\w\\\\]*Controller$/', 'message' => 'Only word characters and backslashes are allowed, and the class name must end with "Controller".'],
  66. ['controllerClass', 'validateNewClass'],
  67. ['baseClass', 'match', 'pattern' => '/^[\w\\\\]*$/', 'message' => 'Only word characters and backslashes are allowed.'],
  68. ['actions', 'match', 'pattern' => '/^[a-z][a-z0-9\\-,\\s]*$/', 'message' => 'Only a-z, 0-9, dashes (-), spaces and commas are allowed.'],
  69. ['viewPath', 'safe'],
  70. ]);
  71. }
  72. /**
  73. * @inheritdoc
  74. */
  75. public function attributeLabels()
  76. {
  77. return [
  78. 'baseClass' => 'Base Class',
  79. 'controllerClass' => 'Controller Class',
  80. 'viewPath' => 'View Path',
  81. 'actions' => 'Action IDs',
  82. ];
  83. }
  84. /**
  85. * @inheritdoc
  86. */
  87. public function requiredTemplates()
  88. {
  89. return [
  90. 'controller.php',
  91. 'view.php',
  92. ];
  93. }
  94. /**
  95. * @inheritdoc
  96. */
  97. public function stickyAttributes()
  98. {
  99. return ['baseClass'];
  100. }
  101. /**
  102. * @inheritdoc
  103. */
  104. public function hints()
  105. {
  106. return [
  107. 'controllerClass' => 'This is the name of the controller class to be generated. You should
  108. provide a fully qualified namespaced class (e.g. <code>app\controllers\PostController</code>),
  109. and class name should be in CamelCase ending with the word <code>Controller</code>. Make sure the class
  110. is using the same namespace as specified by your application\'s controllerNamespace property.',
  111. 'actions' => 'Provide one or multiple action IDs to generate empty action method(s) in the controller. Separate multiple action IDs with commas or spaces.
  112. Action IDs should be in lower case. For example:
  113. <ul>
  114. <li><code>index</code> generates <code>actionIndex()</code></li>
  115. <li><code>create-order</code> generates <code>actionCreateOrder()</code></li>
  116. </ul>',
  117. 'viewPath' => 'Specify the directory for storing the view scripts for the controller. You may use path alias here, e.g.,
  118. <code>/var/www/basic/controllers/views/order</code>, <code>@app/views/order</code>. If not set, it will default
  119. to <code>@app/views/ControllerID</code>',
  120. 'baseClass' => 'This is the class that the new controller class will extend from. Please make sure the class exists and can be autoloaded.',
  121. ];
  122. }
  123. /**
  124. * @inheritdoc
  125. */
  126. public function successMessage()
  127. {
  128. $actions = $this->getActionIDs();
  129. if (in_array('index', $actions)) {
  130. $route = $this->getControllerID() . '/index';
  131. } else {
  132. $route = $this->getControllerID() . '/' . reset($actions);
  133. }
  134. $link = Html::a('try it now', Yii::$app->getUrlManager()->createUrl($route), ['target' => '_blank']);
  135. return "The controller has been generated successfully. You may $link.";
  136. }
  137. /**
  138. * @inheritdoc
  139. */
  140. public function generate()
  141. {
  142. $files = [];
  143. $files[] = new CodeFile(
  144. $this->getControllerFile(),
  145. $this->render('controller.php')
  146. );
  147. foreach ($this->getActionIDs() as $action) {
  148. $files[] = new CodeFile(
  149. $this->getViewFile($action),
  150. $this->render('view.php', ['action' => $action])
  151. );
  152. }
  153. return $files;
  154. }
  155. /**
  156. * Normalizes [[actions]] into an array of action IDs.
  157. * @return array an array of action IDs entered by the user
  158. */
  159. public function getActionIDs()
  160. {
  161. $actions = array_unique(preg_split('/[\s,]+/', $this->actions, -1, PREG_SPLIT_NO_EMPTY));
  162. sort($actions);
  163. return $actions;
  164. }
  165. /**
  166. * @return string the controller class file path
  167. */
  168. public function getControllerFile()
  169. {
  170. return Yii::getAlias('@' . str_replace('\\', '/', $this->controllerClass)) . '.php';
  171. }
  172. /**
  173. * @return string the controller ID
  174. */
  175. public function getControllerID()
  176. {
  177. $name = StringHelper::basename($this->controllerClass);
  178. return Inflector::camel2id(substr($name, 0, strlen($name) - 10));
  179. }
  180. /**
  181. * @param string $action the action ID
  182. * @return string the action view file path
  183. */
  184. public function getViewFile($action)
  185. {
  186. if (empty($this->viewPath)) {
  187. return Yii::getAlias('@app/views/' . $this->getControllerID() . "/$action.php");
  188. } else {
  189. return Yii::getAlias($this->viewPath . "/$action.php");
  190. }
  191. }
  192. /**
  193. * @return string the namespace of the controller class
  194. */
  195. public function getControllerNamespace()
  196. {
  197. $name = StringHelper::basename($this->controllerClass);
  198. return ltrim(substr($this->controllerClass, 0, - (strlen($name) + 1)), '\\');
  199. }
  200. }