From 336a28fa4a09b968ce4705900bf57693e672f0bf Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 25 May 2019 15:46:47 +0200 Subject: Introduce Bookmark object and Service layer to retrieve them See https://github.com/shaarli/Shaarli/issues/1307 for details --- application/bookmark/BookmarkArray.php | 259 +++++++++++++++++++++++++++++++++ 1 file changed, 259 insertions(+) create mode 100644 application/bookmark/BookmarkArray.php (limited to 'application/bookmark/BookmarkArray.php') diff --git a/application/bookmark/BookmarkArray.php b/application/bookmark/BookmarkArray.php new file mode 100644 index 00000000..b427c91a --- /dev/null +++ b/application/bookmark/BookmarkArray.php @@ -0,0 +1,259 @@ +offset. + */ + protected $ids; + + /** + * @var int Position in the $this->keys array (for the Iterator interface) + */ + protected $position; + + /** + * @var array List of offset keys (for the Iterator interface implementation) + */ + protected $keys; + + /** + * @var array List of all recorded URLs (key=url, value=bookmark offset) + * for fast reserve search (url-->bookmark offset) + */ + protected $urls; + + public function __construct() + { + $this->ids = []; + $this->bookmarks = []; + $this->keys = []; + $this->urls = []; + $this->position = 0; + } + + /** + * Countable - Counts elements of an object + * + * @return int Number of bookmarks + */ + public function count() + { + return count($this->bookmarks); + } + + /** + * ArrayAccess - Assigns a value to the specified offset + * + * @param int $offset Bookmark ID + * @param Bookmark $value instance + * + * @throws InvalidBookmarkException + */ + public function offsetSet($offset, $value) + { + if (! $value instanceof Bookmark + || $value->getId() === null || empty($value->getUrl()) + || ($offset !== null && ! is_int($offset)) || ! is_int($value->getId()) + || $offset !== null && $offset !== $value->getId() + ) { + throw new InvalidBookmarkException($value); + } + + // If the bookmark exists, we reuse the real offset, otherwise new entry + if ($offset !== null) { + $existing = $this->getBookmarkOffset($offset); + } else { + $existing = $this->getBookmarkOffset($value->getId()); + } + + if ($existing !== null) { + $offset = $existing; + } else { + $offset = count($this->bookmarks); + } + + $this->bookmarks[$offset] = $value; + $this->urls[$value->getUrl()] = $offset; + $this->ids[$value->getId()] = $offset; + } + + /** + * ArrayAccess - Whether or not an offset exists + * + * @param int $offset Bookmark ID + * + * @return bool true if it exists, false otherwise + */ + public function offsetExists($offset) + { + return array_key_exists($this->getBookmarkOffset($offset), $this->bookmarks); + } + + /** + * ArrayAccess - Unsets an offset + * + * @param int $offset Bookmark ID + */ + public function offsetUnset($offset) + { + $realOffset = $this->getBookmarkOffset($offset); + $url = $this->bookmarks[$realOffset]->getUrl(); + unset($this->urls[$url]); + unset($this->ids[$realOffset]); + unset($this->bookmarks[$realOffset]); + } + + /** + * ArrayAccess - Returns the value at specified offset + * + * @param int $offset Bookmark ID + * + * @return Bookmark|null The Bookmark if found, null otherwise + */ + public function offsetGet($offset) + { + $realOffset = $this->getBookmarkOffset($offset); + return isset($this->bookmarks[$realOffset]) ? $this->bookmarks[$realOffset] : null; + } + + /** + * Iterator - Returns the current element + * + * @return Bookmark corresponding to the current position + */ + public function current() + { + return $this[$this->keys[$this->position]]; + } + + /** + * Iterator - Returns the key of the current element + * + * @return int Bookmark ID corresponding to the current position + */ + public function key() + { + return $this->keys[$this->position]; + } + + /** + * Iterator - Moves forward to next element + */ + public function next() + { + ++$this->position; + } + + /** + * Iterator - Rewinds the Iterator to the first element + * + * Entries are sorted by date (latest first) + */ + public function rewind() + { + $this->keys = array_keys($this->ids); + $this->position = 0; + } + + /** + * Iterator - Checks if current position is valid + * + * @return bool true if the current Bookmark ID exists, false otherwise + */ + public function valid() + { + return isset($this->keys[$this->position]); + } + + /** + * Returns a bookmark offset in bookmarks array from its unique ID. + * + * @param int $id Persistent ID of a bookmark. + * + * @return int Real offset in local array, or null if doesn't exist. + */ + protected function getBookmarkOffset($id) + { + if (isset($this->ids[$id])) { + return $this->ids[$id]; + } + return null; + } + + /** + * Return the next key for bookmark creation. + * E.g. If the last ID is 597, the next will be 598. + * + * @return int next ID. + */ + public function getNextId() + { + if (!empty($this->ids)) { + return max(array_keys($this->ids)) + 1; + } + return 0; + } + + /** + * @param $url + * + * @return Bookmark|null + */ + public function getByUrl($url) + { + if (! empty($url) + && isset($this->urls[$url]) + && isset($this->bookmarks[$this->urls[$url]]) + ) { + return $this->bookmarks[$this->urls[$url]]; + } + return null; + } + + /** + * Reorder links by creation date (newest first). + * + * Also update the urls and ids mapping arrays. + * + * @param string $order ASC|DESC + */ + public function reorder($order = 'DESC') + { + $order = $order === 'ASC' ? -1 : 1; + // Reorder array by dates. + usort($this->bookmarks, function ($a, $b) use ($order) { + /** @var $a Bookmark */ + /** @var $b Bookmark */ + if ($a->isSticky() !== $b->isSticky()) { + return $a->isSticky() ? -1 : 1; + } + return $a->getCreated() < $b->getCreated() ? 1 * $order : -1 * $order; + }); + + $this->urls = []; + $this->ids = []; + foreach ($this->bookmarks as $key => $bookmark) { + $this->urls[$bookmark->getUrl()] = $key; + $this->ids[$bookmark->getId()] = $key; + } + } +} -- cgit v1.2.3 From cf92b4dd1521241eefc58eaf6dcd202cd83969d8 Mon Sep 17 00:00:00 2001 From: ArthurHoaro Date: Sat, 25 May 2019 15:52:27 +0200 Subject: Apply the new system (Bookmark + Service) to the whole code base See https://github.com/shaarli/Shaarli/issues/1307 --- application/bookmark/BookmarkArray.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'application/bookmark/BookmarkArray.php') diff --git a/application/bookmark/BookmarkArray.php b/application/bookmark/BookmarkArray.php index b427c91a..d87d43b4 100644 --- a/application/bookmark/BookmarkArray.php +++ b/application/bookmark/BookmarkArray.php @@ -118,7 +118,7 @@ class BookmarkArray implements \Iterator, \Countable, \ArrayAccess $realOffset = $this->getBookmarkOffset($offset); $url = $this->bookmarks[$realOffset]->getUrl(); unset($this->urls[$url]); - unset($this->ids[$realOffset]); + unset($this->ids[$offset]); unset($this->bookmarks[$realOffset]); } -- cgit v1.2.3