Passed
Push — master ( 4fb543...e7c8f8 )
by Giacomo
10:34
created

MongoSyncTrait::processOneEmbededRelationship()   C

Complexity

Conditions 14
Paths 64

Size

Total Lines 70
Code Lines 39

Duplication

Lines 0
Ratio 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
cc 14
eloc 39
c 3
b 1
f 0
nc 64
nop 14
dl 0
loc 70
rs 6.2666

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->getOptionValue($options, 'request_type');
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
            if ( is_null($request->input($key)) && $is_skippable ) { continue; }//Skip with partial request type
50
51
            if ($is_fillable) {
52
                if ($is_ML) {
53
                    if (is_null($this->$key)) {
54
                        $old_value = array();
55
                    } else {
56
                        $old_value = $this->$key;
57
                    }
58
                    $this->$key = ml($old_value, $request->input($key));
59
                } elseif ($is_MD) {
60
                    if ($request->input($key) == "" || $request->input($key) == null) {
61
                        $this->$key = null;
62
                    } else {
63
                        $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

63
                        $this->$key = new UTCDateTime(/** @scrutinizer ignore-type */ new DateTime($request->input($key)));
Loading history...
64
                    }
65
                } else {
66
                    $this->$key = $request->input($key);
67
                }
68
            }
69
        }
70
71
        $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

71
        $this->/** @scrutinizer ignore-call */ 
72
               save();
Loading history...
72
    }
73
74
    /**
75
     * @param Request $request
76
     * @param string $event
77
     * @param string $parent
78
     * @param string $counter
79
     * @param array $options
80
     * @throws Exception
81
     */
82
    public function processAllRelationships(Request $request, string $event, string $parent, string $counter, array $options)
83
    {
84
        //Get the relation info
85
        $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

85
        /** @scrutinizer ignore-call */ 
86
        $relations = $this->getMongoRelation();
Loading history...
86
87
        //Process all relationships
88
        foreach ($relations as $method => $relation) {
89
            //Get Relation Save Mode
90
            $type = $relation['type'];
91
            $model = $relation['model'];
92
            $hasTarget = hasTarget($relation);
93
            if ($hasTarget) {
94
                $modelTarget = $relation['modelTarget'];
95
                $methodOnTarget = $relation['methodOnTarget'];
96
                $modelOnTarget = $relation['modelOnTarget'];
97
            } else {
98
                $modelTarget = "";
99
                $methodOnTarget = "";
100
                $modelOnTarget = "";
101
            }
102
103
            $is_EO = is_EO($type);
104
            $is_EM = is_EM($type);
105
            $is_skippable = $this->getOptionValue($options, 'request_type');
106
107
            $key = $parent . $method . $counter;
108
            $value = $request->input($key);
109
            if ( is_null($value) && $is_skippable ) { continue; }//Skip with partial request type
110
111
            if (!is_null($value) && !($value == "") && !($value == "[]")) {
112
                $objs = json_decode($value);
113
            } else {
114
                $objs = getArrayWithEmptyObj($model, $is_EO, $is_EM);
115
            }
116
117
            if ($is_EO || $is_EM) {//EmbedsOne Create - EmbedsMany Create
118
                if ($event == "update") {
119
120
                    //Delete EmbedsMany or EmbedsOne on Target
121
                    if ($hasTarget) {
122
                        $this->deleteTargetObj($method, $modelTarget, $methodOnTarget, $is_EO);
123
                    }
124
                    //Delete EmbedsMany or EmbedsOne on current object
125
                    if ($is_EM) {
126
                        $this->$method()->delete();
127
                    }
128
                }
129
130
                if (!empty($objs)) {
131
                    $i = 0;
132
                    foreach ($objs as $obj) {
133
                        $this->processOneEmbededRelationship(
134
                            $request,
135
                            $obj,
136
                            $type,
137
                            $model,
138
                            $method,
139
                            $modelTarget,
140
                            $methodOnTarget,
141
                            $modelOnTarget, $event,
142
                            $hasTarget,
143
                            $is_EO,
144
                            $is_EM,
145
                            $i,
146
                            $options);
147
                        $i++;
148
                    }
149
                } else {
150
                    $this->$method = [];
151
                    $this->save();
152
                }
153
            }
154
        }
155
    }
156
157
    /**
158
     * @param Request $request
159
     * @param $methodOnTarget
160
     * @param $modelOnTarget
161
     * @throws Exception
162
     */
163
    public function updateRelationWithSync(Request $request, $methodOnTarget, $modelOnTarget)
164
    {
165
        $embededModel = new $modelOnTarget;
166
        //Get the item name
167
        $items = $embededModel->getItems();
168
        $embededObj = $request->input($methodOnTarget);
169
        $embededObj = json_decode($embededObj);
170
171
        //Current Obj Create
172
        foreach ($items as $key => $item) {
173
            $is_ML = isML($item);
174
            $is_MD = isMD($item);
175
176
            if ($is_ML) {
177
                $embededModel->$key = ml(array(), $embededObj->$key);
178
            } elseif ($is_MD) {
179
                if ($embededObj->$key == "" || $embededObj->$key == null) {
180
                    $embededModel->$key = null;
181
                } else {
182
                    $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

182
                    $embededModel->$key = new UTCDateTime(/** @scrutinizer ignore-type */ new DateTime($embededObj->$key));
Loading history...
183
                }
184
            } else {
185
                $embededModel->$key = $embededObj->$key;
186
            }
187
        }
188
        $this->$methodOnTarget()->associate($embededModel);
189
        $this->save();
190
    }
