Completed
Push — master ( 0b2e6b...2c86a7 )
by Paul
49:42 queued 39:17
created

Widget   C

Complexity

Total Complexity 53

Size/Duplication

Total Lines 544
Duplicated Lines 0 %

Coupling/Cohesion

Components 6
Dependencies 9

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 53
lcom 6
cbo 9
dl 0
loc 544
rs 6.6956
c 2
b 0
f 0

38 Methods

Rating   Name   Duplication   Size   Complexity  
A isAsynchronous() 0 4 1
A setAsynchronous() 0 4 1
A setEntityProxy() 0 4 1
A getEntityProxy() 0 4 1
A __toString() 0 4 1
A getId() 0 4 1
A __construct() 0 5 1
A setFields() 0 11 3
A getFields() 0 4 1
A setId() 0 4 1
A setSlot() 0 6 1
A getSlot() 0 4 1
A setTheme() 0 6 1
A getTheme() 0 4 1
A getValue() 0 4 1
A getType() 0 4 1
A guessType() 0 6 1
A setMode() 0 4 1
A getMode() 0 4 1
A getViewId() 0 12 2
A getChildrenSlot() 0 4 2
A setChildrenSlot() 0 4 1
A setWidgetMap() 0 7 1
A getWidgetMap() 0 4 1
A setEntity() 0 4 1
A getEntity() 0 16 4
A __clone() 0 16 3
A getView() 0 4 1
A getCriterias() 0 4 1
A setCriterias() 0 4 1
A addCriteria() 0 5 1
A removeCriteria() 0 5 1
A hasCriteria() 0 4 1
A hasCriteriaNamed() 0 6 1
A getQuantum() 0 4 1
A setQuantum() 0 4 1
A generateCacheId() 0 20 3
B getLocale() 0 12 5

How to fix   Complexity   

Complex Class

Complex classes like Widget 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 Widget, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Victoire\Bundle\WidgetBundle\Entity;
4
5
use Doctrine\Common\Collections\ArrayCollection;
6
use Doctrine\ORM\Mapping as ORM;
7
use Gedmo\Timestampable\Traits\TimestampableEntity;
8
use Victoire\Bundle\CoreBundle\Entity\BaseEntityProxy;
9
use Victoire\Bundle\CriteriaBundle\Entity\Criteria;
10
use Victoire\Bundle\QueryBundle\Entity\QueryTrait;
11
use Victoire\Bundle\QueryBundle\Entity\VictoireQueryInterface;
12
use Victoire\Bundle\WidgetBundle\Entity\Traits\StyleTrait;
13
use Victoire\Bundle\WidgetBundle\Model\Widget as BaseWidget;
14
use Victoire\Bundle\WidgetMapBundle\Entity\WidgetMap;
15
16
/**
17
 * Widget.
18
 *
19
 * @ORM\Table("vic_widget")
20
 * @ORM\Entity(repositoryClass="Victoire\Bundle\WidgetBundle\Repository\WidgetRepository")
21
 * @ORM\InheritanceType("JOINED")
22
 * @ORM\DiscriminatorColumn(name="type", type="string")
23
 */
