Completed
Pull Request — master (#325)
by Paul
08:12 queued 49s
created

WidgetMap   C

Complexity

Total Complexity 72

Size/Duplication

Total Lines 437
Duplicated Lines 8.47 %

Coupling/Cohesion

Components 3
Dependencies 2

Importance

Changes 14
Bugs 1 Features 0
Metric Value
wmc 72
c 14
b 1
f 0
lcom 3
cbo 2
dl 37
loc 437
rs 5.5667

32 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 5 1
A getId() 0 4 1
A setId() 0 4 1
A isAsynchronous() 0 4 1
A setAsynchronous() 0 4 1
A setAction() 0 9 4
A getAction() 0 4 1
A getWidget() 0 4 1
A setWidget() 0 6 1
A getView() 0 4 1
A setView() 0 4 1
A getReplaced() 0 4 1
A setReplaced() 0 7 2
A getSlot() 0 4 1
A setSlot() 0 4 1
C getChildren() 37 55 23
A getChildrenRaw() 0 4 1
A hasChild() 0 10 4
A getChild() 0 11 4
A getChilds() 0 11 4
A setChildren() 0 4 1
A removeChildren() 0 6 2
A addChild() 0 4 1
A removeChild() 0 4 1
A getParent() 0 4 1
A setParent() 0 10 3
A getPosition() 0 4 1
A setPosition() 0 4 1
A getSubstitutes() 0 4 1
A getSubstituteForView() 0 10 3
A addSubstitute() 0 4 1
A setSubstitutes() 0 4 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like WidgetMap 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 WidgetMap, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Victoire\Bundle\WidgetMapBundle\Entity;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Doctrine\Common\Collections\Collection;
7
use Doctrine\ORM\Mapping as ORM;
8
use Victoire\Bundle\CoreBundle\Entity\View;
9
use Victoire\Bundle\WidgetBundle\Entity\Widget;
10
11
/**
12
 * @ORM\Table("vic_widget_map")
13
 * @ORM\Entity(repositoryClass="Victoire\Bundle\WidgetMapBundle\Repository\WidgetMapRepository")
14
 */
15
class WidgetMap
16
{
17
    const ACTION_CREATE = 'create';
18
    const ACTION_OVERWRITE = 'overwrite';
19
    const ACTION_DELETE = 'delete';
20
21
    const POSITION_BEFORE = 'before';
22
    const POSITION_AFTER = 'after';
23
24
    /**
25
     * @var int
26
     *
27
     * @ORM\Column(name="id", type="integer")
28
     * @ORM\Id
29
     * @ORM\GeneratedValue(strategy="AUTO")
30
     */
31
    protected $id;
32
33
    /**
34
     * @var string
35
     *
36
     * @ORM\Column(name="action", type="string", length=255)
37
     */
38
    protected $action = null;
39
40
    /**
41
     * @var View
42
     *
43
     * @ORM\ManyToOne(targetEntity="\Victoire\Bundle\CoreBundle\Entity\View", inversedBy="widgetMaps")
44
     * @ORM\JoinColumn(name="view_id", referencedColumnName="id")
45
     */
46
    protected $view;
47
48
    /**
49
     * @var Widget
50
     *
51
     * @ORM\ManyToOne(targetEntity="\Victoire\Bundle\WidgetBundle\Entity\Widget", inversedBy="widgetMaps")
52
     * @ORM\JoinColumn(name="widget_id", referencedColumnName="id")
53
     */
54
    protected $widget;
55
56
    /**
57
     * @ORM\ManyToOne(targetEntity="\Victoire\Bundle\WidgetMapBundle\Entity\WidgetMap", inversedBy="substitutes")
58
     * @ORM\JoinColumn(name="replaced_id", referencedColumnName="id")
59
     */
60
    protected $replaced;
61
62
    /**
63
     * @var ArrayCollection
64
     * @ORM\OneToMany(targetEntity="\Victoire\Bundle\WidgetMapBundle\Entity\WidgetMap", mappedBy="replaced")
65
     */
66
    protected $substitutes;
67
68
    /**
69
     * @var string
70
     *
71
     * @ORM\Column(name="asynchronous", type="boolean")
72
     */
73
    protected $asynchronous = false;
74
75
    /**
76
     * @ORM\ManyToOne(targetEntity="\Victoire\Bundle\WidgetMapBundle\Entity\WidgetMap", inversedBy="children")
77
     * @ORM\JoinColumn(name="parent_id", referencedColumnName="id", onDelete="SET NULL")
78
     */
79
    protected $parent;
80
81
    /**
82
     * @var string
83
     *
84
     * @ORM\Column(name="position", type="string", nullable=true)
85
     */
86
    protected $position;
87
88
    /**
89
     * @var Collection
90
     * @ORM\OneToMany(targetEntity="\Victoire\Bundle\WidgetMapBundle\Entity\WidgetMap", mappedBy="parent")
91
     */
92
    protected $children;
93
94
    /**
95
     * @var string
96
     *
97
     * @ORM\Column(name="slot", type="string", length=255, nullable=true)
98
     */
99
    protected $slot;
100
101
    public function __construct()
102
    {
103
        $this->children = new ArrayCollection();
104
        $this->substitutes = new ArrayCollection();
105
    }
106
107
    /**
108
     * @return int
109
     */
110
    public function getId()
111
    {
112
        return $this->id;
113
    }
114
115
    public function setId($id)
116
    {
117
        $this->id = $id;
118
    }
119
120
    /**
121
     * @return null
122
     */
123
    public function isAsynchronous()
124
    {
125
        return $this->asynchronous;
126
    }
127
128
    /**
129
     * @param null $asynchronous
130
     */
131
    public function setAsynchronous($asynchronous)
132
    {
133
        $this->asynchronous = $asynchronous;
134
    }
135
136
    /**
137
     * Set the action.
138
     *
139
     * @param string $action
140
     *
141
     * @throws \Exception The action is not valid
142
     */
143
    public function setAction($action)
144
    {
145
        //test validity of the action
146
        if ($action !== self::ACTION_CREATE && $action !== self::ACTION_OVERWRITE && $action !== self::ACTION_DELETE) {
147
            throw new \Exception('The action of the widget map is not valid. Action: ['.$action.']');
148
        }
149
150
        $this->action = $action;
151
    }
152
153
    /**
154
     * Get the action.
155
     *
156
     * @return string The action
157
     */
158
    public function getAction()
159
    {
160
        return $this->action;
161
    }
162
163
    /**
164
     * @return Widget
165
     */
166
    public function getWidget()
167
    {
168
        return $this->widget;
169
    }
170
171
    /**
172
     * @param Widget $widget
173
     *
174
     * @return $this
175
     */
176
    public function setWidget(Widget $widget)
177
    {
178
        $this->widget = $widget;
179
180
        return $this;
181
    }
182
183
    /**
184
     * @return View
185
     */
186
    public function getView()
187
    {
188
        return $this->view;
189
    }
190
191
    /**
192
     * @param View $view
193
     */
194
    public function setView(View $view)
195
    {
196
        $this->view = $view;
197
    }
198
199
    /**
200
     * @return mixed
201
     */
202
    public function getReplaced()
203
    {
204
        return $this->replaced;
205
    }
206
207
    /**
208
     * @param mixed $replaced
209
     */
210
    public function setReplaced($replaced)
211
    {
212
        if ($replaced) {
213
            $replaced->addSubstitute($this);
214
        }
215
        $this->replaced = $replaced;
216
    }
217
218
    /**
219
     * @return string
220
     */
221
    public function getSlot()
222
    {
223
        return $this->slot;
224
    }
225
226
    /**
227
     * @param string $slot
228
     */
229
    public function setSlot($slot)
230
    {
231
        $this->slot = $slot;
232
    }
233
234
    /**
235
     * @return mixed
236
     */
237
    public function getChildren(View $view = null)
238
    {
239
        $positions = [self::POSITION_BEFORE, self::POSITION_AFTER];
240
        $children = [];
241
        $widgetMap = $this;
242
        foreach ($positions as $position) {
243
            $children[$position] = null;
244
            if (($childs = $widgetMap->getChilds($position)) && !empty($childs)) {
245 View Code Duplication
                foreach ($childs as $_child) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
246
                    // found child must belongs to the given view or one of it's templates
247
                    if ($view) {
248
                        // if child has a view
249
                        // and child view is same as given view or the child view is a template of given view
250
                        if ($_child->getView() && ($view == $_child->getView() || $_child->getView()->isTemplateOf($view))
251
                        ) {
252
                            // if child is a substitute in view
253
                            if ($substitute = $_child->getSubstituteForView($view)) {
254
                                // if i'm not the parent of the substitute or i does not have the same position, child is not valid
255
                                if ($substitute->getParent() != $this || $substitute->getPosition() != $position) {
256
                                    $_child = null;
257
                                }
258
                            }
259
                            $children[$position] = $_child;
260
                        }
261
                    } else {
262
                        $children[$position] = $_child;
263
                    }
264
                }
265
            }
266
267
            if (!$children[$position]
268
                && ($replaced = $this->getReplaced())
269
                && !empty($this->getReplaced()->getChilds($position))) {
270 View Code Duplication
                foreach ($this->getReplaced()->getChilds($position) as $_child) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
271
                    if ($view) {
272
                        if ($_child->getView() && ($view == $_child->getView() || $_child->getView()->isTemplateOf($view))) {
273
274
                            // if child is a substitute in view
275
                            if ($substitute = $_child->getSubstituteForView($view)) {
276
                                // if i'm not the parent of the substitute or i does not have the same position, child is not valid
277
                                if ($substitute->getParent() != $this || $substitute->getPosition() != $position) {
278
                                    $_child = null;
279
                                }
280
                            }
281
                            $children[$position] = $_child;
282
                        }
283
                    } else {
284
                        $children[$position] = $_child;
285
                    }
286
                }
287
            }
288
        }
289
290
        return $children;
291
    }
