Test Failed
Pull Request — master (#74)
by
unknown
03:51
created

RelationshipMongoTrait   B

Complexity

Total Complexity 52

Size/Duplication

Total Lines 332
Duplicated Lines 0 %

Importance

Changes 7
Bugs 5 Features 2
Metric Value
wmc 52
eloc 152
c 7
b 5
f 2
dl 0
loc 332
rs 7.44

7 Methods

Rating   Name   Duplication   Size   Complexity  
F processAllRelationships() 0 97 18
A handleSubTarget() 0 16 6
A deleteTargetObj() 0 11 5
A processOneEmbeddedRelationship() 0 8 3
B updateRelationWithSync() 0 52 8
A processEmbedOnTargetCollection() 0 6 2
B processEmbedOnCurrentCollection() 0 42 10

How to fix   Complexity   

Complex Class

Complex classes like RelationshipMongoTrait often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use RelationshipMongoTrait, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace OfflineAgency\MongoAutoSync\Traits;
4
5
use DateTime;
6
use Exception;
7
use Illuminate\Http\Request;
8
use Illuminate\Support\Arr;
9
use MongoDB\BSON\UTCDateTime;
10
11
trait RelationshipMongoTrait
12
{
13
    /**
14
     * @param  Request  $request
15
     * @param  string  $event
16
     * @param  string  $parent
17
     * @param  string  $counter
18
     * @param  array  $options
19
     *
20
     * @throws Exception
21
     */
22
    public function processAllRelationships(Request $request, string $event, string $parent, string $counter, array $options)
23
    {
24
        $this->setMiniModels(); // For target Sync
0 ignored issues
show
Bug introduced by
It seems like setMiniModels() 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

24
        $this->/** @scrutinizer ignore-call */ 
25
               setMiniModels(); // For target Sync
Loading history...
25
26
        //Get the relation info
27
        $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

27
        /** @scrutinizer ignore-call */ 
28
        $relations = $this->getMongoRelation();
Loading history...
28
29
        //Process all relationships
30
        foreach ($relations as $method => $relation) {
31
            //Get Relation Save Mode
32
            $type = $relation['type'];
33
            $model = $relation['model'];
34
            $hasTarget = hasTarget($relation);
35
            if ($hasTarget) {
36
                $modelTarget = $relation['modelTarget'];
37
                $methodOnTarget = $relation['methodOnTarget'];
38
                $modelOnTarget = $relation['modelOnTarget'];
39
                $typeOnTarget = getTypeOnTarget($relation);
40
            } else {
41
                $modelTarget = '';
42
                $methodOnTarget = '';
43
                $modelOnTarget = '';
44
                $typeOnTarget = '';
45
            }
46
47
            $is_EO = is_EO($type);
48
            $is_EM = is_EM($type);
49
50
            $is_EM_target = is_EM($typeOnTarget);
51
            $is_EO_target = is_EO($typeOnTarget);
52
53
            $key = $parent.$method.$counter;
54
            $is_skippable = $this->getIsSkippable($request->has($key), $hasTarget);
0 ignored issues
show
Bug introduced by
It seems like getIsSkippable() 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

54
            /** @scrutinizer ignore-call */ 
55
            $is_skippable = $this->getIsSkippable($request->has($key), $hasTarget);
Loading history...
55
56
            if ($is_skippable) {
57
                continue;
58
            }
59
            $current_request = $request->has($key) ? $request : $this->getPartialGeneratedRequest();
0 ignored issues
show
Bug introduced by
It seems like getPartialGeneratedRequest() 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

59
            $current_request = $request->has($key) ? $request : $this->/** @scrutinizer ignore-call */ getPartialGeneratedRequest();
Loading history...
60
61
            $value = $this->getRelationshipRequest($key, $current_request);
0 ignored issues
show
Bug introduced by
It seems like getRelationshipRequest() 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

61
            /** @scrutinizer ignore-call */ 
62
            $value = $this->getRelationshipRequest($key, $current_request);
Loading history...
62
63
            $is_embeds_has_to_be_updated = $request->has($key);
64
65
            if (! is_null($value) && ! ($value == '') && ! ($value == '[]')) {
66
                $objs = json_decode($value);
67
            } else {
68
                $objs = getArrayWithEmptyObj($model, $is_EO, $is_EM);
69
            }
70
71
            if ($is_EO || $is_EM) {//EmbedsOne Create - EmbedsMany Create
72
                if ($event == 'update' && $is_embeds_has_to_be_updated) {
73
74
                    //Delete EmbedsMany or EmbedsOne on Target - TODO: check if it is necessary to run deleteTargetObj method
75
                    if ($hasTarget) {
76
                        $this->deleteTargetObj($method, $modelTarget, $methodOnTarget, $is_EO, $is_EM, $is_EO_target, $is_EM_target);
77
                    }
78
                    //Delete EmbedsMany or EmbedsOne on current object
79
                    if ($is_EM) {
80
                        $this->$method = [];
81
                        $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

81
                        $this->/** @scrutinizer ignore-call */ 
82
                               save();
Loading history...
82
                    }
83
                }
84
85
                if (! empty($objs)) {
86
                    if ($is_EM) {
87
                        $this->tempEM = [];
0 ignored issues
show
Bug Best Practice introduced by
The property tempEM does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
88
                    }
89
90
                    $i = 0;
91
                    foreach ($objs as $obj) {
92
                        $this->processOneEmbeddedRelationship(
93
                            $request,
94
                            $obj,
95
                            $type,
96
                            $model,
97
                            $method,
98
                            $modelTarget,
99
                            $methodOnTarget,
100
                            $modelOnTarget, $event,
101
                            $hasTarget,
102
                            $is_EO,
103
                            $is_EM,
104
                            $is_EO_target,
105
                            $is_EM_target,
106
                            $i,
107
                            $is_embeds_has_to_be_updated,
108
                            $options);
109
                        $i++;
110
                    }
111
112
                    if ($is_EM) {
113
                        $this->$method = $this->tempEM;
114
                    }
115
                } else {
116
                    $this->$method = [];
117
                }
118
                $this->save();
119
            }
120
        }
121
    }
122
123
    /**
124
     * @param $mini_model
125
     * @param  string  $method_on_target
126
     * @param  bool  $is_EO_target
127
     * @param  bool  $is_EM_target
128
     *
129
     * @throws \Throwable
130
     */
131
    public function updateRelationWithSync($mini_model, string $method_on_target, $is_EO_target, $is_EM_target)
132
    {
133
        if ($is_EM_target) {
134
            $new_values = [];
135
            throw_if(
136
                ! isset($this->$method_on_target),
137
                new Exception(
138
                    'Error during target update. Remember to init the attribute '.$method_on_target.
139
                    ' on collection '.$this->getCollection()
0 ignored issues
show
Bug introduced by
The method getCollection() does not exist on OfflineAgency\MongoAutoS...\RelationshipMongoTrait. Did you maybe mean processEmbedOnTargetCollection()? ( Ignorable by Annotation )

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

139
                    ' on collection '.$this->/** @scrutinizer ignore-call */ getCollection()

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...
140
                )
141
            );
142
143
            $is_update_operation = false;
144
            foreach ($this->$method_on_target as $temp) {
145
                throw_if(
146
                    is_array($temp),
147
                    new Exception(
148
                        'Error during target update. Remember to declare '.$method_on_target.' as '.
149
                        'EmbedsMany relationship on model '.get_class($this)
150
                    )
151
                );
152
153
                if (!is_null($temp)) {
154
                    if ($this->getHasPartialRequest()) {
0 ignored issues
show
Bug introduced by
It seems like getHasPartialRequest() 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

154
                    if ($this->/** @scrutinizer ignore-call */ getHasPartialRequest()) {
Loading history...
155
                        if (Arr::get($temp->attributes, 'ref_id') !== Arr::get($mini_model->attributes, 'ref_id')) {
156
                            $new_values[] = $temp->attributes;
157
                        } else {
158
                            $new_values[] = $mini_model->attributes;
159
                            $is_update_operation = true;
160
                        }
161
                    } else {
162
                        $new_values[] = $mini_model->attributes;
163
                    }
164
                }
165
            }
166
167
            if (!$is_update_operation) {
168
                $new_values[] = $mini_model->attributes;
169
            }
170
        } elseif ($is_EO_target) {
171
            throw_if(
172
                is_array($mini_model),
173
                new Exception(
174
                    'Error during target update. Remember to declare '.$method_on_target.' as '.
175
                    'EmbedOne relationship on model '.get_class($this)
176
                )
177
            );
178
            $new_values = $mini_model->attributes;
179
        }
180
181
        $this->$method_on_target = $new_values;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $new_values does not seem to be defined for all execution paths leading up to this point.
Loading history...
182
        $this->save();
183
    }
184
185
    /**
186
     * @param  Request  $request
187
     * @param $obj
188
     * @param $type
189
     * @param $model
190
     * @param $method
191
     * @param $modelTarget
192
     * @param $methodOnTarget
193
     * @param $modelOnTarget
194
     * @param $event
195
     * @param $hasTarget
196
     * @param  bool  $is_EO
197
     * @param  bool  $is_EM
198
     * @param  bool  $is_EO_target
199
     * @param  bool  $is_EM_target
200
     * @param $i
201
     * @param  bool  $is_embeds_has_to_be_updated
202
     * @param $options
203
     *
204
     * @throws Exception
205
     */
206
    public function processOneEmbeddedRelationship(Request $request, $obj, $type, $model, $method, $modelTarget, $methodOnTarget, $modelOnTarget, $event, $hasTarget, $is_EO, $is_EM, $is_EO_target, $is_EM_target, $i, $is_embeds_has_to_be_updated, $options)
207
    {
208
        if ($is_embeds_has_to_be_updated) {
209
            $this->processEmbedOnCurrentCollection($request, $obj, $type, $model, $method, $event, $is_EO, $is_EM, $i, $options);
210
        }
211
212
        if ($hasTarget) {
213
            $this->processEmbedOnTargetCollection($modelTarget, $obj, $methodOnTarget, $modelOnTarget, $is_EO_target, $is_EM_target);
214
        }
215
    }
216
217
    /**
218
     * @param  string  $method
219
     * @param  string  $modelTarget
220
     * @param  string  $methodOnTarget
221
     * @param  bool  $is_EO
222
     * @param  bool  $is_EM
223
     * @param  bool  $is_EO_target
224
     * @param  bool  $is_EM_target
225
     */
226
    public function deleteTargetObj($method, $modelTarget, $methodOnTarget, bool $is_EO, bool $is_EM, bool $is_EO_target, bool $is_EM_target)
227
    {
228
        if ($is_EO) {
229
            $embedObj = $this->$method;
230
            if (! is_null($embedObj)) {
231
                $target_id = $embedObj->ref_id;
232
                $this->handleSubTarget($target_id, $modelTarget, $methodOnTarget, $is_EO_target, $is_EM_target);
233
            }
234
        } elseif ($is_EM) {
235
            foreach ($this->$method as $target) {
236
                $this->handleSubTarget($target->ref_id, $modelTarget, $methodOnTarget, $is_EO_target, $is_EM_target);
237
            }
238
        }
239
    }
240
241
    /**
242
     * @param  string|null  $target_id
243
     * @param  string  $modelTarget
244
     * @param  string  $methodOnTarget
245
     * @param  bool  $is_EO_target
246
     * @param  bool  $is_EM_target
247
     */
248
    public function handleSubTarget(?string $target_id, string $modelTarget, string $methodOnTarget, bool $is_EO_target, bool $is_EM_target)
249
    {
250
        if ($is_EM_target) {
251
            $target = new $modelTarget;
252
            $target = $target->all()->where('id', $target_id)->first();
253
            if (! is_null($target)) {
254
                $new_values = [];
255
                foreach ($target->$methodOnTarget as $temp) {
256
                    if ($temp->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

256
                    if ($temp->ref_id !== $this->/** @scrutinizer ignore-call */ getId()) {
Loading history...
257
                        $new_values[] = $temp->attributes;
258
                    }
259
                }
260
                $target->$methodOnTarget = $new_values;
261
                $target->save();
262
            }
263
        } elseif ($is_EO_target) {
264
            //Do nothing because when we are updating we already init the informations
265
        }
266
    }
267
268
    /**
269
     * @param  Request  $request
270
     * @param $obj
271
     * @param $type
272
     * @param $model
273
     * @param $method
274
     * @param $event
275
     * @param $is_EO
276
     * @param $is_EM
277
     * @param $i
278
     * @param $options
279
     *
280
     * @throws Exception
281
     */
282
    private function processEmbedOnCurrentCollection(Request $request, $obj, $type, $model, $method, $event, $is_EO, $is_EM, $i, $options)
0 ignored issues
show
Unused Code introduced by
The parameter $type is not used and could be removed. ( Ignorable by Annotation )

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

282
    private function processEmbedOnCurrentCollection(Request $request, $obj, /** @scrutinizer ignore-unused */ $type, $model, $method, $event, $is_EO, $is_EM, $i, $options)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
283
    {
284
        //Init the embed one model
285
        $embedObj = new $model;
286
287
        $EOitems = $embedObj->getItems();
288
        //Current Obj Create
289
        foreach ($EOitems as $EOkey => $item) {
290
            if (! is_null($obj)) {
291
                $is_ML = isML($item);
292
                $is_MD = isMD($item);
293
                $this->checkPropertyExistence($obj, $EOkey, $method, $model);
0 ignored issues
show
Bug introduced by
It seems like checkPropertyExistence() 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

293
                $this->/** @scrutinizer ignore-call */ 
294
                       checkPropertyExistence($obj, $EOkey, $method, $model);
Loading history...
294
295
                if ($is_ML) {
296
                    $embedObj->$EOkey = ml([], $obj->$EOkey);
297
                } elseif ($EOkey == 'updated_at' || $EOkey == 'created_at') {
298
                    $embedObj->$EOkey = now();
299
                } elseif ($is_MD) {
300
                    if ($obj->$EOkey == '' || $obj->$EOkey == null) {
301
                        $embedObj->$EOkey = null;
302
                    } else {
303
                        $embedObj->$EOkey = new UTCDateTime(new DateTime($obj->$EOkey));
304
                    }
305
                } else {
306
                    $embedObj->$EOkey = $obj->$EOkey;
307
                }
308
            }
309
        }
310
311
        //else if($is_EM){//To be implemented}
312
        //else if($is_HM){//To be implemented}
313
        //else if($is_HO){//To be implemented}
314
315
        //Get counter for embeds many with level > 1
316
        $counter = getCounterForRelationships($method, $is_EO, $is_EM, $i);
317
        //Check for another Level of Relationship
318
        $embedObj->processAllRelationships($request, $event, $method.'-', $counter, $options);
319
320
        if ($is_EO) {
321
            $this->$method = $embedObj->attributes;
322
        } else {
323
            $this->tempEM[] = $embedObj->attributes;
0 ignored issues
show
Bug Best Practice introduced by
The property tempEM does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
324
        }
325
    }
326
327
    /**
328
     * @param $modelTarget
329
     * @param $obj
330
     * @param $methodOnTarget
331
     * @param $modelOnTarget
332
     * @param  bool  $is_EO_target
333
     * @param  bool  $is_EM_target
334
     *
335
     * @throws Exception
336
     */
337
    private function processEmbedOnTargetCollection($modelTarget, $obj, $methodOnTarget, $modelOnTarget, bool $is_EO_target, bool $is_EM_target)
338
    {
339
        $modelToBeSync = $this->getModelTobeSync($modelTarget, $obj);
0 ignored issues
show
Bug introduced by
It seems like getModelTobeSync() 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

339
        /** @scrutinizer ignore-call */ 
340
        $modelToBeSync = $this->getModelTobeSync($modelTarget, $obj);
Loading history...
340
        if (! is_null($modelToBeSync)) {
341
            $miniModel = $this->getEmbedModel($modelOnTarget);
0 ignored issues
show
Bug introduced by
It seems like getEmbedModel() 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

341
            /** @scrutinizer ignore-call */ 
342
            $miniModel = $this->getEmbedModel($modelOnTarget);
Loading history...
342
            $modelToBeSync->updateRelationWithSync($miniModel, $methodOnTarget, $is_EO_target, $is_EM_target);
343
            //TODO:Sync target on level > 1
344
            //$modelToBeSync->processAllRelationships($request, $event, $methodOnTarget, $methodOnTarget . "-");
345
        }
346
    }
347
}
348