Passed
Pull Request — master (#33)
by Rustam
02:23
created

Generator::setBaseClass()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 1
nc 1
nop 1
dl 0
loc 3
ccs 0
cts 2
cp 0
c 0
b 0
f 0
cc 1
crap 2
rs 10
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Gii\Generator\Controller;
6
7
use Yiisoft\Strings\Inflector;
8
use Yiisoft\Strings\StringHelper;
9
use Yiisoft\Validator\Rule\Callback;
10
use Yiisoft\Validator\Rule\MatchRegularExpression;
11
use Yiisoft\Validator\Rule\Required;
12
use Yiisoft\Yii\Gii\CodeFile;
13
use Yiisoft\Yii\Gii\Generator\AbstractGenerator;
14
15
/**
16
 * This generator will generate a controller and one or a few action view files.
17
 */
18
final class Generator extends AbstractGenerator
19
{
20
    private string $controllerNamespace = 'App\\Controller';
21
    /**
22
     * @var string the controller class name
23
     */
24
    private string $controllerClass = '';
25
    /**
26
     * @var string|null the controller's views path
27
     */
28
    private ?string $viewsPath = null;
29
    /**
30
     * @var string the base class of the controller
31
     */
32
    private string $baseClass = 'App\\Controller';
33
    /**
34
     * @var string list of action IDs separated by commas or spaces
35
     */
36
    private string $actions = 'index';
37
38
    public function getName(): string
39
    {
40
        return 'Controller Generator';
41
    }
42
43
    public function getDescription(): string
44
    {
45
        return 'This generator helps you to quickly generate a new controller class with
46
            one or several controller actions and their corresponding views.';
47
    }
48
49 3
    public function rules(): array
50
    {
51 3
        return array_merge(
52 3
            parent::rules(),
53
            [
54
                'controllerClass' => [
55 3
                    new Required(),
56 3
                    (new MatchRegularExpression('/^[A-Z][\w]*Controller$/'))
57 3
                        ->message(
58 3
                            'Only word characters are allowed, and the class name must start with a capital letter and end with "Controller".'
59
                        ),
60 3
                    (new Callback([$this, 'validateNewClass'])),
61
                ],
62
                'baseClass' => [
63 3
                    new Required(),
64 3
                    (new MatchRegularExpression('/^[\w\\\\]*$/'))
65 3
                        ->message('Only word characters and backslashes are allowed.'),
66
                ],
67
                'actions' => [
68 3
                    (new MatchRegularExpression('/^[a-z][a-z0-9\\-,\\s]*$/'))
69 3
                        ->message('Only a-z, 0-9, dashes (-), spaces and commas are allowed.'),
70
                ],
71
            ]
72
        );
73
    }
74
75
    public function attributeLabels(): array
76
    {
77
        return [
78
            'baseClass' => 'Base Class',
79
            'controllerClass' => 'Controller Class',
80
            'viewsPath' => 'Views Path',
81
            'actions' => 'Action IDs',
82
        ];
83
    }
84
85 1
    public function requiredTemplates(): array
86
    {
87
        return [
88 1
            'controller.php',
89
            'view.php',
90
        ];
91
    }
92
93
    public function stickyAttributes(): array
94
    {
95
        return ['baseClass'];
96
    }
97
98
    public function hints(): array
99
    {
100
        return [
101
            'controllerClass' => 'This is the name of the controller class to be generated. You should
102
                provide a fully qualified namespaced class (e.g. <code>App\Controller\PostController</code>),
103
                and class name should be in CamelCase ending with the word <code>Controller</code>. Make sure the class
104
                is using the same namespace as specified by your application\'s controllerNamespace property.',
105
            'actions' => 'Provide one or multiple action IDs to generate empty action method(s) in the controller. Separate multiple action IDs with commas or spaces.
106
                Action IDs should be in lower case. For example:
107
                <ul>
108
                    <li><code>index</code> generates <code>index()</code></li>
109
                    <li><code>create-order</code> generates <code>createOrder()</code></li>
110
                </ul>',
111
            'viewsPath' => 'Specify the directory for storing the view scripts for the controller. You may use path alias here, e.g.,
112
                <code>/var/www/app/controllers/views/order</code>, <code>@app/views/order</code>. If not set, it will default
113
                to <code>@app/views/ControllerID</code>',
114
            'baseClass' => 'This is the class that the new controller class will extend from. Please make sure the class exists and can be autoloaded.',
115
        ];
116
    }
117
118
    public function successMessage(): string
119
    {
120
        return 'The controller has been generated successfully.';
121
    }
122
123 2
    public function generate(): array
124
    {
125 2
        $files = [];
126
127 2
        $files[] = (new CodeFile(
128 2
            $this->getControllerFile(),
129 2
            $this->render('controller')
130 2
        ))->withBasePath($this->aliases->get('@root'));
131
132 2
        foreach ($this->getActionIDs() as $action) {
133 2
            $files[] = (new CodeFile(
134 2
                $this->getViewFile($action),
135 2
                $this->render('view', ['action' => $action])
136 2
            ))->withBasePath($this->aliases->get('@root'));
137
        }
138
139 2
        return $files;
140
    }
141
142
    /**
143
     * Normalizes [[actions]] into an array of action IDs.
144
     *
145
     * @return array an array of action IDs entered by the user
146
     */
147 2
    public function getActionIDs(): array
148
    {
149 2
        $actions = array_unique(preg_split('/[\s,]+/', $this->actions, -1, PREG_SPLIT_NO_EMPTY));
0 ignored issues
show
Bug introduced by
It seems like preg_split('/[\s,]+/', $...er\PREG_SPLIT_NO_EMPTY) can also be of type false; however, parameter $array of array_unique() does only seem to accept array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

149
        $actions = array_unique(/** @scrutinizer ignore-type */ preg_split('/[\s,]+/', $this->actions, -1, PREG_SPLIT_NO_EMPTY));
Loading history...
150 2
        sort($actions);
151
152 2
        return $actions;
153
    }
154
155
    /**
156
     * @return string the controller class file path
157
     */
158 2
    public function getControllerFile(): string
159
    {
160 2
        return $this->aliases->get(
161 2
            sprintf('%s/%s.php', $this->getDirectory() ?? '', $this->getControllerClass())
162
        );
163
    }
164
165
    /**
166
     * @return string the controller ID
167
     */
168 2
    public function getControllerID(): string
169
    {
170 2
        $name = StringHelper::baseName($this->controllerClass);
171 2
        return (new Inflector())->pascalCaseToId(substr($name, 0, -10));
172
    }
173
174
    /**
175
     * @param string $action the action ID
176
     *
177
     * @return string the action view file path
178
     */
179 2
    public function getViewFile(string $action): string
180
    {
181 2
        if (empty($this->getViewsPath())) {
182 2
            return $this->aliases->get(
183 2
                '@views/' . $this->getControllerID() . "/$action.php"
184
            );
185
        }
186
187
        return $this->aliases->get(str_replace('\\', '/', $this->getViewsPath()) . "/$action.php");
188
    }
189
190
    /**
191
     * @return string the namespace of the controller class
192
     */
193 1
    public function getControllerNamespace(): string
194
    {
195 1
        return $this->controllerNamespace;
196
    }
197
198
    /**
199
     * @param string $controllerNamespace
200
     */
201
    public function setControllerNamespace(string $controllerNamespace): void
202
    {
203
        $this->controllerNamespace = $controllerNamespace;
204
    }
205
206 3
    public function getControllerClass(): string
207
    {
208 3
        return $this->controllerClass;
209
    }
210
211 3
    public function setControllerClass(string $controllerClass): void
212
    {
213 3
        $this->controllerClass = $controllerClass;
214 3
    }
215
216 2
    public function getViewsPath(): ?string
217
    {
218 2
        return $this->viewsPath;
219
    }
220
221
    public function setViewsPath(?string $viewsPath): void
222
    {
223
        $this->viewsPath = $viewsPath;
224
    }
225
226 3
    public function getBaseClass(): string
227
    {
228 3
        return $this->baseClass;
229
    }
230
231
    public function setBaseClass(string $baseClass): void
232
    {
233
        $this->baseClass = $baseClass;
234
    }
235
236 3
    public function getActions(): string
237
    {
238 3
        return $this->actions;
239
    }
240
241 3
    public function setActions(string $actions): void
242
    {
243 3
        $this->actions = $actions;
244 3
    }
245
}
246