292
293
    /**
294
     * @return mixed
295
     */
296
    public function getChildrenRaw()
297
    {
298
        return $this->children;
299
    }
300
301
    public function hasChild($position, View $view = null)
302
    {
303
        foreach ($this->getChildren($view) as $child) {
304
            if ($child && $child->getPosition() === $position) {
305
                return true;
306
            }
307
        }
308
309
        return false;
310
    }
311
312
    /**
313
     * @return WidgetMap|null
314
     */
315
    public function getChild($position)
316
    {
317
        $child = null;
318
        foreach ($this->children as $_child) {
319
            if ($_child && $_child->getPosition() == $position) {
320
                $child = $_child;
321
            }
322
        }
323
324
        return $child;
325
    }
326
327
    /**
328
     * @return [WidgetMap]
0 ignored issues
show
Documentation introduced by
The doc-type [WidgetMap] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
329
     */
330
    public function getChilds($position)
331
    {
332
        $childs = [];
333
        foreach ($this->children as $_child) {
334
            if ($_child && $_child->getPosition() == $position) {
335
                $childs[] = $_child;
336
            }
337
        }
338
339
        return $childs;
340
    }
341
342
    /**
343
     * @param mixed $children
344
     */
345
    public function setChildren($children)
346
    {
347
        $this->children = $children;
348
    }
