Browse Source

Merge branch 'master' of https://git.dev.tencent.com/linyaostalker/Antbasic

wechat_public_accounts
root 5 years ago
parent
commit
d3d52e9864
  1. 3
      common/config/main.php
  2. 9
      environments/skeleton/kcadmin/config/main-local.php
  3. 371
      vendor/blobt/generators/crud/Generator.php
  4. 2
      vendor/blobt/generators/crud/default/views/create.php
  5. 2
      vendor/blobt/generators/crud/default/views/update.php
  6. 17
      vendor/blobt/generators/crud/form.php
  7. 555
      vendor/linyao/generators/crud/Generator.php
  8. 179
      vendor/linyao/generators/crud/default/controller.php
  9. 86
      vendor/linyao/generators/crud/default/search.php
  10. 43
      vendor/linyao/generators/crud/default/views/_form.php
  11. 45
      vendor/linyao/generators/crud/default/views/_search.php
  12. 27
      vendor/linyao/generators/crud/default/views/create.php
  13. 61
      vendor/linyao/generators/crud/default/views/index.php
  14. 38
      vendor/linyao/generators/crud/default/views/update.php
  15. 49
      vendor/linyao/generators/crud/default/views/view.php
  16. 17
      vendor/linyao/generators/crud/form.php
  17. 995
      vendor/linyao/generators/model/Generator.php
  18. 124
      vendor/linyao/generators/model/default/model.php
  19. 56
      vendor/linyao/generators/model/default/query.php
  20. 30
      vendor/linyao/generators/model/form.php

3
common/config/main.php

@ -5,7 +5,8 @@ return [
'@bower' => '@vendor/bower-asset', '@bower' => '@vendor/bower-asset',
'@npm' => '@vendor/npm-asset', '@npm' => '@vendor/npm-asset',
'@blobt' => '@vendor/blobt', '@blobt' => '@vendor/blobt',
'@iron' => '@vendor/iron'
'@iron' => '@vendor/iron',
'@linyao' => '@vendor/linyao'
], ],
'vendorPath' => dirname(dirname(__DIR__)) . '/vendor', 'vendorPath' => dirname(dirname(__DIR__)) . '/vendor',
'timeZone' => 'Asia/Shanghai', 'timeZone' => 'Asia/Shanghai',

9
environments/skeleton/kcadmin/config/main-local.php

@ -22,9 +22,16 @@ if (!YII_ENV_TEST) {
'allowedIPs' => ['127.0.0.1'], 'allowedIPs' => ['127.0.0.1'],
'generators' => [ 'generators' => [
'crud' => [ 'crud' => [
'class' => 'yii\gii\generators\crud\Generator',
'class' => 'blobt\generators\crud\Generator',
'templates' => [ 'templates' => [
'blobtCrud' => '@blobt/generators/crud/default', 'blobtCrud' => '@blobt/generators/crud/default',
'linyaoCrud' => '@linyao/generators/crud/default',
]
],
'model' => [
'class' => 'linyao\generators\model\Generator',
'templates' => [
'linyaoModel' => '@linyao/generators/model/default',
] ]
] ]
], ],

371
vendor/blobt/generators/crud/Generator.php

@ -24,7 +24,7 @@
* THE SOFTWARE. * THE SOFTWARE.
*/ */
namespace blobt\generators\curd;
namespace blobt\generators\crud;
use Yii; use Yii;
use yii\db\ActiveRecord; use yii\db\ActiveRecord;
@ -51,6 +51,9 @@ class Generator extends \yii\gii\Generator {
public $indexWidgetType = 'grid'; public $indexWidgetType = 'grid';
public $searchModelClass = ''; public $searchModelClass = '';
public $enablePjax = false;
public $strictInflector = true;
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -58,6 +61,77 @@ class Generator extends \yii\gii\Generator {
return 'CRUD Generator'; return 'CRUD Generator';
} }
/**
* {@inheritdoc}
*/
public function getDescription() {
return 'This generator generates a controller and views that implement CRUD (Create, Read, Update, Delete)
operations for the specified data model.';
}
/**
* {@inheritdoc}
*/
public function rules() {
return array_merge(parent::rules(), [
[['controllerClass', 'modelClass', 'searchModelClass', 'baseControllerClass'], 'filter', 'filter' => 'trim'],
[['modelClass', 'controllerClass', 'baseControllerClass', 'indexWidgetType'], 'required'],
[['searchModelClass'], 'compare', 'compareAttribute' => 'modelClass', 'operator' => '!==', 'message' => 'Search Model Class must not be equal to Model Class.'],
[['modelClass', 'controllerClass', 'baseControllerClass', 'searchModelClass'], 'match', 'pattern' => '/^[\w\\\\]*$/', 'message' => 'Only word characters and backslashes are allowed.'],
[['modelClass'], 'validateClass', 'params' => ['extends' => BaseActiveRecord::className()]],
[['baseControllerClass'], 'validateClass', 'params' => ['extends' => Controller::className()]],
[['controllerClass'], 'match', 'pattern' => '/Controller$/', 'message' => 'Controller class name must be suffixed with "Controller".'],
[['controllerClass'], 'match', 'pattern' => '/(^|\\\\)[A-Z][^\\\\]+Controller$/', 'message' => 'Controller class name must start with an uppercase letter.'],
[['controllerClass', 'searchModelClass'], 'validateNewClass'],
[['indexWidgetType'], 'in', 'range' => ['grid', 'list']],
[['modelClass'], 'validateModelClass'],
[['enableI18N', 'enablePjax'], 'boolean'],
[['messageCategory'], 'validateMessageCategory', 'skipOnEmpty' => false],
['viewPath', 'safe'],
]);
}
/**
* {@inheritdoc}
*/
public function attributeLabels() {
return array_merge(parent::attributeLabels(), [
'modelClass' => 'Model Class',
'controllerClass' => 'Controller Class',
'viewPath' => 'View Path',
'baseControllerClass' => 'Base Controller Class',
'indexWidgetType' => 'Widget Used in Index Page',
'searchModelClass' => 'Search Model Class',
'enablePjax' => 'Enable Pjax',
]);
}
/**
* {@inheritdoc}
*/
public function hints() {
return array_merge(parent::hints(), [
'modelClass' => 'This is the ActiveRecord class associated with the table that CRUD will be built upon.
You should provide a fully qualified class name, e.g., <code>app\models\Post</code>.',
'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 with an uppercase first letter. Make sure the class
is using the same namespace as specified by your application\'s controllerNamespace property.',
'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/post</code>, <code>@app/views/post</code>. If not set, it will default
to <code>@app/views/ControllerID</code>',
'baseControllerClass' => 'This is the class that the new CRUD controller class will extend from.
You should provide a fully qualified class name, e.g., <code>yii\web\Controller</code>.',
'indexWidgetType' => 'This is the widget type to be used in the index page to display list of the models.
You may choose either <code>GridView</code> or <code>ListView</code>',
'searchModelClass' => 'This is the name of the search model class to be generated. You should provide a fully
qualified namespaced class name, e.g., <code>app\models\PostSearch</code>.',
'enablePjax' => 'This indicates whether the generator should wrap the <code>GridView</code> or <code>ListView</code>
widget on the index page with <code>yii\widgets\Pjax</code> widget. Set this to <code>true</code> if you want to get
sorting, filtering and pagination without page refreshing.',
]);
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -72,6 +146,18 @@ class Generator extends \yii\gii\Generator {
return array_merge(parent::stickyAttributes(), ['baseControllerClass', 'indexWidgetType']); return array_merge(parent::stickyAttributes(), ['baseControllerClass', 'indexWidgetType']);
} }
/**
* Checks if model class is valid
*/
public function validateModelClass() {
/* @var $class ActiveRecord */
$class = $this->modelClass;
$pk = $class::primaryKey();
if (empty($pk)) {
$this->addError('modelClass', "The table associated with $class must have primary key(s).");
}
}
/** /**
* {@inheritdoc} * {@inheritdoc}
*/ */
@ -183,4 +269,287 @@ class Generator extends \yii\gii\Generator {
return "\$form->field(\$model, '$attribute')->$input(['maxlength' => true])"; return "\$form->field(\$model, '$attribute')->$input(['maxlength' => true])";
} }
/**
* Generates column format
* @param \yii\db\ColumnSchema $column
* @return string
*/
public function generateColumnFormat($column) {
if ($column->phpType === 'boolean') {
return 'boolean';
}
if ($column->type === 'text') {
return 'ntext';
}
if (stripos($column->name, 'time') !== false && $column->phpType === 'integer') {
return 'datetime';
}
if (stripos($column->name, 'email') !== false) {
return 'email';
}
if (preg_match('/(\b|[_-])url(\b|[_-])/i', $column->name)) {
return 'url';
}
return 'text';
}
/**
* Generates validation rules for the search model.
* @return array the generated validation rules
*/
public function generateSearchRules()
{
if (($table = $this->getTableSchema()) === false) {
return ["[['" . implode("', '", $this->getColumnNames()) . "'], 'safe']"];
}
$types = [];
foreach ($table->columns as $column) {
switch ($column->type) {
case Schema::TYPE_TINYINT:
case Schema::TYPE_SMALLINT:
case Schema::TYPE_INTEGER:
case Schema::TYPE_BIGINT:
$types['integer'][] = $column->name;
break;
case Schema::TYPE_BOOLEAN:
$types['boolean'][] = $column->name;
break;
case Schema::TYPE_FLOAT:
case Schema::TYPE_DOUBLE:
case Schema::TYPE_DECIMAL:
case Schema::TYPE_MONEY:
$types['number'][] = $column->name;
break;
case Schema::TYPE_DATE:
case Schema::TYPE_TIME:
case Schema::TYPE_DATETIME:
case Schema::TYPE_TIMESTAMP:
default:
$types['safe'][] = $column->name;
break;
}
}
$rules = [];
foreach ($types as $type => $columns) {
$rules[] = "[['" . implode("', '", $columns) . "'], '$type']";
}
return $rules;
}
/**
* @return array searchable attributes
*/
public function getSearchAttributes()
{
return $this->getColumnNames();
}
/**
* Generates the attribute labels for the search model.
* @return array the generated attribute labels (name => label)
*/
public function generateSearchLabels()
{
/* @var $model \yii\base\Model */
$model = new $this->modelClass();
$attributeLabels = $model->attributeLabels();
$labels = [];
foreach ($this->getColumnNames() as $name) {
if (isset($attributeLabels[$name])) {
$labels[$name] = $attributeLabels[$name];
} else {
if (!strcasecmp($name, 'id')) {
$labels[$name] = 'ID';
} else {
$label = Inflector::camel2words($name);
if (!empty($label) && substr_compare($label, ' id', -3, 3, true) === 0) {
$label = substr($label, 0, -3) . ' ID';
}
$labels[$name] = $label;
}
}
}
return $labels;
}
/**
* Generates search conditions
* @return array
*/
public function generateSearchConditions()
{
$columns = [];
if (($table = $this->getTableSchema()) === false) {
$class = $this->modelClass;
/* @var $model \yii\base\Model */
$model = new $class();
foreach ($model->attributes() as $attribute) {
$columns[$attribute] = 'unknown';
}
} else {
foreach ($table->columns as $column) {
$columns[$column->name] = $column->type;
}
}
$likeConditions = [];
$hashConditions = [];
foreach ($columns as $column => $type) {
switch ($type) {
case Schema::TYPE_TINYINT:
case Schema::TYPE_SMALLINT:
case Schema::TYPE_INTEGER:
case Schema::TYPE_BIGINT:
case Schema::TYPE_BOOLEAN:
case Schema::TYPE_FLOAT:
case Schema::TYPE_DOUBLE:
case Schema::TYPE_DECIMAL:
case Schema::TYPE_MONEY:
case Schema::TYPE_DATE:
case Schema::TYPE_TIME:
case Schema::TYPE_DATETIME:
case Schema::TYPE_TIMESTAMP:
$hashConditions[] = "'{$column}' => \$this->{$column},";
break;
default:
$likeKeyword = $this->getClassDbDriverName() === 'pgsql' ? 'ilike' : 'like';
$likeConditions[] = "->andFilterWhere(['{$likeKeyword}', '{$column}', \$this->{$column}])";
break;
}
}
$conditions = [];
if (!empty($hashConditions)) {
$conditions[] = "\$query->andFilterWhere([\n"
. str_repeat(' ', 12) . implode("\n" . str_repeat(' ', 12), $hashConditions)
. "\n" . str_repeat(' ', 8) . "]);\n";
}
if (!empty($likeConditions)) {
$conditions[] = "\$query" . implode("\n" . str_repeat(' ', 12), $likeConditions) . ";\n";
}
return $conditions;
}
/**
* Generates URL parameters
* @return string
*/
public function generateUrlParams() {
/* @var $class ActiveRecord */
$class = $this->modelClass;
$pks = $class::primaryKey();
if (count($pks) === 1) {
if (is_subclass_of($class, 'yii\mongodb\ActiveRecord')) {
return "'id' => (string)\$model->{$pks[0]}";
}
return "'id' => \$model->{$pks[0]}";
}
$params = [];
foreach ($pks as $pk) {
if (is_subclass_of($class, 'yii\mongodb\ActiveRecord')) {
$params[] = "'$pk' => (string)\$model->$pk";
} else {
$params[] = "'$pk' => \$model->$pk";
}
}
return implode(', ', $params);
}
/**
* Generates action parameters
* @return string
*/
public function generateActionParams() {
/* @var $class ActiveRecord */
$class = $this->modelClass;
$pks = $class::primaryKey();
if (count($pks) === 1) {
return '$id';
}
return '$' . implode(', $', $pks);
}
/**
* Generates parameter tags for phpdoc
* @return array parameter tags for phpdoc
*/
public function generateActionParamComments() {
/* @var $class ActiveRecord */
$class = $this->modelClass;
$pks = $class::primaryKey();
if (($table = $this->getTableSchema()) === false) {
$params = [];
foreach ($pks as $pk) {
$params[] = '@param ' . (strtolower(substr($pk, -2)) === 'id' ? 'integer' : 'string') . ' $' . $pk;
}
return $params;
}
if (count($pks) === 1) {
return ['@param ' . $table->columns[$pks[0]]->phpType . ' $id'];
}
$params = [];
foreach ($pks as $pk) {
$params[] = '@param ' . $table->columns[$pk]->phpType . ' $' . $pk;
}
return $params;
}
/**
* Returns table schema for current model class or false if it is not an active record
* @return bool|\yii\db\TableSchema
*/
public function getTableSchema() {
/* @var $class ActiveRecord */
$class = $this->modelClass;
if (is_subclass_of($class, 'yii\db\ActiveRecord')) {
return $class::getTableSchema();
}
return false;
}
/**
* @return array model column names
*/
public function getColumnNames() {
/* @var $class ActiveRecord */
$class = $this->modelClass;
if (is_subclass_of($class, 'yii\db\ActiveRecord')) {
return $class::getTableSchema()->getColumnNames();
}
/* @var $model \yii\base\Model */
$model = new $class();
return $model->attributes();
}
/**
* @return string|null driver name of modelClass db connection.
* In case db is not instance of \yii\db\Connection null will be returned.
* @since 2.0.6
*/
protected function getClassDbDriverName() {
/* @var $class ActiveRecord */
$class = $this->modelClass;
$db = $class::getDb();
return $db instanceof \yii\db\Connection ? $db->driverName : null;
}
} }

