AdminResourceGenerator.php 11.4 KB
<?php
/**
+-----------------------------------------------------------------------------------------------------------------------
 * 管理端类创建
+-----------------------------------------------------------------------------------------------------------------------
 *
 * PHP version 7
 *
 * @category  App\Console\Commands
 * @package   App\Console\Commands
 * @author    Richer <yangzi1028@163.com>
 * @date      2020年7月7日 16:06:50
 * @copyright 2021-2022 Richer (http://www.Richer.com/)
 * @license   http://www.Richer.com/ License
 * @link      http://www.Richer.com/
 */
namespace App\Console\Commands;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Schema;

/**
 * Class AdminResourceGenerator
 *
 * @category  App\Console\Commands
 * @package   App\Console\Commands
 * @author    Richer <yangzi1028@163.com>
 * @date      2020年7月7日 16:06:50
 * @copyright 2021-2022 Richer (http://www.Richer.com/)
 * @license   http://www.Richer.com/ License
 * @link      http://www.Richer.com/
 */
class AdminResourceGenerator
{
    /**
     * 模型
     *
     * @var Model
     */
    protected $model;

    /**
     * 定义字段
     *
     * @var array
     */
    protected $formats = [
        'form_field'  => "\$form->%s('%s', __('%s'))",
        'show_field'  => "\$show->field('%s', __('%s'))",
        'grid_column' => "\$grid->column('%s', __('%s'))",
    ];

    /**
     * 字段类型
     *
     * @var array
     */
    private $_doctrineTypeMapping = [
        'string' => [
            'enum', 'geometry', 'geometrycollection', 'linestring',
            'polygon', 'multilinestring', 'multipoint', 'multipolygon',
            'point',
        ],
    ];

    /**
     * 字段类型映射
     *
     * @var array
     */
    protected $fieldTypeMapping = [
        'ip'       => 'ip',
        'email'    => 'email|mail',
        'password' => 'password|pwd',
        'url'      => 'url|link|src|href',
        'mobile'   => 'mobile|phone',
        'color'    => 'color|rgb',
        'image'    => 'image|img|avatar|pic|picture|cover',
        'file'     => 'file|attachment',
    ];

    /**
     * AdminResourceGenerator constructor.
     *
     * @param $model
     */
    public function __construct($model)
    {
        $this->model = $this->getModel('App\Models\\'.ucfirst($model));
    }

    /**
     * @param mixed $model
     *
     * @return mixed
     */
    protected function getModel($model)
    {
        if ($model instanceof Model) {
            return $model;
        }

        if (!class_exists($model) || !is_string($model) || !is_subclass_of($model, Model::class)) {
            throw new \InvalidArgumentException("Invalid model [$model] !");
        }

        return new $model();
    }

    /**
     * 渲染生成form表单
     *
     * @return string
     * @throws \Exception
     */
    public function generateForm()
    {
        $reservedColumns = $this->getReservedColumns();

        $output = '';

        foreach ($this->getTableColumns() as $column) {
            $name = $column->getName();
            if (in_array($name, $reservedColumns)) {
                continue;
            }
            $type = $column->getType()->getName();

            // 字段长度
            $length     = $column->getLength();
            // 字段注释
//            $comment    = $column->getComment();
            $comment    = "__('$name')";
            // 是否必填
            $notnull    = $column->getNotnull() === true ? 1 : 0;

            $default    = $column->getDefault();

            $defaultValue = "'{$default}'";

            // set column fieldType and defaultValue
            switch ($type) {
                case 'boolean':
                case 'bool':
                    $output .=  sprintf("        \$this->generateFormSwitchField(\$this->form, '%s', '%s', null, %s, %s)", $name, $comment, $defaultValue, $notnull);
                    break;
                //case 'string':
//                    $fieldType = 'text';
//                    foreach ($this->fieldTypeMapping as $type => $regex) {
//                        if (preg_match("/^($regex)$/i", $name) !== 0) {
//                            $fieldType = $type;
//                            break;
//                        }
//                    }
//                    $defaultValue = "'{$default}'";
                case 'text':
                case 'blob':
                case 'json':
                case 'array':
                case 'object':
                    $output .=  sprintf("        \$this->generateFormTextAreaField(\$this->form, '%s', '%s', %s, 3, %s)", $name, $comment, $length, $notnull);
                    break;
                case 'integer':
                case 'bigint':
                case 'smallint':
                case 'timestamp':
                    $output .=  sprintf("        \$this->generateFormNumberField(\$this->form, '%s', '%s', %s, 1, %s)", $name, $comment, $notnull, $defaultValue);
                    break;
                case 'decimal':
                case 'float':
                case 'real':
                    $output .=  sprintf("        \$this->generateFormCurrencyField(\$this->form, '%s', '%s', %s)", $name, $comment, $notnull);
                    break;
                case 'datetime':
                case 'date':
                case 'time':
                    $output .=  sprintf("        \$this->generateFormDateField(\$this->form, '%s', '%s', %s)", $name, $comment, $notnull);
                    break;
                default:
                    $output .=  sprintf("        \$this->generateFormTextField(\$this->form, '%s', '%s', %s, %s)", $name, $comment, $length, $notnull);

            }

            $output .= ";\r\n";
        }

        return $output;
    }