349
350
    /**
351
     * @return void
352
     */
353
    public function removeChildren()
354
    {
355
        foreach ($this->children as $child) {
356
            $this->removeChild($child);
357
        }
358
    }
359
360
    /**
361
     * @param WidgetMap $child
362
     */
363
    public function addChild($child)
364
    {
365
        $this->children->add($child);
366
    }
367
368
    /**
369
     * @param WidgetMap $child
370
     */
371
    public function removeChild($child)
372
    {
373
        $this->children->removeElement($child);
374
    }
375
376
    /**
377
     * @return WidgetMap|null
378
     */
379
    public function getParent()
380
    {
381
        return $this->parent;
382
    }
383
384
    /**
385
     * @param mixed $parent
386
     */
387
    public function setParent(WidgetMap $parent = null)
388
    {
389
        if ($this->parent) {
390
            $this->parent->removeChild($this);
391
        }
392
        if ($parent) {
393
            $parent->addChild($this);
394
        }
395
        $this->parent = $parent;
396
    }
397
398
    /**
399
     * @return string
400
     */
401
    public function getPosition()
402
    {
403
        return $this->position;
404
    }
405
406
    /**
407
     * @param string $position
408
     */
409
    public function setPosition($position)
410
    {
411
        $this->position = $position;
412
    }
413
414
    /**
415
     * @return mixed
416
     */
417
    public function getSubstitutes()
418
    {
419
        return $this->substitutes;
420
    }
421
422
    /**
423
     * @return mixed
424
     */
425
    public function getSubstituteForView(View $view)
426
    {
427
        foreach ($this->substitutes as $substitute) {
428
            if ($substitute->getView() == $view) {
429
                return $substitute;
430
            }
431
        }
432
433
        return;
434
    }
435
436
    /**
437
     * @param WidgetMap $substitute
438
     */
439
    public function addSubstitute(WidgetMap $substitute)
440
    {
441
        $this->substitutes->add($substitute);
442
    }
443
444
    /**
445
     * @param [WidgetMap] $substitutes
0 ignored issues
show
Documentation introduced by
The doc-type [WidgetMap] could not be parsed: Unknown type name "" at position 0. [(view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
446
     */
447
    public function setSubstitutes($substitutes)
448
    {
449
        $this->substitutes = $substitutes;
450
    }
451
}
452