Generator.php 6.87 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;
14
use yii\helpers\StringHelper;
Qiang Xue committed
15 16

/**
17
 * This generator will generate a controller and one or a few action view files.
Qiang Xue committed
18
 *
19 20
 * @property array $actionIDs An array of action IDs entered by the user. This property is read-only.
 * @property string $controllerFile The controller class file path. This property is read-only.
21 22
 * @property string $controllerID The controller ID. This property is read-only.
 * @property string $controllerNamespace The namespace of the controller class. This property is read-only.
23
 *
Qiang Xue committed
24 25 26 27 28
 * @author Qiang Xue <qiang.xue@gmail.com>
 * @since 2.0
 */
class Generator extends \yii\gii\Generator
{
29
    /**
30
     * @var string the controller class name
31
     */
32
    public $controllerClass;
33
    /**
34
     * @var string the controller's view path
35
     */
36
    public $viewPath;
37
    /**
38
     * @var string the base class of the controller
39
     */
40
    public $baseClass = 'yii\web\Controller';
41 42 43 44 45
    /**
     * @var string list of action IDs separated by commas or spaces
     */
    public $actions = 'index';

46

47 48 49 50 51 52 53 54 55 56 57 58 59
    /**
     * @inheritdoc
     */
    public function getName()
    {
        return 'Controller Generator';
    }

    /**
     * @inheritdoc
     */
    public function getDescription()
    {
60
        return 'This generator helps you to quickly generate a new controller class with
61 62 63 64 65 66 67 68 69
            one or several controller actions and their corresponding views.';
    }

    /**
     * @inheritdoc
     */
    public function rules()
    {
        return array_merge(parent::rules(), [
70 71 72 73 74 75
            [['controllerClass', 'actions', 'baseClass'], 'filter', 'filter' => 'trim'],
            [['controllerClass', 'baseClass'], 'required'],
            ['controllerClass', 'match', 'pattern' => '/^[\w\\\\]*Controller$/', 'message' => 'Only word characters and backslashes are allowed, and the class name must end with "Controller".'],
            ['controllerClass', 'validateNewClass'],
            ['baseClass', 'match', 'pattern' => '/^[\w\\\\]*$/', 'message' => 'Only word characters and backslashes are allowed.'],
            ['actions', 'match', 'pattern' => '/^[a-z][a-z0-9\\-,\\s]*$/', 'message' => 'Only a-z, 0-9, dashes (-), spaces and commas are allowed.'],
76
            ['viewPath', 'safe'],
77 78 79 80 81 82 83 84 85 86
        ]);
    }

    /**
     * @inheritdoc
     */
    public function attributeLabels()
    {
        return [
            'baseClass' => 'Base Class',
87 88
            'controllerClass' => 'Controller Class',
            'viewPath' => 'View Path',
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
            'actions' => 'Action IDs',
        ];
    }

    /**
     * @inheritdoc
     */
    public function requiredTemplates()
    {
        return [
            'controller.php',
            'view.php',
        ];
    }

    /**
     * @inheritdoc
     */
    public function stickyAttributes()
    {
109
        return ['baseClass'];
110 111 112 113 114 115 116 117
    }

    /**
     * @inheritdoc
     */
    public function hints()
    {
        return [
118 119 120 121
            'controllerClass' => 'This is the name of the controller class to be generated. You should
                provide a fully qualified namespaced class (e.g. <code>app\controllers\PostController</code>),
                and class name should be in CamelCase ending with the word <code>Controller</code>. Make sure the class
                is using the same namespace as specified by your application\'s controllerNamespace property.',
122 123 124 125 126 127
            '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>',
128 129 130
            'viewPath' => 'Specify the directory for storing the view scripts for the controller. You may use path alias here, e.g.,
                <code>/var/www/basic/controllers/views/order</code>, <code>@app/views/order</code>. If not set, it will default
                to <code>@app/views/ControllerID</code>',
131 132 133 134 135 136 137 138 139 140 141
            'baseClass' => 'This is the class that the new controller class will extend from. Please make sure the class exists and can be autoloaded.',
        ];
    }

    /**
     * @inheritdoc
     */
    public function successMessage()
    {
        $actions = $this->getActionIDs();
        if (in_array('index', $actions)) {
142
            $route = $this->getControllerID() . '/index';
143
        } else {
144
            $route = $this->getControllerID() . '/' . reset($actions);
145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
        }
        $link = Html::a('try it now', Yii::$app->getUrlManager()->createUrl($route), ['target' => '_blank']);

        return "The controller has been generated successfully. You may $link.";
    }

    /**
     * @inheritdoc
     */
    public function generate()
    {
        $files = [];

        $files[] = new CodeFile(
            $this->getControllerFile(),
            $this->render('controller.php')
        );

        foreach ($this->getActionIDs() as $action) {
            $files[] = new CodeFile(
                $this->getViewFile($action),
                $this->render('view.php', ['action' => $action])
            );
        }

        return $files;
    }

    /**
     * Normalizes [[actions]] into an array of action IDs.
     * @return array an array of action IDs entered by the user
     */
    public function getActionIDs()
    {
        $actions = array_unique(preg_split('/[\s,]+/', $this->actions, -1, PREG_SPLIT_NO_EMPTY));
        sort($actions);

        return $actions;
    }

    /**
186
     * @return string the controller class file path
187
     */
188
    public function getControllerFile()
189
    {
190
        return Yii::getAlias('@' . str_replace('\\', '/', $this->controllerClass)) . '.php';
191 192 193
    }

    /**
194
     * @return string the controller ID
195 196 197
     */
    public function getControllerID()
    {
198 199
        $name = StringHelper::basename($this->controllerClass);
        return Inflector::camel2id(substr($name, 0, strlen($name) - 10));
200 201 202
    }

    /**
203 204
     * @param string $action the action ID
     * @return string the action view file path
205
     */
206
    public function getViewFile($action)
207
    {
208 209 210 211
        if (empty($this->viewPath)) {
            return Yii::getAlias('@app/views/' . $this->getControllerID() . "/$action.php");
        } else {
            return Yii::getAlias($this->viewPath . "/$action.php");
212 213 214 215
        }
    }

    /**
216
     * @return string the namespace of the controller class
217
     */
218
    public function getControllerNamespace()
219
    {
220
        $name = StringHelper::basename($this->controllerClass);
pana1990 committed
221
        return ltrim(substr($this->controllerClass, 0, - (strlen($name) + 1)), '\\');
222
    }
Qiang Xue committed
223
}