2
vendor/blobt/generators/crud/default/views/create.php

@ -14,7 +14,7 @@ use yii\helpers\Html;
/* @var $this yii\web\View */ /* @var $this yii\web\View */
/* @var $model <?= ltrim($generator->modelClass, '\\') ?> */ /* @var $model <?= ltrim($generator->modelClass, '\\') ?> */
$this->title = <?= $generator->generateString('Create ' . Inflector::camel2words(StringHelper::basename($generator->modelClass))) ?>;
$this->title = <?= $generator->generateString('创建 ' . Inflector::camel2words(StringHelper::basename($generator->modelClass))) ?>;
$this->params['breadcrumbs'][] = ['label' => <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']]; $this->params['breadcrumbs'][] = ['label' => <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title; $this->params['breadcrumbs'][] = $this->title;
?> ?>

2
vendor/blobt/generators/crud/default/views/update.php

@ -27,7 +27,7 @@ use yii\helpers\Html;
$this->title = <?= $title ?>; $this->title = <?= $title ?>;
$this->params['breadcrumbs'][] = ['label' => <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']]; $this->params['breadcrumbs'][] = ['label' => <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $model-><?= $generator->getNameAttribute() ?>, 'url' => ['view', <?= $urlParams ?>]]; $this->params['breadcrumbs'][] = ['label' => $model-><?= $generator->getNameAttribute() ?>, 'url' => ['view', <?= $urlParams ?>]];
$this->params['breadcrumbs'][] = <?= $generator->generateString('Update') ?>;
$this->params['breadcrumbs'][] = <?= $generator->generateString('Update ') ?>;
?> ?>
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-update"> <div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-update">

17
vendor/blobt/generators/crud/form.php

@ -0,0 +1,17 @@
<?php
/* @var $this yii\web\View */
/* @var $form yii\widgets\ActiveForm */
/* @var $generator yii\gii\generators\crud\Generator */
echo $form->field($generator, 'modelClass');
echo $form->field($generator, 'searchModelClass');
echo $form->field($generator, 'controllerClass');
echo $form->field($generator, 'viewPath');
echo $form->field($generator, 'baseControllerClass');
echo $form->field($generator, 'indexWidgetType')->dropDownList([
'grid' => 'GridView',
'list' => 'ListView',
]);
echo $form->field($generator, 'enableI18N')->checkbox();
echo $form->field($generator, 'enablePjax')->checkbox();
echo $form->field($generator, 'messageCategory');

555
vendor/linyao/generators/crud/Generator.php

@ -0,0 +1,555 @@
<?php
/*
* The MIT License
*
* Copyright 2019 Blobt.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
namespace blobt\generators\crud;
use Yii;
use yii\db\ActiveRecord;
use yii\db\BaseActiveRecord;
use yii\db\Schema;
use yii\gii\CodeFile;
use yii\helpers\Inflector;
use yii\helpers\VarDumper;
use yii\web\Controller;
/**
* Description of Generator
*
* @author Blobt
* @email 380255922@qq.com
* @created Oct 6, 2019
*/
class Generator extends \yii\gii\Generator {
public $modelClass;
public $controllerClass;
public $viewPath;
public $baseControllerClass = 'yii\web\Controller';
public $indexWidgetType = 'grid';
public $searchModelClass = '';
public $enablePjax = false;
public $strictInflector = true;
/**
* {@inheritdoc}
*/
public function getName() {
return 'CRUD Generator';
}
/**
* {@inheritdoc}
*/
public function getDescription() {
return 'This generator generates a controller and views that implement CRUD (Create, Read, Update, Delete)
operations for the specified data model.';
}
/**
* {@inheritdoc}
*/
public function rules() {
return array_merge(parent::rules(), [
[['controllerClass', 'modelClass', 'searchModelClass', 'baseControllerClass'], 'filter', 'filter' => 'trim'],
[['modelClass', 'controllerClass', 'baseControllerClass', 'indexWidgetType'], 'required'],
[['searchModelClass'], 'compare', 'compareAttribute' => 'modelClass', 'operator' => '!==', 'message' => 'Search Model Class must not be equal to Model Class.'],
[['modelClass', 'controllerClass', 'baseControllerClass', 'searchModelClass'], 'match', 'pattern' => '/^[\w\\\\]*$/', 'message' => 'Only word characters and backslashes are allowed.'],
[['modelClass'], 'validateClass', 'params' => ['extends' => BaseActiveRecord::className()]],
[['baseControllerClass'], 'validateClass', 'params' => ['extends' => Controller::className()]],
[['controllerClass'], 'match', 'pattern' => '/Controller$/', 'message' => 'Controller class name must be suffixed with "Controller".'],
[['controllerClass'], 'match', 'pattern' => '/(^|\\\\)[A-Z][^\\\\]+Controller$/', 'message' => 'Controller class name must start with an uppercase letter.'],
[['controllerClass', 'searchModelClass'], 'validateNewClass'],
[['indexWidgetType'], 'in', 'range' => ['grid', 'list']],
[['modelClass'], 'validateModelClass'],
[['enableI18N', 'enablePjax'], 'boolean'],
[['messageCategory'], 'validateMessageCategory', 'skipOnEmpty' => false],
['viewPath', 'safe'],
]);
}
/**
* {@inheritdoc}
*/
public function attributeLabels() {
return array_merge(parent::attributeLabels(), [
'modelClass' => 'Model Class',
'controllerClass' => 'Controller Class',
'viewPath' => 'View Path',
'baseControllerClass' => 'Base Controller Class',
'indexWidgetType' => 'Widget Used in Index Page',
'searchModelClass' => 'Search Model Class',
'enablePjax' => 'Enable Pjax',
]);
}
/**
* {@inheritdoc}
*/
public function hints() {
return array_merge(parent::hints(), [
'modelClass' => 'This is the ActiveRecord class associated with the table that CRUD will be built upon.
You should provide a fully qualified class name, e.g., <code>app\models\Post</code>.',
'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 with an uppercase first letter. Make sure the class
is using the same namespace as specified by your application\'s controllerNamespace property.',
'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/post</code>, <code>@app/views/post</code>. If not set, it will default
to <code>@app/views/ControllerID</code>',
'baseControllerClass' => 'This is the class that the new CRUD controller class will extend from.
You should provide a fully qualified class name, e.g., <code>yii\web\Controller</code>.',
'indexWidgetType' => 'This is the widget type to be used in the index page to display list of the models.
You may choose either <code>GridView</code> or <code>ListView</code>',
'searchModelClass' => 'This is the name of the search model class to be generated. You should provide a fully
qualified namespaced class name, e.g., <code>app\models\PostSearch</code>.',
'enablePjax' => 'This indicates whether the generator should wrap the <code>GridView</code> or <code>ListView</code>
widget on the index page with <code>yii\widgets\Pjax</code> widget. Set this to <code>true</code> if you want to get
sorting, filtering and pagination without page refreshing.',
]);
}
/**
* {@inheritdoc}
*/
public function requiredTemplates() {
return ['controller.php'];
}
/**
* {@inheritdoc}
*/
public function stickyAttributes() {
return array_merge(parent::stickyAttributes(), ['baseControllerClass', 'indexWidgetType']);
}
/**
* Checks if model class is valid
*/
public function validateModelClass() {
/* @var $class ActiveRecord */
$class = $this->modelClass;
$pk = $class::primaryKey();
if (empty($pk)) {
$this->addError('modelClass', "The table associated with $class must have primary key(s).");
}
}
/**
* {@inheritdoc}
*/
public function generate() {
$controllerFile = Yii::getAlias('@' . str_replace('\\', '/', ltrim($this->controllerClass, '\\')) . '.php');
$files = [
new CodeFile($controllerFile, $this->render('controller.php')),
];
if (!empty($this->searchModelClass)) {
$searchModel = Yii::getAlias('@' . str_replace('\\', '/', ltrim($this->searchModelClass, '\\') . '.php'));
$files[] = new CodeFile($searchModel, $this->render('search.php'));
}
$viewPath = $this->getViewPath();
$templatePath = $this->getTemplatePath() . '/views';
foreach (scandir($templatePath) as $file) {
if (empty($this->searchModelClass) && $file === '_search.php') {
continue;
}
if (is_file($templatePath . '/' . $file) && pathinfo($file, PATHINFO_EXTENSION) === 'php') {
$files[] = new CodeFile("$viewPath/$file", $this->render("views/$file"));
}
}
return $files;
}
/**
* @return string the controller ID (without the module ID prefix)
*/
public function getControllerID() {
$pos = strrpos($this->controllerClass, '\\');
$class = substr(substr($this->controllerClass, $pos + 1), 0, -10);
return Inflector::camel2id($class, '-', $this->strictInflector);
}
/**
* @return string the controller view path
*/
public function getViewPath() {
if (empty($this->viewPath)) {
return Yii::getAlias('@app/views/' . $this->getControllerID());
}
return Yii::getAlias(str_replace('\\', '/', $this->viewPath));
}
/**
* @return string
*/
public function getNameAttribute() {
foreach ($this->getColumnNames() as $name) {
if (!strcasecmp($name, 'name') || !strcasecmp($name, 'title')) {
return $name;
}
}
/* @var $class \yii\db\ActiveRecord */
$class = $this->modelClass;
$pk = $class::primaryKey();
return $pk[0];
}
/**
* Generates code for active field
* @param string $attribute
* @return string
*/
public function generateActiveField($attribute) {
$tableSchema = $this->getTableSchema();
if ($tableSchema === false || !isset($tableSchema->columns[$attribute])) {
if (preg_match('/^(password|pass|passwd|passcode)$/i', $attribute)) {
return "\$form->field(\$model, '$attribute')->passwordInput()";
}
return "\$form->field(\$model, '$attribute')";
}
$column = $tableSchema->columns[$attribute];
if ($column->phpType === 'boolean') {
return "\$form->field(\$model, '$attribute')->checkbox()";
}
if ($column->type === 'text') {
return "\$form->field(\$model, '$attribute')->textarea(['rows' => 6])";
}
if (preg_match('/^(password|pass|passwd|passcode)$/i', $column->name)) {
$input = 'passwordInput';
} else {
$input = 'textInput';
}
if (is_array($column->enumValues) && count($column->enumValues) > 0) {
$dropDownOptions = [];
foreach ($column->enumValues as $enumValue) {
$dropDownOptions[$enumValue] = Inflector::humanize($enumValue);
}
return "\$form->field(\$model, '$attribute')->dropDownList("
. preg_replace("/\n\s*/", ' ', VarDumper::export($dropDownOptions)) . ", ['prompt' => ''])";
}
if ($column->phpType !== 'string' || $column->size === null) {
return "\$form->field(\$model, '$attribute')->$input()";
}
return "\$form->field(\$model, '$attribute')->$input(['maxlength' => true])";
}
/**
* Generates column format
* @param \yii\db\ColumnSchema $column
* @return string
*/
public function generateColumnFormat($column) {
if ($column->phpType === 'boolean') {
return 'boolean';
}
if ($column->type === 'text') {
return 'ntext';
}
if (stripos($column->name, 'time') !== false && $column->phpType === 'integer') {
return 'datetime';
}
if (stripos($column->name, 'email') !== false) {
return 'email';
}
if (preg_match('/(\b|[_-])url(\b|[_-])/i', $column->name)) {
return 'url';
}
return 'text';
}
/**
* Generates validation rules for the search model.
* @return array the generated validation rules
*/
public function generateSearchRules()
{
if (($table = $this->getTableSchema()) === false) {
return ["[['" . implode("', '", $this->getColumnNames()) . "'], 'safe']"];
}
$types = [];
foreach ($table->columns as $column) {
switch ($column->type) {
case Schema::TYPE_TINYINT:
case Schema::TYPE_SMALLINT:
case Schema::TYPE_INTEGER:
case Schema::TYPE_BIGINT:
$types['integer'][] = $column->name;
break;
case Schema::TYPE_BOOLEAN:
$types['boolean'][] = $column->name;
break;
case Schema::TYPE_FLOAT:
case Schema::TYPE_DOUBLE:
case Schema::TYPE_DECIMAL:
case Schema::TYPE_MONEY:
$types['number'][] = $column->name;
break;
case Schema::TYPE_DATE:
case Schema::TYPE_TIME:
case Schema::TYPE_DATETIME:
case Schema::TYPE_TIMESTAMP:
default:
$types['safe'][] = $column->name;
break;
}
}
$rules = [];
foreach ($types as $type => $columns) {
$rules[] = "[['" . implode("', '", $columns) . "'], '$type']";
}
return $rules;
}
/**
* @return array searchable attributes
*/
public function getSearchAttributes()
{
return $this->getColumnNames();
}
/**
* Generates the attribute labels for the search model.
* @return array the generated attribute labels (name => label)
*/
public function generateSearchLabels()
{
/* @var $model \yii\base\Model */
$model = new $this->modelClass();
$attributeLabels = $model->attributeLabels();
$labels = [];
foreach ($this->getColumnNames() as $name) {
if (isset($attributeLabels[$name])) {
$labels[$name] = $attributeLabels[$name];
} else {
if (!strcasecmp($name, 'id')) {
$labels[$name] = 'ID';
} else {
$label = Inflector::camel2words($name);
if (!empty($label) && substr_compare($label, ' id', -3, 3, true) === 0) {
$label = substr($label, 0, -3) . ' ID';
}
$labels[$name] = $label;
}
}
}
return $labels;
}
/**
* Generates search conditions
* @return array
*/
public function generateSearchConditions()
{
$columns = [];
if (($table = $this->getTableSchema()) === false) {
$class = $this->modelClass;
/* @var $model \yii\base\Model */
$model = new $class();
foreach ($model->attributes() as $attribute) {
$columns[$attribute] = 'unknown';
}
} else {
foreach ($table->columns as $column) {
$columns[$column->name] = $column->type;
}
}
$likeConditions = [];
$hashConditions = [];
foreach ($columns as $column => $type) {
switch ($type) {
case Schema::TYPE_TINYINT:
case Schema::TYPE_SMALLINT:
case Schema::TYPE_INTEGER:
case Schema::TYPE_BIGINT:
case Schema::TYPE_BOOLEAN:
case Schema::TYPE_FLOAT:
case Schema::TYPE_DOUBLE:
case Schema::TYPE_DECIMAL:
case Schema::TYPE_MONEY:
case Schema::TYPE_DATE:
case Schema::TYPE_TIME:
case Schema::TYPE_DATETIME:
case Schema::TYPE_TIMESTAMP:
$hashConditions[] = "'{$column}' => \$this->{$column},";
break;
default:
$likeKeyword = $this->getClassDbDriverName() === 'pgsql' ? 'ilike' : 'like';
$likeConditions[] = "->andFilterWhere(['{$likeKeyword}', '{$column}', \$this->{$column}])";
break;
}
}
$conditions = [];
if (!empty($hashConditions)) {
$conditions[] = "\$query->andFilterWhere([\n"
. str_repeat(' ', 12) . implode("\n" . str_repeat(' ', 12), $hashConditions)
. "\n" . str_repeat(' ', 8) . "]);\n";
}
if (!empty($likeConditions)) {
$conditions[] = "\$query" . implode("\n" . str_repeat(' ', 12), $likeConditions) . ";\n";
}
return $conditions;
}
/**
* Generates URL parameters
* @return string
*/
public function generateUrlParams() {
/* @var $class ActiveRecord */
$class = $this->modelClass;
$pks = $class::primaryKey();
if (count($pks) === 1) {
if (is_subclass_of($class, 'yii\mongodb\ActiveRecord')) {
return "'id' => (string)\$model->{$pks[0]}";
}
return "'id' => \$model->{$pks[0]}";
}
$params = [];
foreach ($pks as $pk) {
if (is_subclass_of($class, 'yii\mongodb\ActiveRecord')) {
$params[] = "'$pk' => (string)\$model->$pk";
} else {
$params[] = "'$pk' => \$model->$pk";
}
}
return implode(', ', $params);
}
/**
* Generates action parameters
* @return string
*/
public function generateActionParams() {
/* @var $class ActiveRecord */
$class = $this->modelClass;
$pks = $class::primaryKey();
if (count($pks) === 1) {
return '$id';
}
return '$' . implode(', $', $pks);
}
/**
* Generates parameter tags for phpdoc
* @return array parameter tags for phpdoc
*/
public function generateActionParamComments() {
/* @var $class ActiveRecord */
$class = $this->modelClass;
$pks = $class::primaryKey();
if (($table = $this->getTableSchema()) === false) {
$params = [];
foreach ($pks as $pk) {
$params[] = '@param ' . (strtolower(substr($pk, -2)) === 'id' ? 'integer' : 'string') . ' $' . $pk;
}
return $params;
}
if (count($pks) === 1) {
return ['@param ' . $table->columns[$pks[0]]->phpType . ' $id'];
}
$params = [];
foreach ($pks as $pk) {
$params[] = '@param ' . $table->columns[$pk]->phpType . ' $' . $pk;
}
return $params;
}
/**
* Returns table schema for current model class or false if it is not an active record
* @return bool|\yii\db\TableSchema
*/
public function getTableSchema() {
/* @var $class ActiveRecord */
$class = $this->modelClass;
if (is_subclass_of($class, 'yii\db\ActiveRecord')) {
return $class::getTableSchema();
}
return false;
}
/**
* @return array model column names
*/
public function getColumnNames() {
/* @var $class ActiveRecord */
$class = $this->modelClass;
if (is_subclass_of($class, 'yii\db\ActiveRecord')) {
return $class::getTableSchema()->getColumnNames();
}
/* @var $model \yii\base\Model */
$model = new $class();
return $model->attributes();
}
/**
* @return string|null driver name of modelClass db connection.
* In case db is not instance of \yii\db\Connection null will be returned.
* @since 2.0.6
*/
protected function getClassDbDriverName() {
/* @var $class ActiveRecord */
$class = $this->modelClass;
$db = $class::getDb();
return $db instanceof \yii\db\Connection ? $db->driverName : null;
}
}

179
vendor/linyao/generators/crud/default/controller.php

@ -0,0 +1,179 @@
<?php
/**
* This is the template for generating a CRUD controller class file.
*/
use yii\db\ActiveRecordInterface;
use yii\helpers\StringHelper;
/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\crud\Generator */
$controllerClass = StringHelper::basename($generator->controllerClass);
$modelClass = StringHelper::basename($generator->modelClass);
$searchModelClass = StringHelper::basename($generator->searchModelClass);
if ($modelClass === $searchModelClass) {
$searchModelAlias = $searchModelClass . 'Search';
}
/* @var $class ActiveRecordInterface */
$class = $generator->modelClass;
$pks = $class::primaryKey();
$urlParams = $generator->generateUrlParams();
$actionParams = $generator->generateActionParams();
$actionParamComments = $generator->generateActionParamComments();
echo "<?php\n";
?>
namespace <?= StringHelper::dirname(ltrim($generator->controllerClass, '\\')) ?>;
use Yii;
use <?= ltrim($generator->modelClass, '\\') ?>;
<?php if (!empty($generator->searchModelClass)): ?>
use <?= ltrim($generator->searchModelClass, '\\') . (isset($searchModelAlias) ? " as $searchModelAlias" : "") ?>;
<?php else: ?>
use yii\data\ActiveDataProvider;
<?php endif; ?>
use <?= ltrim($generator->baseControllerClass, '\\') ?>;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
/**
* <?= $controllerClass ?> implements the CRUD actions for <?= $modelClass ?> model.
*/
class <?= $controllerClass ?> extends <?= StringHelper::basename($generator->baseControllerClass) . "\n" ?>
{
/**
* {@inheritdoc}
*/
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['POST'],
],
],
];
}
/**
* Lists all <?= $modelClass ?> models.
* @return mixed
*/
public function actionIndex()
{
<?php if (!empty($generator->searchModelClass)): ?>
$searchModel = new <?= isset($searchModelAlias) ? $searchModelAlias : $searchModelClass ?>();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
<?php else: ?>
$dataProvider = new ActiveDataProvider([
'query' => <?= $modelClass ?>::find(),
]);
return $this->render('index', [
'dataProvider' => $dataProvider,
]);
<?php endif; ?>
}
/**
* Displays a single <?= $modelClass ?> model.
* <?= implode("\n * ", $actionParamComments) . "\n" ?>
* @return mixed
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionView(<?= $actionParams ?>)
{
return $this->render('view', [
'model' => $this->findModel(<?= $actionParams ?>),
]);
}
/**
* Creates a new <?= $modelClass ?> model.
* If creation is successful, the browser will be redirected to the 'view' page.
* @return mixed
*/
public function actionCreate()
{
$model = new <?= $modelClass ?>();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', <?= $urlParams ?>]);
}
return $this->render('create', [
'model' => $model,
]);
}
/**
* Updates an existing <?= $modelClass ?> model.
* If update is successful, the browser will be redirected to the 'view' page.
* <?= implode("\n * ", $actionParamComments) . "\n" ?>
* @return mixed
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionUpdate(<?= $actionParams ?>)
{
$model = $this->findModel(<?= $actionParams ?>);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', <?= $urlParams ?>]);
}
return $this->render('update', [
'model' => $model,
]);
}
/**
* Deletes an existing <?= $modelClass ?> model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* <?= implode("\n * ", $actionParamComments) . "\n" ?>
* @return mixed
* @throws NotFoundHttpException if the model cannot be found
*/
public function actionDelete(<?= $actionParams ?>)
{
$this->findModel(<?= $actionParams ?>)->delete();
return $this->redirect(['index']);
}
/**
* Finds the <?= $modelClass ?> model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* <?= implode("\n * ", $actionParamComments) . "\n" ?>
* @return <?= $modelClass ?> the loaded model
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findModel(<?= $actionParams ?>)
{
<?php
if (count($pks) === 1) {
$condition = '$id';
} else {
$condition = [];
foreach ($pks as $pk) {
$condition[] = "'$pk' => \$$pk";
}
$condition = '[' . implode(', ', $condition) . ']';
}
?>
if (($model = <?= $modelClass ?>::findOne(<?= $condition ?>)) !== null) {
return $model;
}
throw new NotFoundHttpException(<?= $generator->generateString('The requested page does not exist.') ?>);
}
}

86
vendor/linyao/generators/crud/default/search.php

@ -0,0 +1,86 @@
<?php
/**
* This is the template for generating CRUD search class of the specified model.
*/
use yii\helpers\StringHelper;
/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\crud\Generator */
$modelClass = StringHelper::basename($generator->modelClass);
$searchModelClass = StringHelper::basename($generator->searchModelClass);
if ($modelClass === $searchModelClass) {
$modelAlias = $modelClass . 'Model';
}
$rules = $generator->generateSearchRules();
$labels = $generator->generateSearchLabels();
$searchAttributes = $generator->getSearchAttributes();
$searchConditions = $generator->generateSearchConditions();
echo "<?php\n";
?>
namespace <?= StringHelper::dirname(ltrim($generator->searchModelClass, '\\')) ?>;
use yii\base\Model;
use yii\data\ActiveDataProvider;
use <?= ltrim($generator->modelClass, '\\') . (isset($modelAlias) ? " as $modelAlias" : "") ?>;
/**
* <?= $searchModelClass ?> represents the model behind the search form of `<?= $generator->modelClass ?>`.
*/
class <?= $searchModelClass ?> extends <?= isset($modelAlias) ? $modelAlias : $modelClass ?>
{
/**
* {@inheritdoc}
*/
public function rules()
{
return [
<?= implode(",\n ", $rules) ?>,
];
}
/**
* {@inheritdoc}
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* Creates data provider instance with search query applied
*
* @param array $params
*
* @return ActiveDataProvider
*/
public function search($params)
{
$query = <?= isset($modelAlias) ? $modelAlias : $modelClass ?>::find();
// add conditions that should always apply here
$dataProvider = new ActiveDataProvider([
'query' => $query,
]);
$this->load($params);
if (!$this->validate()) {
// uncomment the following line if you do not want to return any records when validation fails
// $query->where('0=1');
return $dataProvider;
}
// grid filtering conditions
<?= implode("\n ", $searchConditions) ?>
return $dataProvider;
}
}