    /**
     * 渲染生成详情
     *
     * @return string
     * @throws \Exception
     */
    public function generateShow()
    {
        $output = '';

        foreach ($this->getTableColumns() as $column) {
            $name = $column->getName();

            // set column label
            $label = $this->formatLabel($name);

            $output .= sprintf($this->formats['show_field'], $name, $label);

            $output .= ";\r\n";
        }

        return $output;
    }

    /**
     * 渲染生成 grid
     *
     * @return string
     * @throws \Exception
     */
    public function generateGrid()
    {
        $output = '';

        foreach ($this->getTableColumns() as $column) {
            // 字段
            $name       = $column->getName();
            // 字段类型
            //$type       = $column->getType();
            $type       = $column->getType()->getName();
            // 字段长度
            $length     = $column->getLength();
            // 字段注释
            $comment    = $column->getComment();
            $comment    = "__('$name')";
            // 是否必填
            $notnull    = $column->getNotnull();
            // set column fieldType and defaultValue
            switch ($type) {
                case 'boolean':
                case 'bool':
                    $output .=  sprintf("        \$this->generateGridSwitchField(\$this->grid, '%s', '%s')", $name, $comment);
                    break;
                case 'integer':
                case 'bigint':
                case 'smallint':
                    $output .=  sprintf("        \$this->generateGridNumberField(\$this->grid, '%s', '%s')", $name, $comment);
                    break;
                case 'decimal':
                case 'float':
                case 'real':
                    $output .=  sprintf("        \$this->generateGridCurrencyField(\$this->grid, '%s', '%s')", $name, $comment);
                    break;
                case 'timestamp':
                case 'datetime':
                case 'date':
                case 'time':
                    $output .=  sprintf("        \$this->generateGridDateField(\$this->grid, '%s', '%s')", $name, $comment);
                    break;
                default:
                    $output .=  sprintf("        \$this->generateGridTextField(\$this->grid, '%s', '%s')", $name, $comment);
            }

            $output .= ";\r\n";
        }

        /*foreach ($this->getTableColumns() as $column) {
            // 字段
            $name       = $column->getName();
            // 字段类型
            $type       = $column->getType();
            // 字段长度
            $length     = $column->getLength();
            // 字段注释
            $comment    = $column->getComment();

            $label = $this->formatLabel($name);

            // 根据字段的类型来生成 字段
            switch (class_basename($type)) {
//                case 'BigIntType':
//                case 'IntegerType':
//                case 'StringType':
//                case 'TextType':
//                    $output .=  sprintf("\$this->generateGridTextField(\$this->grid, '%s', '%s')", $name, $comment);
//                    break;
                case 'DateTimeType':
                    $output .=  sprintf("\$this->generateGridDateField(\$this->grid, '%s', '%s')", $name, $comment);
                    break;
                case 'DecimalType':
                    $output .=  sprintf("\$this->generateGridCurrencyField(\$this->grid, '%s', '%s')", $name, $comment);
                    break;
                default:
                    $output .=  sprintf("\$this->generateGridTextField(\$this->grid, '%s', '%s')", $name, $comment);
                    break;
            }

            $output .= ";\r\n";
        }*/
        return $output;
    }

    protected function getReservedColumns()
    {
        return [
            $this->model->getKeyName(),
            $this->model->getCreatedAtColumn(),
            $this->model->getUpdatedAtColumn(),
            'deleted_at',
        ];
    }

    /**
     * Get columns of a giving model.
     *
     * @throws \Exception
     *
     * @return \Doctrine\DBAL\Schema\Column[]
     */
    protected function getTableColumns()
    {
        // update by Richer 于 2021年12月21日15:38:40 重新
        $table = $this->model->getTable();
        $columns = Schema::getColumnListing($table);
        foreach ($columns as $column) {
            $type = Schema::getColumnType($table, $column);
            dump($type);
        }

        dd($columns);
        if (!$this->model->getConnection()->isDoctrineAvailable()) {
            throw new \Exception(
                'You need to require doctrine/dbal: ~2.3 in your own composer.json to get database columns. '
            );
        }

        $table = $this->model->getConnection()->getTablePrefix().$this->model->getTable();

        $schema = $this->model->getConnection()->getDoctrineSchemaManager($table);

        // custom mapping the types that doctrine/dbal does not support
        $databasePlatform = $schema->getDatabasePlatform();

        foreach ($this->_doctrineTypeMapping as $doctrineType => $dbTypes) {
            foreach ($dbTypes as $dbType) {
                $databasePlatform->registerDoctrineTypeMapping($dbType, $doctrineType);
            }
        }

        $database = null;
        if (strpos($table, '.')) {
            list($database, $table) = explode('.', $table);
        }

        return $schema->listTableColumns($table, $database);
    }

    /**
     * Format label.
     *
     * @param string $value
     *
     * @return string
     */
    protected function formatLabel($value)
    {
        return ucfirst(str_replace(['-', '_'], ' ', $value));
    }
}