Issues (150)

src/Blocks/Entities.php (1 issue)

1
<?php
2
3
namespace SoliDry\Blocks;
4
5
use Illuminate\Database\Eloquent\SoftDeletes;
6
use SoliDry\Extension\BaseFormRequest;
7
use SoliDry\Extension\BaseModel;
8
use SoliDry\Helpers\Classes;
9
use SoliDry\Helpers\Console;
10
use SoliDry\Helpers\MethodOptions;
11
use SoliDry\Helpers\MigrationsHelper;
12
use SoliDry\ApiGenerator;
13
use SoliDry\Types\CustomsInterface;
14
use SoliDry\Types\DefaultInterface;
15
use SoliDry\Types\ModelsInterface;
16
use SoliDry\Types\PhpInterface;
17
use SoliDry\Types\ApiInterface;
18
19
/**
20
 * Class FormRequest
21
 * @package SoliDry\Blocks
22
 * @property ApiGenerator generator
23
 */
24
class Entities extends FormRequestModel
25
{
26
    use ContentManager, EntitiesTrait;
0 ignored issues
show
The trait SoliDry\Blocks\ContentManager requires some properties which are not provided by SoliDry\Blocks\Entities: $options, $version, $modulesDir
Loading history...
27
28
    /**
29
     * @var ApiGenerator
30
     */
31
    private ApiGenerator $generator;
32
33
    /**
34
     * @var string
35
     */
36
    private string $className;
37
38
    /**
39
     * @var string
40
     */
41
    protected string $sourceCode   = '';
42
43
    /**
44
     * @var bool
45
     */
46
    protected bool $isSoftDelete = false;
47
48
    /**
49
     * Entities constructor.
50
     * @param $generator
51
     */
52
    public function __construct($generator)
53
    {
54
        $this->generator = $generator;
55
        $this->className = Classes::getClassName($this->generator->objectName);
56
        $isSoftDelete    = empty($this->generator->types[$this->generator->objectName . CustomsInterface::CUSTOM_TYPES_ATTRIBUTES]
57
                                 [ApiInterface::RAML_PROPS][ModelsInterface::COLUMN_DEL_AT]) === false;
58
        $this->setIsSoftDelete($isSoftDelete);
59
    }
60
61
    public function setCodeState($generator)
62
    {
63
        $this->generator = $generator;
64
    }
65
66
    /**
67
     * @return bool
68
     */
69
    public function isSoftDelete() : bool
70
    {
71
        return $this->isSoftDelete;
72
    }
73
74
    /**
75
     * @param bool $isSoftDelete
76
     */
77
    public function setIsSoftDelete(bool $isSoftDelete) : void
78
    {
79
        $this->isSoftDelete = $isSoftDelete;
80
    }
81
82
    private function setRelations()
83
    {
84
        $formRequestEntity = $this->getFormRequestEntity($this->generator->version, $this->className);
85
        /** @var BaseFormRequest $formRequest * */
86
        $formRequest = new $formRequestEntity();
87
        if (method_exists($formRequest, ModelsInterface::MODEL_METHOD_RELATIONS)) {
88
            $this->sourceCode .= PHP_EOL;
89
            $relations        = $formRequest->relations();
90
            foreach ($relations as $relationEntity) {
91
                $ucEntity = MigrationsHelper::getObjectName($relationEntity);
92
                // determine if ManyToMany, OneToMany, OneToOne rels
93
                $current = $this->getRelationType($this->generator->objectName);
94
                $related = $this->getRelationType($ucEntity);
95
                if (empty($current) === false && empty($related) === false) {
96
                    $this->createRelationMethod($current, $related, $relationEntity);
97
                }
98
            }
99
        }
100
    }
101
102
    /**
103
     * @param string $current current entity relations
104
     * @param string $related entities from raml file based on relations method array
105
     * @param string $relationEntity
106
     */
107
    private function createRelationMethod(string $current, string $related, string $relationEntity)
108
    {
109
        $ucEntity    = ucfirst($relationEntity);
110
        $currentRels = explode(PhpInterface::PIPE, $current);
111
        $relatedRels = explode(PhpInterface::PIPE, $related);
112
        foreach ($relatedRels as $rel) {
113
            if (strpos($rel, $this->generator->objectName) !== false) {
114
                foreach ($currentRels as $cur) {
115
                    if (strpos($cur, $ucEntity) !== false) {
116
                        $isManyCurrent = strpos($cur, self::CHECK_MANY_BRACKETS);
117
                        $isManyRelated = strpos($rel, self::CHECK_MANY_BRACKETS);
118
                        if ($isManyCurrent === false && $isManyRelated === false) {// OneToOne
119
                            $this->setRelation($relationEntity, ModelsInterface::MODEL_METHOD_HAS_ONE);
120
                        }
121
                        if ($isManyCurrent !== false && $isManyRelated === false) {// ManyToOne
122
                            $this->setRelation($relationEntity, ModelsInterface::MODEL_METHOD_HAS_MANY);
123
                        }
124
                        if ($isManyCurrent === false && $isManyRelated !== false) {// OneToMany inverse
125
                            $this->setRelation($relationEntity, ModelsInterface::MODEL_METHOD_BELONGS_TO);
126
                        }
127
                        if ($isManyCurrent !== false && $isManyRelated !== false) {// ManyToMany
128
                            // check inversion of a pivot
129
                            $entityFile = $this->generator->formatEntitiesPath()
130
                                . PhpInterface::SLASH . $this->generator->objectName .
131
                                ucfirst($relationEntity) .
132
                                PhpInterface::PHP_EXT;
133
                            $relEntity  = $relationEntity;
134
                            $objName    = $this->generator->objectName;
135
                            if (file_exists($entityFile) === false) {
136
                                $relEntity = $this->generator->objectName;
137
                                $objName   = $relationEntity;
138
                            }
139
                            $this->setRelation(
140
                                $relationEntity, ModelsInterface::MODEL_METHOD_BELONGS_TO_MANY,
141
                                MigrationsHelper::getTableName($objName . ucfirst($relEntity))
142
                            );
143
                        }
144
                    }
145
                }
146
            }
147
        }
148
    }
149
150
    /**
151
     * @param string $ucEntity
152
     * @throws \ReflectionException
153
     */
154
    public function setPivot(string $ucEntity): void
155
    {
156
        $file = $this->generator->formatEntitiesPath() .
157
            PhpInterface::SLASH .
158
            $this->className . Classes::getClassName($ucEntity) . PhpInterface::PHP_EXT;
159
        if ($this->generator->isMerge === true) {
160
            $this->resetPivotContent($ucEntity, $file);
161
        } else {
162
            $this->setPivotContent($ucEntity);
163
        }
164
        $isCreated = FileManager::createFile(
165
            $file, $this->sourceCode,
166
            FileManager::isRegenerated($this->generator->options)
167
        );
168
        if ($isCreated) {
169
            Console::out($file . PhpInterface::SPACE . Console::CREATED, Console::COLOR_GREEN);
170
        }
171
    }
172
173
    public function createPivot()
174
    {
175
        $formRequestEntity = $this->getFormRequestEntity($this->generator->version, $this->className);
176
        /** @var BaseFormRequest $formRequest * */
177
        $formRequest = new $formRequestEntity();
178
        if (method_exists($formRequest, ModelsInterface::MODEL_METHOD_RELATIONS)) {
179
            $relations        = $formRequest->relations();
180
            $this->sourceCode .= PHP_EOL; // margin top from props
181
            foreach ($relations as $relationEntity) {
182
                $ucEntity = ucfirst($relationEntity);
183
                $file     = $this->generator->formatEntitiesPath()
184
                    . PhpInterface::SLASH . ucfirst($relationEntity) . $this->generator->objectName .
185
                    PhpInterface::PHP_EXT;
186
                // check if inverse Entity pivot exists
187
                if (file_exists($file) === false) {
188
                    // determine if ManyToMany, OneToMany, OneToOne rels
189
                    $current = $this->getRelationType($this->generator->objectName);
190
                    $related = $this->getRelationType($ucEntity);
191
                    if (empty($current) === false && empty($related) === false) {
192
                        $this->createPivotClass($current, $related, $relationEntity);
193
                    }
194
                }
195
            }
196
        }
197
    }
198
199
    /**
200
     * @param string $current current entity relations
201
     * @param string $related entities from raml file based on relations method array
202
     * @param string $relationEntity
203
     * @throws \ReflectionException
204
     */
205
    private function createPivotClass(string $current, string $related, string $relationEntity): void
206
    {
207
        $ucEntity    = ucfirst($relationEntity);
208
        $currentRels = explode(PhpInterface::PIPE, $current);
209
        $relatedRels = explode(PhpInterface::PIPE, $related);
210
        foreach ($relatedRels as $rel) {
211
            if (strpos($rel, $this->generator->objectName) !== false) {
212
                foreach ($currentRels as $cur) {
213
                    if (strpos($cur, $ucEntity) !== false) {
214
                        $isManyCurrent = strpos($cur, self::CHECK_MANY_BRACKETS);
215
                        $isManyRelated = strpos($rel, self::CHECK_MANY_BRACKETS);
216
                        if ($isManyCurrent !== false && $isManyRelated !== false) {// ManyToMany
217
                            $this->setPivot($ucEntity);
218
                        }
219
                    }
220
                }
221
            }
222
        }
223
    }
224
225
    /**
226
     * @param string $entity
227
     * @param string $method
228
     * @param \string[] ...$args
229
     */
230
    private function setRelation(string $entity, string $method, string ...$args): void
231
    {
232
        $methodOptions = new MethodOptions();
233
        $methodOptions->setName($entity);
234
        $this->startMethod($methodOptions);
235
        $toReturn = $this->getRelationReturn($entity, $method, $args);
236
        $this->setMethodReturn($toReturn);
237
        $this->endMethod(1);
238
    }
239
240
    /**
241
     * @param string $entity
242
     * @param string $method
243
     * @param \string[] ...$args
244
     * @return string
245
     */
246
    private function getRelationReturn(string $entity, string $method, array $args): string
247
    {
248
        $toReturn = PhpInterface::DOLLAR_SIGN . PhpInterface::PHP_THIS
249
            . PhpInterface::ARROW . $method
250
            . PhpInterface::OPEN_PARENTHESES . Classes::getClassName($entity)
251
            . PhpInterface::DOUBLE_COLON . PhpInterface::PHP_CLASS;
252
253
        if (empty($args) === false) {
254
            foreach ($args as $val) {
255
                $toReturn .= PhpInterface::COMMA
256
                    . PhpInterface::SPACE . PhpInterface::QUOTES . $val .
257
                    PhpInterface::QUOTES;
258
            }
259
        }
260
        $toReturn .= PhpInterface::CLOSE_PARENTHESES;
261
        return $toReturn;
262
    }
263
264
    /**
265
     * Sets entity content to $sourceCode
266
     */
267
    private function setContent(): void
268
    {
269
        $this->setTag();
270
        $this->setNamespace(
271
            $this->generator->entitiesDir
272
        );
273
        $baseMapper     = BaseModel::class;
274
        $baseMapperName = Classes::getName($baseMapper);
275
276
        if ($this->isSoftDelete()) {
277
            $this->setUse(SoftDeletes::class);
278
        }
279
280
        $this->setUse($baseMapper, false, true);
281
        $this->startClass($this->className, $baseMapperName);
282
        $this->setUseSoftDelete();
283
        $this->setComment(DefaultInterface::PROPS_START);
284
        $this->setPropSoftDelete();
285
        $this->createProperty(
286
            ModelsInterface::PROPERTY_PRIMARY_KEY, PhpInterface::PHP_MODIFIER_PROTECTED,
287
            ApiInterface::RAML_ID, true
288
        );
289
        $this->createProperty(
290
            ModelsInterface::PROPERTY_TABLE, PhpInterface::PHP_MODIFIER_PROTECTED,
291
            MigrationsHelper::getTableName($this->generator->objectName), true
292
        );
293
        $this->createProperty(
294
            ModelsInterface::PROPERTY_TIMESTAMPS, PhpInterface::PHP_MODIFIER_PUBLIC,
295
            PhpInterface::PHP_TYPES_BOOL_FALSE
296
        );
297
        $this->setIncrementingProperty();
298
        $this->setComment(DefaultInterface::PROPS_END);
299
        $this->setComment(DefaultInterface::METHOD_START);
300
        $this->setRelations();
301
        $this->setComment(DefaultInterface::METHOD_END);
302
        $this->endClass();
303
    }
304
305
    private function setIncrementingProperty()
306
    {
307
        // O(4)
308
        $idObject = $this->generator->types[$this->generator->types[$this->generator->objectName][ApiInterface::RAML_PROPS][ApiInterface::RAML_ID]];
309
        if ($idObject[ApiInterface::RAML_TYPE] === ApiInterface::RAML_TYPE_STRING) {
310
            $this->createProperty(
311
                ModelsInterface::PROPERTY_INCREMENTING, PhpInterface::PHP_MODIFIER_PUBLIC,
312
                PhpInterface::PHP_TYPES_BOOL_FALSE
313
            );
314
        }
315
    }
316
317
    /**
318
     * Sets entity content to $sourceCode
319
     */
320
    private function resetContent(): void
321
    {
322
        $this->setBeforeProps($this->getEntityFile($this->generator->formatEntitiesPath()));
323
        $this->setComment(DefaultInterface::PROPS_START, 0);
324
        $this->createProperty(
325
            ModelsInterface::PROPERTY_PRIMARY_KEY, PhpInterface::PHP_MODIFIER_PROTECTED,
326
            ApiInterface::RAML_ID, true
327
        );
328
        $this->createProperty(
329
            ModelsInterface::PROPERTY_TABLE, PhpInterface::PHP_MODIFIER_PROTECTED,
330
            strtolower($this->generator->objectName), true
331
        );
332
        $this->createProperty(
333
            ModelsInterface::PROPERTY_TIMESTAMPS, PhpInterface::PHP_MODIFIER_PUBLIC,
334
            PhpInterface::PHP_TYPES_BOOL_FALSE
335
        );
336
        $this->setAfterProps(DefaultInterface::METHOD_START);
337
        $this->setComment(DefaultInterface::METHOD_START, 0);
338
        $this->setRelations();
339
        $this->setAfterMethods();
340
    }
341
342
    /**
343
     *  Sets pivot entity content to $sourceCode
344
     * @param string $ucEntity an entity upper case first name
345
     * @throws \ReflectionException
346
     */
347
    private function setPivotContent(string $ucEntity): void
348
    {
349
        $this->setTag();
350
        $this->setNamespace(
351
            $this->generator->entitiesDir
352
        );
353
        $baseMapper     = BaseModel::class;
354
        $baseMapperName = Classes::getName($baseMapper);
355
356
        $this->setUse($baseMapper, false, true);
357
        $this->startClass($this->className . Classes::getClassName($ucEntity), $baseMapperName);
358
        $this->setComment(DefaultInterface::PROPS_START);
359
        $this->createProperty(
360
            ModelsInterface::PROPERTY_PRIMARY_KEY, PhpInterface::PHP_MODIFIER_PROTECTED,
361
            ApiInterface::RAML_ID, true
362
        );
363
        $this->createProperty(
364
            ModelsInterface::PROPERTY_TABLE, PhpInterface::PHP_MODIFIER_PROTECTED,
365
            strtolower($this->generator->objectName . PhpInterface::UNDERSCORE . $ucEntity), true
366
        );
367
        $this->createProperty(
368
            ModelsInterface::PROPERTY_TIMESTAMPS, PhpInterface::PHP_MODIFIER_PUBLIC,
369
            PhpInterface::PHP_TYPES_BOOL_TRUE
370
        );
371
        $this->setComment(DefaultInterface::PROPS_END);
372
        $this->endClass();
373
    }
374
375
    /**
376
     *  Re-Sets pivot entity content to $sourceCode
377
     * @param string $ucEntity an entity upper case first name
378
     * @param string $file
379
     */
380
    private function resetPivotContent(string $ucEntity, string $file)
381
    {
382
        $this->setBeforeProps($file);
383
        $this->setComment(DefaultInterface::PROPS_START, 0);
384
        $this->createProperty(
385
            ModelsInterface::PROPERTY_PRIMARY_KEY, PhpInterface::PHP_MODIFIER_PROTECTED,
386
            ApiInterface::RAML_ID, true
387
        );
388
        $this->createProperty(
389
            ModelsInterface::PROPERTY_TABLE, PhpInterface::PHP_MODIFIER_PROTECTED,
390
            strtolower($this->generator->objectName . PhpInterface::UNDERSCORE . $ucEntity), true
391
        );
392
        $this->createProperty(
393
            ModelsInterface::PROPERTY_TIMESTAMPS, PhpInterface::PHP_MODIFIER_PUBLIC,
394
            PhpInterface::PHP_TYPES_BOOL_TRUE
395
        );
396
        $this->setAfterProps();
397
    }
398
}