43
vendor/linyao/generators/crud/default/views/_form.php

@ -0,0 +1,43 @@
<?php
use yii\helpers\Inflector;
use yii\helpers\StringHelper;
/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\crud\Generator */
/* @var $model \yii\db\ActiveRecord */
$model = new $generator->modelClass();
$safeAttributes = $model->safeAttributes();
if (empty($safeAttributes)) {
$safeAttributes = $model->attributes();
}
echo "<?php\n";
?>
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $model <?= ltrim($generator->modelClass, '\\') ?> */
/* @var $form yii\widgets\ActiveForm */
?>
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-form">
<?= "<?php " ?>$form = ActiveForm::begin(); ?>
<?php foreach ($generator->getColumnNames() as $attribute) {
if (in_array($attribute, $safeAttributes)) {
echo " <?= " . $generator->generateActiveField($attribute) . " ?>\n\n";
}
} ?>
<div class="form-group">
<?= "<?= " ?>Html::submitButton(<?= $generator->generateString('保存') ?>, ['class' => 'btn btn-success']) ?>
<?= "<?= " ?>Html::a(<?= $generator->generateString('返回') ?>, ['index'], ['class' => 'btn btn-info']) ?>
</div>
<?= "<?php " ?>ActiveForm::end(); ?>
</div>

