Passed
Push — master ( 9bc88c...903b03 )
by 世昌
02:14
created

TableStructBuilder::parseLength()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 11
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

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