├── LICENSE.md
├── README.md
├── composer.json
└── crud
├── Generator.php
├── default
├── controller.php
├── search.php
└── views
│ ├── _form.php
│ ├── _search.php
│ ├── create.php
│ ├── index.php
│ ├── update.php
│ └── view.php
└── form.php
/LICENSE.md:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014, Warrence Oo
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification,
5 | are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice, this
8 | list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice, this
11 | list of conditions and the following disclaimer in the documentation and/or
12 | other materials provided with the distribution.
13 |
14 | * Neither the name of the {organization} nor the names of its
15 | contributors may be used to endorse or promote products derived from
16 | this software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | I would like to apologize for not following up with this plugin because i has been migrate over to Laravel. However i would like to thanks everyone for using this plugin. Please do let me know is there any nice fork of this project, i will share to link for everyone here.
2 |
3 | yii2-kartikgii
4 | ==============
5 |
6 | Gii CRUD Generator base on kartik-v extension. Save repeatitive works on every new CRUD generated. Below are some of the features:
7 |
8 | - Data grid view are generated using kartik-v/yii2-grid, pjax are use for the grid.
9 | - Detail View are generated using kartik-v/yii2-detail-view, controllers are generated to support edit mode saving and delete in Detail View.
10 | - _form are generated using kartik-v/yii2-builder, Date/Time/DateTime/TimeStamp column are automatically generated to use DateTimePicker Widget.
11 | - Using kartik-v/yii2-datecontrol to globalize date format, so date will automatically convert for the display and also for save according to the format you set, for all CRUD generated using this extension.
12 |
13 | By using this extension, you no longer have to change your CRUD to using kartik-v extension, everything will be auto generated for you, and you could customize it later if you need.
14 |
15 | Thanks for the great kartik-v extension.
16 |
17 | For more information about kartik-v extension, please visit [kartik-v at Github](https://www.github.com/kartik-v).
18 |
19 | > NOTE: This is the first extension i created, please kindly comment or suggest for better or correct me if im doing anything wrong. Thanks.
20 |
21 | ## Installation
22 |
23 | The preferred way to install this extension is through [composer](http://getcomposer.org/download/).
24 |
25 | Either run
26 |
27 | ```
28 | $ php composer.phar require warrence/yii2-kartikgii "dev-master"
29 | ```
30 |
31 | or add
32 |
33 | ```
34 | "warrence/yii2-kartikgii": "dev-master"
35 | ```
36 |
37 | to the ```require``` section of your `composer.json` file.
38 |
39 | ## Usage
40 |
41 | ```php
42 | //if your gii modules configuration looks like below:
43 | $config['modules']['gii'] = 'yii\gii\Module';
44 |
45 | //change it to
46 | $config['modules']['gii']['class'] = 'yii\gii\Module';
47 | ```
48 |
49 | ```php
50 | //Add this into backend/config/main-local.php
51 | $config['modules']['gii']['generators'] = [
52 | 'kartikgii-crud' => ['class' => 'warrence\kartikgii\crud\Generator'],
53 | ];
54 | ```
55 |
56 | ```php
57 | //Add 'gridview' into your 'modules' section in backend/config/main.php
58 | 'modules' => [
59 | 'gridview' => [
60 | 'class' => 'kartik\grid\Module',
61 | ],
62 |
63 | ],
64 | ```
65 |
66 | ```php
67 | //add modules 'datecontrol' into your 'modules' section in common/config/main
68 | 'modules' => [
69 | 'datecontrol' => [
70 | 'class' => 'kartik\datecontrol\Module',
71 |
72 | // format settings for displaying each date attribute
73 | 'displaySettings' => [
74 | 'date' => 'd-m-Y',
75 | 'time' => 'H:i:s A',
76 | 'datetime' => 'd-m-Y H:i:s A',
77 | ],
78 |
79 | // format settings for saving each date attribute
80 | 'saveSettings' => [
81 | 'date' => 'Y-m-d',
82 | 'time' => 'H:i:s',
83 | 'datetime' => 'Y-m-d H:i:s',
84 | ],
85 |
86 |
87 |
88 | // automatically use kartik\widgets for each of the above formats
89 | 'autoWidget' => true,
90 |
91 | ]
92 | ],
93 | ```
94 |
95 | ## License
96 |
97 | **yii2-kartikgii** is released under the BSD 3-Clause License. See the bundled `LICENSE.md` for details.
98 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "warrence/yii2-kartikgii",
3 | "description": "Gii Generator base on Kartik-V extension https://github.com/kartik-v",
4 | "authors": [
5 | {
6 |
7 | "name": "Warrence",
8 |
9 | "email": "warrence@gmail.com"
10 | }
11 | ],
12 | "autoload": {
13 | "psr-4": {
14 | "warrence\\kartikgii\\": ""
15 | }
16 | },
17 | "require": {
18 | "kartik-v/yii2-widgets": "*",
19 | "kartik-v/yii2-grid": "*",
20 | "kartik-v/yii2-icons": "*",
21 | "kartik-v/yii2-datecontrol": "*",
22 | "kartik-v/yii2-helpers": "*",
23 | "kartik-v/yii2-builder": "*",
24 | "kartik-v/yii2-detail-view": "*",
25 | "php": ">=5.3.0"
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/crud/Generator.php:
--------------------------------------------------------------------------------
1 |
29 | * @since 2.0
30 | */
31 | class Generator extends \yii\gii\generators\crud\Generator
32 | {
33 | public $modelClass;
34 | public $moduleID;
35 | public $controllerClass;
36 | public $baseControllerClass = 'yii\web\Controller';
37 | public $indexWidgetType = 'grid';
38 | public $searchModelClass = '';
39 |
40 | /**
41 | * @inheritdoc
42 | */
43 | public function getName()
44 | {
45 | return 'Kartik CRUD Generator';
46 | }
47 |
48 | /**
49 | * @inheritdoc
50 | */
51 | public function getDescription()
52 | {
53 | return 'This generator generates a controller and views that implement CRUD (Create, Read, Update, Delete)
54 | operations for the specified data model.';
55 | }
56 |
57 | /**
58 | * @inheritdoc
59 | */
60 | public function rules()
61 | {
62 | return array_merge(parent::rules(), [
63 | [['moduleID', 'controllerClass', 'modelClass', 'searchModelClass', 'baseControllerClass'], 'filter', 'filter' => 'trim'],
64 | [['modelClass', 'controllerClass', 'baseControllerClass', 'indexWidgetType'], 'required'],
65 | [['searchModelClass'], 'compare', 'compareAttribute' => 'modelClass', 'operator' => '!==', 'message' => 'Search Model Class must not be equal to Model Class.'],
66 | [['modelClass', 'controllerClass', 'baseControllerClass', 'searchModelClass'], 'match', 'pattern' => '/^[\w\\\\]*$/', 'message' => 'Only word characters and backslashes are allowed.'],
67 | [['modelClass'], 'validateClass', 'params' => ['extends' => BaseActiveRecord::className()]],
68 | [['baseControllerClass'], 'validateClass', 'params' => ['extends' => Controller::className()]],
69 | [['controllerClass'], 'match', 'pattern' => '/Controller$/', 'message' => 'Controller class name must be suffixed with "Controller".'],
70 | [['controllerClass'], 'match', 'pattern' => '/(^|\\\\)[A-Z][^\\\\]+Controller$/', 'message' => 'Controller class name must start with an uppercase letter.'],
71 | [['controllerClass', 'searchModelClass'], 'validateNewClass'],
72 | [['indexWidgetType'], 'in', 'range' => ['grid', 'list']],
73 | [['modelClass'], 'validateModelClass'],
74 | [['moduleID'], 'validateModuleID'],
75 | [['enableI18N'], 'boolean'],
76 | [['messageCategory'], 'validateMessageCategory', 'skipOnEmpty' => false],
77 | ]);
78 | }
79 |
80 | /**
81 | * @inheritdoc
82 | */
83 | public function attributeLabels()
84 | {
85 | return array_merge(parent::attributeLabels(), [
86 | 'modelClass' => 'Model Class',
87 | 'moduleID' => 'Module ID',
88 | 'controllerClass' => 'Controller Class',
89 | 'baseControllerClass' => 'Base Controller Class',
90 | 'indexWidgetType' => 'Widget Used in Index Page',
91 | 'searchModelClass' => 'Search Model Class',
92 | ]);
93 | }
94 |
95 | /**
96 | * @inheritdoc
97 | */
98 | public function hints()
99 | {
100 | return array_merge(parent::hints(), [
101 | 'modelClass' => 'This is the ActiveRecord class associated with the table that CRUD will be built upon.
102 | You should provide a fully qualified class name, e.g., app\models\Post
.',
103 | 'controllerClass' => 'This is the name of the controller class to be generated. You should
104 | provide a fully qualified namespaced class, .e.g, app\controllers\PostController
.
105 | The controller class name should follow the CamelCase scheme with an uppercase first letter',
106 | 'baseControllerClass' => 'This is the class that the new CRUD controller class will extend from.
107 | You should provide a fully qualified class name, e.g., yii\web\Controller
.',
108 | 'moduleID' => 'This is the ID of the module that the generated controller will belong to.
109 | If not set, it means the controller will belong to the application.',
110 | 'indexWidgetType' => 'This is the widget type to be used in the index page to display list of the models.
111 | You may choose either GridView
or ListView
',
112 | 'searchModelClass' => 'This is the name of the search model class to be generated. You should provide a fully
113 | qualified namespaced class name, e.g., app\models\PostSearch
.',
114 | ]);
115 | }
116 |
117 | /**
118 | * @inheritdoc
119 | */
120 | public function requiredTemplates()
121 | {
122 | return ['controller.php'];
123 | }
124 |
125 | /**
126 | * @inheritdoc
127 | */
128 | public function stickyAttributes()
129 | {
130 | return array_merge(parent::stickyAttributes(), ['baseControllerClass', 'moduleID', 'indexWidgetType']);
131 | }
132 |
133 | /**
134 | * Checks if model class is valid
135 | */
136 | public function validateModelClass()
137 | {
138 | /** @var ActiveRecord $class */
139 | $class = $this->modelClass;
140 | $pk = $class::primaryKey();
141 | if (empty($pk)) {
142 | $this->addError('modelClass', "The table associated with $class must have primary key(s).");
143 | }
144 | }
145 |
146 | /**
147 | * Checks if model ID is valid
148 | */
149 | public function validateModuleID()
150 | {
151 | if (!empty($this->moduleID)) {
152 | $module = Yii::$app->getModule($this->moduleID);
153 | if ($module === null) {
154 | $this->addError('moduleID', "Module '{$this->moduleID}' does not exist.");
155 | }
156 | }
157 | }
158 |
159 | /**
160 | * @inheritdoc
161 | */
162 | public function generate()
163 | {
164 | $controllerFile = Yii::getAlias('@' . str_replace('\\', '/', ltrim($this->controllerClass, '\\')) . '.php');
165 |
166 | $files = [
167 | new CodeFile($controllerFile, $this->render('controller.php')),
168 | ];
169 |
170 | if (!empty($this->searchModelClass)) {
171 | $searchModel = Yii::getAlias('@' . str_replace('\\', '/', ltrim($this->searchModelClass, '\\') . '.php'));
172 | $files[] = new CodeFile($searchModel, $this->render('search.php'));
173 | }
174 |
175 | $viewPath = $this->getViewPath();
176 | $templatePath = $this->getTemplatePath() . '/views';
177 | foreach (scandir($templatePath) as $file) {
178 | if (empty($this->searchModelClass) && $file === '_search.php') {
179 | continue;
180 | }
181 | if (is_file($templatePath . '/' . $file) && pathinfo($file, PATHINFO_EXTENSION) === 'php') {
182 | $files[] = new CodeFile("$viewPath/$file", $this->render("views/$file"));
183 | }
184 | }
185 |
186 | return $files;
187 | }
188 |
189 | /**
190 | * @return string the controller ID (without the module ID prefix)
191 | */
192 | public function getControllerID()
193 | {
194 | $pos = strrpos($this->controllerClass, '\\');
195 | $class = substr(substr($this->controllerClass, $pos + 1), 0, -10);
196 |
197 | return Inflector::camel2id($class);
198 | }
199 |
200 | /**
201 | * @return string the action view file path
202 | */
203 | public function getViewPath()
204 | {
205 | $module = empty($this->moduleID) ? Yii::$app : Yii::$app->getModule($this->moduleID);
206 |
207 | return $module->getViewPath() . '/' . $this->getControllerID() ;
208 | }
209 |
210 | public function getNameAttribute()
211 | {
212 | foreach ($this->getColumnNames() as $name) {
213 | if (!strcasecmp($name, 'name') || !strcasecmp($name, 'title')) {
214 | return $name;
215 | }
216 | }
217 | /** @var \yii\db\ActiveRecord $class */
218 | $class = $this->modelClass;
219 | $pk = $class::primaryKey();
220 |
221 | return $pk[0];
222 | }
223 |
224 | /**
225 | * Generates code for active field
226 | * @param string $attribute
227 | * @return string
228 | */
229 | public function generateActiveField($attribute)
230 | {
231 | $model = new $this->modelClass();
232 | $attributeLabels = $model->attributeLabels();
233 | $tableSchema = $this->getTableSchema();
234 | if ($tableSchema === false || !isset($tableSchema->columns[$attribute])) {
235 | if (preg_match('/^(password|pass|passwd|passcode)$/i', $attribute)) {
236 | return "'$attribute' => ['type' => TabularForm::INPUT_PASSWORD,'options' => ['placeholder' => 'Enter ".$attributeLabels[$attribute]."...']],";
237 | //return "\$form->field(\$model, '$attribute')->passwordInput()";
238 | } else {
239 | return "'$attribute' => ['type' => TabularForm::INPUT_TEXT, 'options' => ['placeholder' => 'Enter ".$attributeLabels[$attribute]."...']],";
240 | //return "\$form->field(\$model, '$attribute')";
241 | }
242 | }
243 | $column = $tableSchema->columns[$attribute];
244 | if ($column->phpType === 'boolean') {
245 | //return "\$form->field(\$model, '$attribute')->checkbox()";
246 | return "'$attribute' => ['type' => Form::INPUT_CHECKBOX, 'options' => ['placeholder' => 'Enter ".$attributeLabels[$attribute]."...']],";
247 | } elseif ($column->type === 'text') {
248 | //return "\$form->field(\$model, '$attribute')->textarea(['rows' => 6])";
249 | return "'$attribute' => ['type' => Form::INPUT_TEXTAREA, 'options' => ['placeholder' => 'Enter ".$attributeLabels[$attribute]."...','rows' => 6]],";
250 | } elseif ($column->type === 'date') {
251 | return "'$attribute' => ['type' => Form::INPUT_WIDGET, 'widgetClass' => DateControl::classname(),'options' => ['type' => DateControl::FORMAT_DATE]],";
252 | } elseif ($column->type === 'time') {
253 | return "'$attribute' => ['type' => Form::INPUT_WIDGET, 'widgetClass' => DateControl::classname(),'options' => ['type' => DateControl::FORMAT_TIME]],";
254 | } elseif ($column->type === 'datetime' || $column->type === 'timestamp') {
255 | return "'$attribute' => ['type' => Form::INPUT_WIDGET, 'widgetClass' => DateControl::classname(),'options' => ['type' => DateControl::FORMAT_DATETIME]],";
256 | } else {
257 | if (preg_match('/^(password|pass|passwd|passcode)$/i', $column->name)) {
258 | $input = 'INPUT_PASSWORD';
259 | } else {
260 | $input = 'INPUT_TEXT';
261 | }
262 | if ($column->phpType !== 'string' || $column->size === null) {
263 | //return "\$form->field(\$model, '$attribute')->$input()";
264 | return "'$attribute' => ['type' => Form::".$input.", 'options' => ['placeholder' => 'Enter ".$attributeLabels[$attribute]."...']],";
265 | } else {
266 | //return "\$form->field(\$model, '$attribute')->$input(['maxlength' => $column->size])";
267 | return "'$attribute' => ['type' => Form::".$input.", 'options' => ['placeholder' => 'Enter ".$attributeLabels[$attribute]."...', 'maxlength' => ".$column->size."]],";
268 | }
269 | }
270 | }
271 |
272 | /**
273 | * Generates code for active search field
274 | * @param string $attribute
275 | * @return string
276 | */
277 | public function generateActiveSearchField($attribute)
278 | {
279 | $tableSchema = $this->getTableSchema();
280 | if ($tableSchema === false) {
281 | return "\$form->field(\$model, '$attribute')";
282 | }
283 | $column = $tableSchema->columns[$attribute];
284 | if ($column->phpType === 'boolean') {
285 | return "\$form->field(\$model, '$attribute')->checkbox()";
286 | } else {
287 | return "\$form->field(\$model, '$attribute')";
288 | }
289 | }
290 |
291 | /**
292 | * Generates column format
293 | * @param \yii\db\ColumnSchema $column
294 | * @return string
295 | */
296 | public function generateColumnFormat($column)
297 | {
298 | if ($column->phpType === 'boolean') {
299 | return 'boolean';
300 | } elseif ($column->type === 'text') {
301 | return 'ntext';
302 | } elseif (stripos($column->name, 'time') !== false && $column->phpType === 'integer') {
303 | return 'datetime';
304 | } elseif (stripos($column->name, 'email') !== false) {
305 | return 'email';
306 | } elseif (stripos($column->name, 'url') !== false) {
307 | return 'url';
308 | } else {
309 | return 'text';
310 | }
311 | }
312 |
313 | /**
314 | * Generates validation rules for the search model.
315 | * @return array the generated validation rules
316 | */
317 | public function generateSearchRules()
318 | {
319 | if (($table = $this->getTableSchema()) === false) {
320 | return ["[['" . implode("', '", $this->getColumnNames()) . "'], 'safe']"];
321 | }
322 | $types = [];
323 | foreach ($table->columns as $column) {
324 | switch ($column->type) {
325 | case Schema::TYPE_SMALLINT:
326 | case Schema::TYPE_INTEGER:
327 | case Schema::TYPE_BIGINT:
328 | $types['integer'][] = $column->name;
329 | break;
330 | case Schema::TYPE_BOOLEAN:
331 | $types['boolean'][] = $column->name;
332 | break;
333 | case Schema::TYPE_FLOAT:
334 | case Schema::TYPE_DECIMAL:
335 | case Schema::TYPE_MONEY:
336 | $types['number'][] = $column->name;
337 | break;
338 | case Schema::TYPE_DATE:
339 | case Schema::TYPE_TIME:
340 | case Schema::TYPE_DATETIME:
341 | case Schema::TYPE_TIMESTAMP:
342 | default:
343 | $types['safe'][] = $column->name;
344 | break;
345 | }
346 | }
347 |
348 | $rules = [];
349 | foreach ($types as $type => $columns) {
350 | $rules[] = "[['" . implode("', '", $columns) . "'], '$type']";
351 | }
352 |
353 | return $rules;
354 | }
355 |
356 | /**
357 | * @return array searchable attributes
358 | */
359 | public function getSearchAttributes()
360 | {
361 | return $this->getColumnNames();
362 | }
363 |
364 | /**
365 | * Generates the attribute labels for the search model.
366 | * @return array the generated attribute labels (name => label)
367 | */
368 | public function generateSearchLabels()
369 | {
370 | /** @var \yii\base\Model $model */
371 | $model = new $this->modelClass();
372 | $attributeLabels = $model->attributeLabels();
373 | $labels = [];
374 | foreach ($this->getColumnNames() as $name) {
375 | if (isset($attributeLabels[$name])) {
376 | $labels[$name] = $attributeLabels[$name];
377 | } else {
378 | if (!strcasecmp($name, 'id')) {
379 | $labels[$name] = 'ID';
380 | } else {
381 | $label = Inflector::camel2words($name);
382 | if (strcasecmp(substr($label, -3), ' id') === 0) {
383 | $label = substr($label, 0, -3) . ' ID';
384 | }
385 | $labels[$name] = $label;
386 | }
387 | }
388 | }
389 |
390 | return $labels;
391 | }
392 |
393 | /**
394 | * Generates search conditions
395 | * @return array
396 | */
397 | public function generateSearchConditions()
398 | {
399 | $columns = [];
400 | if (($table = $this->getTableSchema()) === false) {
401 | $class = $this->modelClass;
402 | /** @var \yii\base\Model $model */
403 | $model = new $class();
404 | foreach ($model->attributes() as $attribute) {
405 | $columns[$attribute] = 'unknown';
406 | }
407 | } else {
408 | foreach ($table->columns as $column) {
409 | $columns[$column->name] = $column->type;
410 | }
411 | }
412 |
413 | $likeConditions = [];
414 | $hashConditions = [];
415 | foreach ($columns as $column => $type) {
416 | switch ($type) {
417 | case Schema::TYPE_SMALLINT:
418 | case Schema::TYPE_INTEGER:
419 | case Schema::TYPE_BIGINT:
420 | case Schema::TYPE_BOOLEAN:
421 | case Schema::TYPE_FLOAT:
422 | case Schema::TYPE_DECIMAL:
423 | case Schema::TYPE_MONEY:
424 | case Schema::TYPE_DATE:
425 | case Schema::TYPE_TIME:
426 | case Schema::TYPE_DATETIME:
427 | case Schema::TYPE_TIMESTAMP:
428 | $hashConditions[] = "'{$column}' => \$this->{$column},";
429 | break;
430 | default:
431 | $likeConditions[] = "->andFilterWhere(['like', '{$column}', \$this->{$column}])";
432 | break;
433 | }
434 | }
435 |
436 | $conditions = [];
437 | if (!empty($hashConditions)) {
438 | $conditions[] = "\$query->andFilterWhere([\n"
439 | . str_repeat(' ', 12) . implode("\n" . str_repeat(' ', 12), $hashConditions)
440 | . "\n" . str_repeat(' ', 8) . "]);\n";
441 | }
442 | if (!empty($likeConditions)) {
443 | $conditions[] = "\$query" . implode("\n" . str_repeat(' ', 12), $likeConditions) . ";\n";
444 | }
445 |
446 | return $conditions;
447 | }
448 |
449 | /**
450 | * Generates URL parameters
451 | * @return string
452 | */
453 | public function generateUrlParams()
454 | {
455 | /** @var ActiveRecord $class */
456 | $class = $this->modelClass;
457 | $pks = $class::primaryKey();
458 | if (count($pks) === 1) {
459 | if (is_subclass_of($class, 'yii\mongodb\ActiveRecord')) {
460 | return "'id' => (string)\$model->{$pks[0]}";
461 | } else {
462 | return "'id' => \$model->{$pks[0]}";
463 | }
464 | } else {
465 | $params = [];
466 | foreach ($pks as $pk) {
467 | if (is_subclass_of($class, 'yii\mongodb\ActiveRecord')) {
468 | $params[] = "'$pk' => (string)\$model->$pk";
469 | } else {
470 | $params[] = "'$pk' => \$model->$pk";
471 | }
472 | }
473 |
474 | return implode(', ', $params);
475 | }
476 | }
477 |
478 | /**
479 | * Generates action parameters
480 | * @return string
481 | */
482 | public function generateActionParams()
483 | {
484 | /** @var ActiveRecord $class */
485 | $class = $this->modelClass;
486 | $pks = $class::primaryKey();
487 | if (count($pks) === 1) {
488 | return '$id';
489 | } else {
490 | return '$' . implode(', $', $pks);
491 | }
492 | }
493 |
494 | /**
495 | * Generates parameter tags for phpdoc
496 | * @return array parameter tags for phpdoc
497 | */
498 | public function generateActionParamComments()
499 | {
500 | /** @var ActiveRecord $class */
501 | $class = $this->modelClass;
502 | $pks = $class::primaryKey();
503 | if (($table = $this->getTableSchema()) === false) {
504 | $params = [];
505 | foreach ($pks as $pk) {
506 | $params[] = '@param ' . (substr(strtolower($pk), -2) == 'id' ? 'integer' : 'string') . ' $' . $pk;
507 | }
508 |
509 | return $params;
510 | }
511 | if (count($pks) === 1) {
512 | return ['@param ' . $table->columns[$pks[0]]->phpType . ' $id'];
513 | } else {
514 | $params = [];
515 | foreach ($pks as $pk) {
516 | $params[] = '@param ' . $table->columns[$pk]->phpType . ' $' . $pk;
517 | }
518 |
519 | return $params;
520 | }
521 | }
522 |
523 | /**
524 | * Returns table schema for current model class or false if it is not an active record
525 | * @return boolean|\yii\db\TableSchema
526 | */
527 | public function getTableSchema()
528 | {
529 | /** @var ActiveRecord $class */
530 | $class = $this->modelClass;
531 | if (is_subclass_of($class, 'yii\db\ActiveRecord')) {
532 | return $class::getTableSchema();
533 | } else {
534 | return false;
535 | }
536 | }
537 |
538 | /**
539 | * @return array model column names
540 | */
541 | public function getColumnNames()
542 | {
543 | /** @var ActiveRecord $class */
544 | $class = $this->modelClass;
545 | if (is_subclass_of($class, 'yii\db\ActiveRecord')) {
546 | return $class::getTableSchema()->getColumnNames();
547 | } else {
548 | /** @var \yii\base\Model $model */
549 | $model = new $class();
550 |
551 | return $model->attributes();
552 | }
553 | }
554 | }
555 |
--------------------------------------------------------------------------------
/crud/default/controller.php:
--------------------------------------------------------------------------------
1 | controllerClass);
14 | $modelClass = StringHelper::basename($generator->modelClass);
15 | $searchModelClass = StringHelper::basename($generator->searchModelClass);
16 | if ($modelClass === $searchModelClass) {
17 | $searchModelAlias = $searchModelClass . 'Search';
18 | }
19 |
20 | /** @var ActiveRecordInterface $class */
21 | $class = $generator->modelClass;
22 | $pks = $class::primaryKey();
23 | $urlParams = $generator->generateUrlParams();
24 | $actionParams = $generator->generateActionParams();
25 | $actionParamComments = $generator->generateActionParamComments();
26 |
27 | echo "
29 |
30 | namespace = StringHelper::dirname(ltrim($generator->controllerClass, '\\')) ?>;
31 |
32 | use Yii;
33 | use = ltrim($generator->modelClass, '\\') ?>;
34 | searchModelClass)): ?>
35 | use = ltrim($generator->searchModelClass, '\\') . (isset($searchModelAlias) ? " as $searchModelAlias" : "") ?>;
36 |
37 | use yii\data\ActiveDataProvider;
38 |
39 | use = ltrim($generator->baseControllerClass, '\\') ?>;
40 | use yii\web\NotFoundHttpException;
41 | use yii\filters\VerbFilter;
42 |
43 | /**
44 | * = $controllerClass ?> implements the CRUD actions for = $modelClass ?> model.
45 | */
46 | class = $controllerClass ?> extends = StringHelper::basename($generator->baseControllerClass) . "\n" ?>
47 | {
48 | public function behaviors()
49 | {
50 | return [
51 | 'verbs' => [
52 | 'class' => VerbFilter::className(),
53 | 'actions' => [
54 | 'delete' => ['post'],
55 | ],
56 | ],
57 | ];
58 | }
59 |
60 | /**
61 | * Lists all = $modelClass ?> models.
62 | * @return mixed
63 | */
64 | public function actionIndex()
65 | {
66 | searchModelClass)): ?>
67 | $searchModel = new = isset($searchModelAlias) ? $searchModelAlias : $searchModelClass ?>;
68 | $dataProvider = $searchModel->search(Yii::$app->request->getQueryParams());
69 |
70 | return $this->render('index', [
71 | 'dataProvider' => $dataProvider,
72 | 'searchModel' => $searchModel,
73 | ]);
74 |
75 | $dataProvider = new ActiveDataProvider([
76 | 'query' => = $modelClass ?>::find(),
77 | ]);
78 |
79 | return $this->render('index', [
80 | 'dataProvider' => $dataProvider,
81 | ]);
82 |
83 | }
84 |
85 | /**
86 | * Displays a single = $modelClass ?> model.
87 | * = implode("\n * ", $actionParamComments) . "\n" ?>
88 | * @return mixed
89 | */
90 | public function actionView(= $actionParams ?>)
91 | {
92 | $model = $this->findModel(= $actionParams ?>);
93 |
94 | if ($model->load(Yii::$app->request->post()) && $model->save()) {
95 | return $this->redirect(['view', 'id' => $model->=$generator->getTableSchema()->primaryKey[0]?>]);
96 | } else {
97 | return $this->render('view', ['model' => $model]);
98 | }
99 | }
100 |
101 | /**
102 | * Creates a new = $modelClass ?> model.
103 | * If creation is successful, the browser will be redirected to the 'view' page.
104 | * @return mixed
105 | */
106 | public function actionCreate()
107 | {
108 | $model = new = $modelClass ?>;
109 |
110 | if ($model->load(Yii::$app->request->post()) && $model->save()) {
111 | return $this->redirect(['view', = $urlParams ?>]);
112 | } else {
113 | return $this->render('create', [
114 | 'model' => $model,
115 | ]);
116 | }
117 | }
118 |
119 | /**
120 | * Updates an existing = $modelClass ?> model.
121 | * If update is successful, the browser will be redirected to the 'view' page.
122 | * = implode("\n * ", $actionParamComments) . "\n" ?>
123 | * @return mixed
124 | */
125 | public function actionUpdate(= $actionParams ?>)
126 | {
127 | $model = $this->findModel(= $actionParams ?>);
128 |
129 | if ($model->load(Yii::$app->request->post()) && $model->save()) {
130 | return $this->redirect(['view', = $urlParams ?>]);
131 | } else {
132 | return $this->render('update', [
133 | 'model' => $model,
134 | ]);
135 | }
136 | }
137 |
138 | /**
139 | * Deletes an existing = $modelClass ?> model.
140 | * If deletion is successful, the browser will be redirected to the 'index' page.
141 | * = implode("\n * ", $actionParamComments) . "\n" ?>
142 | * @return mixed
143 | */
144 | public function actionDelete(= $actionParams ?>)
145 | {
146 | $this->findModel(= $actionParams ?>)->delete();
147 |
148 | return $this->redirect(['index']);
149 | }
150 |
151 | /**
152 | * Finds the = $modelClass ?> model based on its primary key value.
153 | * If the model is not found, a 404 HTTP exception will be thrown.
154 | * = implode("\n * ", $actionParamComments) . "\n" ?>
155 | * @return = $modelClass ?> the loaded model
156 | * @throws NotFoundHttpException if the model cannot be found
157 | */
158 | protected function findModel(= $actionParams ?>)
159 | {
160 | \$$pk";
167 | }
168 | $condition = '[' . implode(', ', $condition) . ']';
169 | }
170 | ?>
171 | if (($model = = $modelClass ?>::findOne(= $condition ?>)) !== null) {
172 | return $model;
173 | } else {
174 | throw new NotFoundHttpException('The requested page does not exist.');
175 | }
176 | }
177 | }
178 |
--------------------------------------------------------------------------------
/crud/default/search.php:
--------------------------------------------------------------------------------
1 | modelClass);
13 | $searchModelClass = StringHelper::basename($generator->searchModelClass);
14 | if ($modelClass === $searchModelClass) {
15 | $modelAlias = $modelClass . 'Model';
16 | }
17 | $rules = $generator->generateSearchRules();
18 | $labels = $generator->generateSearchLabels();
19 | $searchAttributes = $generator->getSearchAttributes();
20 | $searchConditions = $generator->generateSearchConditions();
21 |
22 | echo "
24 |
25 | namespace = StringHelper::dirname(ltrim($generator->searchModelClass, '\\')) ?>;
26 |
27 | use Yii;
28 | use yii\base\Model;
29 | use yii\data\ActiveDataProvider;
30 | use = ltrim($generator->modelClass, '\\') . (isset($modelAlias) ? " as $modelAlias" : "") ?>;
31 |
32 | /**
33 | * = $searchModelClass ?> represents the model behind the search form about `= $generator->modelClass ?>`.
34 | */
35 | class = $searchModelClass ?> extends = isset($modelAlias) ? $modelAlias : $modelClass ?>
36 |
37 | {
38 | public function rules()
39 | {
40 | return [
41 | = implode(",\n ", $rules) ?>,
42 | ];
43 | }
44 |
45 | public function scenarios()
46 | {
47 | // bypass scenarios() implementation in the parent class
48 | return Model::scenarios();
49 | }
50 |
51 | public function search($params)
52 | {
53 | $query = = isset($modelAlias) ? $modelAlias : $modelClass ?>::find();
54 |
55 | $dataProvider = new ActiveDataProvider([
56 | 'query' => $query,
57 | ]);
58 |
59 | if (!($this->load($params) && $this->validate())) {
60 | return $dataProvider;
61 | }
62 |
63 | = implode("\n ", $searchConditions) ?>
64 |
65 | return $dataProvider;
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/crud/default/views/_form.php:
--------------------------------------------------------------------------------
1 | modelClass;
14 | $safeAttributes = $model->safeAttributes();
15 | if (empty($safeAttributes)) {
16 | $safeAttributes = $model->attributes();
17 | }
18 |
19 | echo "
22 |
23 | use yii\helpers\Html;
24 | use kartik\widgets\ActiveForm;
25 | use kartik\builder\Form;
26 | use kartik\datecontrol\DateControl;
27 |
28 | /**
29 | * @var yii\web\View $this
30 | * @var = ltrim($generator->modelClass, '\\') ?> $model
31 | * @var yii\widgets\ActiveForm $form
32 | */
33 | ?>
34 |
35 |
42 | = "Html::a(= $generator->generateString('Create {modelClass}', ['modelClass' => Inflector::camel2words(StringHelper::basename($generator->modelClass))]) ?>, ['create'], ['class' => 'btn btn-success'])= "*/ " ?> ?> 43 |
44 | 45 | indexWidgetType === 'grid'): ?> 46 | = "GridView::widget([ 47 | 'dataProvider' => $dataProvider, 48 | = !empty($generator->searchModelClass) ? "'filterModel' => \$searchModel,\n 'columns' => [\n" : "'columns' => [\n"; ?> 49 | ['class' => 'yii\grid\SerialColumn'], 50 | 51 | getTableSchema()) === false) { 54 | foreach ($generator->getColumnNames() as $name) { 55 | if (++$count < 6) { 56 | echo " '" . $name . "',\n"; 57 | } else { 58 | echo " // '" . $name . "',\n"; 59 | } 60 | } 61 | } else { 62 | foreach ($tableSchema->columns as $column) { 63 | $format = $generator->generateColumnFormat($column); 64 | if ($column->type === 'date') { 65 | $columnDisplay = " ['attribute' => '$column->name','format' => ['date',(isset(Yii::\$app->modules['datecontrol']['displaySettings']['date'])) ? Yii::\$app->modules['datecontrol']['displaySettings']['date'] : 'd-m-Y']],"; 66 | 67 | } elseif ($column->type === 'time') { 68 | $columnDisplay = " ['attribute' => '$column->name','format' => ['time',(isset(Yii::\$app->modules['datecontrol']['displaySettings']['time'])) ? Yii::\$app->modules['datecontrol']['displaySettings']['time'] : 'H:i:s A']],"; 69 | } elseif ($column->type === 'datetime' || $column->type === 'timestamp') { 70 | $columnDisplay = " ['attribute' => '$column->name','format' => ['datetime',(isset(Yii::\$app->modules['datecontrol']['displaySettings']['datetime'])) ? Yii::\$app->modules['datecontrol']['displaySettings']['datetime'] : 'd-m-Y H:i:s A']],"; 71 | } else { 72 | $columnDisplay = " '" . $column->name . ($format === 'text' ? "" : ":" . $format) . "',"; 73 | } 74 | if (++$count < 6) { 75 | echo $columnDisplay ."\n"; 76 | } else { 77 | echo "//" . $columnDisplay . " \n"; 78 | } 79 | } 80 | } 81 | ?> 82 | 83 | [ 84 | 'class' => 'yii\grid\ActionColumn', 85 | 'buttons' => [ 86 | 'update' => function ($url, $model) { 87 | return Html::a('', 88 | Yii::$app->urlManager->createUrl(['= (empty($generator->moduleID) ? '' : $generator->moduleID . '/') . $generator->controllerID?>/view', = $urlParams ?>, 'edit' => 't']), 89 | ['title' => Yii::t('yii', 'Edit'),] 90 | ); 91 | } 92 | ], 93 | ], 94 | ], 95 | 'responsive' => true, 96 | 'hover' => true, 97 | 'condensed' => true, 98 | 'floatHeader' => true, 99 | 100 | 'panel' => [ 101 | 'heading' => '