Passed
Push — master ( 566a3a...fbef46 )
by 世昌
02:19
created

TableStructBuilder::getName()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 4
eloc 4
nc 3
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
namespace suda\database\struct;
3
4
use function explode;
5
use function preg_match;
6
use function preg_replace;
7
use ReflectionClass;
8
use ReflectionException;
9
use ReflectionProperty;
10
use function strtolower;
11
12
/**
13
 * 数据表构建
14
 */
15
class TableStructBuilder
16
{
17
    /**
18
     * 解析对象
19
     *
20
     * @var string
21
     */
22
    protected $object;
23
24
25
    /**
26
     * 反射对象
27
     *
28
     * @var ReflectionClass
29
     */
30
    protected $reflectObject;
31
32
    /**
33
     * TableStructBuilder constructor.
34
     * @param string $object
35
     * @throws ReflectionException
36
     */
37
    public function __construct(string $object)
38
    {
39
        $this->object = $object;
40
        $this->reflectObject = new ReflectionClass($object);
41
    }
42
43
44
    /**
45
     * 创建表结构
46
     *
47
     * @return TableStruct
48
     */
49
    public function createStruct():TableStruct
50
    {
51
        $name = $this->getName();
52
        $struct = new TableStruct($name);
53
        foreach ($this->reflectObject->getProperties(
54
            ReflectionProperty::IS_PUBLIC
55
            | ReflectionProperty::IS_PROTECTED
56
            | ReflectionProperty::IS_PRIVATE
57
        ) as $property) {
58
            if ($this->isTableField($property)) {
59
                $field = $this->createField($name, $property);
60
                $struct->addField($field);
61
            }
62
        }
63
        return $struct;
64
    }
65
66
    /**
67
     * 获取表名
68
     *
69
     * @return string
70
     */
71
    protected function getName()
72
    {
73
        if ($doc = $this->reflectObject->getDocComment()) {
74
            if (is_string($doc) && preg_match('/\@table\s+(\w+)/', $doc, $match)) {
75
                return $match[1];
76
            }
77
        }
78
        return static::createName($this->reflectObject->getShortName());
79
    }
80
81
    /**
82
     * 创建字段
83
     *
84
     * @param string $tableName
85
     * @param ReflectionProperty $property
86
     * @return Field
87
     */
88
    protected function createField(string $tableName, ReflectionProperty $property): Field
89
    {
90
        $name = static::getFieldName($property);
91
        list($type, $length, $modifier) = static::getFieldType($property);
92
        $field = new Field($tableName, $name, $type, $length);
93
        $field->alias($property->getName());
94
        $parser = new FieldModifierParser;
95
        $parser->parse($modifier)->modify($field);
96
        return $field;
97
    }
98
99
    /**
100
     * 转换名称
101
     *
102
     * @param string $name
103
     * @return string
104
     */
105
    public static function createName(string $name):string
106
    {
107
        $name = preg_replace('/([A-Z]+)/', '_$1', $name);
108
        $name = preg_replace('/_+/', '_', $name);
109
        $name = trim($name, '_');
110
        return strtolower($name);
111
    }
112
113
    /**
114
     * 获取表字段名
115
     *
116
     * @param string $object
117
     * @param string $name
118
     * @return string
119
     * @throws ReflectionException
120
     */
121
    public static function getTableFieldName(string $object, string $name)
122
    {
123
        $property = new ReflectionProperty($object, $name);
124
        return static::getFieldName($property);
125
    }
126
127
    /**
128
     * 获取字段名
129
     *
130
     * @param ReflectionProperty $property
131
     * @return string
132
     */
133
    public static function getFieldName(ReflectionProperty $property)
134
    {
135
        if ($doc = $property->getDocComment()) {
136
            if (is_string($doc) && preg_match('/@field-?name\s+(\w+)/i', $doc, $match)) {
137
                return $match[1];
138
            }
139
        }
140
        return $property->getName();
141
    }
142
143
    /**
144
     * 获取字段类型
145
     *
146
     * @param ReflectionProperty $property
147
     * @return array|null
148
     */
149
    public static function getFieldType(ReflectionProperty $property)
150
    {
151
        if ($doc = $property->getDocComment()) {
152
            if (is_string($doc) && preg_match('/@field\s+(\w+)(?:\((.+?)\))?\s+(.+)?$/im', $doc, $match)) {
153
                $type = strtoupper($match[1]);
154
                $length = static::parseLength($match[2] ?? '');
155
                return [$type, $length , trim($match[3] ?? '')];
156
            }
157
        }
158
        return ['text', null, ''];
159
    }
160
161
    /**
162
     * 解析字符串
163
     *
164
     * @param string $length
165
     * @return string|array|null
166
     */
167
    protected static function parseLength(string $length)
168
    {
169
        if (strlen($length)) {
170
            $length = explode(',', $length);
171
            if (count($length) === 1) {
172
                $length = $length[0];
173
            }
174
        } else {
175
            $length = null;
176
        }
177
        return $length;
178
    }
179
180
    /**
181
     * 检查是否为数据库字段
182
     *
183
     * @param ReflectionProperty $property
184
     * @return boolean
185
     */
186
    public static function isTableField(ReflectionProperty $property)
187
    {
188
        if ($doc = $property->getDocComment()) {
189
            if (is_string($doc) && stripos($doc, '@field')) {
190
                return true;
191
            }
192
        }
193
        return false;
194
    }
195
}
196