├── 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 controllerClass, '\\')) ?>; 31 | 32 | use Yii; 33 | use modelClass, '\\') ?>; 34 | searchModelClass)): ?> 35 | use searchModelClass, '\\') . (isset($searchModelAlias) ? " as $searchModelAlias" : "") ?>; 36 | 37 | use yii\data\ActiveDataProvider; 38 | 39 | use baseControllerClass, '\\') ?>; 40 | use yii\web\NotFoundHttpException; 41 | use yii\filters\VerbFilter; 42 | 43 | /** 44 | * implements the CRUD actions for model. 45 | */ 46 | class extends 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 models. 62 | * @return mixed 63 | */ 64 | public function actionIndex() 65 | { 66 | searchModelClass)): ?> 67 | $searchModel = new ; 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' => ::find(), 77 | ]); 78 | 79 | return $this->render('index', [ 80 | 'dataProvider' => $dataProvider, 81 | ]); 82 | 83 | } 84 | 85 | /** 86 | * Displays a single model. 87 | * 88 | * @return mixed 89 | */ 90 | public function actionView() 91 | { 92 | $model = $this->findModel(); 93 | 94 | if ($model->load(Yii::$app->request->post()) && $model->save()) { 95 | return $this->redirect(['view', 'id' => $model->getTableSchema()->primaryKey[0]?>]); 96 | } else { 97 | return $this->render('view', ['model' => $model]); 98 | } 99 | } 100 | 101 | /** 102 | * Creates a new 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 ; 109 | 110 | if ($model->load(Yii::$app->request->post()) && $model->save()) { 111 | return $this->redirect(['view', ]); 112 | } else { 113 | return $this->render('create', [ 114 | 'model' => $model, 115 | ]); 116 | } 117 | } 118 | 119 | /** 120 | * Updates an existing model. 121 | * If update is successful, the browser will be redirected to the 'view' page. 122 | * 123 | * @return mixed 124 | */ 125 | public function actionUpdate() 126 | { 127 | $model = $this->findModel(); 128 | 129 | if ($model->load(Yii::$app->request->post()) && $model->save()) { 130 | return $this->redirect(['view', ]); 131 | } else { 132 | return $this->render('update', [ 133 | 'model' => $model, 134 | ]); 135 | } 136 | } 137 | 138 | /** 139 | * Deletes an existing model. 140 | * If deletion is successful, the browser will be redirected to the 'index' page. 141 | * 142 | * @return mixed 143 | */ 144 | public function actionDelete() 145 | { 146 | $this->findModel()->delete(); 147 | 148 | return $this->redirect(['index']); 149 | } 150 | 151 | /** 152 | * Finds the model based on its primary key value. 153 | * If the model is not found, a 404 HTTP exception will be thrown. 154 | * 155 | * @return the loaded model 156 | * @throws NotFoundHttpException if the model cannot be found 157 | */ 158 | protected function findModel() 159 | { 160 | \$$pk"; 167 | } 168 | $condition = '[' . implode(', ', $condition) . ']'; 169 | } 170 | ?> 171 | if (($model = ::findOne()) !== 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 searchModelClass, '\\')) ?>; 26 | 27 | use Yii; 28 | use yii\base\Model; 29 | use yii\data\ActiveDataProvider; 30 | use modelClass, '\\') . (isset($modelAlias) ? " as $modelAlias" : "") ?>; 31 | 32 | /** 33 | * represents the model behind the search form about `modelClass ?>`. 34 | */ 35 | class extends 36 | 37 | { 38 | public function rules() 39 | { 40 | return [ 41 | , 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 = ::find(); 54 | 55 | $dataProvider = new ActiveDataProvider([ 56 | 'query' => $query, 57 | ]); 58 | 59 | if (!($this->load($params) && $this->validate())) { 60 | return $dataProvider; 61 | } 62 | 63 | 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 modelClass, '\\') ?> $model 31 | * @var yii\widgets\ActiveForm $form 32 | */ 33 | ?> 34 | 35 |
36 | 37 | $form = ActiveForm::begin(['type' => ActiveForm::TYPE_HORIZONTAL]); echo Form::widget([ 38 | 39 | 'model' => $model, 40 | 'form' => $form, 41 | 'columns' => 1, 42 | 'attributes' => [ 43 | 44 | 45 | generateActiveField($attribute) . "\n\n"; ?> 46 | 47 | ] 48 | 49 | ]); 50 | 51 | echo Html::submitButton($model->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), 52 | ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary'] 53 | ); 54 | ActiveForm::end(); ?> 55 | 56 |
57 | -------------------------------------------------------------------------------- /crud/default/views/_search.php: -------------------------------------------------------------------------------- 1 | 13 | 14 | use yii\helpers\Html; 15 | use yii\widgets\ActiveForm; 16 | 17 | /** 18 | * @var yii\web\View $this 19 | * @var searchModelClass, '\\') ?> $model 20 | * @var yii\widgets\ActiveForm $form 21 | */ 22 | ?> 23 | 24 | 49 | -------------------------------------------------------------------------------- /crud/default/views/create.php: -------------------------------------------------------------------------------- 1 | 13 | 14 | use yii\helpers\Html; 15 | 16 | /** 17 | * @var yii\web\View $this 18 | * @var modelClass, '\\') ?> $model 19 | */ 20 | 21 | $this->title = generateString('Create {modelClass}', ['modelClass' => Inflector::camel2words(StringHelper::basename($generator->modelClass))]) ?>; 22 | $this->params['breadcrumbs'][] = ['label' => generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']]; 23 | $this->params['breadcrumbs'][] = $this->title; 24 | ?> 25 |
26 | 29 | $this->render('_form', [ 30 | 'model' => $model, 31 | ]) ?> 32 | 33 |
34 | -------------------------------------------------------------------------------- /crud/default/views/index.php: -------------------------------------------------------------------------------- 1 | generateUrlParams(); 13 | $nameAttribute = $generator->getNameAttribute(); 14 | 15 | echo " 19 | 20 | use yii\helpers\Html; 21 | use indexWidgetType === 'grid' ? "kartik\\grid\\GridView" : "yii\\widgets\\ListView" ?>; 22 | use yii\widgets\Pjax; 23 | 24 | /** 25 | * @var yii\web\View $this 26 | * @var yii\data\ActiveDataProvider $dataProvider 27 | searchModelClass) ? " * @var " . ltrim($generator->searchModelClass, '\\') . " \$searchModel\n" : '' ?> 28 | */ 29 | 30 | $this->title = generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>; 31 | $this->params['breadcrumbs'][] = $this->title; 32 | ?> 33 |
34 | 37 | searchModelClass)): ?> 38 | indexWidgetType === 'grid' ? "// " : "") ?>echo $this->render('_search', ['model' => $searchModel]); ?> 39 | 40 | 41 |

