Browse Source

feat: 重写的gii相关文件提交

wechat_public_accounts
iron 5 years ago
parent
commit
052d83cf89
  1. 15
      environments/skeleton/kcadmin/config/main-local.php
  2. 255
      vendor/iron/generators/controller/Generator.php
  3. 27
      vendor/iron/generators/controller/default/controller.php
  4. 20
      vendor/iron/generators/controller/default/view.php
  5. 9
      vendor/iron/generators/controller/form.php
  6. 555
      vendor/iron/generators/crud/Generator.php
  7. 201
      vendor/iron/generators/crud/default/controller.php
  8. 160
      vendor/iron/generators/crud/default/search.php
  9. 43
      vendor/iron/generators/crud/default/views/_form.php
  10. 57
      vendor/iron/generators/crud/default/views/_search.php
  11. 27
      vendor/iron/generators/crud/default/views/create.php
  12. 41
      vendor/iron/generators/crud/default/views/index.php
  13. 38
      vendor/iron/generators/crud/default/views/update.php
  14. 49
      vendor/iron/generators/crud/default/views/view.php
  15. 17
      vendor/iron/generators/crud/form.php
  16. 995
      vendor/iron/generators/model/Generator.php
  17. 125
      vendor/iron/generators/model/default/model.php
  18. 56
      vendor/iron/generators/model/default/query.php
  19. 30
      vendor/iron/generators/model/form.php

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

@ -22,18 +22,17 @@ if (!YII_ENV_TEST) {
'allowedIPs' => ['127.0.0.1'],
'generators' => [
'crud' => [
'class' => 'blobt\generators\crud\Generator',
'class' => 'iron\generators\crud\Generator',
'templates' => [
'blobtCrud' => '@blobt/generators/crud/default',
'linyaoCrud' => '@linyao/generators/crud/default',
]
'basicModel' => '@iron/generators/crud/default',
],
],
'model' => [
'class' => 'linyao\generators\model\Generator',
'class' => 'iron\generators\model\Generator',
'templates' => [
'linyaoModel' => '@linyao/generators/model/default',
]
]
'basicModel' => '@iron/generators/model/default',
],
],
],
];
}

255
vendor/iron/generators/controller/Generator.php

