Page   B
last analyzed

Complexity

Total Complexity 45

Size/Duplication

Total Lines 498
Duplicated Lines 8.84 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 0
Metric Value
wmc 45
lcom 1
cbo 4
dl 44
loc 498
rs 8.3673
c 0
b 0
f 0

38 Methods

Rating   Name   Duplication   Size   Complexity  
A getSlug() 0 4 1
A getContent() 0 4 1
A getMetaDescription() 0 4 1
A getMetaTitle() 0 4 1
A getMetaKeywords() 0 4 1
A getCategory() 0 4 1
A getCss() 0 4 1
A getJs() 0 4 1
A isHomepage() 0 4 1
A getHost() 0 4 1
A getTree() 12 12 2
A getParent() 0 4 1
getId() 0 1 ?
A __toString() 0 4 1
A __construct() 0 5 1
A getTitle() 0 4 1
A setTitle() 0 6 1
A setSlug() 0 6 1
A setContent() 0 6 1
A setMetaDescription() 0 6 1
A setMetaTitle() 0 6 1
A setMetaKeywords() 0 6 1
A setCategory() 0 6 1
A setCss() 0 6 1
A setJs() 0 6 1
A getCreatedAt() 0 4 1
A isEnabled() 0 4 1
A setEnabled() 0 6 1
A setParent() 18 18 4
A getChildren() 0 4 1
A addChild() 0 10 2
A removeChild() 0 6 1
A setHomepage() 0 6 1
A setHost() 0 6 1
A getLocale() 0 4 1
A setLocale() 0 6 1
A updateSlug() 0 6 2
A onRemove() 14 14 3

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

1
<?php
2
3
/*
4
* This file is part of the OrbitaleCmsBundle package.
5
*
6
* (c) Alexandre Rock Ancelet <[email protected]>
7
*
8
* For the full copyright and license information, please view the LICENSE
9
* file that was distributed with this source code.
10
*/
11
12
namespace Orbitale\Bundle\CmsBundle\Entity;
13
14
use Behat\Transliterator\Transliterator;
15
use Doctrine\Common\Collections\ArrayCollection;
16
use Doctrine\ORM\Event\LifecycleEventArgs;
17
use Doctrine\ORM\Mapping as ORM;
18
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
19
20
/**
21
 * @UniqueEntity("slug")
22
 * @ORM\HasLifecycleCallbacks()
23
 * @ORM\MappedSuperclass(repositoryClass="Orbitale\Bundle\CmsBundle\Repository\PageRepository")
24
 */