45
vendor/linyao/generators/crud/default/views/_search.php

@ -0,0 +1,45 @@
<?php
use yii\helpers\Inflector;
use yii\helpers\StringHelper;
/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\crud\Generator */
echo "<?php\n";
?>
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* @var $this yii\web\View */
/* @var $model <?= ltrim($generator->searchModelClass, '\\') ?> */
/* @var $form yii\widgets\ActiveForm */
?>
<?= "<?php " ?>$form = ActiveForm::begin([
'action' => ['index'],
'method' => 'get',
'validateOnType' => true,
]);
?>
<div class="col-sm-12">
<div class="dataTables_filter">
<?="<?= "?>$form->field($model, 'id', [
"template" => "{input}{error}",
"inputOptions" => [
"placeholder" => "检索ID",
"class" => "form-control",
],
"errorOptions" => [
"class" => "error-tips"
]
])
?>
<div class="form-group">
<?= "<?= " ?>Html::submitButton('<i class="fa fa-filter"></i>', ['class' => 'btn btn-default']) ?>
<?= "<?= " ?>Html::resetButton('<i class="fa fa-eraser"></i>', ['class' => 'btn btn-default']) ?>
</div>
</div>
</div>
<?= "<?php " ?>ActiveForm::end(); ?>

27
vendor/linyao/generators/crud/default/views/create.php

