]> git.immae.eu Git - github/shaarli/Shaarli.git/blobdiff - application/bookmark/Bookmark.php
Store bookmarks as PHP objects and add a service layer to retriā€¦ (#1307)
[github/shaarli/Shaarli.git] / application / bookmark / Bookmark.php
diff --git a/application/bookmark/Bookmark.php b/application/bookmark/Bookmark.php
new file mode 100644 (file)
index 0000000..f9b21d3
--- /dev/null
@@ -0,0 +1,461 @@
+<?php
+
+namespace Shaarli\Bookmark;
+
+use DateTime;
+use Shaarli\Bookmark\Exception\InvalidBookmarkException;
+
+/**
+ * Class Bookmark
+ *
+ * This class represent a single Bookmark with all its attributes.
+ * Every bookmark should manipulated using this, before being formatted.
+ *
+ * @package Shaarli\Bookmark
+ */
+class Bookmark
+{
+    /** @var string Date format used in string (former ID format) */
+    const LINK_DATE_FORMAT = 'Ymd_His';
+
+    /** @var int Bookmark ID */
+    protected $id;
+
+    /** @var string Permalink identifier */
+    protected $shortUrl;
+
+    /** @var string Bookmark's URL - $shortUrl prefixed with `?` for notes */
+    protected $url;
+
+    /** @var string Bookmark's title */
+    protected $title;
+
+    /** @var string Raw bookmark's description */
+    protected $description;
+
+    /** @var array List of bookmark's tags */
+    protected $tags;
+
+    /** @var string Thumbnail's URL - false if no thumbnail could be found */
+    protected $thumbnail;
+
+    /** @var bool Set to true if the bookmark is set as sticky */
+    protected $sticky;
+
+    /** @var DateTime Creation datetime */
+    protected $created;
+
+    /** @var DateTime Update datetime */
+    protected $updated;
+
+    /** @var bool True if the bookmark can only be seen while logged in */
+    protected $private;
+
+    /**
+     * Initialize a link from array data. Especially useful to create a Bookmark from former link storage format.
+     *
+     * @param array $data
+     *
+     * @return $this
+     */
+    public function fromArray($data)
+    {
+        $this->id = $data['id'];
+        $this->shortUrl = $data['shorturl'];
+        $this->url = $data['url'];
+        $this->title = $data['title'];
+        $this->description = $data['description'];
+        $this->thumbnail = isset($data['thumbnail']) ? $data['thumbnail'] : null;
+        $this->sticky = isset($data['sticky']) ? $data['sticky'] : false;
+        $this->created = $data['created'];
+        if (is_array($data['tags'])) {
+            $this->tags = $data['tags'];
+        } else {
+            $this->tags = preg_split('/\s+/', $data['tags'], -1, PREG_SPLIT_NO_EMPTY);
+        }
+        if (! empty($data['updated'])) {
+            $this->updated = $data['updated'];
+        }
+        $this->private = $data['private'] ? true : false;
+
+        return $this;
+    }
+
+    /**
+     * Make sure that the current instance of Bookmark is valid and can be saved into the data store.
+     * A valid link requires:
+     *   - an integer ID
+     *   - a short URL (for permalinks)
+     *   - a creation date
+     *
+     * This function also initialize optional empty fields:
+     *   - the URL with the permalink
+     *   - the title with the URL
+     *
+     * @throws InvalidBookmarkException
+     */
+    public function validate()
+    {
+        if ($this->id === null
+            || ! is_int($this->id)
+            || empty($this->shortUrl)
+            || empty($this->created)
+            || ! $this->created instanceof DateTime
+        ) {
+            throw new InvalidBookmarkException($this);
+        }
+        if (empty($this->url)) {
+            $this->url = '?'. $this->shortUrl;
+        }
+        if (empty($this->title)) {
+            $this->title = $this->url;
+        }
+    }
+
+    /**
+     * Set the Id.
+     * If they're not already initialized, this function also set:
+     *   - created: with the current datetime
+     *   - shortUrl: with a generated small hash from the date and the given ID
+     *
+     * @param int $id
+     *
+     * @return Bookmark
+     */
+    public function setId($id)
+    {
+        $this->id = $id;
+        if (empty($this->created)) {
+            $this->created = new DateTime();
+        }
+        if (empty($this->shortUrl)) {
+            $this->shortUrl = link_small_hash($this->created, $this->id);
+        }
+
+        return $this;
+    }
+
+    /**
+     * Get the Id.
+     *
+     * @return int
+     */
+    public function getId()
+    {
+        return $this->id;
+    }
+
+    /**
+     * Get the ShortUrl.
+     *
+     * @return string
+     */
+    public function getShortUrl()
+    {
+        return $this->shortUrl;
+    }
+
+    /**
+     * Get the Url.
+     *
+     * @return string
+     */
+    public function getUrl()
+    {
+        return $this->url;
+    }
+
+    /**
+     * Get the Title.
+     *
+     * @return string
+     */
+    public function getTitle()
+    {
+        return $this->title;
+    }
+
+    /**
+     * Get the Description.
+     *
+     * @return string
+     */
+    public function getDescription()
+    {
+        return ! empty($this->description) ? $this->description : '';
+    }
+
+    /**
+     * Get the Created.
+     *
+     * @return DateTime
+     */
+    public function getCreated()
+    {
+        return $this->created;
+    }
+
+    /**
+     * Get the Updated.
+     *
+     * @return DateTime
+     */
+    public function getUpdated()
+    {
+        return $this->updated;
+    }
+
+    /**
+     * Set the ShortUrl.
+     *
+     * @param string $shortUrl
+     *
+     * @return Bookmark
+     */
+    public function setShortUrl($shortUrl)
+    {
+        $this->shortUrl = $shortUrl;
+
+        return $this;
+    }
+
+    /**
+     * Set the Url.
+     *
+     * @param string $url
+     * @param array  $allowedProtocols
+     *
+     * @return Bookmark
+     */
+    public function setUrl($url, $allowedProtocols = [])
+    {
+        $url = trim($url);
+        if (! empty($url)) {
+            $url = whitelist_protocols($url, $allowedProtocols);
+        }
+        $this->url = $url;
+
+        return $this;
+    }
+
+    /**
+     * Set the Title.
+     *
+     * @param string $title
+     *
+     * @return Bookmark
+     */
+    public function setTitle($title)
+    {
+        $this->title = trim($title);
+
+        return $this;
+    }
+
+    /**
+     * Set the Description.
+     *
+     * @param string $description
+     *
+     * @return Bookmark
+     */
+    public function setDescription($description)
+    {
+        $this->description = $description;
+
+        return $this;
+    }
+
+    /**
+     * Set the Created.
+     * Note: you shouldn't set this manually except for special cases (like bookmark import)
+     *
+     * @param DateTime $created
+     *
+     * @return Bookmark
+     */
+    public function setCreated($created)
+    {
+        $this->created = $created;
+
+        return $this;
+    }
+
+    /**
+     * Set the Updated.
+     *
+     * @param DateTime $updated
+     *
+     * @return Bookmark
+     */
+    public function setUpdated($updated)
+    {
+        $this->updated = $updated;
+
+        return $this;
+    }
+
+    /**
+     * Get the Private.
+     *
+     * @return bool
+     */
+    public function isPrivate()
+    {
+        return $this->private ? true : false;
+    }
+
+    /**
+     * Set the Private.
+     *
+     * @param bool $private
+     *
+     * @return Bookmark
+     */
+    public function setPrivate($private)
+    {
+        $this->private = $private ? true : false;
+
+        return $this;
+    }
+
+    /**
+     * Get the Tags.
+     *
+     * @return array
+     */
+    public function getTags()
+    {
+        return is_array($this->tags) ? $this->tags : [];
+    }
+
+    /**
+     * Set the Tags.
+     *
+     * @param array $tags
+     *
+     * @return Bookmark
+     */
+    public function setTags($tags)
+    {
+        $this->setTagsString(implode(' ', $tags));
+
+        return $this;
+    }
+
+    /**
+     * Get the Thumbnail.
+     *
+     * @return string|bool
+     */
+    public function getThumbnail()
+    {
+        return !$this->isNote() ? $this->thumbnail : false;
+    }
+
+    /**
+     * Set the Thumbnail.
+     *
+     * @param string|bool $thumbnail
+     *
+     * @return Bookmark
+     */
+    public function setThumbnail($thumbnail)
+    {
+        $this->thumbnail = $thumbnail;
+
+        return $this;
+    }
+
+    /**
+     * Get the Sticky.
+     *
+     * @return bool
+     */
+    public function isSticky()
+    {
+        return $this->sticky ? true : false;
+    }
+
+    /**
+     * Set the Sticky.
+     *
+     * @param bool $sticky
+     *
+     * @return Bookmark
+     */
+    public function setSticky($sticky)
+    {
+        $this->sticky = $sticky ? true : false;
+
+        return $this;
+    }
+
+    /**
+     * @return string Bookmark's tags as a string, separated by a space
+     */
+    public function getTagsString()
+    {
+        return implode(' ', $this->getTags());
+    }
+
+    /**
+     * @return bool
+     */
+    public function isNote()
+    {
+        // We check empty value to get a valid result if the link has not been saved yet
+        return empty($this->url) || $this->url[0] === '?';
+    }
+
+    /**
+     * Set tags from a string.
+     * Note:
+     *   - tags must be separated whether by a space or a comma
+     *   - multiple spaces will be removed
+     *   - trailing dash in tags will be removed
+     *
+     * @param string $tags
+     *
+     * @return $this
+     */
+    public function setTagsString($tags)
+    {
+        // Remove first '-' char in tags.
+        $tags = preg_replace('/(^| )\-/', '$1', $tags);
+        // Explode all tags separted by spaces or commas
+        $tags = preg_split('/[\s,]+/', $tags);
+        // Remove eventual empty values
+        $tags = array_values(array_filter($tags));
+
+        $this->tags = $tags;
+
+        return $this;
+    }
+
+    /**
+     * Rename a tag in tags list.
+     *
+     * @param string $fromTag
+     * @param string $toTag
+     */
+    public function renameTag($fromTag, $toTag)
+    {
+        if (($pos = array_search($fromTag, $this->tags)) !== false) {
+            $this->tags[$pos] = trim($toTag);
+        }
+    }
+
+    /**
+     * Delete a tag from tags list.
+     *
+     * @param string $tag
+     */
+    public function deleteTag($tag)
+    {
+        if (($pos = array_search($tag, $this->tags)) !== false) {
+            unset($this->tags[$pos]);
+            $this->tags = array_values($this->tags);
+        }
+    }
+}