@ -0,0 +1,255 @@
<?php
/**
* @link http://www.yiiframework.com/
* @copyright Copyright (c) 2008 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\gii\generators\controller;
use Yii;
use yii\gii\CodeFile;
use yii\helpers\Html;
use yii\helpers\Inflector;
use yii\helpers\StringHelper;
/**
* This generator will generate a controller and one or a few action view files.
*
* @property array $actionIDs An array of action IDs entered by the user. This property is read-only.
* @property string $controllerFile The controller class file path. This property is read-only.
* @property string $controllerID The controller ID. This property is read-only.
* @property string $controllerNamespace The namespace of the controller class. This property is read-only.
* @property string $controllerSubPath The controller sub path. This property is read-only.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Generator extends \yii\gii\Generator
{
/**
* @var string the controller class name
*/
public $controllerClass;
/**
* @var string the controller's view path
*/
public $viewPath;
/**
* @var string the base class of the controller
*/
public $baseClass = 'yii\web\Controller';
/**
* @var string list of action IDs separated by commas or spaces
*/
public $actions = 'index';
/**
* {@inheritdoc}
*/
public function getName()
{
return 'Controller Generator';
}
/**
* {@inheritdoc}
*/
public function getDescription()
{
return 'This generator helps you to quickly generate a new controller class with
one or several controller actions and their corresponding views.';
}
/**
* {@inheritdoc}
*/
public function rules()
{
return array_merge(parent::rules(), [
[['controllerClass', 'actions', 'baseClass'], 'filter', 'filter' => 'trim'],
[['controllerClass', 'baseClass'], 'required'],
['controllerClass', 'match', 'pattern' => '/^[\w\\\\]*Controller$/', 'message' => 'Only word characters and backslashes are allowed, and the class name must end with "Controller".'],
['controllerClass', 'validateNewClass'],
['baseClass', 'match', 'pattern' => '/^[\w\\\\]*$/', 'message' => 'Only word characters and backslashes are allowed.'],
['actions', 'match', 'pattern' => '/^[a-z][a-z0-9\\-,\\s]*$/', 'message' => 'Only a-z, 0-9, dashes (-), spaces and commas are allowed.'],
['viewPath', 'safe'],
]);
}
/**
* {@inheritdoc}
*/
public function attributeLabels()
{
return [
'baseClass' => 'Base Class',
'controllerClass' => 'Controller Class',
'viewPath' => 'View Path',
'actions' => 'Action IDs',
];
}
/**
* {@inheritdoc}
*/
public function requiredTemplates()
{
return [
'controller.php',
'view.php',
];
}
/**
* {@inheritdoc}
*/
public function stickyAttributes()
{
return ['baseClass'];
}
/**
* {@inheritdoc}
*/
public function hints()
{
return [
'controllerClass' => 'This is the name of the controller class to be generated. You should
provide a fully qualified namespaced class (e.g. <code>app\controllers\PostController</code>),
and class name should be in CamelCase ending with the word <code>Controller</code>. Make sure the class
is using the same namespace as specified by your application\'s controllerNamespace property.',
'actions' => 'Provide one or multiple action IDs to generate empty action method(s) in the controller. Separate multiple action IDs with commas or spaces.
Action IDs should be in lower case. For example:
<ul>
<li><code>index</code> generates <code>actionIndex()</code></li>
<li><code>create-order</code> generates <code>actionCreateOrder()</code></li>
</ul>',
'viewPath' => 'Specify the directory for storing the view scripts for the controller. You may use path alias here, e.g.,
<code>/var/www/basic/controllers/views/order</code>, <code>@app/views/order</code>. If not set, it will default
to <code>@app/views/ControllerID</code>',
'baseClass' => 'This is the class that the new controller class will extend from. Please make sure the class exists and can be autoloaded.',
];
}
/**
* {@inheritdoc}
*/
public function successMessage()
{
return 'The controller has been generated successfully.' . $this->getLinkToTry();
}
/**
* This method returns a link to try controller generated
* @see https://github.com/yiisoft/yii2-gii/issues/182
* @return string
* @since 2.0.6
*/
private function getLinkToTry()
{
if (strpos($this->controllerNamespace, Yii::$app->controllerNamespace) !== 0) {
return '';
}
$actions = $this->getActionIDs();
if (in_array('index', $actions, true)) {
$route = $this->getControllerSubPath() . $this->getControllerID() . '/index';
} else {
$route = $this->getControllerSubPath() . $this->getControllerID() . '/' . reset($actions);
}
return ' You may ' . Html::a('try it now', Yii::$app->getUrlManager()->createUrl($route), ['target' => '_blank', 'rel' => 'noopener noreferrer']) . '.';
}
/**
* {@inheritdoc}
*/
public function generate()
{
$files = [];
$files[] = new CodeFile(
$this->getControllerFile(),
$this->render('controller.php')
);
foreach ($this->getActionIDs() as $action) {
$files[] = new CodeFile(
$this->getViewFile($action),
$this->render('view.php', ['action' => $action])
);
}
return $files;
}
/**
* Normalizes [[actions]] into an array of action IDs.
* @return array an array of action IDs entered by the user
*/
public function getActionIDs()
{
$actions = array_unique(preg_split('/[\s,]+/', $this->actions, -1, PREG_SPLIT_NO_EMPTY));
sort($actions);
return $actions;
}
/**
* @return string the controller class file path
*/
public function getControllerFile()
{
return Yii::getAlias('@' . str_replace('\\', '/', $this->controllerClass)) . '.php';
}
/**
* @return string the controller ID
*/
public function getControllerID()
{
$name = StringHelper::basename($this->controllerClass);
return Inflector::camel2id(substr($name, 0, strlen($name) - 10));
}
/**
* This method will return sub path for controller if it
* is located in subdirectory of application controllers dir
* @see https://github.com/yiisoft/yii2-gii/issues/182
* @since 2.0.6
* @return string the controller sub path
*/
public function getControllerSubPath()
{
$subPath = '';
$controllerNamespace = $this->getControllerNamespace();
if (strpos($controllerNamespace, Yii::$app->controllerNamespace) === 0) {
$subPath = substr($controllerNamespace, strlen(Yii::$app->controllerNamespace));
$subPath = ($subPath !== '') ? str_replace('\\', '/', substr($subPath, 1)) . '/' : '';
}
return $subPath;
}
/**
* @param string $action the action ID
* @return string the action view file path
*/
public function getViewFile($action)
{
if (empty($this->viewPath)) {
return Yii::getAlias('@app/views/' . $this->getControllerSubPath() . $this->getControllerID() . "/$action.php");
}
return Yii::getAlias(str_replace('\\', '/', $this->viewPath) . "/$action.php");
}
/**
* @return string the namespace of the controller class
*/
public function getControllerNamespace()
{
$name = StringHelper::basename($this->controllerClass);
return ltrim(substr($this->controllerClass, 0, - (strlen($name) + 1)), '\\');
}
}

27
vendor/iron/generators/controller/default/controller.php