@ -0,0 +1,27 @@
<?php
use yii\helpers\Inflector;
use yii\helpers\StringHelper;
/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\crud\Generator */
echo "<?php\n";
?>
use yii\helpers\Html;
/* @var $this yii\web\View */
/* @var $model <?= ltrim($generator->modelClass, '\\') ?> */
$this->title = <?= $generator->generateString('创建 ' . Inflector::camel2words(StringHelper::basename($generator->modelClass))) ?>;
$this->params['breadcrumbs'][] = ['label' => <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-create">
<?= "<?= " ?>$this->render('_form', [
'model' => $model,
]) ?>
</div>

61
vendor/linyao/generators/crud/default/views/index.php

@ -0,0 +1,61 @@
<?php
/* blobt */
use yii\helpers\Inflector;
use yii\helpers\StringHelper;
/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\crud\Generator */
$urlParams = $generator->generateUrlParams();
$nameAttribute = $generator->getNameAttribute();
echo "<?php\n";
?>
use yii\helpers\Html;
use blobt\grid\GridView;
/* @var $this yii\web\View */
<?= !empty($generator->searchModelClass) ? "/* @var \$searchModel " . ltrim($generator->searchModelClass, '\\') . " */\n" : '' ?>
/* @var $dataProvider yii\data\ActiveDataProvider */
$this->title = <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>;
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="row">
<div class="col-xs-12">
<?= "<?= " ?>GridView::widget([
'dataProvider' => $dataProvider,
'filter' => $this->render("_search", ['model' => $searchModel]),
'batch' => [
[
"label" => "删除",
"url" => "<?=$generator->controllerID?>/deletes"
],
],
'columns' => [
[
'class' => 'blobt\grid\CheckboxColumn',
'width' => '2%',
'align' => 'center'
],
<?php
$count = 0;
foreach ($generator->getColumnNames() as $name) {
if (++$count < 6) {
echo " '" . $name . "',\n";
} else {
echo " //'" . $name . "',\n";
}
}
?>
[
'class' => 'blobt\grid\ActionColumn',
'align' => 'center'
],
]
]);
<?= "?>" ?>
</div>
</div>

38
vendor/linyao/generators/crud/default/views/update.php

@ -0,0 +1,38 @@
<?php
use yii\helpers\Inflector;
use yii\helpers\StringHelper;
/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\crud\Generator */
$urlParams = $generator->generateUrlParams();
$modelClassName = Inflector::camel2words(StringHelper::basename($generator->modelClass));
$nameAttributeTemplate = '$model->' . $generator->getNameAttribute();
$titleTemplate = $generator->generateString('编辑 ' . $modelClassName . ': {name}', ['name' => '{nameAttribute}']);
if ($generator->enableI18N) {
$title = strtr($titleTemplate, ['\'{nameAttribute}\'' => $nameAttributeTemplate]);
} else {
$title = strtr($titleTemplate, ['{nameAttribute}\'' => '\' . ' . $nameAttributeTemplate]);
}
echo "<?php\n";
?>
use yii\helpers\Html;
/* @var $this yii\web\View */
/* @var $model <?= ltrim($generator->modelClass, '\\') ?> */
$this->title = <?= $title ?>;
$this->params['breadcrumbs'][] = ['label' => <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $model-><?= $generator->getNameAttribute() ?>, 'url' => ['view', <?= $urlParams ?>]];
$this->params['breadcrumbs'][] = <?= $generator->generateString('Update ') ?>;
?>
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-update">
<?= '<?= ' ?>$this->render('_form', [
'model' => $model,
]) ?>
</div>

49
vendor/linyao/generators/crud/default/views/view.php

@ -0,0 +1,49 @@
<?php
use yii\helpers\Inflector;
use yii\helpers\StringHelper;
/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\crud\Generator */
$urlParams = $generator->generateUrlParams();
echo "<?php\n";
?>
use yii\helpers\Html;
use yii\widgets\DetailView;
/* @var $this yii\web\View */
/* @var $model <?= ltrim($generator->modelClass, '\\') ?> */
$this->title = $model-><?= $generator->getNameAttribute() ?>;
$this->params['breadcrumbs'][] = ['label' => <?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>, 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
\yii\web\YiiAsset::register($this);
?>
<div class="<?= Inflector::camel2id(StringHelper::basename($generator->modelClass)) ?>-view">
<p>
<?= "<?= " ?>Html::a(<?= $generator->generateString('返回列表') ?>, ['index'], ['class' => 'btn btn-success']) ?>
</p>
<?= "<?= " ?>DetailView::widget([
'model' => $model,
'attributes' => [
<?php
if (($tableSchema = $generator->getTableSchema()) === false) {
foreach ($generator->getColumnNames() as $name) {
echo " '" . $name . "',\n";
}
} else {
foreach ($generator->getTableSchema()->columns as $column) {
$format = $generator->generateColumnFormat($column);
echo " '" . $column->name . ($format === 'text' ? "" : ":" . $format) . "',\n";
}
}
?>
],
]) ?>
</div>

17
vendor/linyao/generators/crud/form.php

@ -0,0 +1,17 @@
<?php
/* @var $this yii\web\View */
/* @var $form yii\widgets\ActiveForm */
/* @var $generator yii\gii\generators\crud\Generator */
echo $form->field($generator, 'modelClass');
echo $form->field($generator, 'searchModelClass');
echo $form->field($generator, 'controllerClass');
echo $form->field($generator, 'viewPath');
echo $form->field($generator, 'baseControllerClass');
echo $form->field($generator, 'indexWidgetType')->dropDownList([
'grid' => 'GridView',
'list' => 'ListView',
]);
echo $form->field($generator, 'enableI18N')->checkbox();
echo $form->field($generator, 'enablePjax')->checkbox();
echo $form->field($generator, 'messageCategory');

995
vendor/linyao/generators/model/Generator.php

@ -0,0 +1,995 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace linyao\generators\model;
use Yii;
use yii\base\NotSupportedException;
use yii\db\ActiveQuery;
use yii\db\ActiveRecord;
use yii\db\Connection;
use yii\db\Schema;
use yii\db\TableSchema;
use yii\gii\CodeFile;
use yii\helpers\Inflector;
/**
* This generator will generate one or multiple ActiveRecord classes for the specified database table.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Generator extends \yii\gii\Generator
{
const RELATIONS_NONE = 'none';
const RELATIONS_ALL = 'all';
const RELATIONS_ALL_INVERSE = 'all-inverse';
public $db = 'db';
public $ns = 'app\models';
public $tableName;
public $modelClass;
public $baseClass = 'yii\db\ActiveRecord';
public $generateRelations = self::RELATIONS_ALL;
public $generateRelationsFromCurrentSchema = true;
public $generateLabelsFromComments = false;
public $useTablePrefix = false;
public $standardizeCapitals = false;
public $singularize = false;
public $useSchemaName = true;
public $generateQuery = false;
public $queryNs = 'app\models';
public $queryClass;
public $queryBaseClass = 'yii\db\ActiveQuery';
/**
* {@inheritdoc}
*/
public function getName()
{
return 'Model Generator';
}
/**
* {@inheritdoc}
*/
public function getDescription()
{
return 'This generator generates an ActiveRecord class for the specified database table.';
}
/**
* {@inheritdoc}
*/
public function rules()
{
return array_merge(parent::rules(), [
[['db', 'ns', 'tableName', 'modelClass', 'baseClass', 'queryNs', 'queryClass', 'queryBaseClass'], 'filter', 'filter' => 'trim'],
[['ns', 'queryNs'], 'filter', 'filter' => function ($value) { return trim($value, '\\'); }],
[['db', 'ns', 'tableName', 'baseClass', 'queryNs', 'queryBaseClass'], 'required'],
[['db', 'modelClass', 'queryClass'], 'match', 'pattern' => '/^\w+$/', 'message' => 'Only word characters are allowed.'],
[['ns', 'baseClass', 'queryNs', 'queryBaseClass'], 'match', 'pattern' => '/^[\w\\\\]+$/', 'message' => 'Only word characters and backslashes are allowed.'],
[['tableName'], 'match', 'pattern' => '/^([\w ]+\.)?([\w\* ]+)$/', 'message' => 'Only word characters, and optionally spaces, an asterisk and/or a dot are allowed.'],
[['db'], 'validateDb'],
[['ns', 'queryNs'], 'validateNamespace'],
[['tableName'], 'validateTableName'],
[['modelClass'], 'validateModelClass', 'skipOnEmpty' => false],
[['baseClass'], 'validateClass', 'params' => ['extends' => ActiveRecord::className()]],
[['queryBaseClass'], 'validateClass', 'params' => ['extends' => ActiveQuery::className()]],
[['generateRelations'], 'in', 'range' => [self::RELATIONS_NONE, self::RELATIONS_ALL, self::RELATIONS_ALL_INVERSE]],
[['generateLabelsFromComments', 'useTablePrefix', 'useSchemaName', 'generateQuery', 'generateRelationsFromCurrentSchema'], 'boolean'],
[['enableI18N', 'standardizeCapitals', 'singularize'], 'boolean'],
[['messageCategory'], 'validateMessageCategory', 'skipOnEmpty' => false],
]);
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return array_merge(parent::attributeLabels(), [
'ns' => 'Namespace',
'db' => 'Database Connection ID',
'tableName' => 'Table Name',
'standardizeCapitals' => 'Standardize Capitals',
'singularize' => 'Singularize',
'modelClass' => 'Model Class Name',
'baseClass' => 'Base Class',
'generateRelations' => 'Generate Relations',
'generateRelationsFromCurrentSchema' => 'Generate Relations from Current Schema',
'generateLabelsFromComments' => 'Generate Labels from DB Comments',
'generateQuery' => 'Generate ActiveQuery',
'queryNs' => 'ActiveQuery Namespace',
'queryClass' => 'ActiveQuery Class',
'queryBaseClass' => 'ActiveQuery Base Class',
'useSchemaName' => 'Use Schema Name',
]);
}
/**
* {@inheritdoc}
*/
public function hints()
{
return array_merge(parent::hints(), [
'ns' => 'This is the namespace of the ActiveRecord class to be generated, e.g., <code>app\models</code>',
'db' => 'This is the ID of the DB application component.',
'tableName' => 'This is the name of the DB table that the new ActiveRecord class is associated with, e.g. <code>post</code>.
The table name may consist of the DB schema part if needed, e.g. <code>public.post</code>.
The table name may end with asterisk to match multiple table names, e.g. <code>tbl_*</code>
will match tables who name starts with <code>tbl_</code>. In this case, multiple ActiveRecord classes
will be generated, one for each matching table name; and the class names will be generated from
the matching characters. For example, table <code>tbl_post</code> will generate <code>Post</code>
class.',
'modelClass' => 'This is the name of the ActiveRecord class to be generated. The class name should not contain
the namespace part as it is specified in "Namespace". You do not need to specify the class name
if "Table Name" ends with asterisk, in which case multiple ActiveRecord classes will be generated.',
'standardizeCapitals' => 'This indicates whether the generated class names should have standardized capitals. For example,
table names like <code>SOME_TABLE</code> or <code>Other_Table</code> will have class names <code>SomeTable</code>
and <code>OtherTable</code>, respectively. If not checked, the same tables will have class names <code>SOMETABLE</code>
and <code>OtherTable</code> instead.',
'singularize' => 'This indicates whether the generated class names should be singularized. For example,
table names like <code>some_tables</code> will have class names <code>SomeTable</code>.',
'baseClass' => 'This is the base class of the new ActiveRecord class. It should be a fully qualified namespaced class name.',
'generateRelations' => 'This indicates whether the generator should generate relations based on
foreign key constraints it detects in the database. Note that if your database contains too many tables,
you may want to uncheck this option to accelerate the code generation process.',
'generateRelationsFromCurrentSchema' => 'This indicates whether the generator should generate relations from current schema or from all available schemas.',
'generateLabelsFromComments' => 'This indicates whether the generator should generate attribute labels
by using the comments of the corresponding DB columns.',
'useTablePrefix' => 'This indicates whether the table name returned by the generated ActiveRecord class
should consider the <code>tablePrefix</code> setting of the DB connection. For example, if the
table name is <code>tbl_post</code> and <code>tablePrefix=tbl_</code>, the ActiveRecord class
will return the table name as <code>{{%post}}</code>.',
'useSchemaName' => 'This indicates whether to include the schema name in the ActiveRecord class
when it\'s auto generated. Only non default schema would be used.',
'generateQuery' => 'This indicates whether to generate ActiveQuery for the ActiveRecord class.',
'queryNs' => 'This is the namespace of the ActiveQuery class to be generated, e.g., <code>app\models</code>',
'queryClass' => 'This is the name of the ActiveQuery class to be generated. The class name should not contain
the namespace part as it is specified in "ActiveQuery Namespace". You do not need to specify the class name
if "Table Name" ends with asterisk, in which case multiple ActiveQuery classes will be generated.',
'queryBaseClass' => 'This is the base class of the new ActiveQuery class. It should be a fully qualified namespaced class name.',
]);
}
/**
* {@inheritdoc}
*/
public function autoCompleteData()
{
$db = $this->getDbConnection();
if ($db !== null) {
return [
'tableName' => function () use ($db) {
return $db->getSchema()->getTableNames();
},
];
}
return [];
}
/**
* {@inheritdoc}
*/
public function requiredTemplates()
{
// @todo make 'query.php' to be required before 2.1 release
return ['model.php'/*, 'query.php'*/];
}
/**
* {@inheritdoc}
*/
public function stickyAttributes()
{
return array_merge(parent::stickyAttributes(), ['ns', 'db', 'baseClass', 'generateRelations', 'generateLabelsFromComments', 'queryNs', 'queryBaseClass', 'useTablePrefix', 'generateQuery']);
}
/**
* Returns the `tablePrefix` property of the DB connection as specified
*
* @return string
* @since 2.0.5
* @see getDbConnection
*/
public function getTablePrefix()
{
$db = $this->getDbConnection();
if ($db !== null) {
return $db->tablePrefix;
}
return '';
}
/**
* {@inheritdoc}
*/
public function generate()
{
$files = [];
$relations = $this->generateRelations();
$db = $this->getDbConnection();
foreach ($this->getTableNames() as $tableName) {
// model :
$modelClassName = $this->generateClassName($tableName);
$queryClassName = ($this->generateQuery) ? $this->generateQueryClassName($modelClassName) : false;
$tableSchema = $db->getTableSchema($tableName);
$params = [
'tableName' => $tableName,
'className' => $modelClassName,
'queryClassName' => $queryClassName,
'tableSchema' => $tableSchema,
'properties' => $this->generateProperties($tableSchema),
'labels' => $this->generateLabels($tableSchema),
'rules' => $this->generateRules($tableSchema),
'relations' => isset($relations[$tableName]) ? $relations[$tableName] : [],
];
$files[] = new CodeFile(
Yii::getAlias('@' . str_replace('\\', '/', $this->ns)) . '/' . $modelClassName . '.php',
$this->render('model.php', $params)
);
// query :
if ($queryClassName) {
$params['className'] = $queryClassName;
$params['modelClassName'] = $modelClassName;
$files[] = new CodeFile(
Yii::getAlias('@' . str_replace('\\', '/', $this->queryNs)) . '/' . $queryClassName . '.php',
$this->render('query.php', $params)
);
}
}
return $files;
}
/**
* Generates the properties for the specified table.
* @param \yii\db\TableSchema $table the table schema
* @return array the generated properties (property => type)
* @since 2.0.6
*/
protected function generateProperties($table)
{
$properties = [];
foreach ($table->columns as $column) {
$columnPhpType = $column->phpType;
if ($columnPhpType === 'integer') {
$type = 'int';
} elseif ($columnPhpType === 'boolean') {
$type = 'bool';
} else {
$type = $columnPhpType;
}
$properties[$column->name] = [
'type' => $type,
'name' => $column->name,
'comment' => $column->comment,
];
}
return $properties;
}
/**
* Generates the attribute labels for the specified table.
* @param \yii\db\TableSchema $table the table schema
* @return array the generated attribute labels (name => label)
*/
public function generateLabels($table)
{
// $labels = [];
// foreach ($table->columns as $column) {
// if ($this->generateLabelsFromComments && !empty($column->comment)) {
// $labels[$column->name] = $column->comment;
// } elseif (!strcasecmp($column->name, 'id')) {
// $labels[$column->name] = 'ID';
// } else {
// $label = Inflector::camel2words($column->name);
// if (!empty($label) && substr_compare($label, ' id', -3, 3, true) === 0) {
// $label = substr($label, 0, -3) . ' ID';
// }
// $labels[$column->name] = $label;
// }
// }
//
// return $labels;
$labels=array();
$sql ="SELECT COLUMN_NAME, COLUMN_COMMENT FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '$table->name'";
$res = Yii::$app->getDb()->createCommand($sql)->query();
foreach ($res as $column){
if (!empty($column['COLUMN_COMMENT']))
$labels[$column['COLUMN_NAME']]= $column['COLUMN_COMMENT'];
else
$labels[$column['COLUMN_NAME']]= $column['COLUMN_NAME'];
}
return $labels;
}
/**
* Generates validation rules for the specified table.
* @param \yii\db\TableSchema $table the table schema
* @return array the generated validation rules
*/
public function generateRules($table)
{
$types = [];
$lengths = [];
foreach ($table->columns as $column) {
if($column->name == 'created_at' || $column->name == 'updated_at') {
continue;
}
if ($column->autoIncrement) {
continue;
}
if (!$column->allowNull && $column->defaultValue === null) {
$types['required'][] = $column->name;
}
switch ($column->type) {
case Schema::TYPE_SMALLINT:
case Schema::TYPE_INTEGER:
case Schema::TYPE_BIGINT:
case Schema::TYPE_TINYINT:
$types['integer'][] = $column->name;
break;
case Schema::TYPE_BOOLEAN:
$types['boolean'][] = $column->name;
break;
case Schema::TYPE_FLOAT:
case Schema::TYPE_DOUBLE:
case Schema::TYPE_DECIMAL:
case Schema::TYPE_MONEY:
$types['number'][] = $column->name;
break;
case Schema::TYPE_DATE:
case Schema::TYPE_TIME:
case Schema::TYPE_DATETIME:
case Schema::TYPE_TIMESTAMP:
case Schema::TYPE_JSON:
$types['safe'][] = $column->name;
break;
default: // strings
if ($column->size > 0) {
$lengths[$column->size][] = $column->name;
} else {
$types['string'][] = $column->name;
}
}
}
$rules = [];
$driverName = $this->getDbDriverName();
foreach ($types as $type => $columns) {
if ($driverName === 'pgsql' && $type === 'integer') {
$rules[] = "[['" . implode("', '", $columns) . "'], 'default', 'value' => null]";
}
$rules[] = "[['" . implode("', '", $columns) . "'], '$type']";
}
foreach ($lengths as $length => $columns) {
$rules[] = "[['" . implode("', '", $columns) . "'], 'string', 'max' => $length]";
}
$db = $this->getDbConnection();
// Unique indexes rules
try {
$uniqueIndexes = array_merge($db->getSchema()->findUniqueIndexes($table), [$table->primaryKey]);
$uniqueIndexes = array_unique($uniqueIndexes, SORT_REGULAR);
foreach ($uniqueIndexes as $uniqueColumns) {
// Avoid validating auto incremental columns
if (!$this->isColumnAutoIncremental($table, $uniqueColumns)) {
$attributesCount = count($uniqueColumns);
if ($attributesCount === 1) {
$rules[] = "[['" . $uniqueColumns[0] . "'], 'unique']";
} elseif ($attributesCount > 1) {
$columnsList = implode("', '", $uniqueColumns);
$rules[] = "[['$columnsList'], 'unique', 'targetAttribute' => ['$columnsList']]";
}
}
}
} catch (NotSupportedException $e) {
// doesn't support unique indexes information...do nothing
}
// Exist rules for foreign keys
foreach ($table->foreignKeys as $refs) {
$refTable = $refs[0];
$refTableSchema = $db->getTableSchema($refTable);
if ($refTableSchema === null) {
// Foreign key could point to non-existing table: https://github.com/yiisoft/yii2-gii/issues/34
continue;
}
$refClassName = $this->generateClassName($refTable);
unset($refs[0]);
$attributes = implode("', '", array_keys($refs));
$targetAttributes = [];
foreach ($refs as $key => $value) {
$targetAttributes[] = "'$key' => '$value'";
}
$targetAttributes = implode(', ', $targetAttributes);
$rules[] = "[['$attributes'], 'exist', 'skipOnError' => true, 'targetClass' => $refClassName::className(), 'targetAttribute' => [$targetAttributes]]";
}
return $rules;
}
/**
* Generates relations using a junction table by adding an extra viaTable().
* @param \yii\db\TableSchema the table being checked
* @param array $fks obtained from the checkJunctionTable() method
* @param array $relations
* @return array modified $relations
*/
private function generateManyManyRelations($table, $fks, $relations)
{
$db = $this->getDbConnection();
foreach ($fks as $pair) {
list($firstKey, $secondKey) = $pair;
$table0 = $firstKey[0];
$table1 = $secondKey[0];
unset($firstKey[0], $secondKey[0]);
$className0 = $this->generateClassName($table0);
$className1 = $this->generateClassName($table1);
$table0Schema = $db->getTableSchema($table0);
$table1Schema = $db->getTableSchema($table1);
// @see https://github.com/yiisoft/yii2-gii/issues/166
if ($table0Schema === null || $table1Schema === null) {
continue;
}
$link = $this->generateRelationLink(array_flip($secondKey));
$viaLink = $this->generateRelationLink($firstKey);
$relationName = $this->generateRelationName($relations, $table0Schema, key($secondKey), true);
$relations[$table0Schema->fullName][$relationName] = [
"return \$this->hasMany($className1::className(), $link)->viaTable('"
. $this->generateTableName($table->name) . "', $viaLink);",
$className1,
true,
];
$link = $this->generateRelationLink(array_flip($firstKey));
$viaLink = $this->generateRelationLink($secondKey);
$relationName = $this->generateRelationName($relations, $table1Schema, key($firstKey), true);
$relations[$table1Schema->fullName][$relationName] = [
"return \$this->hasMany($className0::className(), $link)->viaTable('"
. $this->generateTableName($table->name) . "', $viaLink);",
$className0,
true,
];
}
return $relations;
}
/**
* @return string[] all db schema names or an array with a single empty string
* @throws NotSupportedException
* @since 2.0.5
*/
protected function getSchemaNames()
{
$db = $this->getDbConnection();
if ($this->generateRelationsFromCurrentSchema) {
if ($db->schema->defaultSchema !== null) {
return [$db->schema->defaultSchema];
}
return [''];
}
$schema = $db->getSchema();
if ($schema->hasMethod('getSchemaNames')) { // keep BC to Yii versions < 2.0.4
try {
$schemaNames = $schema->getSchemaNames();
} catch (NotSupportedException $e) {
// schema names are not supported by schema
}
}
if (!isset($schemaNames)) {
if (($pos = strpos($this->tableName, '.')) !== false) {
$schemaNames = [substr($this->tableName, 0, $pos)];
} else {
$schemaNames = [''];
}
}
return $schemaNames;
}
/**
* @return array the generated relation declarations
*/
protected function generateRelations()
{
if ($this->generateRelations === self::RELATIONS_NONE) {
return [];
}
$db = $this->getDbConnection();
$relations = [];
$schemaNames = $this->getSchemaNames();
foreach ($schemaNames as $schemaName) {
foreach ($db->getSchema()->getTableSchemas($schemaName) as $table) {
$className = $this->generateClassName($table->fullName);
foreach ($table->foreignKeys as $refs) {
$refTable = $refs[0];
$refTableSchema = $db->getTableSchema($refTable);
if ($refTableSchema === null) {
// Foreign key could point to non-existing table: https://github.com/yiisoft/yii2-gii/issues/34
continue;
}
unset($refs[0]);
$fks = array_keys($refs);
$refClassName = $this->generateClassName($refTable);
// Add relation for this table
$link = $this->generateRelationLink(array_flip($refs));
$relationName = $this->generateRelationName($relations, $table, $fks[0], false);
$relations[$table->fullName][$relationName] = [
"return \$this->hasOne($refClassName::className(), $link);",
$refClassName,
false,
];
// Add relation for the referenced table
$hasMany = $this->isHasManyRelation($table, $fks);
$link = $this->generateRelationLink($refs);
$relationName = $this->generateRelationName($relations, $refTableSchema, $className, $hasMany);
$relations[$refTableSchema->fullName][$relationName] = [
"return \$this->" . ($hasMany ? 'hasMany' : 'hasOne') . "($className::className(), $link);",
$className,
$hasMany,
];
}
if (($junctionFks = $this->checkJunctionTable($table)) === false) {
continue;
}
$relations = $this->generateManyManyRelations($table, $junctionFks, $relations);
}
}
if ($this->generateRelations === self::RELATIONS_ALL_INVERSE) {
return $this->addInverseRelations($relations);
}
return $relations;
}
/**
* Adds inverse relations
*
* @param array $relations relation declarations
* @return array relation declarations extended with inverse relation names
* @since 2.0.5
*/
protected function addInverseRelations($relations)
{
$db = $this->getDbConnection();
$relationNames = [];
$schemaNames = $this->getSchemaNames();
foreach ($schemaNames as $schemaName) {
foreach ($db->schema->getTableSchemas($schemaName) as $table) {
$className = $this->generateClassName($table->fullName);
foreach ($table->foreignKeys as $refs) {
$refTable = $refs[0];
$refTableSchema = $db->getTableSchema($refTable);
if ($refTableSchema === null) {
// Foreign key could point to non-existing table: https://github.com/yiisoft/yii2-gii/issues/34
continue;
}
unset($refs[0]);
$fks = array_keys($refs);
$leftRelationName = $this->generateRelationName($relationNames, $table, $fks[0], false);
$relationNames[$table->fullName][$leftRelationName] = true;
$hasMany = $this->isHasManyRelation($table, $fks);
$rightRelationName = $this->generateRelationName(
$relationNames,
$refTableSchema,
$className,
$hasMany
);
$relationNames[$refTableSchema->fullName][$rightRelationName] = true;
$relations[$table->fullName][$leftRelationName][0] =
rtrim($relations[$table->fullName][$leftRelationName][0], ';')
. "->inverseOf('".lcfirst($rightRelationName)."');";
$relations[$refTableSchema->fullName][$rightRelationName][0] =
rtrim($relations[$refTableSchema->fullName][$rightRelationName][0], ';')
. "->inverseOf('".lcfirst($leftRelationName)."');";
}
}
}
return $relations;
}
/**
* Determines if relation is of has many type
*
* @param TableSchema $table
* @param array $fks
* @return bool
* @since 2.0.5
*/
protected function isHasManyRelation($table, $fks)
{
$uniqueKeys = [$table->primaryKey];
try {
$uniqueKeys = array_merge($uniqueKeys, $this->getDbConnection()->getSchema()->findUniqueIndexes($table));
} catch (NotSupportedException $e) {
// ignore
}
foreach ($uniqueKeys as $uniqueKey) {
if (count(array_diff(array_merge($uniqueKey, $fks), array_intersect($uniqueKey, $fks))) === 0) {
return false;
}
}
return true;
}
/**
* Generates the link parameter to be used in generating the relation declaration.
* @param array $refs reference constraint
* @return string the generated link parameter.
*/
protected function generateRelationLink($refs)
{
$pairs = [];
foreach ($refs as $a => $b) {
$pairs[] = "'$a' => '$b'";
}
return '[' . implode(', ', $pairs) . ']';
}
/**
* Checks if the given table is a junction table, that is it has at least one pair of unique foreign keys.
* @param \yii\db\TableSchema the table being checked
* @return array|bool all unique foreign key pairs if the table is a junction table,
* or false if the table is not a junction table.
*/
protected function checkJunctionTable($table)
{
if (count($table->foreignKeys) < 2) {
return false;
}
$uniqueKeys = [$table->primaryKey];
try {
$uniqueKeys = array_merge($uniqueKeys, $this->getDbConnection()->getSchema()->findUniqueIndexes($table));
} catch (NotSupportedException $e) {
// ignore
}
$result = [];
// find all foreign key pairs that have all columns in an unique constraint
$foreignKeys = array_values($table->foreignKeys);
$foreignKeysCount = count($foreignKeys);
for ($i = 0; $i < $foreignKeysCount; $i++) {
$firstColumns = $foreignKeys[$i];
unset($firstColumns[0]);
for ($j = $i + 1; $j < $foreignKeysCount; $j++) {
$secondColumns = $foreignKeys[$j];
unset($secondColumns[0]);
$fks = array_merge(array_keys($firstColumns), array_keys($secondColumns));
foreach ($uniqueKeys as $uniqueKey) {
if (count(array_diff(array_merge($uniqueKey, $fks), array_intersect($uniqueKey, $fks))) === 0) {
// save the foreign key pair
$result[] = [$foreignKeys[$i], $foreignKeys[$j]];
break;
}
}
}
}
return empty($result) ? false : $result;
}
/**
* Generate a relation name for the specified table and a base name.
* @param array $relations the relations being generated currently.
* @param \yii\db\TableSchema $table the table schema
* @param string $key a base name that the relation name may be generated from
* @param bool $multiple whether this is a has-many relation
* @return string the relation name
*/
protected function generateRelationName($relations, $table, $key, $multiple)
{
static $baseModel;
/* @var $baseModel \yii\db\ActiveRecord */
if ($baseModel === null) {
$baseClass = $this->baseClass;
$baseClassReflector = new \ReflectionClass($baseClass);
if ($baseClassReflector->isAbstract()) {
$baseClassWrapper =
'namespace ' . __NAMESPACE__ . ';'.
'class GiiBaseClassWrapper extends \\' . $baseClass . ' {' .
'public static function tableName(){' .
'return "' . addslashes($table->fullName) . '";' .
'}' .
'};' .
'return new GiiBaseClassWrapper();';
$baseModel = eval($baseClassWrapper);
} else {
$baseModel = new $baseClass();
}
$baseModel->setAttributes([]);
}
if (!empty($key) && strcasecmp($key, 'id')) {
if (substr_compare($key, 'id', -2, 2, true) === 0) {
$key = rtrim(substr($key, 0, -2), '_');
} elseif (substr_compare($key, 'id', 0, 2, true) === 0) {
$key = ltrim(substr($key, 2, strlen($key)), '_');
}
}
if ($multiple) {
$key = Inflector::pluralize($key);
}
$name = $rawName = Inflector::id2camel($key, '_');
$i = 0;
while ($baseModel->hasProperty(lcfirst($name))) {
$name = $rawName . ($i++);
}
while (isset($table->columns[lcfirst($name)])) {
$name = $rawName . ($i++);
}
while (isset($relations[$table->fullName][$name])) {
$name = $rawName . ($i++);
}
return $name;
}
/**
* Validates the [[db]] attribute.
*/
public function validateDb()
{
if (!Yii::$app->has($this->db)) {
$this->addError('db', 'There is no application component named "db".');
} elseif (!Yii::$app->get($this->db) instanceof Connection) {
$this->addError('db', 'The "db" application component must be a DB connection instance.');
}
}
/**
* Validates the namespace.
*
* @param string $attribute Namespace variable.
*/
public function validateNamespace($attribute)
{
$value = $this->$attribute;
$value = ltrim($value, '\\');
$path = Yii::getAlias('@' . str_replace('\\', '/', $value), false);
if ($path === false) {
$this->addError($attribute, 'Namespace must be associated with an existing directory.');
}
}
/**
* Validates the [[modelClass]] attribute.
*/
public function validateModelClass()
{
if ($this->isReservedKeyword($this->modelClass)) {
$this->addError('modelClass', 'Class name cannot be a reserved PHP keyword.');
}
if ((empty($this->tableName) || substr_compare($this->tableName, '*', -1, 1)) && $this->modelClass == '') {
$this->addError('modelClass', 'Model Class cannot be blank if table name does not end with asterisk.');
}
}
/**
* Validates the [[tableName]] attribute.
*/
public function validateTableName()
{
if (strpos($this->tableName, '*') !== false && substr_compare($this->tableName, '*', -1, 1)) {
$this->addError('tableName', 'Asterisk is only allowed as the last character.');
return;
}
$tables = $this->getTableNames();
if (empty($tables)) {
$this->addError('tableName', "Table '{$this->tableName}' does not exist.");
} else {
foreach ($tables as $table) {
$class = $this->generateClassName($table);
if ($this->isReservedKeyword($class)) {
$this->addError('tableName', "Table '$table' will generate a class which is a reserved PHP keyword.");
break;
}
}
}
}
protected $tableNames;
protected $classNames;
/**
* @return array the table names that match the pattern specified by [[tableName]].
*/
protected function getTableNames()
{
if ($this->tableNames !== null) {
return $this->tableNames;
}
$db = $this->getDbConnection();
if ($db === null) {
return [];
}
$tableNames = [];
if (strpos($this->tableName, '*') !== false) {
if (($pos = strrpos($this->tableName, '.')) !== false) {
$schema = substr($this->tableName, 0, $pos);
$pattern = '/^' . str_replace('*', '\w+', substr($this->tableName, $pos + 1)) . '$/';
} else {
$schema = '';
$pattern = '/^' . str_replace('*', '\w+', $this->tableName) . '$/';
}
foreach ($db->schema->getTableNames($schema) as $table) {
if (preg_match($pattern, $table)) {
$tableNames[] = $schema === '' ? $table : ($schema . '.' . $table);
}
}
} elseif (($table = $db->getTableSchema($this->tableName, true)) !== null) {
$tableNames[] = $this->tableName;
$this->classNames[$this->tableName] = $this->modelClass;
}
return $this->tableNames = $tableNames;
}
/**
* Generates the table name by considering table prefix.
* If [[useTablePrefix]] is false, the table name will be returned without change.
* @param string $tableName the table name (which may contain schema prefix)
* @return string the generated table name
*/
public function generateTableName($tableName)
{
if (!$this->useTablePrefix) {
return $tableName;
}
$db = $this->getDbConnection();
if (preg_match("/^{$db->tablePrefix}(.*?)$/", $tableName, $matches)) {
$tableName = '{{%' . $matches[1] . '}}';
} elseif (preg_match("/^(.*?){$db->tablePrefix}$/", $tableName, $matches)) {
$tableName = '{{' . $matches[1] . '%}}';
}
return $tableName;
}
/**
* Generates a class name from the specified table name.
* @param string $tableName the table name (which may contain schema prefix)
* @param bool $useSchemaName should schema name be included in the class name, if present
* @return string the generated class name
*/
protected function generateClassName($tableName, $useSchemaName = null)
{
if (isset($this->classNames[$tableName])) {
return $this->classNames[$tableName];
}
$schemaName = '';
$fullTableName = $tableName;
if (($pos = strrpos($tableName, '.')) !== false) {
if (($useSchemaName === null && $this->useSchemaName) || $useSchemaName) {
$schemaName = substr($tableName, 0, $pos) . '_';
}
$tableName = substr($tableName, $pos + 1);
}
$db = $this->getDbConnection();
$patterns = [];
$patterns[] = "/^{$db->tablePrefix}(.*?)$/";
$patterns[] = "/^(.*?){$db->tablePrefix}$/";
if (strpos($this->tableName, '*') !== false) {
$pattern = $this->tableName;
if (($pos = strrpos($pattern, '.')) !== false) {
$pattern = substr($pattern, $pos + 1);
}
$patterns[] = '/^' . str_replace('*', '(\w+)', $pattern) . '$/';
}
$className = $tableName;
foreach ($patterns as $pattern) {
if (preg_match($pattern, $tableName, $matches)) {
$className = $matches[1];
break;
}
}
if ($this->standardizeCapitals) {
$schemaName = ctype_upper(preg_replace('/[_-]/', '', $schemaName)) ? strtolower($schemaName) : $schemaName;
$className = ctype_upper(preg_replace('/[_-]/', '', $className)) ? strtolower($className) : $className;
$this->classNames[$fullTableName] = Inflector::camelize(Inflector::camel2words($schemaName.$className));
} else {
$this->classNames[$fullTableName] = Inflector::id2camel($schemaName.$className, '_');
}
if ($this->singularize) {
$this->classNames[$fullTableName] = Inflector::singularize($this->classNames[$fullTableName]);
}
return $this->classNames[$fullTableName];
}
/**
* Generates a query class name from the specified model class name.
* @param string $modelClassName model class name
* @return string generated class name
*/
protected function generateQueryClassName($modelClassName)
{
$queryClassName = $this->queryClass;
if (empty($queryClassName) || strpos($this->tableName, '*') !== false) {
$queryClassName = $modelClassName . 'Query';
}
return $queryClassName;
}
/**
* @return Connection the DB connection as specified by [[db]].
*/
protected function getDbConnection()
{
return Yii::$app->get($this->db, false);
}
/**
* @return string|null driver name of db connection.
* In case db is not instance of \yii\db\Connection null will be returned.
* @since 2.0.6
*/
protected function getDbDriverName()
{
/** @var Connection $db */
$db = $this->getDbConnection();
return $db instanceof \yii\db\Connection ? $db->driverName : null;
}
/**
* Checks if any of the specified columns is auto incremental.
* @param \yii\db\TableSchema $table the table schema
* @param array $columns columns to check for autoIncrement property
* @return bool whether any of the specified columns is auto incremental.
*/
protected function isColumnAutoIncremental($table, $columns)
{
foreach ($columns as $column) {
if (isset($table->columns[$column]) && $table->columns[$column]->autoIncrement) {
return true;
}
}
return false;
}
}

124
vendor/linyao/generators/model/default/model.php

@ -0,0 +1,124 @@
<?php
/**
* This is the template for generating the model class of a specified table.
*/
/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\model\Generator */
/* @var $tableName string full table name */
/* @var $className string class name */
/* @var $queryClassName string query class name */
/* @var $tableSchema yii\db\TableSchema */
/* @var $properties array list of properties (property => [type, name. comment]) */
/* @var $labels string[] list of attribute labels (name => label) */
/* @var $rules string[] list of validation rules */
/* @var $relations array list of relations (name => relation declaration) */
echo "<?php\n";
?>
namespace <?= $generator->ns ?>;
use Yii;
use yii\behaviors\TimestampBehavior;
/**
* This is the model class for table "<?= $generator->generateTableName($tableName) ?>".
*
<?php foreach ($properties as $property => $data): ?>
* @property <?= "{$data['type']} \${$property}" . ($data['comment'] ? ' ' . strtr($data['comment'], ["\n" => ' ']) : '') . "\n" ?>
<?php endforeach; ?>
<?php if (!empty($relations)): ?>
*
<?php foreach ($relations as $name => $relation): ?>
* @property <?= $relation[1] . ($relation[2] ? '[]' : '') . ' $' . lcfirst($name) . "\n" ?>
<?php endforeach; ?>
<?php endif; ?>
*/
class <?= $className ?> extends <?= '\\' . ltrim($generator->baseClass, '\\') . "\n" ?>
{
/**
* {@inheritdoc}
*/
public static function tableName()
{
return '<?= $generator->generateTableName($tableName) ?>';
}
<?php if ($generator->db !== 'db'): ?>
/**
* @return \yii\db\Connection the database connection used by this AR class.
*/
public static function getDb()
{
return Yii::$app->get('<?= $generator->db ?>');
}
<?php endif; ?>
/**
* {@inheritdoc}
*/
public function rules()
{
return [<?= empty($rules) ? '' : ("\n " . implode(",\n ", $rules) . ",\n ") ?>];
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
<?php foreach ($labels as $name => $label): ?>
<?= "'$name' => " . $generator->generateString($label) . ",\n" ?>
<?php endforeach; ?>
];
}
<?php foreach ($relations as $name => $relation): ?>
/**
* @return \yii\db\ActiveQuery
*/
public function get<?= $name ?>()
{
<?= $relation[0] . "\n" ?>
}
<?php endforeach; ?>
<?php if ($queryClassName): ?>
<?php
$queryClassFullName = ($generator->ns === $generator->queryNs) ? $queryClassName : '\\' . $generator->queryNs . '\\' . $queryClassName;
echo "\n";
?>
/**
* {@inheritdoc}
* @return <?= $queryClassFullName ?> the active query used by this AR class.
*/
public static function find()
{
return new <?= $queryClassFullName ?>(get_called_class());
}
<?php endif; ?>
<?php if (array_key_exists('created_at', $labels) && array_key_exists('updated_at', $labels)): ?>
/**
* @author linyao
* @email 602604991@qq.com
* @created Nov 8, 2019
*
* 行为存储创建时间和更新时间
*/
public function behaviors()
{
return [
[
'class' => TimestampBehavior::className(),
'createdAtAttribute' => 'created_at',
'updatedAtAttribute' => 'updated_at',
'value' => function() {
return time();
},
],
];
}
<?php endif; ?>
}

