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