25
abstract class Page
26
{
27
    /**
28
     * @return int|string
29
     */
30
    abstract public function getId();
31
32
    /**
33
     * @var string
34
     * @ORM\Column(name="title", type="string", length=255)
35
     */
36
    protected $title;
37
38
    /**
39
     * @var string
40
     * @ORM\Column(name="slug", type="string", length=255, unique=true)
41
     */
42
    protected $slug;
43
44
    /**
45
     * @var string
46
     * @ORM\Column(name="page_content", type="text", nullable=true)
47
     */
48
    protected $content;
49
50
    /**
51
     * @var string
52
     * @ORM\Column(name="meta_description", type="string", length=255, nullable=true)
53
     */
54
    protected $metaDescription;
55
56
    /**
57
     * @var string
58
     * @ORM\Column(name="meta_title", type="string", length=255, nullable=true)
59
     */
60
    protected $metaTitle;
61
62
    /**
63
     * @var string
64
     * @ORM\Column(name="meta_keywords", type="string", length=255, nullable=true)
65
     */
66
    protected $metaKeywords;
67
68
    /**
69
     * @var Category
70
     */
71
    protected $category;
72
73
    /**
74
     * @var string
75
     * @ORM\Column(name="css", type="text", nullable=true)
76
     */
77
    protected $css;
78
79
    /**
80
     * @var string
81
     * @ORM\Column(name="js", type="text", nullable=true)
82
     */
83
    protected $js;
84
85
    /**
86
     * @var \DateTime
87
     *
88
     * @ORM\Column(name="created_at", type="datetime")
89
     */
90
    protected $createdAt;
91
92
    /**
93
     * @var bool
94
     * @ORM\Column(name="enabled", type="boolean")
95
     */
96
    protected $enabled = false;
97
98
    /**
99
     * @var bool
100
     * @ORM\Column(name="homepage", type="boolean")
101
     */
102
    protected $homepage = false;
103
104
    /**
105
     * @var string
106
     * @ORM\Column(name="host", type="string", length=255, nullable=true)
107
     */
108
    protected $host;
109
110
    /**
111
     * @var string
112
     * @ORM\Column(name="locale", type="string", length=6, nullable=true)
113
     */
114
    protected $locale;
115
116
    /**
117
     * @var Page
118
     */
119
    protected $parent;
120
121
    /**
122
     * @var Page[]|ArrayCollection
123
     */
124
    protected $children;
125
126
    public function __toString()
127
    {
128
        return $this->title;
129
    }
130
131
    public function __construct()
132
    {
133
        $this->createdAt = new \DateTime();
134
        $this->children  = new ArrayCollection();
135
    }
136
137
    /**
138
     * @return string
139
     */
140
    public function getTitle()
141
    {
142
        return $this->title;
143
    }
144
145
    /**
146
     * @param string $title
147
     *
148
     * @return Page
149
     */
150
    public function setTitle(string $title): Page
151
    {
152
        $this->title = $title;
153
154
        return $this;
155
    }
156
157
    /**
158
     * @return string
159
     */
160
    public function getSlug()
161
    {
162
        return $this->slug;
163
    }
164
165
    /**
166
     * @param string $slug
167
     *
168
     * @return Page
169
     */
170
    public function setSlug(string $slug): Page
171
    {
172
        $this->slug = $slug;
173
174
        return $this;
175
    }
176
177
    /**
178
     * @return string
179
     */
180
    public function getContent()
181
    {
182
        return $this->content;
183
    }
184
185
    /**
186
     * @param string $content
0 ignored issues
show
Documentation introduced by
Should the type for parameter $content not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
187
     *
188
     * @return Page
189
     */
190
    public function setContent(string $content = null): Page
191
    {
192
        $this->content = $content;
193
194
        return $this;
195
    }
196
197
    /**
198
     * @return string
199
     */
200
    public function getMetaDescription()
201
    {
202
        return $this->metaDescription;
203
    }
204
205
    /**
206
     * @param string $metaDescription
0 ignored issues
show
Documentation introduced by
Should the type for parameter $metaDescription not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
207
     *
208
     * @return Page
209
     */
210
    public function setMetaDescription(string $metaDescription = null): Page
211
    {
212
        $this->metaDescription = $metaDescription;
213
214
        return $this;
215
    }
216
217
    /**
218
     * @return string
219
     */
220
    public function getMetaTitle()
221
    {
222
        return $this->metaTitle;
223
    }
224
225
    /**
226
     * @param string $metaTitle
0 ignored issues
show
Documentation introduced by
Should the type for parameter $metaTitle not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
227
     *
228
     * @return Page
229
     */
230
    public function setMetaTitle(string $metaTitle = null): Page
231
    {
232
        $this->metaTitle = $metaTitle;
233
234
        return $this;
235
    }
236
237
    /**
238
     * @return string
239
     */
240
    public function getMetaKeywords()
241
    {
242
        return $this->metaKeywords;
243
    }
244
245
    /**
246
     * @param string $metaKeywords
0 ignored issues
show
Documentation introduced by
Should the type for parameter $metaKeywords not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
247
     *
248
     * @return Page
249
     */
250
    public function setMetaKeywords(string $metaKeywords = null): Page
251
    {
252
        $this->metaKeywords = $metaKeywords;
253
254
        return $this;
255
    }
256
257
    /**
258
     * @return Category
259
     */
260
    public function getCategory()
261
    {
262
        return $this->category;
263
    }
264
265
    /**
266
     * @param Category $category
0 ignored issues
show
Documentation introduced by
Should the type for parameter $category not be null|Category?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
267
     *
268
     * @return Page
269
     */
270
    public function setCategory(Category $category = null): Page
271
    {
272
        $this->category = $category;
273
274
        return $this;
275
    }
276
277
    /**
278
     * @return string
279
     */
280
    public function getCss()
281
    {
282
        return $this->css;
283
    }
284
285
    /**
286
     * @param string $css
0 ignored issues
show
Documentation introduced by
Should the type for parameter $css not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
287
     *
288
     * @return Page
289
     */
290
    public function setCss(string $css = null): Page
291
    {
292
        $this->css = $css;
293
294
        return $this;
295
    }
296
297
    /**
298
     * @return string
299
     */
300
    public function getJs()
301
    {
302
        return $this->js;
303
    }
304
305
    /**
306
     * @param string $js
0 ignored issues
show
Documentation introduced by
Should the type for parameter $js not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
307
     *
308
     * @return Page
309
     */
310
    public function setJs(string $js = null): Page
311
    {
312
        $this->js = $js;
313
314
        return $this;
315
    }
316
317
    /**
318
     * @return \DateTime
319
     */
320
    public function getCreatedAt(): \DateTime
321
    {
322
        return $this->createdAt;
323
    }
324
325
    /**
326
     * @return bool
327
     */
328
    public function isEnabled(): bool
329
    {
330
        return $this->enabled;
331
    }
332
333
    /**
334
     * @param bool $enabled
335
     *
336
     * @return Page
337
     */
338
    public function setEnabled(bool $enabled): Page
339
    {
340
        $this->enabled = $enabled;
341
342
        return $this;
343
    }
344
345
    /**
346
     * @return Page
347
     */
348
    public function getParent()
349
    {
350
        return $this->parent;
351
    }
352
353
    /**
354
     * @param Page|null $parent
355
     *
356
     * @return Page
357
     */
358 View Code Duplication
    public function setParent(Page $parent = null): Page
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
359
    {
360
        if ($parent === $this) {
361
            // Refuse the category to have itself as parent.
362
            $this->parent = null;
363
364
            return $this;
365
        }
366
367
        $this->parent = $parent;
368
369
        // Ensure bidirectional relation is respected.
370
        if ($parent && false === $parent->getChildren()->indexOf($this)) {
371
            $parent->addChild($this);
372
        }
373
374
        return $this;
375
    }
376
377
378
    /**
379
     * @return Page[]|ArrayCollection
380
     */
381
    public function getChildren()
382
    {
383
        return $this->children;
384
    }
385
386
    /**
387
     * @param Page $page
388
     *
389
     * @return Page
390
     */
391
    public function addChild(Page $page): Page
392
    {
393
        $this->children->add($page);
394
395
        if ($page->getParent() !== $this) {
396
            $page->setParent($this);
397
        }
398
399
        return $this;
400
    }
401
402
    /**
403
     * @param Page $page
404
     *
405
     * @return Page
406
     */
407
    public function removeChild(Page $page): Page
408
    {
409
        $this->children->removeElement($page);
410
411
        return $this;
412
    }
413
414
    /**
415
     * @return bool
416
     */
417
    public function isHomepage(): bool
418
    {
419
        return $this->homepage;
420
    }
421
422
    /**
423
     * @param bool $homepage
424
     *
425
     * @return Page
426
     */
427
    public function setHomepage(bool $homepage): Page
428
    {
429
        $this->homepage = $homepage;
430
431
        return $this;
432
    }
433
434
    /**
435
     * @return string
436
     */
437
    public function getHost()
438
    {
439
        return $this->host;
440
    }
441
442
    /**
443
     * @param string $host
0 ignored issues
show
Documentation introduced by
Should the type for parameter $host not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
444
     *
445
     * @return Page
446
     */
447
    public function setHost(string $host = null): Page
448
    {
449
        $this->host = $host;
450
451
        return $this;
452
    }
453
454
    /**
455
     * @return string
456
     */
457
    public function getLocale()
458
    {
459
        return $this->locale;
460
    }
461
462
    /**
463
     * @param string $locale
0 ignored issues
show
Documentation introduced by
Should the type for parameter $locale not be null|string?

This check looks for @param annotations where the type inferred by our type inference engine differs from the declared type.

It makes a suggestion as to what type it considers more descriptive.

Most often this is a case of a parameter that can be null in addition to its declared types.

Loading history...
464
     *
465
     * @return Page
466
     */
467
    public function setLocale(string $locale = null): Page
468
    {
469
        $this->locale = $locale;
470
471
        return $this;
472
    }
473
474
    /**
475
     * @param string $separator
476
     *
477
     * @return string
478
     */
479 View Code Duplication
    public function getTree(string $separator = '/')
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
480
    {
481
        $tree = '';
482
483
        $current = $this;
484
        do {
485
            $tree    = $current->getSlug().$separator.$tree;
486
            $current = $current->getParent();
487
        } while ($current);
488
489
        return trim($tree, $separator);
490
    }
491
492
    /**
493
     * @ORM\PrePersist()
494
     * @ORM\PreUpdate()
495
     */
496
    public function updateSlug()
497
    {
498
        if (!$this->slug) {
499
            $this->slug = Transliterator::transliterate($this->title);
500
        }
501
    }
502
503
    /**
504
     * @ORM\PreRemove()
505
     *
506
     * @param LifecycleEventArgs $event
507
     */
508 View Code Duplication
    public function onRemove(LifecycleEventArgs $event)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in 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...
509
    {
510
        $em = $event->getEntityManager();
511
        if (count($this->children)) {
512
            foreach ($this->children as $child) {
513
                $child->setParent(null);
514
                $em->persist($child);
515
            }
516
        }
517
        $this->enabled = false;
518
        $this->parent  = null;
519
        $this->title .= '-'.$this->getId().'-deleted';
520
        $this->slug .= '-'.$this->getId().'-deleted';
521
    }
522
}
523