191
192
    /**
193
     * @param Request $request
194
     * @param $obj
195
     * @param $type
196
     * @param $model
197
     * @param $method
198
     * @param $modelTarget
199
     * @param $methodOnTarget
200
     * @param $modelOnTarget
201
     * @param $event
202
     * @param $hasTarget
203
     * @param $is_EO
204
     * @param $is_EM
205
     * @param $i
206
     * @throws Exception
207
     */
208
    public function processOneEmbededRelationship(Request $request, $obj, $type, $model, $method, $modelTarget, $methodOnTarget, $modelOnTarget, $event, $hasTarget, $is_EO, $is_EM, $i, $options)
209
    {
210
        //Init the embedone model
211
        $embedObj = new $model;
212
213
        $EOitems = $embedObj->getItems();
214
        //Current Obj Create
215
        foreach ($EOitems as $EOkey => $item) {
216
            if (!is_null($obj)) {
217
                $is_ML = isML($item);
218
                $is_MD = isMD($item);
219
220
                if ($is_ML) {
221
                    $embedObj->$EOkey = ml(array(), $obj->$EOkey);
222
                } elseif ($EOkey == "updated_at" || $EOkey == "created_at") {
223
                    $embedObj->$EOkey = now();
224
                } elseif ($is_MD) {
225
                    if ($obj->$EOkey == "" ||  $obj->$EOkey == null) {
226
                        $embedObj->$EOkey = null;
227
                    } else {
228
                        $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

228
                        $embedObj->$EOkey = new UTCDateTime(/** @scrutinizer ignore-type */ new DateTime($obj->$EOkey));
Loading history...
229
                    }
230
                } else {
231
                    if (!property_exists($obj, $EOkey)) {
232
                        $msg = ('Error - ' . $EOkey . ' attribute not found on obj ' . json_encode($obj));
233
                        (new Exception($msg) );
234
                    }
235
                    $embedObj->$EOkey = $obj->$EOkey;
236
                }
237
            }
238
        }
239
240
        //else if($is_EM){//To be implemented}
241
        //else if($is_HM){//To be implemented}
242
        //else if($is_HO){//To be implemented}
243
244
        //Get counter for embeds many with level > 1
245
        $counter = getCounterForRelationships($method, $is_EO, $is_EM, $i);
246
        //Check for another Level of Relationship
247
        $embedObj->processAllRelationships($request, $event, $method . "-", $counter, $options);
248
249
        if ($is_EO) {
250
            $this->$method = $embedObj->attributes;
251
        } else {
252
            $this->$method()->associate($embedObj);
253
        }
254
        $this->save();
255
256
        //dd($embedObj, $this);
257
258
        if ($hasTarget) {
259
            //sync Permission to Permissiongroup
260
            //Init the Target Model
261
            $target_model = new $modelTarget;
0 ignored issues
show
Unused Code introduced by
The assignment to $target_model is dead and can be removed.
Loading history...
262
263
            if (!property_exists($obj, 'ref_id')) {
264
                $msg = ('Error - ref_id attribute not found on obj ' . json_encode($obj));
265
                throw (new \Exception($msg) );
266
            }
267
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
            $modelToBeSync = new $modelTarget;
275
            $modelToBeSync = $modelToBeSync->find($target_id);
276
            if (!is_null($modelToBeSync)) {
277
                $modelToBeSync->updateRelationWithSync($requestToBeSync, $methodOnTarget, $modelOnTarget);
278
                //TODO:Sync target on level > 1
279
                //$modelToBeSync->processAllRelationships($request, $event, $methodOnTarget, $methodOnTarget . "-");
280
            }
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
370
                if ($is_EO || $is_EM) {//EmbedsOne Create - EmbedsMany Create
371
                    //Delete EmbedsMany or EmbedsOne on Target
372
                    $this->deleteTargetObj($method, $modelTarget, $methodOnTarget, $is_EO);
373
                }
374
375
                //TODO: Need to be implemented
376
               /* elseif ($is_HM) {//HasMany
377
                } elseif ($is_HO) {//HasOne Create
378
                }*/
379
            }
380
        }
381
        //Delete current object
382
        $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

382
        $this->/** @scrutinizer ignore-call */ 
383
               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...
383
384
        //Dispatch the destroy event
385
        $this->fireModelEvent('destroyWithSync');
386
387
        return $this;
388
    }
389
390
    /**
391
     * @param array $options
392
     * @param string $key
393
     * @return bool|mixed
394
     */
395
    private function getOptionValue(array $options, string $key){
396
        return array_key_exists('',  $options) ?   $options[$key] : false;
397
    }
398
}
399