Passed
Push — master ( e7c191...883056 )
by Giacomo
11:51
created

MongoSyncTrait::getIsSkippable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 5
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace OfflineAgency\MongoAutoSync\Traits;
4
5
use DateTime;
6
use Exception;
7
use Illuminate\Http\Request;
8
use MongoDB\BSON\UTCDateTime;
9
10
trait MongoSyncTrait
11
{
12
    /**
13
     * @param Request $request
14
     * @param array $additionalData
15
     * @param array $options
16
     * @return $this
17
     * @throws Exception
18
     */
19
    public function storeWithSync(Request $request, array $additionalData = [], array $options = [])
20
    {
21
        $request = $request->merge($additionalData);
22
23
        $this->storeEditAllItems($request, 'add', $options);
24
        $this->processAllRelationships($request, 'add', '', '', $options);
25
26
        //Dispatch the creation event
27
        $this->fireModelEvent('storeWithSync');
0 ignored issues
show
Bug introduced by
It seems like fireModelEvent() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

27
        $this->/** @scrutinizer ignore-call */ 
28
               fireModelEvent('storeWithSync');
Loading history...
28
29
        return $this;
30
    }
31
32
    /**
33
     * @param Request $request
34
     * @param string $event
35
     * @param array $options
36
     * @throws Exception
37
     */
38
    public function storeEditAllItems(Request $request, string $event, array $options)
39
    {
40
        //Get the item name
41
        $items = $this->getItems();
0 ignored issues
show
Bug introduced by
It seems like getItems() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

41
        /** @scrutinizer ignore-call */ 
42
        $items = $this->getItems();
Loading history...
42
        $is_skippable = $this->getIsSkippable($options);
43
        //Current Obj Create
44
        foreach ($items as $key => $item) {
45
            $is_ML = isML($item);
46
            $is_MD = isMD($item);
47
48
            $is_fillable = isFillable($item, $event);
49
50
            if ( is_null($request->input($key)) && $is_skippable ) {
51
                continue;
52
            }else{
53
                $this->checkRequestExistence(
54
                    $request,
55
                    $key
56
                );
57
            }
58
59
            if ($is_fillable) {
60
                if ($is_ML) {
61
                    if (is_null($this->$key)) {
62
                        $old_value = [];
63
                    } else {
64
                        $old_value = $this->$key;
65
                    }
66
                    $this->$key = ml($old_value, $request->input($key));
67
                } elseif ($is_MD) {
68
                    if ($request->input($key) == '' || $request->input($key) == null) {
69
                        $this->$key = null;
70
                    } else {
71
                        $this->$key = new UTCDateTime(new DateTime($request->input($key)));
0 ignored issues
show
Bug introduced by
new DateTime($request->input($key)) of type DateTime is incompatible with the type integer expected by parameter $milliseconds of MongoDB\BSON\UTCDateTime::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

71
                        $this->$key = new UTCDateTime(/** @scrutinizer ignore-type */ new DateTime($request->input($key)));
Loading history...
72
                    }
73
                } else {
74
                    $this->$key = $request->input($key);
75
                }
76
            }
77
        }
78
79
        $this->save();
0 ignored issues
show
Bug introduced by
It seems like save() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

79
        $this->/** @scrutinizer ignore-call */ 
80
               save();
Loading history...
80
    }
81
82
    /**
83
     * @param Request $request
84
     * @param string $event
85
     * @param string $parent
86
     * @param string $counter
87
     * @param array $options
88
     * @throws Exception
89
     */
90
    public function processAllRelationships(Request $request, string $event, string $parent, string $counter, array $options)
91
    {
92
        //Get the relation info
93
        $relations = $this->getMongoRelation();
0 ignored issues
show
Bug introduced by
It seems like getMongoRelation() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

93
        /** @scrutinizer ignore-call */ 
94
        $relations = $this->getMongoRelation();
Loading history...
94
        $is_skippable = $this->getIsSkippable($options);
95
96
        //Process all relationships
97
        foreach ($relations as $method => $relation) {
98
            //Get Relation Save Mode
99
            $type = $relation['type'];
100
            $model = $relation['model'];
101
            $hasTarget = hasTarget($relation);
102
            if ($hasTarget) {
103
                $modelTarget = $relation['modelTarget'];
104
                $methodOnTarget = $relation['methodOnTarget'];
105
                $modelOnTarget = $relation['modelOnTarget'];
106
            } else {
107
                $modelTarget = '';
108
                $methodOnTarget = '';
109
                $modelOnTarget = '';
110
            }
111
112
            $is_EO = is_EO($type);
113
            $is_EM = is_EM($type);
114
115
            $key = $parent.$method.$counter;
116
            $value = $request->input($key);
117
            if (is_null($value) && $is_skippable) {
118
                continue;
119
            }//Skip with partial request type
120
121
            if (! is_null($value) && ! ($value == '') && ! ($value == '[]')) {
122
                $objs = json_decode($value);
123
            } else {
124
                $objs = getArrayWithEmptyObj($model, $is_EO, $is_EM);
125
            }
126
127
            if ($is_EO || $is_EM) {//EmbedsOne Create - EmbedsMany Create
128
                if ($event == 'update') {
129
130
                    //Delete EmbedsMany or EmbedsOne on Target
131
                    if ($hasTarget) {
132
                        $this->deleteTargetObj($method, $modelTarget, $methodOnTarget, $is_EO);
133
                    }
134
                    //Delete EmbedsMany or EmbedsOne on current object
135
                    if ($is_EM) {
136
                        $this->$method()->delete();
137
                    }
138
                }
139
140
                if (! empty($objs)) {
141
                    $i = 0;
142
                    foreach ($objs as $obj) {
143
                        $this->processOneEmbededRelationship(
144
                            $request,
145
                            $obj,
146
                            $type,
147
                            $model,
148
                            $method,
149
                            $modelTarget,
150
                            $methodOnTarget,
151
                            $modelOnTarget, $event,
152
                            $hasTarget,
153
                            $is_EO,
154
                            $is_EM,
155
                            $i,
156
                            $options);
157
                        $i++;
158
                    }
159
                } else {
160
                    $this->$method = [];
161
                    $this->save();
162
                }
163
            }
164
        }
165
    }
166
167
    /**
168
     * @param Request $request
169
     * @param $methodOnTarget
170
     * @param $modelOnTarget
171
     * @throws Exception
172
     */
173
    public function updateRelationWithSync(Request $request, $methodOnTarget, $modelOnTarget)
174
    {
175
        $embededModel = new $modelOnTarget;
176
        //Get the item name
177
        $items = $embededModel->getItems();
178
        $embededObj = $request->input($methodOnTarget);
179
        $embededObj = json_decode($embededObj);
180
181
        //Current Obj Create
182
        foreach ($items as $key => $item) {
183
            $is_ML = isML($item);
184
            $is_MD = isMD($item);
185
186
            if ($is_ML) {
187
                $embededModel->$key = ml([], $embededObj->$key);
188
            } elseif ($is_MD) {
189
                if ($embededObj->$key == '' || $embededObj->$key == null) {
190
                    $embededModel->$key = null;
191
                } else {
192
                    $embededModel->$key = new UTCDateTime(new DateTime($embededObj->$key));
0 ignored issues
show
Bug introduced by
new DateTime($embededObj->$key) of type DateTime is incompatible with the type integer expected by parameter $milliseconds of MongoDB\BSON\UTCDateTime::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

192
                    $embededModel->$key = new UTCDateTime(/** @scrutinizer ignore-type */ new DateTime($embededObj->$key));
Loading history...
193
                }
194
            } else {
195
                $embededModel->$key = $embededObj->$key;
196
            }
197
        }
198
        $this->$methodOnTarget()->associate($embededModel);
199
        $this->save();
200
    }
201
202
    /**
203
     * @param Request $request
204
     * @param $obj
205
     * @param $type
206
     * @param $model
207
     * @param $method
208
     * @param $modelTarget
209
     * @param $methodOnTarget
210
     * @param $modelOnTarget
211
     * @param $event
212
     * @param $hasTarget
213
     * @param $is_EO
214
     * @param $is_EM
215
     * @param $i
216
     * @param $options
217
     * @throws Exception
218
     */
219
    public function processOneEmbededRelationship(Request $request, $obj, $type, $model, $method, $modelTarget, $methodOnTarget, $modelOnTarget, $event, $hasTarget, $is_EO, $is_EM, $i, $options)
220
    {
221
        //Init the embedone model
222
        $embedObj = new $model;
223
224
        $EOitems = $embedObj->getItems();
225
        //Current Obj Create
226
        foreach ($EOitems as $EOkey => $item) {
227
            if (! is_null($obj)) {
228
                $is_ML = isML($item);
229
                $is_MD = isMD($item);
230
231
                if ($is_ML) {
232
                    $embedObj->$EOkey = ml([], $obj->$EOkey);
233
                } elseif ($EOkey == 'updated_at' || $EOkey == 'created_at') {
234
                    $embedObj->$EOkey = now();
235
                } elseif ($is_MD) {
236
                    if ($obj->$EOkey == '' || $obj->$EOkey == null) {
237
                        $embedObj->$EOkey = null;
238
                    } else {
239
                        $embedObj->$EOkey = new UTCDateTime(new DateTime($obj->$EOkey));
0 ignored issues
show
Bug introduced by
new DateTime($obj->$EOkey) of type DateTime is incompatible with the type integer expected by parameter $milliseconds of MongoDB\BSON\UTCDateTime::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

239
                        $embedObj->$EOkey = new UTCDateTime(/** @scrutinizer ignore-type */ new DateTime($obj->$EOkey));
Loading history...
240
                    }
241
                } else {
242
                    $this->checkPropertyExistence($obj, $EOkey);
243
                    $embedObj->$EOkey = $obj->$EOkey;
244
                }
245
            }
246
        }
247
248
        //else if($is_EM){//To be implemented}
249
        //else if($is_HM){//To be implemented}
250
        //else if($is_HO){//To be implemented}
251
252
        //Get counter for embeds many with level > 1
253
        $counter = getCounterForRelationships($method, $is_EO, $is_EM, $i);
254
        //Check for another Level of Relationship
255
        $embedObj->processAllRelationships($request, $event, $method.'-', $counter, $options);
256
257
        if ($is_EO) {
258
            $this->$method = $embedObj->attributes;
259
        } else {
260
            $this->$method()->associate($embedObj);
261
        }
262
        $this->save();
263
264
        //dd($embedObj, $this);
265
266
        if ($hasTarget) {//sync Permission to Permissiongroup
267
            $this->checkPropertyExistence($obj, 'ref_id');
268
            $target_id = $obj->ref_id;
269
270
            $ref_id = $this->getId();
0 ignored issues
show
Bug introduced by
It seems like getId() must be provided by classes using this trait. How about adding it as abstract method to this trait? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

270
            /** @scrutinizer ignore-call */ 
271
            $ref_id = $this->getId();
Loading history...
271
272
            $requestToBeSync = getRequestToBeSync($ref_id, $modelOnTarget, $request, $methodOnTarget);
273
274
            //Init the Target Model
275
            $modelToBeSync = new $modelTarget;
276
            $modelToBeSync = $modelToBeSync->find($target_id);
277
            if (! is_null($modelToBeSync)) {
278
                $modelToBeSync->updateRelationWithSync($requestToBeSync, $methodOnTarget, $modelOnTarget);
279
                //TODO:Sync target on level > 1
280
                //$modelToBeSync->processAllRelationships($request, $event, $methodOnTarget, $methodOnTarget . "-");
281
            }
282
        }
283
    }
284
285
    /**
286
     * @param Request $request
287
     * @param array $additionalData
288
     * @param array $options
289
     * @return $this
290
     * @throws Exception
291
     */
292
    public function updateWithSync(Request $request, array $additionalData = [], array $options)
293
    {
294
        $request = $request->merge($additionalData);
295
        $this->storeEditAllItems($request, 'update', $options);
296
        $this->processAllRelationships($request, 'update', '', '', $options);
297
298
        //Dispatch the update event
299
        $this->fireModelEvent('updateWithSync');
300
301
        return $this;
302
    }
303
304
    /**
305
     * @param $method
306
     * @param $modelTarget
307
     * @param $methodOnTarget
308
     * @param $id
309
     */
310
    public function deleteTargetObj($method, $modelTarget, $methodOnTarget, $is_EO)
311
    {
312
        if ($is_EO) {
313
            $embedObj = $this->$method;
314
            if (! is_null($embedObj)) {
315
                $target_id = $embedObj->ref_id;
316
                $this->handleSubTarget($target_id, $modelTarget, $methodOnTarget);
317
            }
318
        } else {
319
            foreach ($this->$method as $target) {
320
                $this->handleSubTarget($target->ref_id, $modelTarget, $methodOnTarget);
321
            }
322
        }
323
    }
324
325
    /**
326
     * @param $target_id
327
     * @param $modelTarget
328
     * @param $methodOnTarget
329
     */
330
    public function handleSubTarget($target_id, $modelTarget, $methodOnTarget)
331
    {
332
        $id = $this->getId();
333
        $target = new $modelTarget;
334
        $target = $target->all()->where('id', $target_id)->first();
335
        if (! is_null($target)) {
336
            $subTarget = $target->$methodOnTarget()->where('ref_id', $id)->first();
337
            $temps = $target->$methodOnTarget()->where('ref_id', '!=', $id);
338
            $target->$methodOnTarget()->delete($subTarget);
339
            foreach ($temps as $temp) {
340
                $target->$methodOnTarget()->associate($temp);
341
                $target->save();
342
            }
343
        }
344
    }
345
346
    /**
347
     * @return $this
348
     */
349
    public function destroyWithSync()
350
    {
351
        //Get the relation info
352
        $relations = $this->getMongoRelation();
353
354
        //Process all relationships
355
        foreach ($relations as $method => $relation) {
356
            //Get Relation Save Mode
357
            $type = $relation['type'];
358
            $hasTarget = hasTarget($relation);
359
            if ($hasTarget) {
360
                $modelTarget = $relation['modelTarget'];
361
                $methodOnTarget = $relation['methodOnTarget'];
362
                $modelOnTarget = $relation['modelOnTarget'];
0 ignored issues
show
Unused Code introduced by
The assignment to $modelOnTarget is dead and can be removed.
Loading history...
363
364
                $is_EO = is_EO($type);
365
                $is_EM = is_EM($type);
366
                $is_HO = is_HO($type);
0 ignored issues
show
Unused Code introduced by
The assignment to $is_HO is dead and can be removed.
Loading history...
367
                $is_HM = is_HM($type);
0 ignored issues
show
Unused Code introduced by
The assignment to $is_HM is dead and can be removed.
Loading history...
368
369
                if ($is_EO || $is_EM) {//EmbedsOne Create - EmbedsMany Create
370
                    //Delete EmbedsMany or EmbedsOne on Target
371
                    $this->deleteTargetObj($method, $modelTarget, $methodOnTarget, $is_EO);
372
                }
373
374
                //TODO: Need to be implemented
375
               /* elseif ($is_HM) {//HasMany
376
                } elseif ($is_HO) {//HasOne Create
377
                }*/
378
            }
379
        }
380
        //Delete current object
381
        $this->delete();
0 ignored issues
show
Bug introduced by
The method delete() does not exist on OfflineAgency\MongoAutoSync\Traits\MongoSyncTrait. Did you maybe mean deleteTargetObj()? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

381
        $this->/** @scrutinizer ignore-call */ 
382
               delete();

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
382
383
        //Dispatch the destroy event
384
        $this->fireModelEvent('destroyWithSync');
385
386
        return $this;
387
    }
388
389
    /**
390
     * @param array $options
391
     * @param string $key
392
     * @return bool|mixed
393
     */
394
    private function getOptionValue(array $options, string $key){
395
        return array_key_exists($key,  $options) ? $options[$key] : '';
396
    }
397
398
    /**
399
     * @param array $options
400
     * @return bool
401
     */
402
    private function getIsSkippable(array $options){
403
        return $this->getOptionValue(
404
            $options,
405
            'request_type'
406
            ) == 'partial';
407
    }
408
409
    /**
410
     * @param $obj
411
     * @param string $EOkey
412
     */
413
    private function checkPropertyExistence($obj, string $EOkey){
414
        try {
415
            if (!property_exists($obj, $EOkey)) {
416
                $msg = ('Error - ' . $EOkey . ' attribute not found on obj ' . json_encode($obj));
417
                (new Exception($msg) );
418
            }
419
        }catch (Exception $exception){
420
            $exception->getMessage();
421
        }
422
    }
423
424
    /**
425
     * @param Request $request
426
     * @param string $key
427
     */
428
    private function checkRequestExistence(Request $request, string $key){//Can be optimized
429
        try {
430
            if ( is_null($request->input($key)) ) {
431
                $msg = ('Error - ' . $key . ' attribute not found in Request ' . json_encode($request));
432
                (new Exception($msg) );
433
            }
434
        }catch (Exception $exception){
435
            $exception->getMessage();
436
        }
437
    }
438
}
439