Completed
Push — master ( f38c14...74727a )
by ARCANEDEV
8s
created

SitemapManager::generate()   D

Complexity

Conditions 9
Paths 64

Size

Total Lines 39
Code Lines 25

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 39
cc 9
eloc 25
nc 64
nop 2
ccs 0
cts 29
cp 0
crap 90
rs 4.909
1
<?php namespace Arcanedev\LaravelSitemap;
2
3
use Arcanedev\LaravelSitemap\Contracts\SitemapGenerator;
4
use Arcanedev\LaravelSitemap\Contracts\SitemapManager as SitemapManagerContract;
5
use Arcanedev\LaravelSitemap\Contracts\SitemapStyler;
6
use Illuminate\Contracts\Cache\Repository as Cache;
7
use Illuminate\Contracts\Config\Repository as Config;
8
use Illuminate\Filesystem\Filesystem as Filesystem;
9
10
/**
11
 * Class     SitemapManager
12
 *
13
 * @package  Arcanedev\LaravelSitemap
14
 * @author   ARCANEDEV <[email protected]>
15
 */
16
class SitemapManager implements SitemapManagerContract
17
{
18
    /* ------------------------------------------------------------------------------------------------
19
     |  Properties
20
     | ------------------------------------------------------------------------------------------------
21
     */
22
    /**
23
     * @var array
24
     */
25
    protected $sitemaps = [];
26
27
    /**
28
     * @var string
29
     */
30
    protected $title = null;
31
32
    /**
33
     * @var string
34
     */
35
    protected $link = null;
36
37
    /**
38
     * @var Entities\SitemapItemCollection
39
     */
40
    protected $items;
41
42
    /**
43
     * Escaping html entities.
44
     *
45
     * @var bool
46
     */
47
    private $escaping = true;
48
49
    /**
50
     * Custom max size for limitSize()
51
     *
52
     * @var bool
53
     */
54
    protected $maxSize = null;
55
56
    /**
57
     * Enable or disable cache
58
     *
59
     * @var boolean
60
     */
61
    protected $cacheEnabled = false;
62
63
    /**
64
     * Unique cache key.
65
     *
66
     * @var string
67
     */
68
    protected $cacheKey = 'laravel-sitemap.your-key';
69
70
    /**
71
     * Cache duration, can be int or timestamp
72
     *
73
     * @var int
74
     */
75
    protected $cacheDuration = 3600;
76
77
    /**
78
     * Use limit size for big sitemaps
79
     *
80
     * @var bool
81
     */
82
    protected $useLimitSize;
83
84
    /** @var  \Illuminate\Contracts\Config\Repository */
85
    protected $config;
86
87
    /** @var  \Illuminate\Contracts\Cache\Repository */
88
    protected $cache;
89
90
    /** @var  \Illuminate\Filesystem\Filesystem */
91
    protected $filesystem;
92
93
    /** @var \Arcanedev\LaravelSitemap\Contracts\SitemapGenerator */
94
    private $generator;
95
96
    /* ------------------------------------------------------------------------------------------------
97
     |  Constructor
98
     | ------------------------------------------------------------------------------------------------
99
     */
100
    /**
101
     * SitemapManager constructor.
102
     *
103
     * @param  \Illuminate\Contracts\Cache\Repository                $cache
104
     * @param  \Illuminate\Contracts\Config\Repository               $config
105
     * @param  \Illuminate\Filesystem\Filesystem                     $filesystem
106
     * @param  \Arcanedev\LaravelSitemap\Contracts\SitemapGenerator  $generator
107
     */
108 48
    public function __construct(
109
        Cache $cache,
110
        Config $config,
111
        Filesystem $filesystem,
112
        SitemapGenerator $generator
113
    ) {
114 48
        $this->cache      = $cache;
115 48
        $this->config     = $config;
116 48
        $this->filesystem = $filesystem;
117 48
        $this->generator = $generator;
118
119 48
        $this->init();
120 48
    }
121
122 48
    private function init()
123
    {
124 48
        $this->resetItems();
125 48
        $this->resetSitemaps();
126 48
        $this->setCache(
127 48
            $this->config->get('sitemap.cache.key',      $this->cacheKey),
128 48
            $this->config->get('sitemap.cache.lifetime', $this->cacheDuration),
129 48
            $this->config->get('sitemap.cache.enabled',  $this->cacheEnabled)
130 36
        );
131 48
        $this->setUseLimitSize($this->config->get('sitemap.use-limit-size', $this->useLimitSize));
132 48
        $this->setEscaping($this->config->get('sitemap.escaping', $this->escaping));
133 48
        $this->setMaxSize($this->config->get('sitemap.max-size', $this->maxSize));
134 48
    }
135
136
    /* ------------------------------------------------------------------------------------------------
137
     |  Getters & Setters
138
     | ------------------------------------------------------------------------------------------------
139
     */
140
    /**
141
     * Get all sitemaps.
142
     *
143
     * @return array
144
     */
145
    public function getSitemaps()
146
    {
147
        return $this->sitemaps;
148
    }
149
150
    /**
151
     * Add a sitemap to the sitemap container.
152
     *
153
     * @param  array  $sitemap
154
     *
155
     * @return self
156
     */
157
    public function setSitemap(array $sitemap)
158
    {
159
        $this->sitemaps[] = $sitemap;
160
161
        return $this;
162
    }
163
164
    /**
165
     * Get the sitemap items.
166
     *
167
     * @return \Arcanedev\LaravelSitemap\Entities\SitemapItemCollection
168
     */
169 16
    public function getItems()
170
    {
171 16
        return $this->items;
172
    }
173
174
    /**
175
     * Get the title.
176
     *
177
     * @return string
178
     */
179 8
    public function getTitle()
180
    {
181 8
        return $this->title;
182
    }
183
184
    /**
185
     * Set the title.
186
     *
187
     * @param  string  $title
188
     *
189
     * @return self
190
     */
191 8
    public function setTitle($title)
192
    {
193 8
        $this->title = $title;
194
195 8
        return $this;
196
    }
197
198
    /**
199
     * Get the link.
200
     *
201
     * @return string
202
     */
203 8
    public function getLink()
204
    {
205 8
        return $this->link;
206
    }
207
208
    /**
209
     * Sets $link value.
210
     *
211
     * @param  string  $link
212
     *
213
     * @return self
214
     */
215 8
    public function setLink($link)
216
    {
217 8
        $this->link = $link;
218
219 8
        return $this;
220
    }
221
222
    /**
223
     * Get the sitemap styles location.
224
     *
225
     * @return string
226
     */
227 8
    public function getStyleLocation()
228
    {
229 8
        return $this->generator->getStylesLocation();
230
    }
231
232
    /**
233
     * Set the sitemap styles location.
234
     *
235
     * @param  string  $location
236
     *
237
     * @return self
238
     */
239 8
    public function setStyleLocation($location)
240
    {
241 8
        $this->generator->setStylesLocation($location);
242
243 8
        return $this;
244
    }
245
246
    /**
247
     * Get the escaping value.
248
     *
249
     * @return bool
250
     */
251 24
    public function isEscaped()
252
    {
253 24
        return $this->escaping;
254
    }
255
256
    /**
257
     * Set the escaping value.
258
     *
259
     * @param  bool  $escape
260
     *
261
     * @return self
262
     */
263 48
    public function setEscaping($escape)
264
    {
265 48
        $this->escaping = (bool) $escape;
266
267 48
        return $this;
268
    }
269
270
    /**
271
     * Get the max size value.
272
     *
273
     * @return int
274
     */
275 8
    public function getMaxSize()
276
    {
277 8
        return $this->maxSize;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->maxSize; (boolean) is incompatible with the return type declared by the interface Arcanedev\LaravelSitemap...emapManager::getMaxSize of type integer.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
278
    }
279
280
    /**
281
     * Set the max size value.
282
     *
283
     * @param  int  $maxSize
284
     *
285
     * @return self
286
     */
287 48
    public function setMaxSize($maxSize)
288
    {
289 48
        $this->maxSize = $maxSize;
0 ignored issues
show
Documentation Bug introduced by
The property $maxSize was declared of type boolean, but $maxSize is of type integer. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
290
291 48
        return $this;
292
    }
293
294
    /**
295
     * Set cache options.
296
     *
297
     * @param  string|null                        $key
298
     * @param  \Carbon\Carbon|\Datetime|int|null  $duration
299
     * @param  bool                               $useCache
300
     */
301 48
    public function setCache($key = null, $duration = null, $useCache = true)
302
    {
303 48
        $this->setCacheEnabled($useCache);
304 48
        $this->setCacheKey($key);
305 48
        $this->setCacheDuration($duration);
0 ignored issues
show
Bug introduced by
It seems like $duration defined by parameter $duration on line 301 can also be of type null or object<DateTime>; however, Arcanedev\LaravelSitemap...ger::setCacheDuration() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that have been passed in as parameters and are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
306 48
    }
307
308
    /**
309
     * Get the cache enabled value.
310
     *
311
     * @return bool
312
     */
313 16
    public function isCacheEnabled()
314
    {
315 16
        return $this->cacheEnabled;
316
    }
317
318
    /**
319
     * Set the cache enabled value.
320
     *
321
     * @param  bool  $cacheEnabled
322
     *
323
     * @return self
324
     */
325 48
    public function setCacheEnabled($cacheEnabled)
326
    {
327 48
        $this->cacheEnabled = $cacheEnabled;
328
329 48
        return $this;
330
    }
331
332
    /**
333
     * Get the cache key value.
334
     *
335
     * @return string
336
     */
337 8
    public function getCacheKey()
338
    {
339 8
        return $this->cacheKey;
340
    }
341
342
    /**
343
     * Set the cache key value.
344
     *
345
     * @param  string  $key
346
     *
347
     * @return self
348
     */
349 48
    public function setCacheKey($key)
350
    {
351 48
        if ( ! is_null($key)) {
352 48
            $this->cacheKey = $key;
353 36
        }
354
355 48
        return $this;
356
    }
357
358
    /**
359
     * Get the cache duration value.
360
     *
361
     * @return int
362
     */
363 8
    public function getCacheDuration()
364
    {
365 8
        return $this->cacheDuration;
366
    }
367
368
    /**
369
     * Set cache duration value.
370
     *
371
     * @param  int  $duration
372
     *
373
     * @return self
374
     */
375 48
    public function setCacheDuration($duration)
376
    {
377 48
        if ( ! is_null($duration)) {
378 48
            $this->cacheDuration = $duration;
379 36
        }
380
381 48
        return $this;
382
    }
383
384
    /**
385
     * Checks if content is cached.
386
     *
387
     * @return bool
388
     */
389
    public function isCached()
390
    {
391
        return $this->isCacheEnabled() && $this->cache->has($this->getCacheKey());
392
    }
393
394
    /**
395
     * Get the use limit size value.
396
     *
397
     * @return bool
398
     */
399 8
    public function getUseLimitSize()
400
    {
401 8
        return $this->useLimitSize;
402
    }
403
404
    /**
405
     * Set the use limit size value.
406
     *
407
     * @param  bool  $useLimitSize
408
     *
409
     * @return self
410
     */
411 48
    public function setUseLimitSize($useLimitSize)
412
    {
413 48
        $this->useLimitSize = (bool) $useLimitSize;
414
415 48
        return $this;
416
    }
417
418
    /**
419
     * Limit size of $items array to 50000 elements (1000 for google-news).
420
     *
421
     * @param  int  $max
422
     *
423
     * @return self
424
     */
425
    public function limitSize($max = 50000)
426
    {
427
        $this->items = $this->items->slice(0, $max);
428
429
        return $this;
430
    }
431
432
    /**
433
     * Get the use styles value.
434
     *
435
     * @return bool
436
     */
437 8
    public function getUseStyles()
438
    {
439 8
        return $this->generator->isStylesEnabled();
440
    }
441
442
    /**
443
     * Set the use styles value.
444
     *
445
     * @param  bool  $useStyles
446
     *
447
     * @return self
448
     */
449 8
    public function setUseStyles($useStyles)
450
    {
451 8
        $this->generator->setUseStyles($useStyles);
452
453 8
        return $this;
454
    }
455
456
    /* ------------------------------------------------------------------------------------------------
457
     |  Main Functions
458
     | ------------------------------------------------------------------------------------------------
459
     */
460
    /**
461
     * Add new sitemap item to $items array.
462
     *
463
     * @param  string       $loc
464
     * @param  string|null  $lastmod
465
     * @param  string|null  $priority
466
     * @param  string|null  $freq
467
     * @param  array        $images
468
     * @param  string|null  $title
469
     * @param  array        $translations
470
     * @param  array        $videos
471
     * @param  array        $googlenews
472
     * @param  array        $alternates
473
     */
474 8
    public function add(
475
        $loc, $lastmod = null, $priority = null, $freq = null, $images = [], $title = null,
476
        $translations = [], $videos = [], $googlenews = [], $alternates = []
477
    ) {
478 8
        $this->addItem(compact(
479 8
            'loc', 'lastmod', 'priority', 'freq', 'images', 'title', 'translations', 'videos', 'googlenews', 'alternates'
480 6
        ));
481 8
    }
482
483
    /**
484
     * Add a new sitemap item.
485
     *
486
     * @param  array  $params
487
     */
488 16
    public function addItem($params = [])
489
    {
490 16
        $this->items->addItem($params, $this->isEscaped());
491 16
    }
492
493
    /**
494
     * Add multiple sitemap items.
495
     *
496
     * @param  array  $items
497
     */
498 8
    public function addItems(array $items)
499
    {
500 8
        foreach ($items as $item) { $this->addItem($item); }
501 8
    }
502
503
    /**
504
     * Add new sitemap to $sitemaps array.
505
     *
506
     * @param  string       $loc
507
     * @param  string|null  $lastmod
508
     */
509
    public function addSitemap($loc, $lastmod = null)
510
    {
511
        $this->setSitemap(compact('loc', 'lastmod'));
512
    }
513
514
    /**
515
     * Returns document with all sitemap items from $items array.
516
     *
517
     * @param  string  $format  (options: xml, html, txt, ror-rss, ror-rdf, google-news)
518
     * @param  string  $style   (path to custom xls style like '/styles/xsl/xml-sitemap.xsl')
519
     *
520
     * @return \Symfony\Component\HttpFoundation\Response|\Illuminate\Contracts\Routing\ResponseFactory|array
521
     */
522
    public function render($format = 'xml', $style = null)
523
    {
524
        // limit size of sitemap
525
        if ($this->getMaxSize() > 0 && count($this->getItems()) > $this->getMaxSize())
526
            $this->limitSize($this->getMaxSize());
0 ignored issues
show
Documentation introduced by
$this->getMaxSize() is of type boolean, but the function expects a integer.

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...
527
        elseif ($format === SitemapStyler::GOOGLE_NEWS_FORMAT && count($this->getItems()) > 1000)
528
            $this->limitSize(1000);
529
        elseif ($format !== SitemapStyler::GOOGLE_NEWS_FORMAT && count($this->getItems()) > 50000)
530
            $this->limitSize();
531
532
        $data = $this->generate($format, $style);
533
534
        return $format === 'html'
535
            ? $data['content']
536
            : response($data['content'], 200, $data['headers']);
537
    }
538
539
    /**
540
     * Generates document with all sitemap items from $items array.
541
     *
542
     * @param  string       $format  (options: xml, html, txt, ror-rss, ror-rdf, sitemapindex, google-news)
543
     * @param  string|null  $style   (path to custom xls style like '/styles/xsl/xml-sitemap.xsl')
544
     *
545
     * @return array
546
     */
547
    public function generate($format = 'xml', $style = null)
548
    {
549
        // check if caching is enabled, there is a cached content and its duration isn't expired
550
        if ($this->isCached()) {
551
            $cached = $this->cache->get($this->getCacheKey());
552
            ($format === SitemapStyler::SITEMAPINDEX_FORMAT)
553
                ? $this->resetSitemaps($cached)
554
                : $this->resetItems($cached);
555
        }
556
        elseif ($this->isCacheEnabled()) {
557
            $this->cache->put(
558
                $this->getCacheKey(),
559
                $format === SitemapStyler::SITEMAPINDEX_FORMAT ? $this->getSitemaps() : $this->getItems(),
560
                $this->getCacheDuration()
561
            );
562
        }
563
564
        if ( ! $this->getLink())
565
            $this->setLink($this->config->get('app.url'));
566
567
        if ( ! $this->getTitle())
568
            $this->setTitle('SitemapManager for ' . $this->getLink());
569
570
        $data = [];
571
572
        if ($format === SitemapStyler::SITEMAPINDEX_FORMAT)
573
            $data['sitemaps'] = $this->getSitemaps();
574
        else
575
            $data['items']    = $this->getItems();
576
577
        if (in_array($format, ['ror-rss', 'ror-rdf', 'html'])) {
578
            $data['channel'] = [
579
                'title' => $this->getTitle(),
580
                'link'  => $this->getLink(),
581
            ];
582
        }
583
584
        $this->generator->generate($data, $format, $style);
585
    }
586
587
    /**
588
     * Generate sitemap and store it to a file.
589
     *
590
     * @param  string  $format    (options: xml, html, txt, ror-rss, ror-rdf, sitemapindex, google-news)
591
     * @param  string  $filename  (without file extension, may be a path like 'sitemaps/sitemap1' but must exist)
592
     * @param  string  $path      (path to store sitemap like '/www/site/public')
593
     * @param  string  $style     (path to custom xls style like '/styles/xsl/xml-sitemap.xsl')
594
     *
595
     * @return bool
596
     */
597
    public function store($format = 'xml', $filename = 'sitemap', $path = null, $style = null)
598
    {
599
        // Turn off caching for this method
600
        $this->setCacheEnabled(false);
601
602
        // Use correct file extension
603
        $extension = in_array($format, ['txt', 'html']) ? $format : 'xml';
604
605
        // Use custom size limit for sitemaps
606
        if (
607
            $this->getMaxSize() > 0 &&
608
            count($this->getItems()) >= $this->getMaxSize()
609
        ) {
610
            if ($this->getUseLimitSize()) {
611
                // limit size
612
                $this->limitSize($this->getMaxSize());
0 ignored issues
show
Documentation introduced by
$this->getMaxSize() is of type boolean, but the function expects a integer.

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...
613
            }
614
            else {
615
                // use sitemapindex and generate partial sitemaps
616
                foreach ($this->getItems()->chunk($this->getMaxSize()) as $key => $item) {
0 ignored issues
show
Documentation introduced by
$this->getMaxSize() is of type boolean, but the function expects a integer.

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...
617
                    // reset current items
618
                    $this->resetItems($item);
619
620
                    // generate new partial sitemap
621
                    $this->store($format, "$filename-$key", $path, $style);
622
623
                    // add sitemap to sitemapindex
624
                    if ( ! is_null($path))
625
                        // if using custom path generate relative urls for sitemaps in the sitemapindex
626
                        $this->addSitemap("$filename-$key.$extension");
627
                    else
628
                        // else generate full urls based on app's domain
629
                        $this->addSitemap(url("$filename-$key.$extension"));
630
                }
631
632
                $format = SitemapStyler::SITEMAPINDEX_FORMAT;
633
            }
634
        }
635
        elseif (
636
            ($format !== SitemapStyler::GOOGLE_NEWS_FORMAT && count($this->getItems()) > 50000) ||
637
            ($format === SitemapStyler::GOOGLE_NEWS_FORMAT && count($this->getItems()) > 1000)
638
        ) {
639
            ($format !== SitemapStyler::GOOGLE_NEWS_FORMAT) ? $max = 50000 : $max = 1000;
640
641
            // check if limiting size of items array is enabled
642
            if ( ! $this->getUseLimitSize()) {
643
                // use sitemapindex and generate partial sitemaps
644
                foreach ($this->getItems()->chunk($max) as $key => $item) {
645
                    // reset current items
646
                    $this->resetItems($item);
647
648
                    // generate new partial sitemap
649
                    $this->store($format, "$filename-$key", $path, $style);
650
651
                    // add sitemap to sitemapindex
652
                    if ( ! is_null($path))
653
                        // if using custom path generate relative urls for sitemaps in the sitemapindex
654
                        $this->addSitemap("$filename-$key.$extension");
655
                    else
656
                        // else generate full urls based on app's domain
657
                        $this->addSitemap(url("$filename-$key.$extension"));
658
                }
659
660
                $format = SitemapStyler::SITEMAPINDEX_FORMAT;
661
            }
662
            else {
663
                // reset items and use only most recent $max items
664
                $this->limitSize($max);
665
            }
666
        }
667
668
        $data = $this->generate($format, $style);
669
670
        // if custom path
671
        $file = $path == null
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $path of type string|null against null; this is ambiguous if the string can be empty. Consider using a strict comparison === instead.
Loading history...
672
            ? public_path("$filename.$extension")
673
            : $path . DS . "$filename.$extension";
674
675
        // must return something
676
        return $this->filesystem->put($file, $data['content']);
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->filesystem...ile, $data['content']); (integer) is incompatible with the return type declared by the interface Arcanedev\LaravelSitemap...s\SitemapManager::store of type boolean.

If you return a value from a function or method, it should be a sub-type of the type that is given by the parent type f.e. an interface, or abstract method. This is more formally defined by the Lizkov substitution principle, and guarantees that classes that depend on the parent type can use any instance of a child type interchangably. This principle also belongs to the SOLID principles for object oriented design.

Let’s take a look at an example:

class Author {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }
}