56
vendor/linyao/generators/model/default/query.php

@ -0,0 +1,56 @@
<?php
/**
* This is the template for generating the ActiveQuery class.
*/
/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\model\Generator */
/* @var $tableName string full table name */
/* @var $className string class name */
/* @var $tableSchema yii\db\TableSchema */
/* @var $labels string[] list of attribute labels (name => label) */
/* @var $rules string[] list of validation rules */
/* @var $relations array list of relations (name => relation declaration) */
/* @var $className string class name */
/* @var $modelClassName string related model class name */
$modelFullClassName = $modelClassName;
if ($generator->ns !== $generator->queryNs) {
$modelFullClassName = '\\' . $generator->ns . '\\' . $modelFullClassName;
}
echo "<?php\n";
?>
namespace <?= $generator->queryNs ?>;
/**
* This is the ActiveQuery class for [[<?= $modelFullClassName ?>]].
*
* @see <?= $modelFullClassName . "\n" ?>
*/
class <?= $className ?> extends <?= '\\' . ltrim($generator->queryBaseClass, '\\') . "\n" ?>
{
/*public function active()
{
return $this->andWhere('[[status]]=1');
}*/
/**
* {@inheritdoc}
* @return <?= $modelFullClassName ?>[]|array
*/
public function all($db = null)
{
return parent::all($db);
}
/**
* {@inheritdoc}
* @return <?= $modelFullClassName ?>|array|null
*/
public function one($db = null)
{
return parent::one($db);
}
}