@ -0,0 +1,27 @@
<?php
/**
* This is the template for generating a controller class file.
*/
use yii\helpers\Inflector;
use yii\helpers\StringHelper;
/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\controller\Generator */
echo "<?php\n";
?>
namespace <?= $generator->getControllerNamespace() ?>;
class <?= StringHelper::basename($generator->controllerClass) ?> extends <?= '\\' . trim($generator->baseClass, '\\') . "\n" ?>
{
<?php foreach ($generator->getActionIDs() as $action): ?>
public function action<?= Inflector::id2camel($action) ?>()
{
return $this->render('<?= $action ?>');
}
<?php endforeach; ?>

20
vendor/iron/generators/controller/default/view.php

@ -0,0 +1,20 @@
<?php
/**
* This is the template for generating an action view file.
*/
/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\controller\Generator */
/* @var $action string the action ID */
echo "<?php\n";
?>
/* @var $this yii\web\View */
<?= "?>" ?>
<h1><?= $generator->getControllerSubPath() . $generator->getControllerID() . '/' . $action ?></h1>
<p>
You may change the content of this page by modifying
the file <code><?= '<?=' ?> __FILE__; ?></code>.
</p>

9
vendor/iron/generators/controller/form.php

@ -0,0 +1,9 @@
<?php
/* @var $this yii\web\View */
/* @var $form yii\widgets\ActiveForm */
/* @var $generator yii\gii\generators\controller\Generator */
echo $form->field($generator, 'controllerClass');
echo $form->field($generator, 'actions');
echo $form->field($generator, 'viewPath');
echo $form->field($generator, 'baseClass');

555
vendor/iron/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 iron\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;
}
}

201
vendor/iron/generators/crud/default/controller.php

@ -0,0 +1,201 @@
<?php
/**
* This is the template for generating a CRUD controller class file.
*/
use yii\db\ActiveRecordInterface;
use yii\helpers\StringHelper;
use yii\helpers\Inflector;
/* @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,
'columns' => $searchModel->columns()
]);
<?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('index');
}
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('index');
}
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.') ?>);
}
/**
* @author iron
* 文件导出
*/
public function actionExport()
{
$searchModel = new <?= isset($searchModelAlias) ? $searchModelAlias : $searchModelClass ?>();
$params = Yii::$app->request->queryParams;
if ($params['page-type'] == 'all') {
$dataProvider = $searchModel->allData($params);
} else {
$dataProvider = $searchModel->search($params);
}
\iron\widget\Excel::export([
'models' => $dataProvider->getModels(),
'format' => 'Xlsx',
'asAttachment' => true,
'fileName' =><?= $generator->generateString(Inflector::pluralize(Inflector::camel2words(StringHelper::basename($generator->modelClass)))) ?>. "-" .date('Y-m-d H/i/s', time()),
'columns' => $searchModel->columns()
]);
}
}

160
vendor/iron/generators/crud/default/search.php

@ -0,0 +1,160 @@
<?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 yii\helpers\ArrayHelper;
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 ?>
{
/**
* @return array
* 增加创建时间查询字段
*/
public function attributes()
{
return ArrayHelper::merge(['created_at_range'], parent::attributes());
}
/**
* {@inheritdoc}
*/
public function rules()
{
return [
<?= implode(",\n ", $rules) ?>,
['created_at_range','safe'],
];
}
/**
* {@inheritdoc}
*/
public function scenarios()
{
// bypass scenarios() implementation in the parent class
return Model::scenarios();
}
/**
* @return array
* 列格式
*/
public function columns()
{
return [
[
'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' => 'iron\grid\ActionColumn',
'align' => 'center',
],
];
}
/**
* @param $params
* @return ActiveDataProvider
* 不分页的所有数据
*/
public function allData($params)
{
$query = <?= isset($modelAlias) ? $modelAlias : $modelClass ?>::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
'pagination' => false,
'sort' => false
]);
$this->load($params);
return $this->filter($query, $dataProvider);
}
/**
* 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,
'pagination' => [
'pageSizeLimit' => [1, 200]
],
'sort' => [
'defaultOrder' => [
'id' => SORT_DESC,
]
],
]);
$this->load($params);
return $this->filter($query, $dataProvider);
}
/**
* @param $query
* @param $dataProvider
* @return ActiveDataProvider
* 条件筛选
*/
private function filter($query, $dataProvider){
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) ?>
if ($this->created_at_range) {
$arr = explode(' ~ ', $this->created_at_range);
$start = strtotime($arr[0]);
$end = strtotime($arr[1]) + 3600 * 24;
$query->andFilterWhere(['between', 'created_at', $start, $end]);
}
return $dataProvider;
}
}

43
vendor/iron/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>

57
vendor/iron/generators/crud/default/views/_search.php

@ -0,0 +1,57 @@
<?php
use yii\helpers\Inflector;
use yii\helpers\StringHelper;
use blobt\widgets\DateRangePicker;
/* @var $this yii\web\View */
/* @var $generator yii\gii\generators\crud\Generator */
echo "<?php\n";
?>
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use \blobt\widgets\DateRangePicker;
/* @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"
]
])
?>
<?="<?= "?>$form->field($model, "created_at_range", [
"template" => "{input}{error}",
"inputOptions" => [
"placeholder" => "创建时间",
],
"errorOptions" => [
"class" => "error-tips"
]
])->widget(DateRangePicker::className());
?>
<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/iron/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>

41
vendor/iron/generators/crud/default/views/index.php

@ -0,0 +1,41 @@
<?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' => $columns
]);
<?= "?>" ?>
</div>
</div>

38
vendor/iron/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/iron/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/iron/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/iron/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 iron\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;
}
}

125
vendor/iron/generators/model/default/model.php

@ -0,0 +1,125 @@
<?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/iron/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/iron/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