SitemapManager::render()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 4
rs 10
c 0
b 0
f 0
ccs 2
cts 2
cp 1
crap 1
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Arcanedev\LaravelSitemap;
6
7
use Arcanedev\LaravelSitemap\Contracts\Entities\Sitemap as SitemapContract;
8
use Arcanedev\LaravelSitemap\Contracts\SitemapManager as SitemapManagerContract;
9
use Arcanedev\LaravelSitemap\Entities\Sitemap;
10
use Illuminate\Support\{Arr, Collection, Str};
11
use Symfony\Component\HttpFoundation\Response;
12
13
/**
14
 * Class     SitemapManager
15
 *
16
 * @package  Arcanedev\LaravelSitemap
17
 * @author   ARCANEDEV <[email protected]>
18
 */
19
class SitemapManager implements SitemapManagerContract
20
{
21
    /* -----------------------------------------------------------------
22
     |  Properties
23
     | -----------------------------------------------------------------
24
     */
25
26
    /** @var  \Illuminate\Support\Collection */
27
    protected $sitemaps;
28
29
    /** @var  string */
30
    protected $format = 'xml';
31
32
    /* -----------------------------------------------------------------
33
     |  Constructor
34
     | -----------------------------------------------------------------
35
     */
36
37
    /**
38
     * SitemapManager constructor.
39
     */
40 114
    public function __construct()
41
    {
42 114
        $this->sitemaps = new Collection;
43 114
    }
44
45
    /* -----------------------------------------------------------------
46
     |  Getters & Setters
47
     | -----------------------------------------------------------------
48
     */
49
50
    /**
51
     * Set the format.
52
     *
53
     * @param  string  $format
54
     *
55
     * @return $this
56
     */
57 30
    public function format($format)
58
    {
59 30
        $this->format = $format;
60
61 30
        return $this;
62
    }
63
64
    /* -----------------------------------------------------------------
65
     |  Main Methods
66
     | -----------------------------------------------------------------
67
     */
68
69
    /**
70
     * Create and add a sitemap to the collection.
71
     *
72
     * @param  string    $name
73
     * @param  callable  $callback
74
     *
75
     * @return $this
76
     */
77 6
    public function create(string $name, callable $callback)
78
    {
79 6
        return $this->add($name, tap(Sitemap::make()->setPath($name), $callback));
80
    }
81
82
    /**
83
     * Add a sitemap to the collection.
84
     *
85
     * @param  string                                                $name
86
     * @param  \Arcanedev\LaravelSitemap\Contracts\Entities\Sitemap  $sitemap
87
     *
88
     * @return $this
89
     */
90 96
    public function add(string $name, SitemapContract $sitemap)
91
    {
92 96
        $this->sitemaps->put($name, $sitemap);
93
94 96
        return $this;
95
    }
96
97
    /**
98
     * Get the sitemaps collection.
99
     *
100
     * @return \Illuminate\Support\Collection
101
     */
102 30
    public function all(): Collection
103
    {
104 30
        return $this->sitemaps;
105
    }
106
107
    /**
108
     * Get a sitemap instance.
109
     *
110
     * @param  string      $name
111
     * @param  mixed|null  $default
112
     *
113
     * @return \Arcanedev\LaravelSitemap\Entities\Sitemap|mixed|null
114
     */
115 12
    public function get(string $name, $default = null)
116
    {
117 12
        return $this->sitemaps->get($name, $default);
118
    }
119
120
    /**
121
     * Check if a sitemap exists.
122
     *
123
     * @param  string  $name
124
     *
125
     * @return bool
126
     */
127 12
    public function has(string $name): bool
128
    {
129 12
        if ( ! Str::contains($name, '.'))
130 6
            return $this->sitemaps->has($name);
131
132 6
        list($name, $key) = explode('.', $name, 2);
133
134
        $map = $this->sitemaps->filter(function (SitemapContract $map) {
135 6
            return $map->isExceeded();
136 6
        })->get($name);
137
138 6
        return is_null($map)
139
            ? false
140 6
            : $map->chunk()->has(intval($key));
141
    }
142
143
    /**
144
     * Remove a sitemap from the collection by key.
145
     *
146
     * @param  string|array  $names
147
     *
148
     * @return $this
149
     */
150 6
    public function forget($names)
151
    {
152 6
        $this->sitemaps->forget($names);
153
154 6
        return $this;
155
    }
156
157
    /**
158
     * Get the sitemaps count.
159
     *
160
     * @return int
161
     */
162 24
    public function count(): int
163
    {
164 24
        return $this->sitemaps->count();
165
    }
166
167
    /**
168
     * Render the sitemaps.
169
     *
170
     * @param  string  $name
171
     *
172
     * @throws \Throwable
173
     *
174
     * @return string|null
175
     */
176 66
    public function render(string $name = null): ?string
177
    {
178 66
        return SitemapBuilder::make()->build($name, $this->sitemaps, $this->format);
179
    }
180
181
    /**
182
     * Save the sitemaps.
183
     *
184
     * @param  string       $path
185
     * @param  string|null  $name
186
     *
187
     * @throws \Throwable
188
     *
189
     * @return $this
190
     */
191 24
    public function save(string $path, string $name = null)
192
    {
193 24
        if ($this->sitemaps->isEmpty())
194 6
            return $this;
195
196 24
        file_put_contents($path, $this->render($name));
197
198
        /** @var  \Arcanedev\LaravelSitemap\Contracts\Entities\Sitemap  $sitemap */
199 24
        foreach ($this->sitemaps as $key => $sitemap) {
200 24
            if ($sitemap->isExceeded())
201 6
                $this->saveMultiple($path, $sitemap);
202
        }
203
204 24
        return $this;
205
    }
206
207
    /**
208
     * Render the Http response.
209
     *
210
     * @param  string  $name
211
     * @param  int     $status
212
     * @param  array   $headers
213
     *
214
     * @throws \Throwable
215
     *
216
     * @return \Illuminate\Http\Response|mixed
217
     */
218 6
    public function respond(string $name = null, int $status = Response::HTTP_OK, array $headers = [])
219
    {
220 6
        return response($this->render($name), $status, array_merge($this->getResponseHeaders(), $headers));
221
    }
222
223
    /**
224
     * Get the collection of items as a plain array.
225
     *
226
     * @return array
227
     */
228 12
    public function toArray(): array
229
    {
230 12
        return $this->all()->toArray();
231
    }
232
233
    /**
234
     * Get the collection of sitemaps as JSON.
235
     *
236
     * @param  int  $options
237
     *
238
     * @return string
239
     */
240 6
    public function toJson($options = 0): string
241
    {
242 6
        return json_encode($this->jsonSerialize(), $options);
243
    }
244
245
    /**
246
     * Convert the object into something JSON serializable.
247
     *
248
     * @return array
249
     */
250 6
    public function jsonSerialize(): array
251
    {
252 6
        return $this->toArray();
253
    }
254
255
    /**
256
     * Save multiple sitemap.
257
     *
258
     * @param  string                                                $path
259
     * @param  \Arcanedev\LaravelSitemap\Contracts\Entities\Sitemap  $sitemap
260
     *
261
     * @throws \Throwable
262
     */
263 6
    private function saveMultiple(string $path, SitemapContract $sitemap)
264
    {
265 6
        $pathInfo = pathinfo($path);
266 6
        $chunks   = $sitemap->chunk();
267
268 6
        foreach ($chunks as $key => $item) {
269 6
            file_put_contents(
270 6
                $pathInfo['dirname'].DIRECTORY_SEPARATOR.$pathInfo['filename'].'-'.$key.'.'.$pathInfo['extension'],
271 6
                SitemapBuilder::make()->build((string) $key, $chunks, $this->format)
272
            );
273
        }
274 6
    }
275
276
    /**
277
     * Get the response header.
278
     *
279
     * @return array
280
     */
281 6
    protected function getResponseHeaders(): array
282
    {
283 6
        return Arr::get([
284 6
            'xml' => ['Content-Type' => 'application/xml'],
285
            'rss' => ['Content-Type' => 'application/rss+xml'],
286
            'txt' => ['Content-Type' => 'text/plain'],
287 6
        ], $this->format, []);
288
    }
289
}
290