1
|
|
|
<?php namespace Arcanedev\LaravelSitemap\Entities; |
2
|
|
|
|
3
|
|
|
use Arcanedev\LaravelSitemap\Contracts\Entities\Url as UrlContract; |
4
|
|
|
use Arcanedev\LaravelSitemap\Exceptions\SitemapException; |
5
|
|
|
use ArrayAccess; |
6
|
|
|
use DateTime; |
7
|
|
|
use Illuminate\Support\Arr; |
8
|
|
|
use Illuminate\Support\Str; |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Class Url |
12
|
|
|
* |
13
|
|
|
* @package Arcanedev\LaravelSitemap\Entities |
14
|
|
|
* @author ARCANEDEV <[email protected]> |
15
|
|
|
*/ |
16
|
|
|
class Url implements ArrayAccess, UrlContract |
17
|
|
|
{ |
18
|
|
|
/* ----------------------------------------------------------------- |
19
|
|
|
| Properties |
20
|
|
|
| ----------------------------------------------------------------- |
21
|
|
|
*/ |
22
|
|
|
|
23
|
|
|
/** @var string */ |
24
|
|
|
protected $loc; |
25
|
|
|
|
26
|
|
|
/** @var string|null */ |
27
|
|
|
protected $title; |
28
|
|
|
|
29
|
|
|
/** @var \DateTimeInterface */ |
30
|
|
|
protected $lastModDate; |
31
|
|
|
|
32
|
|
|
/** @var string */ |
33
|
|
|
protected $changeFrequency; |
34
|
|
|
|
35
|
|
|
/** @var float */ |
36
|
|
|
protected $priority; |
37
|
|
|
|
38
|
|
|
/* ----------------------------------------------------------------- |
39
|
|
|
| Constructor |
40
|
|
|
| ----------------------------------------------------------------- |
41
|
|
|
*/ |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* Url constructor. |
45
|
|
|
* |
46
|
|
|
* @param array|string $attributes |
47
|
|
|
*/ |
48
|
76 |
|
public function __construct($attributes) |
49
|
|
|
{ |
50
|
76 |
|
if (is_string($attributes)) |
51
|
32 |
|
$attributes = ['loc' => $attributes]; |
52
|
|
|
|
53
|
76 |
|
$this->setLoc(Arr::get($attributes, 'loc')); |
54
|
76 |
|
$this->setLastMod(Arr::get($attributes, 'lastmod', new DateTime)); |
55
|
76 |
|
$this->setChangeFreq(Arr::get($attributes, 'changefreq', ChangeFrequency::DAILY)); |
56
|
76 |
|
$this->setPriority(Arr::get($attributes, 'priority', 0.8)); |
57
|
76 |
|
$this->setTitle(Arr::get($attributes, 'title')); |
58
|
76 |
|
} |
59
|
|
|
|
60
|
|
|
/* ----------------------------------------------------------------- |
61
|
|
|
| Getters & Setters |
62
|
|
|
| ----------------------------------------------------------------- |
63
|
|
|
*/ |
64
|
|
|
|
65
|
|
|
/** |
66
|
|
|
* Get the url location. |
67
|
|
|
* |
68
|
|
|
* @return string |
69
|
|
|
*/ |
70
|
58 |
|
public function getLoc() |
71
|
|
|
{ |
72
|
58 |
|
return $this->escape($this->loc); |
73
|
|
|
} |
74
|
|
|
|
75
|
|
|
/** |
76
|
|
|
* Get the url location (alias). |
77
|
|
|
* |
78
|
|
|
* @see getLoc() |
79
|
|
|
* |
80
|
|
|
* @return string |
81
|
|
|
*/ |
82
|
14 |
|
public function loc() |
83
|
|
|
{ |
84
|
14 |
|
return $this->getLoc(); |
85
|
|
|
} |
86
|
|
|
|
87
|
|
|
/** |
88
|
|
|
* Set the url location. |
89
|
|
|
* |
90
|
|
|
* @param string $loc |
91
|
|
|
* |
92
|
|
|
* @return self |
93
|
|
|
* |
94
|
|
|
* @throws \Arcanedev\LaravelSitemap\Exceptions\SitemapException |
95
|
|
|
*/ |
96
|
76 |
|
public function setLoc($loc) |
97
|
|
|
{ |
98
|
76 |
|
$this->loc = $this->checkLoc($loc); |
99
|
|
|
|
100
|
76 |
|
return $this; |
101
|
|
|
} |
102
|
|
|
|
103
|
|
|
/** |
104
|
|
|
* Get the last modification date. |
105
|
|
|
* |
106
|
|
|
* @return \DateTimeInterface |
107
|
|
|
*/ |
108
|
34 |
|
public function getLastMod() |
109
|
|
|
{ |
110
|
34 |
|
return $this->lastModDate; |
111
|
|
|
} |
112
|
|
|
|
113
|
|
|
/** |
114
|
|
|
* Get the last modification date (alias). |
115
|
|
|
* |
116
|
|
|
* @see getLastMod() |
117
|
|
|
* |
118
|
|
|
* @return \DateTimeInterface |
119
|
|
|
*/ |
120
|
10 |
|
public function lastMod() |
121
|
|
|
{ |
122
|
10 |
|
return $this->getLastMod(); |
123
|
|
|
} |
124
|
|
|
|
125
|
|
|
/** |
126
|
|
|
* Format the url last modification. |
127
|
|
|
* |
128
|
|
|
* @param string $format |
129
|
|
|
* |
130
|
|
|
* @return string |
131
|
|
|
*/ |
132
|
28 |
|
public function formatLastMod($format = DateTime::ATOM) |
133
|
|
|
{ |
134
|
28 |
|
return $this->getLastMod()->format($format); |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
/** |
138
|
|
|
* Set the last modification date. |
139
|
|
|
* |
140
|
|
|
* @param string|\DateTimeInterface $lastModDate |
141
|
|
|
* @param string $format |
142
|
|
|
* |
143
|
|
|
* @return self |
144
|
|
|
*/ |
145
|
76 |
|
public function setLastMod($lastModDate, $format = 'Y-m-d H:i:s') |
146
|
|
|
{ |
147
|
76 |
|
if (is_string($lastModDate)) |
148
|
46 |
|
$lastModDate = DateTime::createFromFormat($format, $lastModDate); |
149
|
|
|
|
150
|
76 |
|
$this->lastModDate = $lastModDate; |
|
|
|
|
151
|
|
|
|
152
|
76 |
|
return $this; |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
/** |
156
|
|
|
* Get the change frequency. |
157
|
|
|
* |
158
|
|
|
* @return string |
159
|
|
|
*/ |
160
|
32 |
|
public function getChangeFreq() |
161
|
|
|
{ |
162
|
32 |
|
return $this->changeFrequency; |
163
|
|
|
} |
164
|
|
|
|
165
|
|
|
/** |
166
|
|
|
* Get the change frequency (alias). |
167
|
|
|
* |
168
|
|
|
* @see getChangeFreq() |
169
|
|
|
* |
170
|
|
|
* @return string |
171
|
|
|
*/ |
172
|
10 |
|
public function changeFreq() |
173
|
|
|
{ |
174
|
10 |
|
return $this->getChangeFreq(); |
175
|
|
|
} |
176
|
|
|
|
177
|
|
|
/** |
178
|
|
|
* Set the change frequency. |
179
|
|
|
* |
180
|
|
|
* @param string $changeFreq |
181
|
|
|
* |
182
|
|
|
* @return self |
183
|
|
|
*/ |
184
|
76 |
|
public function setChangeFreq($changeFreq) |
185
|
|
|
{ |
186
|
76 |
|
$this->changeFrequency = strtolower(trim($changeFreq)); |
187
|
|
|
|
188
|
76 |
|
return $this; |
189
|
|
|
} |
190
|
|
|
|
191
|
|
|
/** |
192
|
|
|
* Get the priority. |
193
|
|
|
* |
194
|
|
|
* @return float |
195
|
|
|
*/ |
196
|
32 |
|
public function getPriority() |
197
|
|
|
{ |
198
|
32 |
|
return $this->priority; |
199
|
|
|
} |
200
|
|
|
|
201
|
|
|
/** |
202
|
|
|
* Get the priority (alias). |
203
|
|
|
* |
204
|
|
|
* @see getPriority() |
205
|
|
|
* |
206
|
|
|
* @return float |
207
|
|
|
*/ |
208
|
10 |
|
public function priority() |
209
|
|
|
{ |
210
|
10 |
|
return $this->getPriority(); |
211
|
|
|
} |
212
|
|
|
|
213
|
|
|
/** |
214
|
|
|
* Set the priority. |
215
|
|
|
* |
216
|
|
|
* @param float $priority |
217
|
|
|
* |
218
|
|
|
* @return self |
219
|
|
|
* |
220
|
|
|
* @throws \Arcanedev\LaravelSitemap\Exceptions\SitemapException |
221
|
|
|
*/ |
222
|
76 |
|
public function setPriority($priority) |
223
|
|
|
{ |
224
|
76 |
|
$this->priority = $this->checkPriority($priority); |
225
|
|
|
|
226
|
76 |
|
return $this; |
227
|
|
|
} |
228
|
|
|
|
229
|
|
|
/** |
230
|
|
|
* Get the title. |
231
|
|
|
* |
232
|
|
|
* @return string|null |
233
|
|
|
*/ |
234
|
28 |
|
public function getTitle() |
235
|
|
|
{ |
236
|
28 |
|
return $this->escape($this->title); |
237
|
|
|
} |
238
|
|
|
|
239
|
|
|
/** |
240
|
|
|
* Get the title. |
241
|
|
|
* |
242
|
|
|
* @param string $title |
243
|
|
|
* |
244
|
|
|
* @return self |
245
|
|
|
*/ |
246
|
76 |
|
public function setTitle($title) |
247
|
|
|
{ |
248
|
76 |
|
$this->title = $title; |
249
|
|
|
|
250
|
76 |
|
return $this; |
251
|
|
|
} |
252
|
|
|
|
253
|
|
|
/* ----------------------------------------------------------------- |
254
|
|
|
| Main Methods |
255
|
|
|
| ----------------------------------------------------------------- |
256
|
|
|
*/ |
257
|
|
|
|
258
|
|
|
/** |
259
|
|
|
* Create a sitemap url instance. |
260
|
|
|
* |
261
|
|
|
* @param string $loc |
262
|
|
|
* |
263
|
|
|
* @return \Arcanedev\LaravelSitemap\Entities\Url |
264
|
|
|
*/ |
265
|
54 |
|
public static function make($loc) |
266
|
|
|
{ |
267
|
54 |
|
return new static(compact('loc')); |
268
|
|
|
} |
269
|
|
|
|
270
|
|
|
/** |
271
|
|
|
* Make a URL instance with attributes. |
272
|
|
|
* |
273
|
|
|
* @param array $attributes |
274
|
|
|
* |
275
|
|
|
* @return \Arcanedev\LaravelSitemap\Entities\Url |
276
|
|
|
*/ |
277
|
4 |
|
public static function makeFromArray(array $attributes) |
278
|
|
|
{ |
279
|
4 |
|
return new static($attributes); |
280
|
|
|
} |
281
|
|
|
|
282
|
|
|
/** |
283
|
|
|
* Get the collection of items as a plain array. |
284
|
|
|
* |
285
|
|
|
* @return array |
286
|
|
|
*/ |
287
|
18 |
|
public function toArray() |
288
|
|
|
{ |
289
|
|
|
return [ |
290
|
18 |
|
'title' => $this->getTitle(), |
291
|
18 |
|
'loc' => $this->getLoc(), |
292
|
18 |
|
'lastmod' => $this->formatLastMod(), |
293
|
18 |
|
'changefreq' => $this->getChangeFreq(), |
294
|
18 |
|
'priority' => $this->getPriority(), |
295
|
|
|
]; |
296
|
|
|
} |
297
|
|
|
|
298
|
|
|
/** |
299
|
|
|
* Get the sitemap url as JSON. |
300
|
|
|
* |
301
|
|
|
* @param int $options |
302
|
|
|
* |
303
|
|
|
* @return string |
304
|
|
|
*/ |
305
|
2 |
|
public function toJson($options = 0) |
306
|
|
|
{ |
307
|
2 |
|
return json_encode($this->jsonSerialize(), $options); |
308
|
|
|
} |
309
|
|
|
|
310
|
|
|
/** |
311
|
|
|
* Convert the object into something JSON serializable. |
312
|
|
|
* |
313
|
|
|
* @return array |
314
|
|
|
*/ |
315
|
2 |
|
public function jsonSerialize() |
316
|
|
|
{ |
317
|
2 |
|
return $this->toArray(); |
318
|
|
|
} |
319
|
|
|
|
320
|
|
|
/* ----------------------------------------------------------------- |
321
|
|
|
| Other Methods |
322
|
|
|
| ----------------------------------------------------------------- |
323
|
|
|
*/ |
324
|
|
|
|
325
|
|
|
/** |
326
|
|
|
* Escape the given value. |
327
|
|
|
* |
328
|
|
|
* @param string $value |
329
|
|
|
* |
330
|
|
|
* @return string |
331
|
|
|
*/ |
332
|
60 |
|
protected function escape($value) |
333
|
|
|
{ |
334
|
60 |
|
if (is_null($value)) |
335
|
16 |
|
return $value; |
336
|
|
|
|
337
|
60 |
|
return config('sitemap.escaping', true) |
338
|
60 |
|
? htmlentities($value, ENT_XML1, 'UTF-8') |
339
|
60 |
|
: $value; |
340
|
|
|
} |
341
|
|
|
|
342
|
|
|
/** |
343
|
|
|
* Determine if the given attribute exists. |
344
|
|
|
* |
345
|
|
|
* @param mixed $offset |
346
|
|
|
* |
347
|
|
|
* @return bool |
348
|
|
|
*/ |
349
|
2 |
|
public function offsetExists($offset) |
350
|
|
|
{ |
351
|
2 |
|
return method_exists($this, 'get'.Str::studly($offset)); |
352
|
|
|
} |
353
|
|
|
|
354
|
|
|
/** |
355
|
|
|
* Get the value for a given offset. |
356
|
|
|
* |
357
|
|
|
* @param mixed $offset |
358
|
|
|
* |
359
|
|
|
* @return mixed |
360
|
|
|
*/ |
361
|
2 |
|
public function offsetGet($offset) |
362
|
|
|
{ |
363
|
2 |
|
return call_user_func([$this, 'get'.Str::studly($offset)]); |
364
|
|
|
} |
365
|
|
|
|
366
|
|
|
/** |
367
|
|
|
* Set the value for a given offset. |
368
|
|
|
* |
369
|
|
|
* @param mixed $offset |
370
|
|
|
* @param mixed $value |
371
|
|
|
* |
372
|
|
|
* @return void |
373
|
|
|
*/ |
374
|
|
|
public function offsetSet($offset, $value) {} // Do nothing... |
375
|
|
|
|
376
|
|
|
/** |
377
|
|
|
* Unset the value for a given offset. |
378
|
|
|
* |
379
|
|
|
* @param mixed $offset |
380
|
|
|
* |
381
|
|
|
* @return void |
382
|
|
|
*/ |
383
|
|
|
public function offsetUnset($offset) {} // Do nothing... |
384
|
|
|
|
385
|
|
|
/** |
386
|
|
|
* Check the loc value. |
387
|
|
|
* |
388
|
|
|
* @param string $loc |
389
|
|
|
* |
390
|
|
|
* @return string |
391
|
|
|
* |
392
|
|
|
* @throws \Arcanedev\LaravelSitemap\Exceptions\SitemapException |
393
|
|
|
*/ |
394
|
76 |
|
protected function checkLoc($loc) |
395
|
|
|
{ |
396
|
76 |
|
if (is_null($loc) || ! is_string($loc)) |
397
|
4 |
|
throw new SitemapException('The [loc] attribute is required and must be string value.'); |
398
|
|
|
|
399
|
76 |
|
return $loc; |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
/** |
403
|
|
|
* Check the priority value. |
404
|
|
|
* |
405
|
|
|
* @param float $priority |
406
|
|
|
* |
407
|
|
|
* @return float |
408
|
|
|
* |
409
|
|
|
* @throws \Arcanedev\LaravelSitemap\Exceptions\SitemapException |
410
|
|
|
*/ |
411
|
76 |
|
protected function checkPriority($priority) |
412
|
|
|
{ |
413
|
76 |
|
if ( ! is_numeric($priority)) |
414
|
2 |
|
throw new SitemapException("The [priority] value must be numeric."); |
415
|
|
|
|
416
|
76 |
|
$priority = round($priority, 1); |
417
|
|
|
|
418
|
76 |
|
if ($priority > 1 || $priority < 0) |
419
|
2 |
|
throw new SitemapException("The [priority] value must be between `0.0` and `1.0`, `{$priority}` was given."); |
420
|
|
|
|
421
|
76 |
|
return $priority; |
422
|
|
|
} |
423
|
|
|
} |
424
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountId
that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theid
property of an instance of theAccount
class. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.