Sitemap::add()   B
last analyzed

Complexity

Conditions 7
Paths 12

Size

Total Lines 23
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 11
c 0
b 0
f 0
dl 0
loc 23
rs 8.8333
cc 7
nc 12
nop 1
1
<?php
2
3
namespace Mfonte\Sitemap;
4
5
use Illuminate\Contracts\Support\Renderable;
6
use Illuminate\Contracts\Support\Responsable;
7
use Illuminate\Support\Facades\Response;
8
use Illuminate\Support\Facades\Storage;
9
use Mfonte\Sitemap\Contracts\Sitemapable;
10
use Mfonte\Sitemap\Renderer\NativeRenderer;
11
use Mfonte\Sitemap\Tags\Tag;
12
use Mfonte\Sitemap\Tags\Url;
13
14
class Sitemap implements Responsable, Renderable
15
{
16
    /** @var \Mfonte\Sitemap\Tags\Url[] */
17
    protected $tags = [];
18
19
    public static function create()
20
    {
21
        return new static();
22
    }
23
24
    final public function __construct()
25
    {
26
    }
27
28
    /**
29
     * @param $tag string|Url|Sitemapable
30
     */
31
    public function add($tag)
32
    {
33
        if (is_object($tag) && array_key_exists(Sitemapable::class, class_implements($tag))) {
34
            $tag = $tag->toSitemapTag();
35
        }
36
37
        if (is_iterable($tag)) {
38
            foreach ($tag as $item) {
39
                $this->add($item);
40
            }
41
42
            return $this;
43
        }
44
45
        if (is_string($tag)) {
46
            $tag = Url::create($tag);
47
        }
48
49
        if (! in_array($tag, $this->tags)) {
50
            $this->tags[] = $tag;
51
        }
52
53
        return $this;
54
    }
55
56
    public function getTags(): array
57
    {
58
        return $this->tags;
59
    }
60
61
    public function getUrl(string $url): ?Url
62
    {
63
        return collect($this->tags)->first(function (Tag $tag) use ($url) {
0 ignored issues
show
Bug introduced by
$this->tags of type Mfonte\Sitemap\Tags\Url[] is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

63
        return collect(/** @scrutinizer ignore-type */ $this->tags)->first(function (Tag $tag) use ($url) {
Loading history...
64
            return $tag->getType() === 'url' && $tag->url === $url;
65
        });
66
    }
67
68
    public function hasUrl(string $url): bool
69
    {
70
        return (bool) $this->getUrl($url);
71
    }
72
73
    public function hasImages() : bool
74
    {
75
        return (bool) collect($this->tags)->first(function (Tag $tag) {
0 ignored issues
show
Bug introduced by
$this->tags of type Mfonte\Sitemap\Tags\Url[] is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

75
        return (bool) collect(/** @scrutinizer ignore-type */ $this->tags)->first(function (Tag $tag) {
Loading history...
76
            return $tag->getType() === 'url' && ! empty($tag->images);
77
        });
78
    }
79
80
    public function hasNews() : bool
81
    {
82
        return (bool) collect($this->tags)->first(function (Tag $tag) {
0 ignored issues
show
Bug introduced by
$this->tags of type Mfonte\Sitemap\Tags\Url[] is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

82
        return (bool) collect(/** @scrutinizer ignore-type */ $this->tags)->first(function (Tag $tag) {
Loading history...
83
            return $tag->getType() === 'url' && ! empty($tag->news);
84
        });
85
    }
86
87
    /**
88
     * Renders the sitemap.
89
     * Optionally, you can pass a boolean to use the native renderer instead of the blade template. This is useful if you need to use this package in a non-Laravel project.
90
     *
91
     * @param bool $nativeRenderer - if true, uses the native renderer instead of the blade template (default: false)
92
     *
93
     * @return string
94
     */
95
    public function render(bool $nativeRenderer = false): string
96
    {
97
        $tags = collect($this->tags)->unique('url')->filter();
0 ignored issues
show
Bug introduced by
$this->tags of type Mfonte\Sitemap\Tags\Url[] is incompatible with the type Illuminate\Contracts\Support\Arrayable expected by parameter $value of collect(). ( Ignorable by Annotation )

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

97
        $tags = collect(/** @scrutinizer ignore-type */ $this->tags)->unique('url')->filter();
Loading history...
98
        $hasImages = $this->hasImages();
99
        $hasNews = $this->hasNews();
100
101
        if (! $nativeRenderer) {
102
            return view('sitemap::sitemap')
103
                ->with(compact('tags', 'hasImages', 'hasNews'))
104
                ->render();
105
        } else {
106
            $renderer = NativeRenderer::instance(compact('tags', 'hasImages', 'hasNews'));
107
108
            return $renderer->render('sitemap');
109
        }
110
    }
111
112
    /**
113
     * Writes the sitemap to file.
114
     * Optionally, you can pass a boolean to use the native renderer instead of the blade template. This is useful if you need to use this package in a non-Laravel project.
115
     *
116
     * @param string $path
117
     * @param bool $nativeRenderer - if true, uses the native renderer instead of the blade template (default: false)
118
     * @param int $flags - see https://www.php.net/manual/en/function.file-put-contents.php
119
     * @param resource $context - see https://www.php.net/manual/en/function.file-put-contents.php
120
     *
121
     * @return self
122
     */
123
    public function writeToFile(string $path, bool $nativeRenderer = false, int $flags = 0, $context = null) : self
124
    {
125
        file_put_contents($path, $this->render($nativeRenderer), $flags, $context);
126
127
        return $this;
128
    }
129
130
    public function writeToDisk(string $disk, string $path) : self
131
    {
132
        Storage::disk($disk)->put($path, $this->render());
133
134
        return $this;
135
    }
136
137
    /**
138
     * Create an HTTP response that represents the object.
139
     *
140
     * @param  \Illuminate\Http\Request  $request
141
     * @return \Symfony\Component\HttpFoundation\Response
142
     */
143
    public function toResponse($request)
144
    {
145
        return Response::make($this->render(), 200, [
146
            'Content-Type' => 'text/xml',
147
        ]);
148
    }
149
}
150