Browse Source

合并master分支和antshop分支的vendor/iron/文件夹

wechat_public_accounts
linyaostalker 5 years ago
parent
commit
24e012e7dd
  1. 255
      vendor/iron/generators/controller/Generator.php
  2. 27
      vendor/iron/generators/controller/default/controller.php
  3. 20
      vendor/iron/generators/controller/default/view.php
  4. 9
      vendor/iron/generators/controller/form.php
  5. 555
      vendor/iron/generators/crud/Generator.php
  6. 201
      vendor/iron/generators/crud/default/controller.php
  7. 160
      vendor/iron/generators/crud/default/search.php
  8. 43
      vendor/iron/generators/crud/default/views/_form.php
  9. 57
      vendor/iron/generators/crud/default/views/_search.php
  10. 27
      vendor/iron/generators/crud/default/views/create.php
  11. 41
      vendor/iron/generators/crud/default/views/index.php
  12. 38
      vendor/iron/generators/crud/default/views/update.php
  13. 49
      vendor/iron/generators/crud/default/views/view.php
  14. 17
      vendor/iron/generators/crud/form.php
  15. 995
      vendor/iron/generators/model/Generator.php
  16. 125
      vendor/iron/generators/model/default/model.php
  17. 56
      vendor/iron/generators/model/default/query.php
  18. 30
      vendor/iron/generators/model/form.php
  19. 246
      vendor/iron/grid/ActionColumn.php
  20. 958
      vendor/iron/widget/Excel.php

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();

246
vendor/iron/grid/ActionColumn.php

