]> git.immae.eu Git - github/shaarli/Shaarli.git/blob - application/bookmark/Bookmark.php
1beb8be2e127a2b0b905e71e256b0279f8018598
[github/shaarli/Shaarli.git] / application / bookmark / Bookmark.php
1 <?php
2
3 namespace Shaarli\Bookmark;
4
5 use DateTime;
6 use DateTimeInterface;
7 use Shaarli\Bookmark\Exception\InvalidBookmarkException;
8
9 /**
10 * Class Bookmark
11 *
12 * This class represent a single Bookmark with all its attributes.
13 * Every bookmark should manipulated using this, before being formatted.
14 *
15 * @package Shaarli\Bookmark
16 */
17 class Bookmark
18 {
19 /** @var string Date format used in string (former ID format) */
20 const LINK_DATE_FORMAT = 'Ymd_His';
21
22 /** @var int Bookmark ID */
23 protected $id;
24
25 /** @var string Permalink identifier */
26 protected $shortUrl;
27
28 /** @var string Bookmark's URL - $shortUrl prefixed with `?` for notes */
29 protected $url;
30
31 /** @var string Bookmark's title */
32 protected $title;
33
34 /** @var string Raw bookmark's description */
35 protected $description;
36
37 /** @var array List of bookmark's tags */
38 protected $tags;
39
40 /** @var string|bool|null Thumbnail's URL - initialized at null, false if no thumbnail could be found */
41 protected $thumbnail;
42
43 /** @var bool Set to true if the bookmark is set as sticky */
44 protected $sticky;
45
46 /** @var DateTimeInterface Creation datetime */
47 protected $created;
48
49 /** @var DateTimeInterface datetime */
50 protected $updated;
51
52 /** @var bool True if the bookmark can only be seen while logged in */
53 protected $private;
54
55 /**
56 * Initialize a link from array data. Especially useful to create a Bookmark from former link storage format.
57 *
58 * @param array $data
59 *
60 * @return $this
61 */
62 public function fromArray($data)
63 {
64 $this->id = $data['id'];
65 $this->shortUrl = $data['shorturl'];
66 $this->url = $data['url'];
67 $this->title = $data['title'];
68 $this->description = $data['description'];
69 $this->thumbnail = isset($data['thumbnail']) ? $data['thumbnail'] : null;
70 $this->sticky = isset($data['sticky']) ? $data['sticky'] : false;
71 $this->created = $data['created'];
72 if (is_array($data['tags'])) {
73 $this->tags = $data['tags'];
74 } else {
75 $this->tags = preg_split('/\s+/', $data['tags'], -1, PREG_SPLIT_NO_EMPTY);
76 }
77 if (! empty($data['updated'])) {
78 $this->updated = $data['updated'];
79 }
80 $this->private = $data['private'] ? true : false;
81
82 return $this;
83 }
84
85 /**
86 * Make sure that the current instance of Bookmark is valid and can be saved into the data store.
87 * A valid link requires:
88 * - an integer ID
89 * - a short URL (for permalinks)
90 * - a creation date
91 *
92 * This function also initialize optional empty fields:
93 * - the URL with the permalink
94 * - the title with the URL
95 *
96 * @throws InvalidBookmarkException
97 */
98 public function validate()
99 {
100 if ($this->id === null
101 || ! is_int($this->id)
102 || empty($this->shortUrl)
103 || empty($this->created)
104 || ! $this->created instanceof DateTimeInterface
105 ) {
106 throw new InvalidBookmarkException($this);
107 }
108 if (empty($this->url)) {
109 $this->url = '/shaare/'. $this->shortUrl;
110 }
111 if (empty($this->title)) {
112 $this->title = $this->url;
113 }
114 }
115
116 /**
117 * Set the Id.
118 * If they're not already initialized, this function also set:
119 * - created: with the current datetime
120 * - shortUrl: with a generated small hash from the date and the given ID
121 *
122 * @param int $id
123 *
124 * @return Bookmark
125 */
126 public function setId($id)
127 {
128 $this->id = $id;
129 if (empty($this->created)) {
130 $this->created = new DateTime();
131 }
132 if (empty($this->shortUrl)) {
133 $this->shortUrl = link_small_hash($this->created, $this->id);
134 }
135
136 return $this;
137 }
138
139 /**
140 * Get the Id.
141 *
142 * @return int
143 */
144 public function getId()
145 {
146 return $this->id;
147 }
148
149 /**
150 * Get the ShortUrl.
151 *
152 * @return string
153 */
154 public function getShortUrl()
155 {
156 return $this->shortUrl;
157 }
158
159 /**
160 * Get the Url.
161 *
162 * @return string
163 */
164 public function getUrl()
165 {
166 return $this->url;
167 }
168
169 /**
170 * Get the Title.
171 *
172 * @return string
173 */
174 public function getTitle()
175 {
176 return $this->title;
177 }
178
179 /**
180 * Get the Description.
181 *
182 * @return string
183 */
184 public function getDescription()
185 {
186 return ! empty($this->description) ? $this->description : '';
187 }
188
189 /**
190 * Get the Created.
191 *
192 * @return DateTimeInterface
193 */
194 public function getCreated()
195 {
196 return $this->created;
197 }
198
199 /**
200 * Get the Updated.
201 *
202 * @return DateTimeInterface
203 */
204 public function getUpdated()
205 {
206 return $this->updated;
207 }
208
209 /**
210 * Set the ShortUrl.
211 *
212 * @param string $shortUrl
213 *
214 * @return Bookmark
215 */
216 public function setShortUrl($shortUrl)
217 {
218 $this->shortUrl = $shortUrl;
219
220 return $this;
221 }
222
223 /**
224 * Set the Url.
225 *
226 * @param string $url
227 * @param array $allowedProtocols
228 *
229 * @return Bookmark
230 */
231 public function setUrl($url, $allowedProtocols = [])
232 {
233 $url = trim($url);
234 if (! empty($url)) {
235 $url = whitelist_protocols($url, $allowedProtocols);
236 }
237 $this->url = $url;
238
239 return $this;
240 }
241
242 /**
243 * Set the Title.
244 *
245 * @param string $title
246 *
247 * @return Bookmark
248 */
249 public function setTitle($title)
250 {
251 $this->title = trim($title);
252
253 return $this;
254 }
255
256 /**
257 * Set the Description.
258 *
259 * @param string $description
260 *
261 * @return Bookmark
262 */
263 public function setDescription($description)
264 {
265 $this->description = $description;
266
267 return $this;
268 }
269
270 /**
271 * Set the Created.
272 * Note: you shouldn't set this manually except for special cases (like bookmark import)
273 *
274 * @param DateTimeInterface $created
275 *
276 * @return Bookmark
277 */
278 public function setCreated($created)
279 {
280 $this->created = $created;
281
282 return $this;
283 }
284
285 /**
286 * Set the Updated.
287 *
288 * @param DateTimeInterface $updated
289 *
290 * @return Bookmark
291 */
292 public function setUpdated($updated)
293 {
294 $this->updated = $updated;
295
296 return $this;
297 }
298
299 /**
300 * Get the Private.
301 *
302 * @return bool
303 */
304 public function isPrivate()
305 {
306 return $this->private ? true : false;
307 }
308
309 /**
310 * Set the Private.
311 *
312 * @param bool $private
313 *
314 * @return Bookmark
315 */
316 public function setPrivate($private)
317 {
318 $this->private = $private ? true : false;
319
320 return $this;
321 }
322
323 /**
324 * Get the Tags.
325 *
326 * @return array
327 */
328 public function getTags()
329 {
330 return is_array($this->tags) ? $this->tags : [];
331 }
332
333 /**
334 * Set the Tags.
335 *
336 * @param array $tags
337 *
338 * @return Bookmark
339 */
340 public function setTags($tags)
341 {
342 $this->setTagsString(implode(' ', $tags));
343
344 return $this;
345 }
346
347 /**
348 * Get the Thumbnail.
349 *
350 * @return string|bool|null Thumbnail's URL - initialized at null, false if no thumbnail could be found
351 */
352 public function getThumbnail()
353 {
354 return !$this->isNote() ? $this->thumbnail : false;
355 }
356
357 /**
358 * Set the Thumbnail.
359 *
360 * @param string|bool $thumbnail Thumbnail's URL - false if no thumbnail could be found
361 *
362 * @return Bookmark
363 */
364 public function setThumbnail($thumbnail)
365 {
366 $this->thumbnail = $thumbnail;
367
368 return $this;
369 }
370
371 /**
372 * Get the Sticky.
373 *
374 * @return bool
375 */
376 public function isSticky()
377 {
378 return $this->sticky ? true : false;
379 }
380
381 /**
382 * Set the Sticky.
383 *
384 * @param bool $sticky
385 *
386 * @return Bookmark
387 */
388 public function setSticky($sticky)
389 {
390 $this->sticky = $sticky ? true : false;
391
392 return $this;
393 }
394
395 /**
396 * @return string Bookmark's tags as a string, separated by a space
397 */
398 public function getTagsString()
399 {
400 return implode(' ', $this->getTags());
401 }
402
403 /**
404 * @return bool
405 */
406 public function isNote()
407 {
408 // We check empty value to get a valid result if the link has not been saved yet
409 return empty($this->url) || startsWith($this->url, '/shaare/') || $this->url[0] === '?';
410 }
411
412 /**
413 * Set tags from a string.
414 * Note:
415 * - tags must be separated whether by a space or a comma
416 * - multiple spaces will be removed
417 * - trailing dash in tags will be removed
418 *
419 * @param string $tags
420 *
421 * @return $this
422 */
423 public function setTagsString($tags)
424 {
425 // Remove first '-' char in tags.
426 $tags = preg_replace('/(^| )\-/', '$1', $tags);
427 // Explode all tags separted by spaces or commas
428 $tags = preg_split('/[\s,]+/', $tags);
429 // Remove eventual empty values
430 $tags = array_values(array_filter($tags));
431
432 $this->tags = $tags;
433
434 return $this;
435 }
436
437 /**
438 * Rename a tag in tags list.
439 *
440 * @param string $fromTag
441 * @param string $toTag
442 */
443 public function renameTag($fromTag, $toTag)
444 {
445 if (($pos = array_search($fromTag, $this->tags)) !== false) {
446 $this->tags[$pos] = trim($toTag);
447 }
448 }
449
450 /**
451 * Delete a tag from tags list.
452 *
453 * @param string $tag
454 */
455 public function deleteTag($tag)
456 {
457 if (($pos = array_search($tag, $this->tags)) !== false) {
458 unset($this->tags[$pos]);
459 $this->tags = array_values($this->tags);
460 }
461 }
462 }