2
2
3
3
namespace InfyOm \Generator \Generators ;
4
4
5
+ use Illuminate \Support \Str ;
5
6
use InfyOm \Generator \Common \CommandData ;
6
7
use InfyOm \Generator \Utils \FileUtil ;
7
8
use InfyOm \Generator \Utils \GeneratorFieldsInputUtil ;
@@ -17,6 +18,8 @@ class FactoryGenerator extends BaseGenerator
17
18
private $ path ;
18
19
/** @var string */
19
20
private $ fileName ;
21
+ /** @var array */
22
+ private $ relations = [];
20
23
21
24
/**
22
25
* FactoryGenerator constructor.
@@ -28,6 +31,28 @@ public function __construct(CommandData $commandData)
28
31
$ this ->commandData = $ commandData ;
29
32
$ this ->path = $ commandData ->config ->pathFactory ;
30
33
$ this ->fileName = $ this ->commandData ->modelName .'Factory.php ' ;
34
+ //setup relations if available
35
+ //assumes relation fields are tailed with _id if not supplied
36
+ if (property_exists ($ this ->commandData , 'relations ' )) {
37
+ foreach ($ this ->commandData ->relations as $ r ) {
38
+ if ($ r ->type == 'mt1 ' ) {
39
+ $ relation = (isset ($ r ->inputs [0 ])) ? $ r ->inputs [0 ] : null ;
40
+ $ field = false ;
41
+ if (isset ($ r ->inputs [1 ])) {
42
+ $ field = $ r ->inputs [1 ];
43
+ } else {
44
+ $ field = Str::snake ($ relation ).'_id ' ;
45
+ }
46
+ if ($ field ) {
47
+ $ rel = $ relation ;
48
+ $ this ->relations [$ field ] = [
49
+ 'relation ' => $ rel ,
50
+ 'model_class ' => $ this ->commandData ->config ->nsModel .'\\' .$ relation ,
51
+ ];
52
+ }
53
+ }
54
+ }
55
+ }
31
56
}
32
57
33
58
public function generate ()
@@ -53,7 +78,21 @@ private function fillTemplate($templateData)
53
78
54
79
$ templateData = str_replace (
55
80
'$FIELDS$ ' ,
56
- implode (', ' .infy_nl_tab (1 , 2 ), $ this ->generateFields ()),
81
+ implode (', ' .infy_nl_tab (1 , 3 ), $ this ->generateFields ()),
82
+ $ templateData
83
+ );
84
+
85
+ $ extra = $ this ->getRelationsBootstrap ();
86
+
87
+ $ templateData = str_replace (
88
+ '$RELATION_USES$ ' ,
89
+ $ extra ['uses ' ],
90
+ $ templateData
91
+ );
92
+
93
+ $ templateData = str_replace (
94
+ '$RELATIONS$ ' ,
95
+ $ extra ['text ' ],
57
96
$ templateData
58
97
);
59
98
@@ -67,28 +106,72 @@ private function generateFields()
67
106
{
68
107
$ fields = [];
69
108
109
+ //get model validation rules
110
+ $ class = $ this ->commandData ->config ->nsModel .'\\' .$ this ->commandData ->modelName ;
111
+ $ rules = $ class ::$ rules ;
112
+ $ relations = array_keys ($ this ->relations );
113
+
70
114
foreach ($ this ->commandData ->fields as $ field ) {
71
115
if ($ field ->isPrimary ) {
72
116
continue ;
73
117
}
74
118
75
119
$ fieldData = "' " .$ field ->name ."' => " .'$this->faker-> ' ;
120
+ $ rule = null ;
121
+ if (isset ($ rules [$ field ->name ])) {
122
+ $ rule = $ rules [$ field ->name ];
123
+ }
76
124
77
125
switch ($ field ->fieldType ) {
78
126
case 'integer ' :
127
+ case 'smallinteger ' :
79
128
case 'float ' :
80
- $ fakerData = 'randomDigitNotNull ' ;
129
+ $ fakerData = in_array ($ field ->name , $ relations ) ? ':relation ' : $ this ->getValidNumber ($ rule , 999 );
130
+ break ;
131
+ case 'long ' :
132
+ case 'biginteger ' :
133
+ case 'double ' :
134
+ case 'decimal ' :
135
+ $ fakerData = $ this ->getValidNumber ($ rule );
81
136
break ;
82
137
case 'string ' :
83
- $ fakerData = 'word ' ;
138
+ case 'char ' :
139
+ $ lower = strtolower ($ field ->name );
140
+ $ firstChar = substr ($ lower , 0 , 1 );
141
+ if (strpos ($ lower , 'email ' ) !== false ) {
142
+ $ fakerData = 'email ' ;
143
+ } elseif ($ firstChar == 'f ' && strpos ($ lower , 'name ' ) !== false ) {
144
+ $ fakerData = 'firstName ' ;
145
+ } elseif (($ firstChar == 's ' || $ firstChar == 'l ' ) && strpos ($ lower , 'name ' ) !== false ) {
146
+ $ fakerData = 'lastName ' ;
147
+ } elseif (strpos ($ lower , 'phone ' ) !== false ) {
148
+ $ fakerData = "numerify('0##########') " ;
149
+ } elseif (strpos ($ lower , 'password ' ) !== false ) {
150
+ $ fakerData = "lexify('1???@???A???') " ;
151
+ } elseif (strpos ($ lower , 'address ' )) {
152
+ $ fakerData = 'address ' ;
153
+ } else {
154
+ if (!$ rule ) {
155
+ $ rule = 'max:255 ' ;
156
+ }
157
+ $ fakerData = $ this ->getValidText ($ rule );
158
+ }
84
159
break ;
85
160
case 'text ' :
86
- $ fakerData = 'text ' ;
161
+ $ fakerData = $ rule ? $ this ->getValidText ($ rule ) : 'text(500) ' ;
162
+ case 'boolean ' :
163
+ $ fakerData = 'boolean ' ;
164
+ break ;
165
+ case 'date ' :
166
+ $ fakerData = "date('Y-m-d') " ;
87
167
break ;
88
168
case 'datetime ' :
89
169
case 'timestamp ' :
90
170
$ fakerData = "date('Y-m-d H:i:s') " ;
91
171
break ;
172
+ case 'time ' :
173
+ $ fakerData = "date('H:i:s') " ;
174
+ break ;
92
175
case 'enum ' :
93
176
$ fakerData = 'randomElement( ' .
94
177
GeneratorFieldsInputUtil::prepareValuesArrayStr ($ field ->htmlValues ).
@@ -98,14 +181,130 @@ private function generateFields()
98
181
$ fakerData = 'word ' ;
99
182
}
100
183
101
- $ fieldData .= $ fakerData ;
184
+ if ($ fakerData == ':relation ' ) {
185
+ $ fieldData = $ this ->getValidRelation ($ field ->name );
186
+ } else {
187
+ $ fieldData .= $ fakerData ;
188
+ }
102
189
103
190
$ fields [] = $ fieldData ;
104
191
}
105
192
106
193
return $ fields ;
107
194
}
108
195
196
+ /**
197
+ * Generates a valid number based on applicable model rule.
198
+ *
199
+ * @param string $rule The applicable model rule
200
+ * @param int $max The maximum number to generate.
201
+ *
202
+ * @return string
203
+ */
204
+ public function getValidNumber ($ rule = null , $ max = PHP_INT_MAX )
205
+ {
206
+ if ($ rule ) {
207
+ $ max = $ this ->extractMinMax ($ rule , 'max ' ) ?? $ max ;
208
+ $ min = $ this ->extractMinMax ($ rule , 'min ' ) ?? 0 ;
209
+
210
+ return "numberBetween( $ min, $ max) " ;
211
+ } else {
212
+ return 'randomDigitNotNull ' ;
213
+ }
214
+ }
215
+
216
+ /**
217
+ * Generates a valid relation if applicable
218
+ * This method assumes the related field primary key is id.
219
+ *
220
+ * @param string $fieldName The field name
221
+ *
222
+ * @return string
223
+ */
224
+ public function getValidRelation ($ fieldName )
225
+ {
226
+ $ relation = $ this ->relations [$ fieldName ]['relation ' ];
227
+ $ variable = Str::camel ($ relation );
228
+
229
+ return "' " .$ fieldName ."' => " .'$ ' .$ variable .'->id ' ;
230
+ }
231
+
232
+ /**
233
+ * Generates a valid text based on applicable model rule.
234
+ *
235
+ * @param string $rule The applicable model rule.
236
+ *
237
+ * @return string
238
+ */
239
+ public function getValidText ($ rule = null )
240
+ {
241
+ if ($ rule ) {
242
+ $ max = $ this ->extractMinMax ($ rule , 'max ' ) ?? 4096 ;
243
+ $ min = $ this ->extractMinMax ($ rule , 'min ' ) ?? 5 ;
244
+
245
+ if ($ max < 5 ) {
246
+ //faker text requires at least 5 characters
247
+ return "lexify('?????') " ;
248
+ }
249
+ if ($ min < 5 ) {
250
+ //faker text requires at least 5 characters
251
+ $ min = 5 ;
252
+ }
253
+
254
+ return 'text( ' .'$this->faker->numberBetween( ' .$ min .', ' .$ max .')) ' ;
255
+ } else {
256
+ return 'text ' ;
257
+ }
258
+ }
259
+
260
+ /**
261
+ * Extracts min or max rule for a laravel model.
262
+ */
263
+ public function extractMinMax ($ rule , $ t = 'min ' )
264
+ {
265
+ $ i = strpos ($ rule , $ t );
266
+ $ e = strpos ($ rule , '| ' , $ i );
267
+ if ($ e === false ) {
268
+ $ e = strlen ($ rule );
269
+ }
270
+ if ($ i !== false ) {
271
+ $ len = $ e - ($ i + 4 );
272
+ $ result = substr ($ rule , $ i + 4 , $ len );
273
+
274
+ return $ result ;
275
+ }
276
+
277
+ return null ;
278
+ }
279
+
280
+ /**
281
+ * Generate valid model so we can use the id where applicable
282
+ * This method assumes the model has a factory.
283
+ */
284
+ public function getRelationsBootstrap ()
285
+ {
286
+ $ text = '' ;
287
+ $ uses = '' ;
288
+ foreach ($ this ->relations as $ field => $ data ) {
289
+ $ relation = $ data ['relation ' ];
290
+ $ qualifier = $ data ['model_class ' ];
291
+ $ variable = Str::camel ($ relation );
292
+ $ model = Str::studly ($ relation );
293
+ $ text .= infy_nl_tab (1 , 2 ).'$ ' .$ variable .' = ' .$ model .'::first(); ' .
294
+ infy_nl_tab (1 , 2 ).
295
+ 'if (!$ ' .$ variable .') { ' .
296
+ infy_nl_tab (1 , 3 ).
297
+ '$ ' .$ variable .' = ' .$ model .'::factory()->create(); ' .
298
+ infy_nl_tab (1 , 2 ).'} ' .infy_nl ();
299
+ $ uses .= infy_nl ()."use $ qualifier; " ;
300
+ }
301
+
302
+ return [
303
+ 'text ' => $ text ,
304
+ 'uses ' => $ uses ,
305
+ ];
306
+ }
307
+
109
308
public function rollback ()
110
309
{
111
310
if ($ this ->rollbackFile ($ this ->path , $ this ->fileName )) {
0 commit comments