Completed
Pull Request — master (#9)
by ARCANEDEV
03:59
created

Url::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 7
c 0
b 0
f 0
cc 1
eloc 5
nc 1
nop 1
ccs 6
cts 6
cp 1
crap 1
rs 9.4285
1
<?php namespace Arcanedev\LaravelSitemap\Entities;
2
3
use ArrayAccess;
4
use DateTime;
5
use Arcanedev\LaravelSitemap\Contracts\Entities\Url as UrlContract;
6
use Illuminate\Support\Str;
7
8
/**
9
 * Class     Url
10
 *
11
 * @package  Arcanedev\LaravelSitemap\Entities
12
 * @author   ARCANEDEV <[email protected]>
13
 */
14
class Url implements ArrayAccess, UrlContract
15
{
16
    /* -----------------------------------------------------------------
17
     |  Properties
18
     | -----------------------------------------------------------------
19
     */
20
21
    /** @var  string  */
22
    protected $loc;
23
24
    /** @var  string|null */
25
    protected $title;
26
27
    /** @var  \Carbon\Carbon */
28
    protected $lastModDate;
29
30
    /** @var  string */
31
    protected $changeFrequency;
32
33
    /** @var  float */
34
    protected $priority;
35
36
    /* -----------------------------------------------------------------
37
     |  Constructor
38
     | -----------------------------------------------------------------
39
     */
40
41
    /**
42
     * Url constructor.
43
     *
44
     * @param  string  $loc
45
     */
46 56
    public function __construct($loc)
47
    {
48 56
        $this->setLoc($loc);
49 56
        $this->setLastMod(new DateTime);
50 56
        $this->setChangeFreq(static::CHANGE_FREQUENCY_DAILY);
51 56
        $this->setPriority(0.8);
52 56
    }
53
54
    /* -----------------------------------------------------------------
55
     |  Getters & Setters
56
     | -----------------------------------------------------------------
57
     */
58
59
    /**
60
     * Get the url location.
61
     *
62
     * @return string
63
     */
64 46
    public function getLoc()
65
    {
66 46
        return $this->escape($this->loc);
67
    }
68
69
    /**
70
     * Get the url location (alias).
71
     *
72
     * @see getLoc()
73
     *
74
     * @return string
75
     */
76 10
    public function loc()
77
    {
78 10
        return $this->getLoc();
79
    }
80
81
    /**
82
     * Set the url location.
83
     *
84
     * @param  string  $loc
85
     *
86
     * @return self
87
     */
88 56
    public function setLoc($loc)
89
    {
90 56
        $this->loc = $loc;
91
92 56
        return $this;
93
    }
94
95
    /**
96
     * Get the last modification date.
97
     *
98
     * @return DateTime
99
     */
100 26
    public function getLastMod()
101
    {
102 26
        return $this->lastModDate;
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->lastModDate; (Carbon\Carbon) is incompatible with the return type declared by the interface Arcanedev\LaravelSitemap...ntities\Url::getLastMod of type DateTimeInterface.

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...
103
    }
104
105
    /**
106
     * Get the last modification date (alias).
107
     *
108
     * @see getLastMod()
109
     *
110
     * @return \DateTimeInterface
111
     */
112 8
    public function lastMod()
113
    {
114 8
        return $this->getLastMod();
0 ignored issues
show
Bug Best Practice introduced by
The return type of return $this->getLastMod(); (Carbon\Carbon) is incompatible with the return type declared by the interface Arcanedev\LaravelSitemap...s\Entities\Url::lastMod of type DateTimeInterface.

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...
115
    }
116
117
    /**
118
     * Format the url last modification.
119
     *
120
     * @param  string  $format
121
     *
122
     * @return string
123
     */
124 20
    public function formatLastMod($format = DateTime::ATOM)
125
    {
126 20
        return $this->getLastMod()->format($format);
127
    }
128
129
    /**
130
     * Set the last modification date.
131
     *
132
     * @param  string|DateTime  $lastModDate
133
     * @param  string           $format
134
     *
135
     * @return self
136
     */
137 56
    public function setLastMod($lastModDate, $format = 'Y-m-d H:i:s')
138
    {
139 56
        $this->lastModDate = gettype($lastModDate) === 'string'
0 ignored issues
show
Documentation Bug introduced by
It seems like gettype($lastModDate) ==...ModDate) : $lastModDate of type object<DateTime> is incompatible with the declared type object<Carbon\Carbon> of property $lastModDate.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
140 40
            ? DateTime::createFromFormat($format, $lastModDate)
141 56
            : $lastModDate;
142
143 56
        return $this;
144
    }
145
146
    /**
147
     * Get the change frequency.
148
     *
149
     * @return string
150
     */
151 24
    public function getChangeFreq()
152
    {
153 24
        return $this->changeFrequency;
154
    }
155
156
    /**
157
     * Get the change frequency (alias).
158
     *
159
     * @see getChangeFreq()
160
     *
161
     * @return string
162
     */
163 8
    public function changeFreq()
164
    {
165 8
        return $this->getChangeFreq();
166
    }
167
168
    /**
169
     * Set the change frequency.
170
     *
171
     * @param  string  $changeFreq
172
     *
173
     * @return self
174
     */
175 56
    public function setChangeFreq($changeFreq)
176
    {
177 56
        $this->changeFrequency = $changeFreq;
178
179 56
        return $this;
180
    }
181
182
    /**
183
     * Get the priority.
184
     *
185
     * @return float
186
     */
187 24
    public function getPriority()
188
    {
189 24
        return $this->priority;
190
    }
191
192
    /**
193
     * Get the priority (alias).
194
     *
195
     * @see getPriority()
196
     *
197
     * @return float
198
     */
199 8
    public function priority()
200
    {
201 8
        return $this->getPriority();
202
    }
203
204
    /**
205
     * Set the priority.
206
     *
207
     * @param  float  $priority
208
     *
209
     * @return self
210
     */
211 56
    public function setPriority($priority)
212
    {
213 56
        $this->priority = (float) $priority;
214
215 56
        return $this;
216
    }
217
218
    /**
219
     * Get the title.
220
     *
221
     * @return string|null
222
     */
223 10
    public function getTitle()
224
    {
225 10
        return $this->escape($this->title);
226
    }
227
228
    /**
229
     * Get the title.
230
     *
231
     * @param  string  $title
232
     *
233
     * @return self
234
     */
235 36
    public function setTitle($title)
236
    {
237 36
        $this->title = $title;
238
239 36
        return $this;
240
    }
241
242
    /* -----------------------------------------------------------------
243
     |  Main Methods
244
     | -----------------------------------------------------------------
245
     */
246
247
    /**
248
     * Create a sitemap url instance.
249
     *
250
     * @param  string  $loc
251
     *
252
     * @return \Arcanedev\LaravelSitemap\Entities\Url
253
     */
254 40
    public static function make($loc)
255
    {
256 40
        return new static($loc);
257
    }
258
259
    /**
260
     * Get the collection of items as a plain array.
261
     *
262
     * @return array
263
     */
264 12
    public function toArray()
265
    {
266
        return [
267 12
            'loc'        => $this->getLoc(),
268 12
            'lastmod'    => $this->formatLastMod(),
269 12
            'changefreq' => $this->getChangeFreq(),
270 12
            'priority'   => $this->getPriority(),
271
        ];
272
    }
273
274
    /**
275
     * Get the sitemap url as JSON.
276
     *
277
     * @param  int  $options
278
     *
279
     * @return string
280
     */
281 2
    public function toJson($options = 0)
282
    {
283 2
        return json_encode($this->jsonSerialize(), $options);
284
    }
285
286
    /**
287
     * Convert the object into something JSON serializable.
288
     *
289
     * @return array
290
     */
291 2
    public function jsonSerialize()
292
    {
293 2
        return $this->toArray();
294
    }
295
296
    /* -----------------------------------------------------------------
297
     |  Other Methods
298
     | -----------------------------------------------------------------
299
     */
300
301
    /**
302
     * Escape the given value.
303
     *
304
     * @param  string  $value
305
     *
306
     * @return string
307
     */
308 48
    protected function escape($value)
309
    {
310 48
        if (is_null($value))
311 4
            return $value;
312
313 48
        return config('sitemap.escaping', true)
314 48
            ? htmlentities($value, ENT_XML1, 'UTF-8')
315 48
            : $value;
316
    }
317
318
    /**
319
     * Determine if the given attribute exists.
320
     *
321
     * @param  mixed  $offset
322
     *
323
     * @return bool
324
     */
325 2
    public function offsetExists($offset)
326
    {
327 2
        return method_exists($this, 'get'.Str::studly($offset));
328
    }
329
330
    /**
331
     * Get the value for a given offset.
332
     *
333
     * @param  mixed  $offset
334
     *
335
     * @return mixed
336
     */
337 2
    public function offsetGet($offset)
338
    {
339 2
        return call_user_func([$this, 'get'.Str::studly($offset)]);
340
    }
341
342
    /**
343
     * Set the value for a given offset.
344
     *
345
     * @param  mixed  $offset
346
     * @param  mixed  $value
347
     *
348
     * @return void
349
     */
350
    public function offsetSet($offset, $value) {} // Do nothing...
351
352
    /**
353
     * Unset the value for a given offset.
354
     *
355
     * @param  mixed  $offset
356
     *
357
     * @return void
358
     */
359
    public function offsetUnset($offset) {} // Do nothing...
360
}
361