7
7
8
8
namespace cebe \yii2openapi \lib ;
9
9
10
+ use cebe \yii2openapi \lib \items \Attribute ;
10
11
use cebe \yii2openapi \lib \items \DbModel ;
11
12
use cebe \yii2openapi \lib \items \ValidationRule ;
13
+ use function in_array ;
14
+ use function preg_match ;
15
+ use function strtolower ;
12
16
13
17
class ValidationRulesBuilder
14
18
{
@@ -19,11 +23,14 @@ class ValidationRulesBuilder
19
23
20
24
/**
21
25
* @var array|ValidationRule[]
22
- * */
26
+ */
23
27
private $ rules = [];
24
28
25
29
private $ typeScope = [
26
- 'safe ' => [], 'required ' => [], 'int ' => [], 'bool ' => [], 'float ' => [], 'string ' => [], 'ref ' => []
30
+ 'required ' => [],
31
+ 'ref ' => [],
32
+ 'trim ' => [],
33
+ 'safe ' => [],
27
34
];
28
35
29
36
public function __construct (DbModel $ model )
@@ -34,13 +41,124 @@ public function __construct(DbModel $model)
34
41
/**
35
42
* @return array|\cebe\yii2openapi\lib\items\ValidationRule[]
36
43
*/
37
- public function build (): array
44
+ public function build ():array
38
45
{
39
46
$ this ->prepareTypeScope ();
40
- $ this ->rulesByType ();
47
+
48
+ if (!empty ($ this ->typeScope ['trim ' ])) {
49
+ $ this ->rules [] = new ValidationRule ($ this ->typeScope ['trim ' ], 'trim ' );
50
+ }
51
+
52
+ if (!empty ($ this ->typeScope ['required ' ])) {
53
+ $ this ->rules [] = new ValidationRule ($ this ->typeScope ['required ' ], 'required ' );
54
+ }
55
+ if (!empty ($ this ->typeScope ['ref ' ])) {
56
+ $ this ->addExistRules ($ this ->typeScope ['ref ' ]);
57
+ }
58
+ foreach ($ this ->model ->attributes as $ attribute ) {
59
+ $ this ->resolveAttributeRules ($ attribute );
60
+ }
61
+ if (!empty ($ this ->typeScope ['safe ' ])) {
62
+ $ this ->rules [] = new ValidationRule ($ this ->typeScope ['safe ' ], 'safe ' );
63
+ }
41
64
return $ this ->rules ;
42
65
}
43
66
67
+ private function resolveAttributeRules (Attribute $ attribute ):void
68
+ {
69
+ if ($ attribute ->isReadOnly ()) {
70
+ return ;
71
+ }
72
+ if ($ attribute ->isUnique ()) {
73
+ $ this ->rules [] = new ValidationRule ([$ attribute ->columnName ], 'unique ' );
74
+ }
75
+ if ($ attribute ->phpType === 'bool ' ) {
76
+ $ this ->rules [] = new ValidationRule ([$ attribute ->columnName ], 'boolean ' );
77
+ return ;
78
+ }
79
+
80
+ if (in_array ($ attribute ->dbType , ['date ' , 'time ' , 'datetime ' ], true )) {
81
+ $ this ->rules [] = new ValidationRule ([$ attribute ->columnName ], $ attribute ->dbType , []);
82
+ return ;
83
+ }
84
+ if (in_array ($ attribute ->phpType , ['int ' , 'double ' , 'float ' ]) && !$ attribute ->isReference ()) {
85
+ $ this ->addNumericRule ($ attribute );
86
+ return ;
87
+ }
88
+ if ($ attribute ->phpType === 'string ' && !$ attribute ->isReference ()) {
89
+ $ this ->addStringRule ($ attribute );
90
+ }
91
+ if (!empty ($ attribute ->enumValues )) {
92
+ $ this ->rules [] = new ValidationRule ([$ attribute ->columnName ], 'in ' , ['range ' => $ attribute ->enumValues ]);
93
+ return ;
94
+ }
95
+ $ this ->addRulesByAttributeName ($ attribute );
96
+ }
97
+
98
+ private function addRulesByAttributeName (Attribute $ attribute ):void
99
+ {
100
+ //@TODO: probably also patterns for file, image
101
+ $ patterns = [
102
+ '~e?mail~i ' => 'email ' ,
103
+ '~(url|site|website|href|link)~i ' => 'url ' ,
104
+ '~(ip|ipaddr)~i ' => 'ip ' ,
105
+ ];
106
+ foreach ($ patterns as $ pattern => $ validator ) {
107
+ if (preg_match ($ pattern , strtolower ($ attribute ->columnName ))) {
108
+ $ this ->rules [] = new ValidationRule ([$ attribute ->columnName ], $ validator );
109
+ return ;
110
+ }
111
+ }
112
+ }
113
+
114
+ /**
115
+ * @param array|Attribute[] $relations
116
+ */
117
+ private function addExistRules (array $ relations ):void
118
+ {
119
+ foreach ($ relations as $ attribute ) {
120
+ if ($ attribute ->phpType === 'int ' ) {
121
+ $ this ->addNumericRule ($ attribute );
122
+ } elseif ($ attribute ->phpType === 'string ' ) {
123
+ $ this ->addStringRule ($ attribute );
124
+ }
125
+ $ this ->rules [] = new ValidationRule (
126
+ [$ attribute ->columnName ],
127
+ 'exist ' ,
128
+ ['targetRelation ' => $ attribute ->camelName ()]
129
+ );
130
+ }
131
+ }
132
+
133
+ private function addStringRule (Attribute $ attribute ):void
134
+ {
135
+ $ params = [];
136
+ if ($ attribute ->maxLength === $ attribute ->minLength && $ attribute ->minLength !== null ) {
137
+ $ params ['length ' ] = $ attribute ->minLength ;
138
+ } else {
139
+ if ($ attribute ->minLength !== null ) {
140
+ $ params ['min ' ] = $ attribute ->minLength ;
141
+ }
142
+ if ($ attribute ->maxLength !== null ) {
143
+ $ params ['max ' ] = $ attribute ->maxLength ;
144
+ }
145
+ }
146
+ $ this ->rules [] = new ValidationRule ([$ attribute ->columnName ], 'string ' , $ params );
147
+ }
148
+
149
+ private function addNumericRule (Attribute $ attribute ):void
150
+ {
151
+ $ params = [];
152
+ if ($ attribute ->limits ['min ' ] !== null ) {
153
+ $ params ['min ' ] = $ attribute ->limits ['min ' ];
154
+ }
155
+ if ($ attribute ->limits ['max ' ] !== null ) {
156
+ $ params ['max ' ] = $ attribute ->limits ['max ' ];
157
+ }
158
+ $ validator = $ attribute ->phpType === 'int ' ? 'integer ' : 'double ' ;
159
+ $ this ->rules [] = new ValidationRule ([$ attribute ->columnName ], $ validator , $ params );
160
+ }
161
+
44
162
private function prepareTypeScope ():void
45
163
{
46
164
foreach ($ this ->model ->attributes as $ attribute ) {
@@ -51,57 +169,20 @@ private function prepareTypeScope():void
51
169
$ this ->typeScope ['required ' ][$ attribute ->columnName ] = $ attribute ->columnName ;
52
170
}
53
171
54
- if ($ attribute ->isReference ()) {
55
- if (in_array ($ attribute ->phpType , ['int ' , 'string ' ])) {
56
- $ this ->typeScope [$ attribute ->phpType ][$ attribute ->columnName ] = $ attribute ->columnName ;
57
- }
58
- $ this ->typeScope ['ref ' ][] = ['attr ' => $ attribute ->columnName , 'rel ' => $ attribute ->camelName ()];
59
- continue ;
172
+ if ($ attribute ->phpType === 'string ' ) {
173
+ $ this ->typeScope ['trim ' ][$ attribute ->columnName ] = $ attribute ->columnName ;
60
174
}
61
175
62
- if (in_array ( $ attribute ->phpType , [ ' int ' , ' string ' , ' bool ' , ' float ' ] )) {
63
- $ this ->typeScope [$ attribute -> phpType ][ $ attribute -> columnName ] = $ attribute-> columnName ;
176
+ if ($ attribute ->isReference ( )) {
177
+ $ this ->typeScope [' ref ' ][ ] = $ attribute ;
64
178
continue ;
65
179
}
66
180
67
- if ($ attribute ->phpType === 'double ' ) {
68
- $ this ->typeScope ['float ' ][$ attribute ->columnName ] = $ attribute ->columnName ;
181
+ if (in_array ($ attribute ->phpType , ['int ' , 'string ' , 'bool ' , 'float ' , 'double ' ])) {
69
182
continue ;
70
183
}
71
184
72
185
$ this ->typeScope ['safe ' ][$ attribute ->columnName ] = $ attribute ->columnName ;
73
186
}
74
187
}
75
-
76
- private function rulesByType ():void
77
- {
78
- if (!empty ($ this ->typeScope ['string ' ])) {
79
- $ this ->rules [] = new ValidationRule ($ this ->typeScope ['string ' ], 'trim ' );
80
- }
81
- if (!empty ($ this ->typeScope ['required ' ])) {
82
- $ this ->rules [] = new ValidationRule ($ this ->typeScope ['required ' ], 'required ' );
83
- }
84
-
85
- if (!empty ($ this ->typeScope ['int ' ])) {
86
- $ this ->rules [] = new ValidationRule ($ this ->typeScope ['int ' ], 'integer ' );
87
- }
88
-
89
- foreach ($ this ->typeScope ['ref ' ] as $ relation ) {
90
- $ this ->rules [] = new ValidationRule ([$ relation ['attr ' ]], 'exist ' , ['targetRelation ' =>$ relation ['rel ' ]]);
91
- }
92
-
93
- if (!empty ($ this ->typeScope ['string ' ])) {
94
- $ this ->rules [] = new ValidationRule ($ this ->typeScope ['string ' ], 'string ' );
95
- }
96
-
97
- if (!empty ($ this ->typeScope ['float ' ])) {
98
- $ this ->rules [] = new ValidationRule ($ this ->typeScope ['float ' ], 'double ' );
99
- }
100
- if (!empty ($ this ->typeScope ['bool ' ])) {
101
- $ this ->rules [] = new ValidationRule ($ this ->typeScope ['bool ' ], 'boolean ' );
102
- }
103
- if (!empty ($ this ->typeScope ['safe ' ])) {
104
- $ this ->rules [] = new ValidationRule ($ this ->typeScope ['safe ' ], 'safe ' );
105
- }
106
- }
107
188
}
0 commit comments