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

MongoSyncTrait::processOneEmbededRelationship()   C

Complexity

Conditions 12
Paths 42

Size

Total Lines 60
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
cc 12
eloc 34
nc 42
nop 14
dl 0
loc 60
rs 6.9666
c 3
b 1
f 0

How to fix   Long Method    Complexity    Many Parameters   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

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