abstract class Post {
    public function getAuthor() {
        return 'Johannes';
    }
}

class BlogPost extends Post {
    public function getAuthor() {
        return new Author('Johannes');
    }
}

class ForumPost extends Post { /* ... */ }

function my_function(Post $post) {
    echo strtoupper($post->getAuthor());
}

Our function my_function expects a Post object, and outputs the author of the post. The base class Post returns a simple string and outputting a simple string will work just fine. However, the child class BlogPost which is a sub-type of Post instead decided to return an object, and is therefore violating the SOLID principles. If a BlogPost were passed to my_function, PHP would not complain, but ultimately fail when executing the strtoupper call in its body.

Loading history...
677
    }
678
679
    /**
680
     * Reset the sitemaps container.
681
     *
682
     * @param  array  $sitemaps
683
     *
684
     * @return self
685
     */
686 48
    public function resetSitemaps(array $sitemaps = [])
687
    {
688 48
        $this->sitemaps = $sitemaps;
689
690 48
        return $this;
691
    }
692
693
    /**
694
     * Reset the items array.
695
     *
696
     * @param  array  $items
697
     *
698
     * @return self
699
     */
700 48
    public function resetItems(array $items = [])
701
    {
702 48
        $this->items = new Entities\SitemapItemCollection($items);
703
704 48
        return $this;
705
    }
706
}
707