Files
kiri-core/Gii/GiiModel.php
T

414 lines
8.7 KiB
PHP
Raw Normal View History

2020-09-07 17:12:46 +08:00
<?php
2020-10-30 01:07:28 +08:00
declare(strict_types=1);
2020-09-07 17:12:46 +08:00
2020-09-08 15:59:15 +08:00
namespace Gii;
2020-09-07 17:12:46 +08:00
use Database\Db;
2020-12-17 14:09:14 +08:00
use Exception;
use ReflectionException;
2020-09-07 17:12:46 +08:00
use Snowflake\Snowflake;
/**
* Class GiiModel
2020-09-08 15:59:15 +08:00
* @package Gii
2020-09-07 17:12:46 +08:00
*/
class GiiModel extends GiiBase
{
2020-12-17 14:09:14 +08:00
public ?string $classFileName;
public ?array $visible;
public ?array $res;
public ?array $fields;
2020-09-07 17:12:46 +08:00
/**
* ModelFile constructor.
* @param $classFileName
* @param $tableName
* @param $visible
* @param $res
* @param $fields
*/
2020-12-17 14:09:14 +08:00
public function __construct(string $classFileName, string $tableName, array $visible, array $res, array $fields)
2020-09-07 17:12:46 +08:00
{
$this->classFileName = $classFileName;
$this->tableName = $tableName;
$this->visible = $visible;
$this->res = $res;
$this->fields = $fields;
}
/**
2020-12-17 14:09:14 +08:00
* @throws ReflectionException
* @throws Exception
2020-09-07 17:12:46 +08:00
*/
2020-12-17 14:09:14 +08:00
public function generate(): string
2020-09-07 17:12:46 +08:00
{
$class = '';
$modelPath = $this->getModelPath();
$managerName = $this->classFileName;
$namespace = rtrim($modelPath['namespace'], '\\');
$prefix = str_replace('_', '', $this->db->tablePrefix);
$managerName = str_replace(ucfirst($prefix), '', $managerName);
if (file_exists($modelPath['path'] . '/' . $managerName . '.php')) {
try {
2021-03-25 18:05:31 +08:00
$className = str_replace('\\\\', '\\', "{$modelPath['namespace']}\\{$managerName}");
2021-01-19 18:40:28 +08:00
2021-03-25 18:05:31 +08:00
$class = Snowflake::getDi()->getReflect($className);
$html = '<?php
namespace ' . $namespace . ';
';
$imports = $this->getImports($modelPath['path'] . '/' . $managerName . '.php', $class);
if (!empty($imports)) {
2021-03-25 18:06:15 +08:00
$html .= $imports . PHP_EOL;
2021-03-25 18:05:31 +08:00
}
2020-11-06 16:47:17 +08:00
} catch (\Throwable $e) {
2021-03-30 11:56:29 +08:00
logger()->addError($e,'throwable');
2020-09-07 17:12:46 +08:00
}
}
2021-01-19 18:40:28 +08:00
if (!isset($html) || empty($html)) {
2020-09-07 17:12:46 +08:00
$html = '<?php
namespace ' . $namespace . ';
2021-03-25 18:05:31 +08:00
2020-09-07 17:12:46 +08:00
use Exception;
2021-03-02 18:04:57 +08:00
use Annotation\Target;
2020-09-07 17:12:46 +08:00
use Snowflake\Core\JSON;
2020-09-08 16:07:50 +08:00
use Database\Connection;
2021-03-25 18:05:31 +08:00
use Database\ActiveRecord;
' . PHP_EOL;
2020-09-07 17:12:46 +08:00
}
$createSql = $this->setCreateSql($this->tableName);
2020-12-17 14:09:14 +08:00
if (!str_contains($html, $createSql)) {
2020-09-07 17:12:46 +08:00
$html .= '
' . $this->setCreateSql($this->tableName);
}
$html .= '
/**
* Class ' . $managerName . '
* @package Inter\mysql
*' . implode('', $this->visible) . '
* @sql
*/
2021-03-02 18:04:57 +08:00
#[Target] class ' . $managerName . ' extends ActiveRecord
2021-03-30 16:33:53 +08:00
{
';
2020-09-07 17:12:46 +08:00
if (!empty($class)) {
2021-03-25 18:28:41 +08:00
$html .= $this->getClassProperty($class);
2021-01-19 19:57:46 +08:00
}
$primary = $this->createPrimary($this->fields);
if (!empty($primary)) {
$html .= $primary . "\n";
2020-09-07 17:12:46 +08:00
}
$html .= $this->createTableName($this->tableName) . "\n";
$html .= $this->createRules($this->fields);
if (is_object($class)) {
2021-03-25 18:28:41 +08:00
$html .= $this->getClassMethods($class, ['rules', 'tableName', 'attributes']);
2020-09-07 17:12:46 +08:00
} else {
$html .= $this->createDatabaseSource();
$other = $this->generate_json_function($html, $this->fields);
if (!empty($other)) {
$html .= implode($other);
}
}
$html .= '
}';
$file = rtrim($modelPath['path'], '/') . '/' . $managerName . '.php';
if (file_exists($file)) {
unlink($file);
}
Snowflake::writeFile($file, $html);
return $managerName . '.php';
}
2020-12-17 14:09:14 +08:00
/**
* @param $html
* @param $fields
* @return array
*/
private function generate_json_function($html, $fields): array
2020-09-07 17:12:46 +08:00
{
$strings = [];
foreach ($fields as $field) {
if ($field['Type'] === 'json') {
$function = '
/**
* @param $value
2021-01-19 19:46:00 +08:00
* @return int|bool|string
2020-12-14 10:16:03 +08:00
* @throws Exception
*/
2021-01-19 19:46:00 +08:00
public function set' . ucfirst($field['Field']) . 'Attribute($value): int|bool|string
2020-09-07 17:12:46 +08:00
{
if ( !is_string($value) ) {
return JSON::encode($value);
}
return $value;
}
';
$get_function = '
/**
* @param $value
2021-01-19 19:46:00 +08:00
* @return array|null|bool
2020-09-07 17:12:46 +08:00
*/
2021-01-19 20:02:57 +08:00
#[Get(\'' . $field['Field'] . '\')]
2021-01-19 19:46:00 +08:00
public function get' . ucfirst($field['Field']) . 'Attribute($value): array|null|bool
2020-09-07 17:12:46 +08:00
{
2020-12-14 10:14:50 +08:00
$value = stripcslashes($value);
2020-09-07 17:12:46 +08:00
if ( is_string($value) ) {
return JSON::decode($value, true);
}
return $value;
}
';
2020-12-17 14:09:14 +08:00
if (!str_contains($html, 'set' . ucfirst($field['Field']) . 'Attribute')) {
2020-09-07 17:12:46 +08:00
$strings[] = $function;
}
2020-12-17 14:09:14 +08:00
if (!str_contains($html, 'get' . ucfirst($field['Field']) . 'Attribute')) {
2020-09-07 17:12:46 +08:00
$strings[] = $get_function;
}
}
}
return $strings;
}
/**
* @param $field
* @return string
* 创建表名称
*/
2020-12-17 14:09:14 +08:00
private function createTableName($field): string
2020-09-07 17:12:46 +08:00
{
$prefixed = $this->db->tablePrefix;
if (!empty($prefixed)) {
$field = str_replace($prefixed, '', $field);
$field = '{{%' . $field . '}}';
}
return '
/**
* @inheritdoc
*/
2020-12-17 15:08:38 +08:00
public static function tableName(): string
{
2020-09-07 17:12:46 +08:00
return \'' . $field . '\';
}
';
}
/**
* @param $fields
* @return string
* 创建效验规则
*/
2020-12-17 14:09:14 +08:00
private function createRules($fields): string
2020-09-07 17:12:46 +08:00
{
$data = [];
foreach ($fields as $key => $val) {
if ($val['Extra'] == 'auto_increment') continue;
$type = preg_replace('/\(.*?\)|\s+\w+/', '', $val['Type']);
foreach ($this->type as $_key => $_val) {
if (in_array($type, $_val)) {
$type = lcfirst(str_replace('get', '', $_key));
break;
}
}
$data[$type][] = $val;
}
$_field_one = '';
$required = $this->getRequired($fields);
if (!empty($required)) {
$_field_one .= $required;
}
foreach ($data as $key => $val) {
$field = '[\'' . implode('\', \'', array_column($val, 'Field')) . '\']';
if (count($val) == 1) {
$field = '\'' . current($val)['Field'] . '\'';
}
$_field_one .= '
[' . $field . ', \'' . $key . '\'],';
}
foreach ($data as $key => $val) {
$length = $this->getLength($val);
if (!empty($length)) {
$_field_one .= $length . ',';
}
}
$required = $this->getUnique($fields);
if (!empty($required)) {
$_field_one .= $required;
}
return '
/**
* @return array
*/
public function rules(): array
{
return [' . $_field_one . '
];
}
';
}
/**
* @param $val
* @return string
*/
2020-12-17 14:09:14 +08:00
public function getLength($val): string
2020-09-07 17:12:46 +08:00
{
$data = [];
foreach ($val as $key => $_val) {
$preg = preg_match('/(\w+)\((.*?)\)/', $_val['Type'], $results);
if ($preg && isset($results[2])) {
$results[] = $_val['Field'];
$data[$results[2]][] = $results;
}
}
if (empty($data)) return '';
$string = [];
foreach ($data as $key => $_val) {
2020-12-17 14:09:14 +08:00
if (is_string($key) && str_contains($key, ',')) {
2020-09-07 17:12:46 +08:00
$key = '[' . $key . ']';
}
if (count($_val) == 1) {
[$typeRule, $type, $rule, $field] = current($_val);
$_tmp = '
[\'' . $field . '\', \'' . ($type == 'enum' ? 'enum' : 'maxLength') . '\' => ' . $key . ']';
} else {
$_tmp = '
[[\'' . implode('\', \'', array_column($_val, 3)) . '\'], \'maxLength\' => ' . $key . ']';
}
$string[] = $_tmp;
}
return implode(',', $string);
}
/**
* @param $fields
* @return string
*/
2020-12-17 14:09:14 +08:00
public function getUnique($fields): string
2020-09-07 17:12:46 +08:00
{
$data = [];
foreach ($fields as $_key => $_val) {
if ($_val['Extra'] == 'auto_increment') continue;
2020-12-17 14:09:14 +08:00
if (str_contains($_val['Type'], 'unique')) {
2020-09-07 17:12:46 +08:00
$data[] = $_val['Field'];
}
}
if (empty($data)) {
return '';
}
return '
[[\'' . implode('\', \'', $data) . '\'], \'unique\'],';
}
/**
* @param $val
* @return string
*/
2020-12-17 14:09:14 +08:00
public function getRequired($val): string
2020-09-07 17:12:46 +08:00
{
$data = [];
foreach ($val as $_key => $_val) {
if ($_val['Extra'] == 'auto_increment') continue;
if ($_val['Key'] == 'PRI' || $_val['Key'] == 'UNI' || $this->checkIsRequired($_val) === 'true') {
array_push($data, $_val['Field']);
}
}
if (empty($data)) {
return '';
}
return '
[[\'' . implode('\', \'', $data) . '\'], \'required\'],';
}
/**
* 用来生成文档的
* 格式
* @param $fields
* @return null|string
* array(
* 'field' ,'字段類型' ,'是否必填' ,'字段长度' , '字段解释',
* 'field' ,'字段類型' ,'是否必填' ,'字段长度' , '字段解释',
* 'field' ,'字段類型' ,'是否必填' ,'字段长度' , '字段解释',
* 'field' ,'字段類型' ,'是否必填' ,'字段长度' , '字段解释',
* 'field' ,'字段類型' ,'是否必填' ,'字段长度' , '字段解释',
* 'field' ,'字段類型' ,'是否必填' ,'字段长度' , '字段解释',
* )
*/
2020-12-17 14:09:14 +08:00
private function createPrimary($fields): ?string
2020-09-07 17:12:46 +08:00
{
$field = $this->getPrimaryKey($fields);
if (empty($field)) {
return null;
}
return '
2020-11-19 18:10:44 +08:00
public ?string $primary = \'' . $field . '\';';
2020-09-07 17:12:46 +08:00
}
/**
* @return string
*/
2020-12-17 14:09:14 +08:00
private function createDatabaseSource(): string
2020-09-07 17:12:46 +08:00
{
return '
/**
2020-12-17 15:08:38 +08:00
* @return Connection
2020-09-07 17:12:46 +08:00
* @throws Exception
*/
2020-12-17 15:08:38 +08:00
public static function getDb(): Connection
2020-09-07 17:12:46 +08:00
{
return static::setDatabaseConnect(\'' . $this->db->id . '\');
}
';
}
/**
* @param $table
* @return string
2020-12-17 14:09:14 +08:00
* @throws Exception
2020-09-07 17:12:46 +08:00
*/
2020-12-17 14:09:14 +08:00
private function setCreateSql($table): string
2020-09-07 17:12:46 +08:00
{
$text = Db::showCreateSql($table, $this->db)['Create Table'] ?? '';
$_tmp = [];
foreach (explode(PHP_EOL, $text) as $val) {
$_tmp[] = '// ' . $val;
}
return implode(PHP_EOL, $_tmp);
}
}