From 24e012e7dde2864d0c5db1f686b5bb13b56e1d67 Mon Sep 17 00:00:00 2001
From: linyaostalker <602604991@qq.com>
Date: Wed, 13 Nov 2019 16:05:48 +0800
Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B6master=E5=88=86=E6=94=AF?=
=?UTF-8?q?=E5=92=8Cantshop=E5=88=86=E6=94=AF=E7=9A=84vendor/iron/?=
=?UTF-8?q?=E6=96=87=E4=BB=B6=E5=A4=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../iron/generators/controller/Generator.php | 255 +++++
.../controller/default/controller.php | 27 +
.../generators/controller/default/view.php | 20 +
vendor/iron/generators/controller/form.php | 9 +
vendor/iron/generators/crud/Generator.php | 555 ++++++++++
.../generators/crud/default/controller.php | 201 ++++
.../iron/generators/crud/default/search.php | 160 +++
.../generators/crud/default/views/_form.php | 43 +
.../generators/crud/default/views/_search.php | 57 +
.../generators/crud/default/views/create.php | 27 +
.../generators/crud/default/views/index.php | 41 +
.../generators/crud/default/views/update.php | 38 +
.../generators/crud/default/views/view.php | 49 +
vendor/iron/generators/crud/form.php | 17 +
vendor/iron/generators/model/Generator.php | 995 ++++++++++++++++++
.../iron/generators/model/default/model.php | 125 +++
.../iron/generators/model/default/query.php | 56 +
vendor/iron/generators/model/form.php | 30 +
vendor/iron/grid/ActionColumn.php | 246 +++++
vendor/iron/widget/Excel.php | 958 +++++++++++++++++
20 files changed, 3909 insertions(+)
create mode 100644 vendor/iron/generators/controller/Generator.php
create mode 100644 vendor/iron/generators/controller/default/controller.php
create mode 100644 vendor/iron/generators/controller/default/view.php
create mode 100644 vendor/iron/generators/controller/form.php
create mode 100644 vendor/iron/generators/crud/Generator.php
create mode 100644 vendor/iron/generators/crud/default/controller.php
create mode 100644 vendor/iron/generators/crud/default/search.php
create mode 100644 vendor/iron/generators/crud/default/views/_form.php
create mode 100644 vendor/iron/generators/crud/default/views/_search.php
create mode 100644 vendor/iron/generators/crud/default/views/create.php
create mode 100644 vendor/iron/generators/crud/default/views/index.php
create mode 100644 vendor/iron/generators/crud/default/views/update.php
create mode 100644 vendor/iron/generators/crud/default/views/view.php
create mode 100644 vendor/iron/generators/crud/form.php
create mode 100644 vendor/iron/generators/model/Generator.php
create mode 100644 vendor/iron/generators/model/default/model.php
create mode 100644 vendor/iron/generators/model/default/query.php
create mode 100644 vendor/iron/generators/model/form.php
create mode 100644 vendor/iron/grid/ActionColumn.php
create mode 100755 vendor/iron/widget/Excel.php
diff --git a/vendor/iron/generators/controller/Generator.php b/vendor/iron/generators/controller/Generator.php
new file mode 100644
index 0000000..eec6f71
--- /dev/null
+++ b/vendor/iron/generators/controller/Generator.php
@@ -0,0 +1,255 @@
+
+ * @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. app\controllers\PostController
),
+ and class name should be in CamelCase ending with the word Controller
. 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:
+
index
generates actionIndex()
create-order
generates actionCreateOrder()
/var/www/basic/controllers/views/order
, @app/views/order
. If not set, it will default
+ to @app/views/ControllerID
',
+ '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)), '\\');
+ }
+}
diff --git a/vendor/iron/generators/controller/default/controller.php b/vendor/iron/generators/controller/default/controller.php
new file mode 100644
index 0000000..e574bd6
--- /dev/null
+++ b/vendor/iron/generators/controller/default/controller.php
@@ -0,0 +1,27 @@
+
+
+namespace = $generator->getControllerNamespace() ?>;
+
+class = StringHelper::basename($generator->controllerClass) ?> extends = '\\' . trim($generator->baseClass, '\\') . "\n" ?>
+{
+getActionIDs() as $action): ?>
+ public function action= Inflector::id2camel($action) ?>()
+ {
+ return $this->render('= $action ?>');
+ }
+
+
+
+
diff --git a/vendor/iron/generators/controller/default/view.php b/vendor/iron/generators/controller/default/view.php
new file mode 100644
index 0000000..c46b542
--- /dev/null
+++ b/vendor/iron/generators/controller/default/view.php
@@ -0,0 +1,20 @@
+
+/* @var $this yii\web\View */
+= "?>" ?>
+
+
+ You may change the content of this page by modifying
+ the file = '=' ?> __FILE__; ?>
.
+
app\models\Post
.',
+ 'controllerClass' => 'This is the name of the controller class to be generated. You should
+ provide a fully qualified namespaced class (e.g. app\controllers\PostController
),
+ 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.,
+ /var/www/basic/controllers/views/post
, @app/views/post
. If not set, it will default
+ to @app/views/ControllerID
',
+ 'baseControllerClass' => 'This is the class that the new CRUD controller class will extend from.
+ You should provide a fully qualified class name, e.g., yii\web\Controller
.',
+ 'indexWidgetType' => 'This is the widget type to be used in the index page to display list of the models.
+ You may choose either GridView
or ListView
',
+ 'searchModelClass' => 'This is the name of the search model class to be generated. You should provide a fully
+ qualified namespaced class name, e.g., app\models\PostSearch
.',
+ 'enablePjax' => 'This indicates whether the generator should wrap the GridView
or ListView
+ widget on the index page with yii\widgets\Pjax
widget. Set this to true
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;
+ }
+
+}
diff --git a/vendor/iron/generators/crud/default/controller.php b/vendor/iron/generators/crud/default/controller.php
new file mode 100644
index 0000000..7afcb98
--- /dev/null
+++ b/vendor/iron/generators/crud/default/controller.php
@@ -0,0 +1,201 @@
+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 "
+
+namespace = StringHelper::dirname(ltrim($generator->controllerClass, '\\')) ?>;
+
+use Yii;
+use = ltrim($generator->modelClass, '\\') ?>;
+searchModelClass)): ?>
+use = ltrim($generator->searchModelClass, '\\') . (isset($searchModelAlias) ? " as $searchModelAlias" : "") ?>;
+
+use yii\data\ActiveDataProvider;
+
+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()
+ {
+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()
+ ]);
+
+ $dataProvider = new ActiveDataProvider([
+ 'query' => = $modelClass ?>::find(),
+ ]);
+
+ return $this->render('index', [
+ 'dataProvider' => $dataProvider,
+ ]);
+
+ }
+
+ /**
+ * 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 ?>)
+ {
+ \$$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()
+ ]);
+ }
+}
diff --git a/vendor/iron/generators/crud/default/search.php b/vendor/iron/generators/crud/default/search.php
new file mode 100644
index 0000000..9d2e954
--- /dev/null
+++ b/vendor/iron/generators/crud/default/search.php
@@ -0,0 +1,160 @@
+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 "
+
+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'
+ ],
+ 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;
+ }
+}
diff --git a/vendor/iron/generators/crud/default/views/_form.php b/vendor/iron/generators/crud/default/views/_form.php
new file mode 100644
index 0000000..b370036
--- /dev/null
+++ b/vendor/iron/generators/crud/default/views/_form.php
@@ -0,0 +1,43 @@
+modelClass();
+$safeAttributes = $model->safeAttributes();
+if (empty($safeAttributes)) {
+ $safeAttributes = $model->attributes();
+}
+
+echo "
+
+use yii\helpers\Html;
+use yii\widgets\ActiveForm;
+
+/* @var $this yii\web\View */
+/* @var $model = ltrim($generator->modelClass, '\\') ?> */
+/* @var $form yii\widgets\ActiveForm */
+?>
+
++ = "= " ?>Html::a(= $generator->generateString('返回列表') ?>, ['index'], ['class' => 'btn btn-success']) ?> +
+ + = "= " ?>DetailView::widget([ + 'model' => $model, + 'attributes' => [ +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"; + } +} +?> + ], + ]) ?> + +app\models
',
+ '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. post
.
+ The table name may consist of the DB schema part if needed, e.g. public.post
.
+ The table name may end with asterisk to match multiple table names, e.g. tbl_*
+ will match tables who name starts with tbl_
. 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 tbl_post
will generate Post
+ 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 SOME_TABLE
or Other_Table
will have class names SomeTable
+ and OtherTable
, respectively. If not checked, the same tables will have class names SOMETABLE
+ and OtherTable
instead.',
+ 'singularize' => 'This indicates whether the generated class names should be singularized. For example,
+ table names like some_tables
will have class names SomeTable
.',
+ '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 tablePrefix
setting of the DB connection. For example, if the
+ table name is tbl_post
and tablePrefix=tbl_
, the ActiveRecord class
+ will return the table name as {{%post}}
.',
+ '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., app\models
',
+ '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;
+ }
+}
diff --git a/vendor/iron/generators/model/default/model.php b/vendor/iron/generators/model/default/model.php
new file mode 100644
index 0000000..f1ec568
--- /dev/null
+++ b/vendor/iron/generators/model/default/model.php
@@ -0,0 +1,125 @@
+ [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 "
+
+namespace = $generator->ns ?>;
+
+use Yii;
+use yii\behaviors\TimestampBehavior;
+
+/**
+ * This is the model class for table "= $generator->generateTableName($tableName) ?>".
+ *
+ $data): ?>
+ * @property = "{$data['type']} \${$property}" . ($data['comment'] ? ' ' . strtr($data['comment'], ["\n" => ' ']) : '') . "\n" ?>
+
+
+ *
+ $relation): ?>
+ * @property = $relation[1] . ($relation[2] ? '[]' : '') . ' $' . lcfirst($name) . "\n" ?>
+
+
+ */
+class = $className ?> extends = '\\' . ltrim($generator->baseClass, '\\') . "\n" ?>
+{
+ /**
+ * {@inheritdoc}
+ */
+ public static function tableName()
+ {
+ return '= $generator->generateTableName($tableName) ?>';
+ }
+db !== 'db'): ?>
+
+ /**
+ * @return \yii\db\Connection the database connection used by this AR class.
+ */
+ public static function getDb()
+ {
+ return Yii::$app->get('= $generator->db ?>');
+ }
+
+
+ /**
+ * {@inheritdoc}
+ */
+ public function rules()
+ {
+ return [= empty($rules) ? '' : ("\n " . implode(",\n ", $rules) . ",\n ") ?>];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function attributeLabels()
+ {
+ return [
+ $label): ?>
+ = "'$name' => " . $generator->generateString($label) . ",\n" ?>
+
+ ];
+ }
+ $relation): ?>
+
+ /**
+ * @return \yii\db\ActiveQuery
+ */
+ public function get= $name ?>()
+ {
+ = $relation[0] . "\n" ?>
+ }
+
+
+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());
+ }
+
+
+
+
+ /**
+ * @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();
+ },
+ ],
+ ];
+ }
+
+}
diff --git a/vendor/iron/generators/model/default/query.php b/vendor/iron/generators/model/default/query.php
new file mode 100644
index 0000000..c362dfe
--- /dev/null
+++ b/vendor/iron/generators/model/default/query.php
@@ -0,0 +1,56 @@
+ 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 "
+
+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);
+ }
+}
diff --git a/vendor/iron/generators/model/form.php b/vendor/iron/generators/model/form.php
new file mode 100644
index 0000000..2fa118f
--- /dev/null
+++ b/vendor/iron/generators/model/form.php
@@ -0,0 +1,30 @@
+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();
diff --git a/vendor/iron/grid/ActionColumn.php b/vendor/iron/grid/ActionColumn.php
new file mode 100644
index 0000000..40af31b
--- /dev/null
+++ b/vendor/iron/grid/ActionColumn.php
@@ -0,0 +1,246 @@
+ 'view',
+ 'icon' => 'menu-hamburger',
+ 'title' => '详情',
+ ],
+ [
+ 'name' => 'update',
+ 'icon' => 'edit',
+ 'title' => '修改'
+ ],
+ [
+ 'name' => 'delete',
+ 'icon' => 'trash',
+ 'title' => '删除',
+ 'contents' => '确定删除?'
+ ]
+ ];
+ /**
+ * @var string 处理的控制器ID
+ */
+ public $controller;
+
+ /**
+ * @var string 按钮模板
+ */
+ public $template = '';
+
+ /**
+ * @var array 以按钮名为键,以匿名函数为值,通过匿名函数返回html,用来控制按钮的表现形式
+ * 匿名函数必须遵循以下申明方式:
+ *
+ * ```php
+ * function ($url, $model, $key) {
+ * // return the button HTML code
+ * }
+ * ```
+ *
+ * - `$url`: 按钮的跳转路径
+ * - `$model`: 每行的模型
+ * - `$key`: id值
+ *
+ * 使用案例:
+ * ```php
+ * [
+ * 'update' => function ($url, $model, $key) {
+ * return $model->status === 'editable' ? Html::a('Update', $url) : '';
+ * },
+ * ],
+ *
+ */
+ public $buttons = [];
+
+ /** @var array 和上述$buttons功能类似,只是匿名函数返回布尔,只控制是否展示
+ * 匿名函数必须遵循以下申明方式:
+ *
+ * ```php
+ * function ($model, $key, $index) {
+ * return $model->status === 'editable';
+ * }
+ * ```
+ *
+ * 使用案例:
+ * ```php
+ * [
+ * 'update' => \Yii::$app->user->can('update'),
+ * ],
+ * ```
+ * @since 2.0.7
+ */
+ public $visibleButtons = [];
+
+ /**
+ * @var callable 匿名函数,用作控制按钮Url
+ *
+ * 匿名函数必须遵循以下申明方式:
+ * ```php
+ * function (string $action, mixed $model, mixed $key, integer $index, ActionColumn $this) {
+ * //return string;
+ * }
+ * ```
+ *
+ * 如果没有设置,默认使用本类的[[createUrl()]].
+ */
+ public $urlCreator;
+
+ /**
+ * @var array 按钮的html属性
+ */
+ public $buttonOptions = [];
+
+ /**
+ * {@inheritdoc}
+ */
+ public function init()
+ {
+ parent::init();
+ foreach ($this->config as $config) {
+ if (isset($config['contents'])) {
+ $options = ['alertify-confirm' => Yii::t('yii', "{$config['contents']}?")];
+ } else {
+ $options = [];
+ }
+ if (isset($config['icon'])) {
+ $icon = $config['icon'];
+ } else {
+ $icon = 'th-large';
+ }
+ if (isset($config['title'])) {
+ $title = $config['title'];
+ } else {
+ $title = $config['name'];
+ }
+ if (isset($config['hide'])) {
+ $this->visibleButtons($config['name'], $config['hide']);
+ }
+ $this->initButton($config['name'], $icon, $options, $title);
+ $this->template .= " {{$config['name']}}";
+ }
+ }
+
+ /**
+ * 初始化按钮
+ * @param string $name
+ * @param string $iconName
+ * @param array $additionalOptions 附加html属性
+ */
+ protected function initButton($name, $iconName, $additionalOptions = [], $title = '')
+ {
+ $this->buttons[$name] = function ($url, $model, $key) use ($name, $iconName, $additionalOptions, $title) {
+ $title = $title ?: Yii::t('yii', $name);
+ $options = array_merge([
+ 'title' => $title,
+ 'aria-label' => $title,
+ 'data-pjax' => '0',
+ ], $additionalOptions, $this->buttonOptions);
+ $icon = Html::tag('span', '', ['class' => "glyphicon glyphicon-$iconName"]);
+ return Html::a($icon, $url, $options);
+ };
+ }
+
+ protected function visibleButtons($name, $config)
+ {
+ $this->visibleButtons[$name] = function ($model, $key, $index) use ($config) {
+ $attributes = $config['attributes'];
+ $values = $config['values'];
+ if (isset($config['rule']) && $config['rule'] == 'or') {
+ foreach ($attributes as $k => $attribute) {
+ if ($model->$attribute == $values[$k]) {
+ return false;
+ }
+ }
+ return true;
+ }else{
+ foreach ($attributes as $k => $attribute) {
+ if ($model->$attribute != $values[$k]) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ };
+ }
+
+ /**
+ * 通过给定的action和model创建一个URL.
+ *
+ * @param string $action 按钮名
+ * @param \yii\db\ActiveRecordInterface $model 数据模型
+ * @param mixed $key 模型的ID
+ * @param int $index 行号
+ * @return string the created URL
+ */
+ public function createUrl($action, $model, $key, $index)
+ {
+ if (is_callable($this->urlCreator)) {
+ return call_user_func($this->urlCreator, $action, $model, $key, $index, $this);
+ }
+
+ $params = is_array($key) ? $key : ['id' => (string)$key];
+ $params[0] = $this->controller ? $this->controller . '/' . $action : $action;
+
+ return Url::toRoute($params);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function renderDataCellContent($model, $key, $index)
+ {
+ return preg_replace_callback('/\\{([\w\-\/]+)\\}/', function ($matches) use ($model, $key, $index) {
+ $name = $matches[1];
+
+ if (isset($this->visibleButtons[$name])) {
+ $isVisible = $this->visibleButtons[$name] instanceof \Closure ? call_user_func($this->visibleButtons[$name], $model, $key, $index) : $this->visibleButtons[$name];
+ } else {
+ $isVisible = true;
+ }
+
+ if ($isVisible && isset($this->buttons[$name])) {
+ $url = $this->createUrl($name, $model, $key, $index);
+ return call_user_func($this->buttons[$name], $url, $model, $key);
+ }
+
+ return '';
+ }, $this->template);
+ }
+
+}
diff --git a/vendor/iron/widget/Excel.php b/vendor/iron/widget/Excel.php
new file mode 100755
index 0000000..5aaed07
--- /dev/null
+++ b/vendor/iron/widget/Excel.php
@@ -0,0 +1,958 @@
+ $allModels,
+ * 'mode' => 'export', //default value as 'export'
+ * 'columns' => ['column1','column2','column3'],
+ * //without header working, because the header will be get label from attribute label.
+ * 'headers' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'],
+ * ]);
+ *
+ * \moonland\phpexcel\Excel::export([
+ * 'models' => $allModels,
+ * 'columns' => ['column1','column2','column3'],
+ * //without header working, because the header will be get label from attribute label.
+ * 'headers' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'],
+ * ]);
+ *
+ * // export data with multiple worksheet.
+ *
+ * \moonland\phpexcel\Excel::widget([
+ * 'isMultipleSheet' => true,
+ * 'models' => [
+ * 'sheet1' => $allModels1,
+ * 'sheet2' => $allModels2,
+ * 'sheet3' => $allModels3
+ * ],
+ * 'mode' => 'export', //default value as 'export'
+ * 'columns' => [
+ * 'sheet1' => ['column1','column2','column3'],
+ * 'sheet2' => ['column1','column2','column3'],
+ * 'sheet3' => ['column1','column2','column3']
+ * ],
+ * //without header working, because the header will be get label from attribute label.
+ * 'headers' => [
+ * 'sheet1' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'],
+ * 'sheet2' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'],
+ * 'sheet3' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3']
+ * ],
+ * ]);
+ *
+ * \moonland\phpexcel\Excel::export([
+ * 'isMultipleSheet' => true,
+ * 'models' => [
+ * 'sheet1' => $allModels1,
+ * 'sheet2' => $allModels2,
+ * 'sheet3' => $allModels3
+ * ],
+ * 'columns' => [
+ * 'sheet1' => ['column1','column2','column3'],
+ * 'sheet2' => ['column1','column2','column3'],
+ * 'sheet3' => ['column1','column2','column3']
+ * ],
+ * //without header working, because the header will be get label from attribute label.
+ * 'headers' => [
+ * 'sheet1' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'],
+ * 'sheet2' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3'],
+ * 'sheet3' => ['column1' => 'Header Column 1','column2' => 'Header Column 2', 'column3' => 'Header Column 3']
+ * ],
+ * ]);
+ *
+ * ~~~
+ *
+ * New Feature for exporting data, you can use this if you familiar yii gridview.
+ * That is same with gridview data column.
+ * Columns in array mode valid params are 'attribute', 'header', 'format', 'value', and footer (TODO).
+ * Columns in string mode valid layout are 'attribute:format:header:footer(TODO)'.
+ *
+ * ~~~
+ *
+ * \moonland\phpexcel\Excel::export([
+ * 'models' => Post::find()->all(),
+ * 'columns' => [
+ * 'author.name:text:Author Name',
+ * [
+ * 'attribute' => 'content',
+ * 'header' => 'Content Post',
+ * 'format' => 'text',
+ * 'value' => function($model) {
+ * return ExampleClass::removeText('example', $model->content);
+ * },
+ * ],
+ * 'like_it:text:Reader like this content',
+ * 'created_at:datetime',
+ * [
+ * 'attribute' => 'updated_at',
+ * 'format' => 'date',
+ * ],
+ * ],
+ * 'headers' => [
+ * 'created_at' => 'Date Created Content',
+ * ],
+ * ]);
+ *
+ * ~~~
+ *
+ *
+ * Import file excel and return into an array.
+ *
+ * ~~~
+ *
+ * $data = \moonland\phpexcel\Excel::import($fileName, $config); // $config is an optional
+ *
+ * $data = \moonland\phpexcel\Excel::widget([
+ * 'mode' => 'import',
+ * 'fileName' => $fileName,
+ * 'setFirstRecordAsKeys' => true, // if you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
+ * 'setIndexSheetByName' => true, // set this if your excel data with multiple worksheet, the index of array will be set with the sheet name. If this not set, the index will use numeric.
+ * 'getOnlySheet' => 'sheet1', // you can set this property if you want to get the specified sheet from the excel data with multiple worksheet.
+ * ]);
+ *
+ * $data = \moonland\phpexcel\Excel::import($fileName, [
+ * 'setFirstRecordAsKeys' => true, // if you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
+ * 'setIndexSheetByName' => true, // set this if your excel data with multiple worksheet, the index of array will be set with the sheet name. If this not set, the index will use numeric.
+ * 'getOnlySheet' => 'sheet1', // you can set this property if you want to get the specified sheet from the excel data with multiple worksheet.
+ * ]);
+ *
+ * // import data with multiple file.
+ *
+ * $data = \moonland\phpexcel\Excel::widget([
+ * 'mode' => 'import',
+ * 'fileName' => [
+ * 'file1' => $fileName1,
+ * 'file2' => $fileName2,
+ * 'file3' => $fileName3,
+ * ],
+ * 'setFirstRecordAsKeys' => true, // if you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
+ * 'setIndexSheetByName' => true, // set this if your excel data with multiple worksheet, the index of array will be set with the sheet name. If this not set, the index will use numeric.
+ * 'getOnlySheet' => 'sheet1', // you can set this property if you want to get the specified sheet from the excel data with multiple worksheet.
+ * ]);
+ *
+ * $data = \moonland\phpexcel\Excel::import([
+ * 'file1' => $fileName1,
+ * 'file2' => $fileName2,
+ * 'file3' => $fileName3,
+ * ], [
+ * 'setFirstRecordAsKeys' => true, // if you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
+ * 'setIndexSheetByName' => true, // set this if your excel data with multiple worksheet, the index of array will be set with the sheet name. If this not set, the index will use numeric.
+ * 'getOnlySheet' => 'sheet1', // you can set this property if you want to get the specified sheet from the excel data with multiple worksheet.
+ * ]);
+ *
+ * ~~~
+ *
+ * Result example from the code on the top :
+ *
+ * ~~~
+ *
+ * // only one sheet or specified sheet.
+ *
+ * Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
+ * [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2));
+ *
+ * // data with multiple worksheet
+ *
+ * Array([Sheet1] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
+ * [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)),
+ * [Sheet2] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
+ * [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)));
+ *
+ * // data with multiple file and specified sheet or only one worksheet
+ *
+ * Array([file1] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
+ * [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)),
+ * [file2] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
+ * [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)));
+ *
+ * // data with multiple file and multiple worksheet
+ *
+ * Array([file1] => Array([Sheet1] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
+ * [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)),
+ * [Sheet2] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
+ * [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2))),
+ * [file2] => Array([Sheet1] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
+ * [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2)),
+ * [Sheet2] => Array([0] => Array([name] => Anam, [email] => moh.khoirul.anaam@gmail.com, [framework interest] => Yii2),
+ * [1] => Array([name] => Example, [email] => example@moonlandsoft.com, [framework interest] => Yii2))));
+ *
+ * ~~~
+ *
+ * @property string $mode is an export mode or import mode. valid value are 'export' and 'import'
+ * @property boolean $isMultipleSheet for set the export excel with multiple sheet.
+ * @property array $properties for set property on the excel object.
+ * @property array $models Model object or DataProvider object with much data.
+ * @property array $columns to get the attributes from the model, this valid value only the exist attribute on the model.
+ * If this is not set, then all attribute of the model will be set as columns.
+ * @property array $headers to set the header column on first line. Set this if want to custom header.
+ * If not set, the header will get attributes label of model attributes.
+ * @property string|array $fileName is a name for file name to export or import. Multiple file name only use for import mode, not work if you use the export mode.
+ * @property string $savePath is a directory to save the file or you can blank this to set the file as attachment.
+ * @property string $format for excel to export. Valid value are 'Xls','Xlsx','Xml','Ods','Slk','Gnumeric','Csv', and 'Html'.
+ * @property boolean $setFirstTitle to set the title column on the first line. The columns will have a header on the first line.
+ * @property boolean $asAttachment to set the file excel to download mode.
+ * @property boolean $setFirstRecordAsKeys to set the first record on excel file to a keys of array per line.
+ * If you want to set the keys of record column with first record, if it not set, the header with use the alphabet column on excel.
+ * @property boolean $setIndexSheetByName to set the sheet index by sheet name or array result if the sheet not only one
+ * @property string $getOnlySheet is a sheet name to getting the data. This is only get the sheet with same name.
+ * @property array|Formatter $formatter the formatter used to format model attribute values into displayable texts.
+ * This can be either an instance of [[Formatter]] or an configuration array for creating the [[Formatter]]
+ * instance. If this property is not set, the "formatter" application component will be used.
+ *
+ * @author Moh Khoirul Anam