30
vendor/linyao/generators/model/form.php

@ -0,0 +1,30 @@
<?php
use yii\gii\generators\model\Generator;
/* @var $this yii\web\View */
/* @var $form yii\widgets\ActiveForm */
/* @var $generator yii\gii\generators\model\Generator */
echo $form->field($generator, 'tableName')->textInput(['table_prefix' => $generator->getTablePrefix()]);
echo $form->field($generator, 'modelClass');
echo $form->field($generator, 'standardizeCapitals')->checkbox();
echo $form->field($generator, 'singularize')->checkbox();
echo $form->field($generator, 'ns');
echo $form->field($generator, 'baseClass');
echo $form->field($generator, 'db');
echo $form->field($generator, 'useTablePrefix')->checkbox();
echo $form->field($generator, 'generateRelations')->dropDownList([
Generator::RELATIONS_NONE => 'No relations',
Generator::RELATIONS_ALL => 'All relations',
Generator::RELATIONS_ALL_INVERSE => 'All relations with inverse',
]);
echo $form->field($generator, 'generateRelationsFromCurrentSchema')->checkbox();
echo $form->field($generator, 'generateLabelsFromComments')->checkbox();
echo $form->field($generator, 'generateQuery')->checkbox();
echo $form->field($generator, 'queryNs');
echo $form->field($generator, 'queryClass');
echo $form->field($generator, 'queryBaseClass');
echo $form->field($generator, 'enableI18N')->checkbox();
echo $form->field($generator, 'messageCategory');
echo $form->field($generator, 'useSchemaName')->checkbox();
Loading…
Cancel
Save