3 namespace Shaarli\Bookmark
;
6 use Shaarli\Bookmark\Exception\InvalidBookmarkException
;
11 * This class represent a single Bookmark with all its attributes.
12 * Every bookmark should manipulated using this, before being formatted.
14 * @package Shaarli\Bookmark
18 /** @var string Date format used in string (former ID format) */
19 const LINK_DATE_FORMAT
= 'Ymd_His';
21 /** @var int Bookmark ID */
24 /** @var string Permalink identifier */
27 /** @var string Bookmark's URL - $shortUrl prefixed with `?` for notes */
30 /** @var string Bookmark's title */
33 /** @var string Raw bookmark's description */
34 protected $description;
36 /** @var array List of bookmark's tags */
39 /** @var string Thumbnail's URL - false if no thumbnail could be found */
42 /** @var bool Set to true if the bookmark is set as sticky */
45 /** @var DateTime Creation datetime */
48 /** @var DateTime Update datetime */
51 /** @var bool True if the bookmark can only be seen while logged in */
55 * Initialize a link from array data. Especially useful to create a Bookmark from former link storage format.
61 public function fromArray($data)
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
= isset($data['thumbnail']) ? $data['thumbnail'] : null;
69 $this->sticky
= isset($data['sticky']) ? $data['sticky'] : false;
70 $this->created
= $data['created'];
71 if (is_array($data['tags'])) {
72 $this->tags
= $data['tags'];
74 $this->tags
= preg_split('/\s+/', $data['tags'], -1, PREG_SPLIT_NO_EMPTY
);
76 if (! empty($data['updated'])) {
77 $this->updated
= $data['updated'];
79 $this->private = $data['private'] ? true : false;
85 * Make sure that the current instance of Bookmark is valid and can be saved into the data store.
86 * A valid link requires:
88 * - a short URL (for permalinks)
91 * This function also initialize optional empty fields:
92 * - the URL with the permalink
93 * - the title with the URL
95 * @throws InvalidBookmarkException
97 public function validate()
99 if ($this->id
=== null
100 || ! is_int($this->id
)
101 || empty($this->shortUrl
)
102 || empty($this->created
)
103 || ! $this->created
instanceof DateTime
105 throw new InvalidBookmarkException($this);
107 if (empty($this->url
)) {
108 $this->url
= '?'. $this->shortUrl
;
110 if (empty($this->title
)) {
111 $this->title
= $this->url
;
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
125 public function setId($id)
128 if (empty($this->created
)) {
129 $this->created
= new DateTime();
131 if (empty($this->shortUrl
)) {
132 $this->shortUrl
= link_small_hash($this->created
, $this->id
);
143 public function getId()
153 public function getShortUrl()
155 return $this->shortUrl
;
163 public function getUrl()
173 public function getTitle()
179 * Get the Description.
183 public function getDescription()
185 return ! empty($this->description
) ? $this->description
: '';
193 public function getCreated()
195 return $this->created
;
203 public function getUpdated()
205 return $this->updated
;
211 * @param string $shortUrl
215 public function setShortUrl($shortUrl)
217 $this->shortUrl
= $shortUrl;
226 * @param array $allowedProtocols
230 public function setUrl($url, $allowedProtocols = [])
234 $url = whitelist_protocols($url, $allowedProtocols);
244 * @param string $title
248 public function setTitle($title)
250 $this->title
= trim($title);
256 * Set the Description.
258 * @param string $description
262 public function setDescription($description)
264 $this->description
= $description;
271 * Note: you shouldn't set this manually except for special cases (like bookmark import)
273 * @param DateTime $created
277 public function setCreated($created)
279 $this->created
= $created;
287 * @param DateTime $updated
291 public function setUpdated($updated)
293 $this->updated
= $updated;
303 public function isPrivate()
305 return $this->private ? true : false;
311 * @param bool $private
315 public function setPrivate($private)
317 $this->private = $private ? true : false;
327 public function getTags()
329 return is_array($this->tags
) ? $this->tags
: [];
339 public function setTags($tags)
341 $this->setTagsString(implode(' ', $tags));
349 * @return string|bool|null
351 public function getThumbnail()
353 return !$this->isNote() ? $this->thumbnail
: false;
359 * @param string|bool $thumbnail
363 public function setThumbnail($thumbnail)
365 $this->thumbnail
= $thumbnail;
375 public function isSticky()
377 return $this->sticky
? true : false;
383 * @param bool $sticky
387 public function setSticky($sticky)
389 $this->sticky
= $sticky ? true : false;
395 * @return string Bookmark's tags as a string, separated by a space
397 public function getTagsString()
399 return implode(' ', $this->getTags());
405 public function isNote()
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] === '?';
412 * Set tags from a string.
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
418 * @param string $tags
422 public function setTagsString($tags)
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));
437 * Rename a tag in tags list.
439 * @param string $fromTag
440 * @param string $toTag
442 public function renameTag($fromTag, $toTag)
444 if (($pos = array_search($fromTag, $this->tags)) !== false) {
445 $this->tags[$pos] = trim($toTag);
450 * Delete a tag from tags list.
454 public function deleteTag($tag)
456 if (($pos = array_search($tag, $this->tags)) !== false) {
457 unset($this->tags[$pos]);
458 $this->tags = array_values($this->tags);