42 | Html::a(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 | 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(['moduleID) ? '' : $generator->moduleID . '/') . $generator->controllerID?>/view', , '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' => '

'.Html::encode($this->title).'

', 102 | 'type' => 'info', 103 | 'before' => Html::a(' Add', ['create'], ['class' => 'btn btn-success']), 104 | 'after' => Html::a(' Reset List', ['index'], ['class' => 'btn btn-info']), 105 | 'showFooter' => false 106 | ], 107 | ]); Pjax::end(); ?> 108 | 109 | ListView::widget([ 110 | 'dataProvider' => $dataProvider, 111 | 'itemOptions' => ['class' => 'item'], 112 | 'itemView' => function ($model, $key, $index, $widget) { 113 | return Html::a(Html::encode($model->), ['view', ]); 114 | }, 115 | ]) ?> 116 | 117 | 118 |
119 | -------------------------------------------------------------------------------- /crud/default/views/update.php: -------------------------------------------------------------------------------- 1 | generateUrlParams(); 12 | 13 | echo " 15 | 16 | use yii\helpers\Html; 17 | 18 | /** 19 | * @var yii\web\View $this 20 | * @var modelClass, '\\') ?> $model 21 | */ 22 | 23 | $this->title = generateString('Update {modelClass}: ', ['modelClass' => Inflector::camel2words(StringHelper::basename($generator->modelClass))]) ?> . ' ' . $model->getNameAttribute() ?>; 24 | $this->params['breadcrumbs'][] = ['label' => generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']]; 25 | $this->params['breadcrumbs'][] = ['label' => $model->getNameAttribute() ?>, 'url' => ['view', ]]; 26 | $this->params['breadcrumbs'][] = generateString('Update') ?>; 27 | ?> 28 |
29 | 30 |

Html::encode($this->title) ?>

31 | 32 | $this->render('_form', [ 33 | 'model' => $model, 34 | ]) ?> 35 | 36 |
37 | -------------------------------------------------------------------------------- /crud/default/views/view.php: -------------------------------------------------------------------------------- 1 | generateUrlParams(); 12 | 13 | echo " 15 | 16 | use yii\helpers\Html; 17 | use kartik\detail\DetailView; 18 | use kartik\datecontrol\DateControl; 19 | 20 | /** 21 | * @var yii\web\View $this 22 | * @var modelClass, '\\') ?> $model 23 | */ 24 | 25 | $this->title = $model->getNameAttribute() ?>; 26 | $this->params['breadcrumbs'][] = ['label' => generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']]; 27 | $this->params['breadcrumbs'][] = $this->title; 28 | ?> 29 |
30 | 33 | 34 | 35 | DetailView::widget([ 36 | 'model' => $model, 37 | 'condensed' => false, 38 | 'hover' => true, 39 | 'mode' => Yii::$app->request->get('edit') == 't' ? DetailView::MODE_EDIT : DetailView::MODE_VIEW, 40 | 'panel' => [ 41 | 'heading' => $this->title, 42 | 'type' => DetailView::TYPE_INFO, 43 | ], 44 | 'attributes' => [ 45 | getTableSchema()) === false) { 47 | foreach ($generator->getColumnNames() as $name) { 48 | echo " '" . $name . "',\n"; 49 | } 50 | } else { 51 | foreach ($generator->getTableSchema()->columns as $column) { 52 | 53 | $format = $generator->generateColumnFormat($column); 54 | 55 | if ($column->type === 'date') { 56 | echo 57 | " [ 58 | 'attribute' => '$column->name', 59 | 'format' => [ 60 | 'date', (isset(Yii::\$app->modules['datecontrol']['displaySettings']['date'])) 61 | ? Yii::\$app->modules['datecontrol']['displaySettings']['date'] 62 | : 'd-m-Y' 63 | ], 64 | 'type' => DetailView::INPUT_WIDGET, 65 | 'widgetOptions' => [ 66 | 'class' => DateControl::classname(), 67 | 'type' => DateControl::FORMAT_DATE 68 | ] 69 | ],\n"; 70 | 71 | } elseif ($column->type === 'time') { 72 | echo 73 | " [ 74 | 'attribute' => '$column->name', 75 | 'format' => [ 76 | 'time', (isset(Yii::\$app->modules['datecontrol']['displaySettings']['time'])) 77 | ? Yii::\$app->modules['datecontrol']['displaySettings']['time'] 78 | : 'H:i:s A' 79 | ], 80 | 'type' => DetailView::INPUT_WIDGET, 81 | 'widgetOptions' => [ 82 | 'class' => DateControl::classname(), 83 | 'type' => DateControl::FORMAT_TIME 84 | ] 85 | ],\n"; 86 | } elseif ($column->type === 'datetime' || $column->type === 'timestamp') { 87 | echo 88 | " [ 89 | 'attribute' => '$column->name', 90 | 'format' => [ 91 | 'datetime', (isset(Yii::\$app->modules['datecontrol']['displaySettings']['datetime'])) 92 | ? Yii::\$app->modules['datecontrol']['displaySettings']['datetime'] 93 | : 'd-m-Y H:i:s A' 94 | ], 95 | 'type' => DetailView::INPUT_WIDGET, 96 | 'widgetOptions' => [ 97 | 'class' => DateControl::classname(), 98 | 'type' => DateControl::FORMAT_DATETIME 99 | ] 100 | ],\n"; 101 | } else { 102 | echo " '" . $column->name . ($format === 'text' ? "" : ":" . $format) . "',\n"; 103 | } 104 | } 105 | } 106 | ?> 107 | ], 108 | 'deleteOptions' => [ 109 | 'url' => ['delete', 'id' => $model->getTableSchema()->primaryKey[0]?>], 110 | ], 111 | 'enableEditMode' => true, 112 | ]) ?> 113 | 114 |
115 | -------------------------------------------------------------------------------- /crud/form.php: -------------------------------------------------------------------------------- 1 | field($generator, 'modelClass'); 9 | echo $form->field($generator, 'searchModelClass'); 10 | echo $form->field($generator, 'controllerClass'); 11 | echo $form->field($generator, 'baseControllerClass'); 12 | echo $form->field($generator, 'moduleID'); 13 | echo $form->field($generator, 'indexWidgetType')->dropDownList([ 14 | 'grid' => 'GridView', 15 | 'list' => 'ListView', 16 | ]); 17 | echo $form->field($generator, 'enableI18N')->checkbox(); 18 | echo $form->field($generator, 'messageCategory'); 19 | --------------------------------------------------------------------------------