@ -0,0 +1,246 @@
<?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\grid;
use Yii;
use yii\helpers\Html;
use yii\helpers\Url;
use blobt\grid\Column;
class ActionColumn extends Column
{
public $config = [
[
'name' => '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);
}
}

958
vendor/iron/widget/Excel.php

@ -0,0 +1,958 @@
<?php
namespace iron\widget;
use yii\helpers\ArrayHelper;
use yii\base\InvalidConfigException;
use yii\base\InvalidParamException;
use yii\i18n\Formatter;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
/**
* Excel Widget for generate Excel File or for load Excel File.
*
* Usage
* -----
*
* Exporting data into an excel file.
*
* ~~~
*
* // export data only one worksheet.
*
* \moonland\phpexcel\Excel::widget([
* 'models' => $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 <moh.khoirul.anaam@gmail.com>
* @copyright 2014
* @since 1
*/
class Excel extends \yii\base\Widget
{
// Border style
const BORDER_NONE = 'none';
const BORDER_DASHDOT = 'dashDot';
const BORDER_DASHDOTDOT = 'dashDotDot';
const BORDER_DASHED = 'dashed';
const BORDER_DOTTED = 'dotted';
const BORDER_DOUBLE = 'double';
const BORDER_HAIR = 'hair';
const BORDER_MEDIUM = 'medium';
const BORDER_MEDIUMDASHDOT = 'mediumDashDot';
const BORDER_MEDIUMDASHDOTDOT = 'mediumDashDotDot';
const BORDER_MEDIUMDASHED = 'mediumDashed';
const BORDER_SLANTDASHDOT = 'slantDashDot';
const BORDER_THICK = 'thick';
const BORDER_THIN = 'thin';
// Colors
const COLOR_BLACK = 'FF000000';
const COLOR_WHITE = 'FFFFFFFF';
const COLOR_RED = 'FFFF0000';
const COLOR_DARKRED = 'FF800000';
const COLOR_BLUE = 'FF0000FF';
const COLOR_DARKBLUE = 'FF000080';
const COLOR_GREEN = 'FF00FF00';
const COLOR_DARKGREEN = 'FF008000';
const COLOR_YELLOW = 'FFFFFF00';
const COLOR_DARKYELLOW = 'FF808000';
// Horizontal alignment styles
const HORIZONTAL_GENERAL = 'general';
const HORIZONTAL_LEFT = 'left';
const HORIZONTAL_RIGHT = 'right';
const HORIZONTAL_CENTER = 'center';
const HORIZONTAL_CENTER_CONTINUOUS = 'centerContinuous';
const HORIZONTAL_JUSTIFY = 'justify';
const HORIZONTAL_FILL = 'fill';
const HORIZONTAL_DISTRIBUTED = 'distributed'; // Excel2007 only
// Vertical alignment styles
const VERTICAL_BOTTOM = 'bottom';
const VERTICAL_TOP = 'top';
const VERTICAL_CENTER = 'center';
const VERTICAL_JUSTIFY = 'justify';
const VERTICAL_DISTRIBUTED = 'distributed'; // Excel2007 only
// Read order
const READORDER_CONTEXT = 0;
const READORDER_LTR = 1;
const READORDER_RTL = 2;
// Fill types
const FILL_NONE = 'none';
const FILL_SOLID = 'solid';
const FILL_GRADIENT_LINEAR = 'linear';
const FILL_GRADIENT_PATH = 'path';
const FILL_PATTERN_DARKDOWN = 'darkDown';
const FILL_PATTERN_DARKGRAY = 'darkGray';
const FILL_PATTERN_DARKGRID = 'darkGrid';
const FILL_PATTERN_DARKHORIZONTAL = 'darkHorizontal';
const FILL_PATTERN_DARKTRELLIS = 'darkTrellis';
const FILL_PATTERN_DARKUP = 'darkUp';
const FILL_PATTERN_DARKVERTICAL = 'darkVertical';
const FILL_PATTERN_GRAY0625 = 'gray0625';
const FILL_PATTERN_GRAY125 = 'gray125';
const FILL_PATTERN_LIGHTDOWN = 'lightDown';
const FILL_PATTERN_LIGHTGRAY = 'lightGray';
const FILL_PATTERN_LIGHTGRID = 'lightGrid';
const FILL_PATTERN_LIGHTHORIZONTAL = 'lightHorizontal';
const FILL_PATTERN_LIGHTTRELLIS = 'lightTrellis';
const FILL_PATTERN_LIGHTUP = 'lightUp';
const FILL_PATTERN_LIGHTVERTICAL = 'lightVertical';
const FILL_PATTERN_MEDIUMGRAY = 'mediumGray';
// Pre-defined formats
const FORMAT_GENERAL = 'General';
const FORMAT_TEXT = '@';
const FORMAT_NUMBER = '0';
const FORMAT_NUMBER_00 = '0.00';
const FORMAT_NUMBER_COMMA_SEPARATED1 = '#,##0.00';
const FORMAT_NUMBER_COMMA_SEPARATED2 = '#,##0.00_-';
const FORMAT_PERCENTAGE = '0%';
const FORMAT_PERCENTAGE_00 = '0.00%';
const FORMAT_DATE_YYYYMMDD2 = 'yyyy-mm-dd';
const FORMAT_DATE_YYYYMMDD = 'yy-mm-dd';
const FORMAT_DATE_DDMMYYYY = 'dd/mm/yy';
const FORMAT_DATE_DMYSLASH = 'd/m/yy';
const FORMAT_DATE_DMYMINUS = 'd-m-yy';
const FORMAT_DATE_DMMINUS = 'd-m';
const FORMAT_DATE_MYMINUS = 'm-yy';
const FORMAT_DATE_XLSX14 = 'mm-dd-yy';
const FORMAT_DATE_XLSX15 = 'd-mmm-yy';
const FORMAT_DATE_XLSX16 = 'd-mmm';
const FORMAT_DATE_XLSX17 = 'mmm-yy';
const FORMAT_DATE_XLSX22 = 'm/d/yy h:mm';
const FORMAT_DATE_DATETIME = 'd/m/yy h:mm';
const FORMAT_DATE_TIME1 = 'h:mm AM/PM';
const FORMAT_DATE_TIME2 = 'h:mm:ss AM/PM';
const FORMAT_DATE_TIME3 = 'h:mm';
const FORMAT_DATE_TIME4 = 'h:mm:ss';
const FORMAT_DATE_TIME5 = 'mm:ss';
const FORMAT_DATE_TIME6 = 'h:mm:ss';
const FORMAT_DATE_TIME7 = 'i:s.S';
const FORMAT_DATE_TIME8 = 'h:mm:ss;@';
const FORMAT_DATE_YYYYMMDDSLASH = 'yy/mm/dd;@';
const FORMAT_CURRENCY_USD_SIMPLE = '"$"#,##0.00_-';
const FORMAT_CURRENCY_USD = '$#,##0_-';
const FORMAT_CURRENCY_EUR_SIMPLE = '#,##0.00_-"€"';
const FORMAT_CURRENCY_EUR = '#,##0_-"€"';
/**
* @var string mode is an export mode or import mode. valid value are 'export' and 'import'.
*/
public $mode = 'export';
/**
* @var boolean for set the export excel with multiple sheet.
*/
public $isMultipleSheet = false;
/**
* @var array properties for set property on the excel object.
*/
public $properties;
/**
* @var Model object or DataProvider object with much data.
*/
public $models;
/**
* @var 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.
*/
public $columns = [];
/**
* @var array header 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.
*/
public $headers = [];
/**
* @var string|array name for file name to export or save.
*/
public $fileName;
/**
* @var string save path is a directory to save the file or you can blank this to set the file as attachment.
*/
public $savePath;
/**
* @var string format for excel to export. Valid value are 'Xls','Xlsx','Xml','Ods','Slk','Gnumeric','Csv', and 'Html'.
*/
public $format;
/**
* @var boolean to set the title column on the first line.
*/
public $setFirstTitle = true;
/**
* @var boolean to set the file excel to download mode.
*/
public $asAttachment = false;
/**
* @var boolean 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.
*/
public $setFirstRecordAsKeys = true;
/**
* @var boolean to set the sheet index by sheet name or array result if the sheet not only one.
*/
public $setIndexSheetByName = false;
/**
* @var string sheetname to getting. This is only get the sheet with same name.
*/
public $getOnlySheet;
/**
* @var boolean to set the import data will return as array.
*/
public $asArray;
/**
* @var array to unread record by index number.
*/
public $leaveRecordByIndex = [];
/**
* @var array to read record by index, other will leave.
*/
public $getOnlyRecordByIndex = [];
/**
* @var array|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.
*/
public $formatter;
/**
* @var boolean define the column autosize
*/
public $autoSize = false;
/**
* @var boolean if true, this writer pre-calculates all formulas in the spreadsheet. This can be slow on large spreadsheets, and maybe even unwanted.
*/
public $preCalculationFormula = false;
/**
* @var boolean Because of a bug in the Office2003 compatibility pack, there can be some small issues when opening Xlsx spreadsheets (mostly related to formula calculation)
*/
public $compatibilityOffice2003 = false;
/**
* @var custom CSV delimiter for import. Works only with CSV files
*/
public $CSVDelimiter = ";";
/**
* @var custom CSV encoding for import. Works only with CSV files
*/
public $CSVEncoding = "UTF-8";
/**
* (non-PHPdoc)
* @see \yii\base\Object::init()
*/
public function init()
{
parent::init();
if ($this->formatter == null) {
$this->formatter = \Yii::$app->getFormatter();
} elseif (is_array($this->formatter)) {
$this->formatter = \Yii::createObject($this->formatter);
}
if (!$this->formatter instanceof Formatter) {
throw new InvalidConfigException('The "formatter" property must be either a Format object or a configuration array.');
}
}
/**
* Setting data from models
*/
public function executeColumns(&$activeSheet = null, $models, $columns = [], $headers = [])
{
if ($activeSheet == null) {
$activeSheet = $this->activeSheet;
}
$hasHeader = false;
$row = 1;
$char = 26;
foreach ($models as $model) {
if (empty($columns)) {
$columns = $model->attributes();
}
if ($this->setFirstTitle && !$hasHeader) {
$isPlus = false;
$colplus = 0;
$colnum = 1;
foreach ($columns as $key=>$column) {
$col = '';
if ($colnum > $char) {
$colplus += 1;
$colnum = 1;
$isPlus = true;
}
if ($isPlus) {
$col .= chr(64+$colplus);
}
$col .= chr(64+$colnum);
$header = '';
if (is_array($column)) {
if (isset($column['header'])) {
$header = $column['header'];
}elseif(isset($column['label'])){
$header = $column['label'];
} elseif (isset($column['attribute']) && isset($headers[$column['attribute']])) {
$header = $headers[$column['attribute']];
} elseif (isset($column['attribute'])) {
$header = $model->getAttributeLabel($column['attribute']);
} elseif (isset($column['cellFormat']) && is_array($column['cellFormat'])) {
$activeSheet->getStyle($col.$row)->applyFromArray($column['cellFormat']);
}
} else {
if(isset($headers[$column])) {
$header = $headers[$column];
} else {
$header = $model->getAttributeLabel($column);
}
}
if (isset($column['width'])) {
$activeSheet->getColumnDimension(strtoupper($col))->setWidth($column['width']);
}
$activeSheet->setCellValue($col.$row,$header);
$colnum++;
}
$hasHeader=true;
$row++;
}
$isPlus = false;
$colplus = 0;
$colnum = 1;
foreach ($columns as $key=>$column) {
$col = '';
if ($colnum > $char) {
$colplus++;
$colnum = 1;
$isPlus = true;
}
if ($isPlus) {
$col .= chr(64+$colplus);
}
$col .= chr(64+$colnum);
if (is_array($column)) {
$column_value = $this->executeGetColumnData($model, $column);
if (isset($column['cellFormat']) && is_array($column['cellFormat'])) {
$activeSheet->getStyle($col.$row)->applyFromArray($column['cellFormat']);
}
} else {
$column_value = $this->executeGetColumnData($model, ['attribute' => $column]);
}
$activeSheet->setCellValue($col.$row,$column_value);
$colnum++;
}
$row++;
if($this->autoSize){
foreach (range(0, $colnum) as $col) {
$activeSheet->getColumnDimensionByColumn($col)->setAutoSize(true);
}
}
}
}
/**
* Setting label or keys on every record if setFirstRecordAsKeys is true.
* @param array $sheetData
* @return multitype:multitype:array
*/
public function executeArrayLabel($sheetData)
{
$keys = ArrayHelper::remove($sheetData, '1');
$new_data = [];
foreach ($sheetData as $values)
{
$new_data[] = array_combine($keys, $values);
}
return $new_data;
}
/**
* Leave record with same index number.
* @param array $sheetData
* @param array $index
* @return array
*/
public function executeLeaveRecords($sheetData = [], $index = [])
{
foreach ($sheetData as $key => $data)
{
if (in_array($key, $index))
{
unset($sheetData[$key]);
}
}
return $sheetData;
}
/**
* Read record with same index number.
* @param array $sheetData
* @param array $index
* @return array
*/
public function executeGetOnlyRecords($sheetData = [], $index = [])
{
foreach ($sheetData as $key => $data)
{
if (!in_array($key, $index))
{
unset($sheetData[$key]);
}
}
return $sheetData;
}
/**
* Getting column value.
* @param Model $model
* @param array $params
* @return Ambigous <NULL, string, mixed>
*/
public function executeGetColumnData($model, $params = [])
{
$value = null;
if (isset($params['value']) && $params['value'] !== null) {
if (is_string($params['value'])) {
$value = ArrayHelper::getValue($model, $params['value']);
} else {
$value = call_user_func($params['value'], $model, $this);
}
} elseif (isset($params['attribute']) && $params['attribute'] !== null) {
$value = ArrayHelper::getValue($model, $params['attribute']);
}
if (isset($params['format']) && $params['format'] != null)
$value = $this->formatter()->format($value, $params['format']);
return $value;
}
/**
* Populating columns for checking the column is string or array. if is string this will be checking have a formatter or header.
* @param array $columns
* @throws InvalidParamException
* @return multitype:multitype:array
*/
public function populateColumns($columns = [])
{
$_columns = [];
foreach ($columns as $key => $value)
{
if (is_string($value))
{
$value_log = explode(':', $value);
$_columns[$key] = ['attribute' => $value_log[0]];
if (isset($value_log[1]) && $value_log[1] !== null) {
$_columns[$key]['format'] = $value_log[1];
}
if (isset($value_log[2]) && $value_log[2] !== null) {
$_columns[$key]['header'] = $value_log[2];
}
} elseif (is_array($value)) {
if(isset($value['class'])){
continue;
}
if (!isset($value['attribute']) && !isset($value['value'])) {
throw new \InvalidArgumentException('Attribute or Value must be defined.');
}
$_columns[$key] = $value;
}
}
return $_columns;
}
/**
* Formatter for i18n.
* @return Formatter
*/
public function formatter()
{
if (!isset($this->formatter))
$this->formatter = \Yii::$app->getFormatter();
return $this->formatter;
}
/**
* Setting header to download generated file xls
*/
public function setHeaders()
{
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Content-Disposition: attachment;filename="' . $this->getFileName() .'"');
header('Cache-Control: max-age=0');
}
/**
* Getting the file name of exporting xls file
* @return string
*/
public function getFileName()
{
$fileName = 'exports.xlsx';
if (isset($this->fileName)) {
$fileName = $this->fileName;
if (strpos($fileName, '.xlsx') === false)
$fileName .= '.xlsx';
}
return $fileName;
}
/**
* Setting properties for excel file
* @param PHPExcel $objectExcel
* @param array $properties
*/
public function properties(&$objectExcel, $properties = [])
{
foreach ($properties as $key => $value)
{
$keyname = "set" . ucfirst($key);
$objectExcel->getProperties()->{$keyname}($value);
}
}
/**
* saving the xls file to download or to path
*/
public function writeFile($sheet)
{
if (!isset($this->format))
$this->format = 'Xlsx';
$objectwriter = \PhpOffice\PhpSpreadsheet\IOFactory::createWriter($sheet, $this->format);
$path = 'php://output';
if (isset($this->savePath) && $this->savePath != null) {
$path = $this->savePath . '/' . $this->getFileName();
}
$objectwriter->setOffice2003Compatibility($this->compatibilityOffice2003);
$objectwriter->setPreCalculateFormulas($this->preCalculationFormula);
$objectwriter->save($path);
if ($path == 'php://output')
exit();
return true;
}
/**
* reading the xls file
*/
public function readFile($fileName)
{
if (!isset($this->format))
$this->format = \PhpOffice\PhpSpreadsheet\IOFactory::identify($fileName);
$objectreader = \PhpOffice\PhpSpreadsheet\IOFactory::createReader($this->format);
if ($this->format == "Csv") {
$objectreader->setDelimiter($this->CSVDelimiter);
$objectreader->setInputEncoding($this->CSVEncoding);
}
$objectPhpExcel = $objectreader->load($fileName);
$sheetCount = $objectPhpExcel->getSheetCount();
$sheetDatas = [];
if ($sheetCount > 1) {
foreach ($objectPhpExcel->getSheetNames() as $sheetIndex => $sheetName) {
if (isset($this->getOnlySheet) && $this->getOnlySheet != null) {
if(!$objectPhpExcel->getSheetByName($this->getOnlySheet)) {
return $sheetDatas;
}
$objectPhpExcel->setActiveSheetIndexByName($this->getOnlySheet);
$indexed = $this->getOnlySheet;
$sheetDatas[$indexed] = $objectPhpExcel->getActiveSheet()->toArray(null, true, true, true);
if ($this->setFirstRecordAsKeys) {
$sheetDatas[$indexed] = $this->executeArrayLabel($sheetDatas[$indexed]);
}
if (!empty($this->getOnlyRecordByIndex)) {
$sheetDatas[$indexed] = $this->executeGetOnlyRecords($sheetDatas[$indexed], $this->getOnlyRecordByIndex);
}
if (!empty($this->leaveRecordByIndex)) {
$sheetDatas[$indexed] = $this->executeLeaveRecords($sheetDatas[$indexed], $this->leaveRecordByIndex);
}
return $sheetDatas[$indexed];
} else {
$objectPhpExcel->setActiveSheetIndexByName($sheetName);
$indexed = $this->setIndexSheetByName==true ? $sheetName : $sheetIndex;
$sheetDatas[$indexed] = $objectPhpExcel->getActiveSheet()->toArray(null, true, true, true);
if ($this->setFirstRecordAsKeys) {
$sheetDatas[$indexed] = $this->executeArrayLabel($sheetDatas[$indexed]);
}
if (!empty($this->getOnlyRecordByIndex) && isset($this->getOnlyRecordByIndex[$indexed]) && is_array($this->getOnlyRecordByIndex[$indexed])) {
$sheetDatas = $this->executeGetOnlyRecords($sheetDatas, $this->getOnlyRecordByIndex[$indexed]);
}
if (!empty($this->leaveRecordByIndex) && isset($this->leaveRecordByIndex[$indexed]) && is_array($this->leaveRecordByIndex[$indexed])) {
$sheetDatas[$indexed] = $this->executeLeaveRecords($sheetDatas[$indexed], $this->leaveRecordByIndex[$indexed]);
}
}
}
} else {
$sheetDatas = $objectPhpExcel->getActiveSheet()->toArray(null, true, true, true);
if ($this->setFirstRecordAsKeys) {
$sheetDatas = $this->executeArrayLabel($sheetDatas);
}
if (!empty($this->getOnlyRecordByIndex)) {
$sheetDatas = $this->executeGetOnlyRecords($sheetDatas, $this->getOnlyRecordByIndex);
}
if (!empty($this->leaveRecordByIndex)) {
$sheetDatas = $this->executeLeaveRecords($sheetDatas, $this->leaveRecordByIndex);
}
}
return $sheetDatas;
}
/**
* (non-PHPdoc)
* @see \yii\base\Widget::run()
*/
public function run()
{
if ($this->mode == 'export')
{
$sheet = new Spreadsheet();
if (!isset($this->models))
throw new InvalidConfigException('Config models must be set');
if (isset($this->properties))
{
$this->properties($sheet, $this->properties);
}
if ($this->isMultipleSheet) {
$index = 0;
$worksheet = [];
foreach ($this->models as $title => $models) {
$sheet->createSheet($index);
$sheet->getSheet($index)->setTitle($title);
$worksheet[$index] = $sheet->getSheet($index);
$columns = isset($this->columns[$title]) ? $this->columns[$title] : [];
$headers = isset($this->headers[$title]) ? $this->headers[$title] : [];
$this->executeColumns($worksheet[$index], $models, $this->populateColumns($columns), $headers);
$index++;
}
} else {
$worksheet = $sheet->getActiveSheet();
$this->executeColumns($worksheet, $this->models, isset($this->columns) ? $this->populateColumns($this->columns) : [], isset($this->headers) ? $this->headers : []);
}
if ($this->asAttachment) {
$this->setHeaders();
}
$this->writeFile($sheet);
$sheet->disconnectWorksheets();
unset($sheet);
}
elseif ($this->mode == 'import')
{
if (is_array($this->fileName)) {
$datas = [];
foreach ($this->fileName as $key => $filename) {
$datas[$key] = $this->readFile($filename);
}
return $datas;
} else {
return $this->readFile($this->fileName);
}
}
}
/**
* Exporting data into an excel file.
*
* ~~~
*
* \moonland\phpexcel\Excel::export([
* 'models' => $allModels,
* 'columns' => ['column1','column2','column3'],
* //without header working, because the header will be get label from attribute label.
* 'header' => ['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',
* ],
* ]);
*
* ~~~
*
* @param array $config
* @return string
*/
public static function export($config=[])
{
$config = ArrayHelper::merge(['mode' => 'export'], $config);
return self::widget($config);
}
/**
* Import file excel and return into an array.
*
* ~~~
*
* $data = \moonland\phpexcel\Excel::import($fileName, ['setFirstRecordAsKeys' => true]);
*
* ~~~
*
* @param string!array $fileName to load.
* @param array $config is a more configuration.
* @return string
*/
public static function import($fileName, $config=[])
{
$config = ArrayHelper::merge(['mode' => 'import', 'fileName' => $fileName, 'asArray' => true], $config);
return self::widget($config);
}
/**
* @param array $config
* @return string
*/
public static function widget($config = [])
{
if ((isset($config['mode']) and $config['mode'] == 'import') && !isset($config['asArray'])) {
$config['asArray'] = true;
}
if (isset($config['asArray']) && $config['asArray']==true)
{
$config['class'] = get_called_class();
$widget = \Yii::createObject($config);
return $widget->run();
} else {
return parent::widget($config);
}
}
}
Loading…
Cancel
Save