24
class Widget extends BaseWidget implements VictoireQueryInterface
25
{
26
    use StyleTrait;
27
    use QueryTrait;
28
    use TimestampableEntity;
29
30
    public function __construct()
31
    {
32
        $this->childrenSlot = uniqid();
33
        $this->criterias = new ArrayCollection();
34
    }
35
36
    /**
37
     * @var int
38
     *
39
     * @ORM\Column(name="id", type="integer")
40
     * @ORM\Id
41
     * @ORM\GeneratedValue(strategy="AUTO")
42
     */
43
    protected $id;
44
45
    /**
46
     * @var string
47
     *
48
     * @ORM\Column(name="slot", type="string", length=255, nullable=true)
49
     */
50
    protected $slot;
51
52
    /**
53
     * @var string
54
     *
55
     * @ORM\Column(name="childrenSlot", type="string", length=100, nullable=true)
56
     */
57
    protected $childrenSlot;
58
59
    /**
60
     * @var string
61
     *
62
     * @ORM\Column(name="theme", type="string", length=255, nullable=true)
63
     */
64
    protected $theme;
65
66
    /**
67
     * @var string
68
     *
69
     * @ORM\Column(name="asynchronous", type="boolean", nullable=true)
70
     */
71
    protected $asynchronous;
72
73
    /**
74
     * @var string
75
     *
76
     * @ORM\Column(name="fields", type="text")
77
     */
78
    protected $fields = 'a:0:{}';
79
80
    /**
81
     * @var string
82
     *
83
     * @ORM\Column(name="mode", type="string", length=255, nullable=false)
84
     */
85
    protected $mode = self::MODE_STATIC;
86
87
    /**
88
     * Auto simple mode: joined entity.
89
     *
90
     * @var EntityProxy
91
     *
92
     * @ORM\ManyToOne(targetEntity="\Victoire\Bundle\CoreBundle\Entity\EntityProxy", inversedBy="widgets", cascade={"persist"})
93
     * @ORM\JoinColumn(name="entityProxy_id", referencedColumnName="id", onDelete="CASCADE")
94
     */
95
    protected $entityProxy;
96
97
    /**
98
     * The entity linked to the widget.
99
     *
100
     * @var unknown
101
     */
102
    protected $entity;
103
104
    /**
105
     * @deprecated
106
     *
107
     * @var string
108
     *
109
     * @ORM\ManyToOne(targetEntity="\Victoire\Bundle\CoreBundle\Entity\View", inversedBy="widgets", cascade={"persist"})
110
     * @ORM\JoinColumn(name="view_id", referencedColumnName="id", onDelete="CASCADE")
111
     */
112
    protected $view;
113
    /**
114
     * @var WidgetMap
115
     *
116
     * @ORM\ManyToOne(targetEntity="\Victoire\Bundle\WidgetMapBundle\Entity\WidgetMap", inversedBy="widgets")
117
     * @ORM\JoinColumn(name="widget_map_id", referencedColumnName="id", onDelete="SET NULL"))
118
     */
119
    protected $widgetMap;
120
121
    /**
122
     * @var [Criteria]
123
     *
124
     * @ORM\OneToMany(targetEntity="\Victoire\Bundle\CriteriaBundle\Entity\Criteria", mappedBy="widget", cascade={"persist", "remove"}, orphanRemoval=true)
125
     */
126
    protected $criterias;
127
128
    /**
129
     * @var string
130
     *
131
     * @ORM\Column(name="quantum", type="string", length=255, nullable=true)
132
     */
133
    protected $quantum;
134
135
    /**
136
     * @return string
137
     */
138
    public function isAsynchronous()
139
    {
140
        return $this->asynchronous;
141
    }
142
143
    /**
144
     * @param string $asynchronous
145
     */
146
    public function setAsynchronous($asynchronous)
147
    {
148
        $this->asynchronous = $asynchronous;
149
    }
150
151
    /**
152
     * Set the entity proxy.
153
     *
154
     * @param BaseEntityProxy $entityProxy
155
     */
156
    public function setEntityProxy(BaseEntityProxy $entityProxy)
157
    {
158
        $this->entityProxy = $entityProxy;
0 ignored issues
show
Documentation Bug introduced by
It seems like $entityProxy of type object<Victoire\Bundle\C...Entity\BaseEntityProxy> is incompatible with the declared type object<Victoire\Bundle\W...dle\Entity\EntityProxy> of property $entityProxy.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
159
    }
160
161
    /**
162
     * Get the entity proxy.
163
     *
164
     * @return EntityProxy
165
     */
166
    public function getEntityProxy()
167
    {
168
        return $this->entityProxy;
169
    }
170
171
    /**
172
     * to string.
173
     *
174
     * @return string
175
     */
176
    public function __toString()
177
    {
178
        return (string) $this->getId();
179
    }
180
181
    /**
182
     * Get id.
183
     *
184
     * @return int
185
     */
186
    public function getId()
187
    {
188
        return $this->id;
189
    }
190
191
    /**
192
     * Set fields.
193
     *
194
     * @param string $fields
195
     *
196
     * @return Widget
197
     */
198
    public function setFields($fields)
199
    {
200
        $data = @unserialize($fields);
201
        if ($fields === 'b:0;' || $data !== false) {
202
            $this->fields = $fields;
203
        } else {
204
            $this->fields = serialize($fields);
205
        }
206
207
        return $this;
208
    }
209
210
    /**
211
     * Get fields.
212
     *
213
     * @return string
214
     */
215
    public function getFields()
216
    {
217
        return unserialize($this->fields);
218
    }
219
220
    /**
221
     * Set The Id.
222
     *
223
     * @param int $id The id
224
     */
225
    public function setId($id)
226
    {
227
        $this->id = $id;
228
    }
229
230
    /**
231
     * Set slot.
232
     *
233
     * @param string $slot
234
     *
235
     * @return Widget
236
     */
237
    public function setSlot($slot)
238
    {
239
        $this->slot = $slot;
240
241
        return $this;
242
    }
243
244
    /**
245
     * Get slot.
246
     *
247
     * @return string
248
     */
249
    public function getSlot()
250
    {
251
        return $this->slot;
252
    }
253
254
    /**
255
     * Set theme.
256
     *
257
     * @param string $theme
258
     *
259
     * @return Widget
260
     */
261
    public function setTheme($theme)
262
    {
263
        $this->theme = $theme;
264
265
        return $this;
266
    }
267
268
    /**
269
     * Get theme.
270
     *
271
     * @return string
272
     */
273
    public function getTheme()
274
    {
275
        return $this->theme;
276
    }
277
278
    /**
279
     * Get the content.
280
     *
281
     * @return unknown
282
     */
283
    public function getValue()
284
    {
285
        //return $this->getContent();
0 ignored issues
show
Unused Code Comprehensibility introduced by
75% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
286
    }
287
288
    /**
289
     * Get the type of the object.
290
     *
291
     * @return string The type
292
     */
293
    public function getType()
294
    {
295
        return $this->guessType();
296
    }
297
298
    /**
299
     * Guess the type of this by exploding and getting the last item.
300
     *
301
     * @return string The guessed type
302
     */
303
    protected function guessType()
304
    {
305
        $type = explode('\\', get_class($this));
306
307
        return strtolower(preg_replace('/Widget/', '', end($type)));
308
    }
309
310
    /**
311
     * Set the mode.
312
     *
313
     * @param string $mode
314
     */
315
    public function setMode($mode)
316
    {
317
        $this->mode = $mode;
318
    }
319
320
    /**
321
     * Get the mode.
322
     *
323
     * @return string
324
     */
325
    public function getMode()
326
    {
327
        return $this->mode;
328
    }
329
330
    /**
331
     * Get the view id.
332
     *
333
     * @return int The view id
334
     */
335
    public function getViewId()
336
    {
337
        $viewId = null;
338
339
        $view = $this->getView();
0 ignored issues
show
Deprecated Code introduced by
The method Victoire\Bundle\WidgetBu...ntity\Widget::getView() has been deprecated with message: Get view.

This method has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the method will be removed from the class and what other method or class to use instead.

Loading history...
340
341
        if ($view !== null) {
342
            $viewId = $view->getId();
0 ignored issues
show
Bug introduced by
The method getId cannot be called on $view (of type string).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
343
        }
344
345
        return $viewId;
346
    }
347
348
    /**
349
     * @return string
350
     */
351
    public function getChildrenSlot()
352
    {
353
        return $this->childrenSlot ?: $this->getId();
354
    }
355
356
    /**
357
     * @param string $childrenSlot
358
     */
359
    public function setChildrenSlot($childrenSlot)
360
    {
361
        $this->childrenSlot = $childrenSlot;
362
    }
363
364
    /**
365
     * Set widgets.
366
     *
367
     * @param [WidgetMap] $widgetMaps
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...
Documentation introduced by
There is no parameter named $widgetMaps. Did you maybe mean $widgetMap?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function. It has, however, found a similar but not annotated parameter which might be a good fit.

Consider the following example. The parameter $ireland is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $ireland
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was changed, but the annotation was not.

Loading history...
368
     *
369
     * @return Widget
370
     */
371
    public function setWidgetMap(WidgetMap $widgetMap)
372
    {
373
        $this->widgetMap = $widgetMap;
374
        $widgetMap->addWidget($this);
375
376
        return $this;
377
    }
378
379
    /**
380
     * Get widgets.
381
     *
382
     * @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...
383
     */
384
    public function getWidgetMap()
385
    {
386
        return $this->widgetMap;
387
    }
388
389
    /**
390
     * Set the entity.
391
     *
392
     * @param object $entity
393
     */
394
    public function setEntity($entity)
395
    {
396
        $this->entity = $entity;
397
    }
398
399
    /**
400
     * Get the entity.
401
     *
402
     * @return number
403
     */
404
    public function getEntity()
405
    {
406
        //if there is no entity
407
        if ($this->entity === null) {
408
            //we try to get one from the proxy
409
            $entityProxy = $this->getEntityProxy();
410
411
            //if there is a proxy
412
            if ($entityProxy !== null && $this->getBusinessEntityId()) {
413
                $entity = $entityProxy->getEntity($this->getBusinessEntityId());
414
                $this->entity = $entity;
415
            }
416
        }
417
418
        return $this->entity;
419
    }
420
421
    /**
422
     * Clone a widget.
423
     */
424
    public function __clone()
425
    {
426
        // if there is a proxy
427
        if ($this->entityProxy) {
428
            // we clone this one
429
            $this->entityProxy = clone $this->entityProxy;
430
        }
431
432
        // This check should be in the __constructor, but Doctrine does not use __constructor to
433
        // instanciate entites but __clone method.
434
        if (property_exists(get_called_class(), 'widget')) {
435
            throw new \Exception(sprintf('A property $widget was found in %s object.
436
                The $widget property is reserved for Victoire.
437
                You should chose a different property name.', get_called_class()));
438
        }
439
    }
440
441
    /**
442
     * @deprecated
443
     * Get view.
444
     *
445
     * @return string
446
     */
447
    public function getView()
448
    {
449
        return $this->view;
0 ignored issues
show
Deprecated Code introduced by
The property Victoire\Bundle\WidgetBundle\Entity\Widget::$view has been deprecated.

This property has been deprecated. The supplier of the class has supplied an explanatory message.

The explanatory message should give you some clue as to whether and when the property will be removed from the class and what other property to use instead.

Loading history...
450
    }
451
452
    /**
453
     * @return [Criteria]
0 ignored issues
show
Documentation introduced by
The doc-type [Criteria] 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...
454
     */
455
    public function getCriterias()
456
    {
457
        return $this->criterias;
458
    }
459
460
    /**
461
     * @param [Criteria] $criterias
0 ignored issues
show
Documentation introduced by
The doc-type [Criteria] 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...
462
     */
463
    public function setCriterias($criterias)
464
    {
465
        $this->criterias = $criterias;
466
    }
467
468
    /**
469
     * @param Criteria $criteria
470
     */
471
    public function addCriteria($criteria)
472
    {
473
        $criteria->setWidget($this);
474
        $this->criterias[] = $criteria;
475
    }
476
477
    /**
478
     * @param Criteria $criteria
479
     */
480
    public function removeCriteria(Criteria $criteria)
481
    {
482
        $criteria->setWidget(null);
0 ignored issues
show
Documentation introduced by
null is of type null, but the function expects a object<Victoire\Bundle\W...etBundle\Entity\Widget>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
483
        $this->criterias->removeElement($criteria);
484
    }
485
486
    /**
487
     * @param Criteria $criteria
488
     *
489
     * @return bool
490
     */
491
    public function hasCriteria(Criteria $criteria)
492
    {
493
        return $this->criterias->contains($criteria);
494
    }
495
496
    /**
497
     * @param $criteriaAlias
498
     *
499
     * @return bool
500
     */
501
    public function hasCriteriaNamed($criteriaAlias)
502
    {
503
        return $this->criterias->exists(function ($key, $element) use ($criteriaAlias) {
504
            return $criteriaAlias === $element->getName();
505
        });
506
    }
507
508
    /**
509
     * @return string
510
     */
511
    public function getQuantum()
512
    {
513
        return $this->quantum;
514
    }
515
516
    /**
517
     * @param string $quantum
518
     */
519
    public function setQuantum($quantum)
520
    {
521
        $this->quantum = $quantum;
522
    }
523
524
    /**
525
     * Generate the CacheId, insert params that can invalid the cache.
526
     *
527
     * @return string
528
     */
529
    public function generateCacheId()
530
    {
531
        if (!$this->getCurrentView()) {
532
            throw new \Exception(sprintf('Cannot generate an hash for widget %s if currentView is not defined.',
533
                $this->getId()
534
            ));
535
            if (!$this->getCurrentView()->getReference()) {
0 ignored issues
show
Unused Code introduced by
if (!$this->getCurrentVi...entView()->getId())); } does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
536
                throw new \Exception(sprintf('Cannot generate an hash for widget %s if currentView %s Reference is not defined.',
537
                    $this->getId(),
538
                    $widget->getCurrentView()->getId()
539
                ));
540
            }
541
        }
542
543
        return sprintf('%s-%s-%s',
544
            $this->getId(),
545
            $this->getUpdatedAt()->getTimestamp(),
546
            $this->getCurrentView()->getReference()->getId()
547
        );
548
    }
549
550
    /**
551
     * @param $defaultLocale
552
     *
553
     * @return mixed
554
     */
555
    public function getLocale($defaultLocale)
556
    {
557
        if ($this->hasCriteriaNamed('locale')) {
558
            foreach ($this->getCriterias() as $criteria) {
559
                if ($criteria->getName() === 'locale' &&  $criteria->getValue() === $defaultLocale) {
560
                    return $criteria->getValue();
561
                }
562
            }
563
        }
564
565
        return $defaultLocale;
566
    }
567
}
568