Completed
Pull Request — master (#9)
by ARCANEDEV
02:40
created

Url::escape()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 9
c 0
b 0
f 0
cc 3
eloc 6
nc 3
nop 1
ccs 6
cts 6
cp 1
crap 3
rs 9.6666
1
<?php namespace Arcanedev\LaravelSitemap\Entities;
2
3
use DateTime;
4
use Arcanedev\LaravelSitemap\Contracts\Entities\Url as UrlContract;
5
/**
6
 * Class     Url
7
 *
8
 * @package  Arcanedev\LaravelSitemap\Entities
9
 * @author   ARCANEDEV <[email protected]>
10
 */
11
class Url implements UrlContract
12
{
13
    /* -----------------------------------------------------------------
14
     |  Properties
15
     | -----------------------------------------------------------------
16
     */
17
18
    /** @var  string  */
19
    protected $loc;
20
21
    /** @var  string|null */
22
    protected $title;
23
24
    /** @var  \Carbon\Carbon */
25
    protected $lastModDate;
26
27
    /** @var  string */
28
    protected $changeFrequency;
29
30
    /** @var  float */
31
    protected $priority;
32
33
    /* -----------------------------------------------------------------
34
     |  Constructor
35
     | -----------------------------------------------------------------
36
     */
37
38
    /**
39
     * Url constructor.
40
     *
41
     * @param  string  $loc
42
     */
43 48
    public function __construct($loc)
44
    {
45 48
        $this->setLoc($loc);
46 48
        $this->setLastMod(new DateTime);
47 48
        $this->setChangeFreq(static::CHANGE_FREQUENCY_DAILY);
48 48
        $this->setPriority(0.8);
49 48
    }
50
51
    /* -----------------------------------------------------------------
52
     |  Getters & Setters
53
     | -----------------------------------------------------------------
54
     */
55
56
    /**
57
     * Get the url location.
58
     *
59
     * @return string
60
     */
61 38
    public function getLoc()
62
    {
63 38
        return $this->escape($this->loc);
64
    }
65
66
    /**
67
     * Get the url location (alias).
68
     *
69
     * @see getLoc()
70
     *
71
     * @return string
72
     */
73 6
    public function loc()
74
    {
75 6
        return $this->getLoc();
76
    }
77
78
    /**
79
     * Set the url location.
80
     *
81
     * @param  string  $loc
82
     *
83
     * @return self
84
     */
85 48
    public function setLoc($loc)
86
    {
87 48
        $this->loc = $loc;
88
89 48
        return $this;
90
    }
91
92
    /**
93
     * Get the last modification date.
94
     *
95
     * @return DateTime
96
     */
97 24
    public function getLastMod()
98
    {
99 24
        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...
100
    }
101
102
    /**
103
     * Get the last modification date (alias).
104
     *
105
     * @see getLastMod()
106
     *
107
     * @return \DateTimeInterface
108
     */
109 6
    public function lastMod()
110
    {
111 6
        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...
112
    }
113
114
    /**
115
     * Format the url last modification.
116
     *
117
     * @param  string  $format
118
     *
119
     * @return string
120
     */
121 18
    public function formatLastMod($format = DateTime::ATOM)
122
    {
123 18
        return $this->getLastMod()->format($format);
124
    }
125
126
    /**
127
     * Set the last modification date.
128
     *
129
     * @param  string|DateTime  $lastModDate
130
     * @param  string           $format
131
     *
132
     * @return self
133
     */
134 48
    public function setLastMod($lastModDate, $format = 'Y-m-d H:i:s')
135
    {
136 48
        $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...
137 32
            ? DateTime::createFromFormat($format, $lastModDate)
138 48
            : $lastModDate;
139
140 48
        return $this;
141
    }
142
143
    /**
144
     * Get the change frequency.
145
     *
146
     * @return string
147
     */
148 22
    public function getChangeFreq()
149
    {
150 22
        return $this->changeFrequency;
151
    }
152
153
    /**
154
     * Get the change frequency (alias).
155
     *
156
     * @see getChangeFreq()
157
     *
158
     * @return string
159
     */
160 6
    public function changeFreq()
161
    {
162 6
        return $this->getChangeFreq();
163
    }
164
165
    /**
166
     * Set the change frequency.
167
     *
168
     * @param  string  $changeFreq
169
     *
170
     * @return self
171
     */
172 48
    public function setChangeFreq($changeFreq)
173
    {
174 48
        $this->changeFrequency = $changeFreq;
175
176 48
        return $this;
177
    }
178
179
    /**
180
     * Get the priority.
181
     *
182
     * @return float
183
     */
184 22
    public function getPriority()
185
    {
186 22
        return $this->priority;
187
    }
188
189
    /**
190
     * Get the priority (alias).
191
     *
192
     * @see getPriority()
193
     *
194
     * @return float
195
     */
196 6
    public function priority()
197
    {
198 6
        return $this->getPriority();
199
    }
200
201
    /**
202
     * Set the priority.
203
     *
204
     * @param  float  $priority
205
     *
206
     * @return self
207
     */
208 48
    public function setPriority($priority)
209
    {
210 48
        $this->priority = (float) $priority;
211
212 48
        return $this;
213
    }
214
215
    /**
216
     * Get the title.
217
     *
218
     * @return string|null
219
     */
220 6
    public function getTitle()
221
    {
222 6
        return $this->escape($this->title);
223
    }
224
225
    /**
226
     * Get the title.
227
     *
228
     * @param  string  $title
229
     *
230
     * @return self
231
     */
232 28
    public function setTitle($title)
233
    {
234 28
        $this->title = $title;
235
236 28
        return $this;
237
    }
238
239
    /* -----------------------------------------------------------------
240
     |  Main Methods
241
     | -----------------------------------------------------------------
242
     */
243
244
    /**
245
     * Create a sitemap url instance.
246
     *
247
     * @param  string  $loc
248
     *
249
     * @return \Arcanedev\LaravelSitemap\Entities\Url
250
     */
251 32
    public static function make($loc)
252
    {
253 32
        return new static($loc);
254
    }
255
256
    /**
257
     * Get the collection of items as a plain array.
258
     *
259
     * @return array
260
     */
261 12
    public function toArray()
262
    {
263
        return [
264 12
            'loc'        => $this->getLoc(),
265 12
            'lastmod'    => $this->formatLastMod(),
266 12
            'changefreq' => $this->getChangeFreq(),
267 12
            'priority'   => $this->getPriority(),
268
        ];
269
    }
270
271
    /**
272
     * Get the sitemap url as JSON.
273
     *
274
     * @param  int  $options
275
     *
276
     * @return string
277
     */
278 2
    public function toJson($options = 0)
279
    {
280 2
        return json_encode($this->jsonSerialize(), $options);
281
    }
282
283
    /**
284
     * Convert the object into something JSON serializable.
285
     *
286
     * @return array
287
     */
288 2
    public function jsonSerialize()
289
    {
290 2
        return $this->toArray();
291
    }
292
293
    /* -----------------------------------------------------------------
294
     |  Other Methods
295
     | -----------------------------------------------------------------
296
     */
297
298
    /**
299
     * Escape the given value.
300
     *
301
     * @param  string  $value
302
     *
303
     * @return string
304
     */
305 40
    protected function escape($value)
306
    {
307 40
        if (is_null($value))
308 2
            return $value;
309
310 40
        return config('sitemap.escaping', true)
311 40
            ? htmlentities($value, ENT_XML1, 'UTF-8')
312 40
            : $value;
313
    }
314
}
315