mirror of https://github.com/nextcloud/bookmarks
Refactor stuff into services
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
This commit is contained in:
parent
0570fdc770
commit
8770351825
|
@ -9,6 +9,7 @@
|
|||
"psr/http-client": "^0.2.0",
|
||||
"rowbot/url": "^2.0",
|
||||
"ext-pdo": "*",
|
||||
"ext-json": "*"
|
||||
}
|
||||
"ext-json": "*",
|
||||
"ext-libxml": "*"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,18 +38,6 @@ class Bookmark extends Entity {
|
|||
$this->addType('lastPreview', 'integer');
|
||||
}
|
||||
|
||||
// todo
|
||||
public function hashBookmark($userId, $bookmarkId, $fields) {
|
||||
$bookmarkRecord = $this->findUniqueBookmark($bookmarkId, $userId);
|
||||
$bookmark = [];
|
||||
foreach ($fields as $field) {
|
||||
if (isset($bookmarkRecord[$field])) {
|
||||
$bookmark[$field] = $bookmarkRecord[$field];
|
||||
}
|
||||
}
|
||||
return hash('sha256', json_encode($bookmark, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
}
|
||||
|
||||
public function markPreviewCreated() {
|
||||
$this->setLastPreview(time());
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
<?php
|
||||
namespace OCA\Bookmarks\Db;
|
||||
|
||||
use OCA\Bookmarks\UrlNormalizer;
|
||||
use OCA\Bookmarks\Exception\AlreadyExistsError;
|
||||
use OCA\Bookmarks\Exception\UrlParseError;
|
||||
use OCA\Bookmarks\Service\UrlNormalizer;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
|
@ -9,6 +11,7 @@ use OCP\DB\QueryBuilder\IQueryBuilder;
|
|||
use OCP\IConfig;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\AppFramework\Db\QBMapper;
|
||||
use Rowbot\URL\Exception\TypeError;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\EventDispatcher\GenericEvent;
|
||||
|
||||
|
@ -291,10 +294,12 @@ class BookmarkMapper extends QBMapper {
|
|||
/**
|
||||
* @param Entity $entity
|
||||
* @return Entity
|
||||
* @throws UrlParseError
|
||||
*/
|
||||
public function update(Entity $entity) : Entity {
|
||||
// normalize url
|
||||
$entity->setUrl($this->urlNormalizer->normalize($entity->getUrl()));
|
||||
$entity->setLastmodified(time());
|
||||
|
||||
$newEntity = parent::update($entity);
|
||||
|
||||
|
@ -310,11 +315,14 @@ class BookmarkMapper extends QBMapper {
|
|||
/**
|
||||
* @param Entity $entity
|
||||
* @return Entity
|
||||
* @throws \Exception
|
||||
* @throws AlreadyExistsError
|
||||
* @throws UrlParseError
|
||||
*/
|
||||
public function insert(Entity $entity) : Entity {
|
||||
// normalize url
|
||||
$entity->setUrl($this->urlNormalizer->normalize($entity->getUrl()));
|
||||
if ($entity->getAdded() === null) $entity->setAdded(time());
|
||||
$entity->setLastmodified(time());
|
||||
|
||||
$exists = true;
|
||||
try {
|
||||
|
@ -326,8 +334,7 @@ class BookmarkMapper extends QBMapper {
|
|||
}
|
||||
|
||||
if ($exists) {
|
||||
// TODO: Create a separate Exception for this!
|
||||
throw new \Exception('A bookmark with this URL already exists');
|
||||
throw new AlreadyExistsError('A bookmark with this URL already exists');
|
||||
}
|
||||
|
||||
$newEntity = parent::insert($entity);
|
||||
|
@ -342,6 +349,7 @@ class BookmarkMapper extends QBMapper {
|
|||
* @param Entity $entity
|
||||
* @return Entity
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws UrlParseError
|
||||
*/
|
||||
public function insertOrUpdate(Entity $entity) : Entity {
|
||||
// normalize url
|
||||
|
@ -374,19 +382,9 @@ class BookmarkMapper extends QBMapper {
|
|||
$bookmark = [];
|
||||
foreach ($fields as $field) {
|
||||
if (isset($entity->{$field})) {
|
||||
$bookmark[$field] = $entity->{$field};
|
||||
$bookmark[$field] = $entity->{'get'.$field}();
|
||||
}
|
||||
}
|
||||
return hash('sha256', json_encode($bookmark, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
* @return Entity
|
||||
*/
|
||||
public function markPreviewCreated(Entity $entity) {
|
||||
$entity->setLastPreview(time());
|
||||
return $this->update($entity);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace OCA\Bookmarks\Exception;
|
||||
|
||||
|
||||
class AlreadyExistsError extends Exception {
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace OCA\Bookmarks\Exception;
|
||||
|
||||
|
||||
class Exception extends \Exception {
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
namespace OCA\Bookmarks\Exception;
|
||||
|
||||
class UnauthorizedAccessError extends Exception {
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<?php
|
||||
namespace OCA\Bookmarks\Exception;
|
||||
|
||||
class UrlParseError extends \Exception {
|
||||
|
||||
}
|
|
@ -2,7 +2,7 @@
|
|||
/*
|
||||
* (c) Pedro Rodrigues <relvas.rodrigues@gmail.com>
|
||||
*/
|
||||
namespace OCA\Bookmarks;
|
||||
namespace OCA\Bookmarks\Service;
|
||||
|
||||
/**
|
||||
* Bookmark parser
|
|
@ -0,0 +1,128 @@
|
|||
<?php
|
||||
|
||||
|
||||
namespace OCA\Bookmarks\Service;
|
||||
|
||||
|
||||
use OCA\Bookmarks\BookmarksParser;
|
||||
use OCA\Bookmarks\Db\BookmarkMapper;
|
||||
use OCA\Bookmarks\Db\FolderMapper;
|
||||
use OCA\Bookmarks\Db\TagMapper;
|
||||
use OCA\Bookmarks\Exception\UnauthorizedAccessError;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
use OCP\Util;
|
||||
|
||||
/**
|
||||
* Class HtmlExporter
|
||||
*
|
||||
* @package OCA\Bookmarks\Service
|
||||
*/
|
||||
class HtmlExporter {
|
||||
|
||||
/**
|
||||
* @var BookmarkMapper
|
||||
*/
|
||||
protected $bookmarkMapper;
|
||||
|
||||
/**
|
||||
* @var FolderMapper
|
||||
*/
|
||||
protected $folderMapper;
|
||||
|
||||
/**
|
||||
* @var TagMapper
|
||||
*/
|
||||
protected $tagMapper;
|
||||
|
||||
/** @var BookmarksParser */
|
||||
private $bookmarksParser;
|
||||
|
||||
/**
|
||||
* ImportService constructor.
|
||||
*
|
||||
* @param BookmarkMapper $bookmarkMapper
|
||||
* @param FolderMapper $folderMapper
|
||||
* @param TagMapper $tagMapper
|
||||
*/
|
||||
public function __construct(BookmarkMapper $bookmarkMapper, FolderMapper $folderMapper, TagMapper $tagMapper) {
|
||||
$this->bookmarkMapper = $bookmarkMapper;
|
||||
$this->folderMapper = $folderMapper;
|
||||
$this->tagMapper = $tagMapper;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
* @param int $folderId
|
||||
* @return string
|
||||
* @throws UnauthorizedAccessError
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
*/
|
||||
public function exportFolder(int $userId, int $folderId = -1): string {
|
||||
$file = "<!DOCTYPE NETSCAPE-Bookmark-file-1>
|
||||
<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">
|
||||
<TITLE>Bookmarks</TITLE>";
|
||||
|
||||
$file .= $this->serializeFolder($userId, $folderId);
|
||||
|
||||
return $file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
* @param int $id
|
||||
* @return string
|
||||
* @throws UnauthorizedAccessError
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
*/
|
||||
protected function serializeFolder(int $userId, int $id): string {
|
||||
if ($id !== -1) {
|
||||
$folder = $this->folderMapper->find($id);
|
||||
if ($folder->getUserId() !== $userId) {
|
||||
throw new UnauthorizedAccessError();
|
||||
}
|
||||
$output = '<DT><h3>' . htmlspecialchars($folder['title']) . '</h3>' . "\n"
|
||||
. '<DL><p>';
|
||||
} else {
|
||||
$output = '<H1>Bookmarks</h1>' . "\n"
|
||||
. '<DL><p>';
|
||||
}
|
||||
|
||||
$childBookmarks = $id !== -1 ? $this->bookmarkMapper->findByFolder($id) : $this->bookmarkMapper->findByRootFolder($userId);
|
||||
foreach ($childBookmarks as $bookmark) {
|
||||
// discards records with no URL. This should not happen but
|
||||
// a database could have old entries
|
||||
if ($bookmark->getUrl() === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tags = $this->tagMapper->findByBookmark($bookmark->getId());
|
||||
|
||||
$tags = Util::sanitizeHTML(implode(',', $tags));
|
||||
$title = trim($bookmark->getTitle());
|
||||
$url = Util::sanitizeHTML($bookmark->getUrl());
|
||||
if ($title === '') {
|
||||
$title = $url;
|
||||
}
|
||||
$title = Util::sanitizeHTML($title);
|
||||
$description = Util::sanitizeHTML($bookmark->getDescription());
|
||||
|
||||
$output .= '<DT><A HREF="' . $url . '" TAGS="' . $tags . '" ADD_DATE="' . $bookmark['added'] . '">' . $title . '</A>' . "\n";
|
||||
if (strlen($description) > 0) {
|
||||
$output .= '<DD>' . $description . '</DD>';
|
||||
}
|
||||
$output .= "\n";
|
||||
}
|
||||
|
||||
$childFolders = $this->folderMapper->findByParentFolder($id);
|
||||
foreach ($childFolders as $childFolder) {
|
||||
$output .= $this->serializeFolder($userId, $childFolder->getId());
|
||||
}
|
||||
|
||||
$output .= '</p></DL>';
|
||||
return $output;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
<?php
|
||||
|
||||
namespace OCA\Bookmarks\Service;
|
||||
|
||||
use OCA\Bookmarks\BookmarksParser;
|
||||
use OCA\Bookmarks\Db\Bookmark;
|
||||
use OCA\Bookmarks\Db\BookmarkMapper;
|
||||
use OCA\Bookmarks\Db\Folder;
|
||||
use OCA\Bookmarks\Db\FolderMapper;
|
||||
use OCA\Bookmarks\Db\TagMapper;
|
||||
use OCA\Bookmarks\Exception\UnauthorizedAccessError;
|
||||
use OCA\Bookmarks\Exception\UrlParseError;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
|
||||
/**
|
||||
* Class HtmlImporter
|
||||
*
|
||||
* @package OCA\Bookmarks\Service
|
||||
*/
|
||||
class HtmlImporter {
|
||||
|
||||
/**
|
||||
* @var BookmarkMapper
|
||||
*/
|
||||
protected $bookmarkMapper;
|
||||
|
||||
/**
|
||||
* @var FolderMapper
|
||||
*/
|
||||
protected $folderMapper;
|
||||
|
||||
/**
|
||||
* @var TagMapper
|
||||
*/
|
||||
protected $tagMapper;
|
||||
|
||||
/** @var BookmarksParser */
|
||||
private $bookmarksParser;
|
||||
|
||||
/**
|
||||
* ImportService constructor.
|
||||
*
|
||||
* @param BookmarkMapper $bookmarkMapper
|
||||
* @param FolderMapper $folderMapper
|
||||
* @param TagMapper $tagMapper
|
||||
* @param BookmarksParser $bookmarksParser
|
||||
*/
|
||||
public function __construct(BookmarkMapper $bookmarkMapper, FolderMapper $folderMapper, TagMapper $tagMapper, BookmarksParser $bookmarksParser) {
|
||||
$this->bookmarkMapper = $bookmarkMapper;
|
||||
$this->folderMapper = $folderMapper;
|
||||
$this->tagMapper = $tagMapper;
|
||||
$this->bookmarksParser = $bookmarksParser;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Import Bookmarks from html formatted file
|
||||
* @param int $userId
|
||||
* @param string $file Content to import
|
||||
* @param int $rootFolder
|
||||
* @return array
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws UnauthorizedAccessError
|
||||
*/
|
||||
public function importFile(int $userId, string $file, int $rootFolder = -1) {
|
||||
$content = file_get_contents($file);
|
||||
return $this->import($userId, $content, $rootFolder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Import Bookmarks from html
|
||||
* @param int $userId
|
||||
* @param string $content
|
||||
* @param int $rootFolder
|
||||
* @return array
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws UnauthorizedAccessError
|
||||
*/
|
||||
public function import(int $userId, string $content, int $rootFolder = -1) {
|
||||
$imported = [];
|
||||
$errors = [];
|
||||
if ($rootFolder !== -1) {
|
||||
$folder = $this->folderMapper->find($rootFolder);
|
||||
if ($folder->getUserId() !== $userId) {
|
||||
throw new UnauthorizedAccessError('Not allowed to access folder '.$rootFolder);
|
||||
}
|
||||
}
|
||||
$this->bookmarksParser->parse($content, false);
|
||||
foreach ($this->bookmarksParser->currentFolder['children'] as $folder) {
|
||||
$imported[] = $this->importFolder($userId, $folder, $rootFolder, $errors);
|
||||
}
|
||||
foreach ($this->bookmarksParser->currentFolder['bookmarks'] as $bookmark) {
|
||||
try {
|
||||
$bm = $this->importBookmark($userId, $rootFolder, $bookmark);
|
||||
} catch (UrlParseError $e) {
|
||||
$errors[] = 'Failed to parse URL: '.$bookmark['href'];
|
||||
continue;
|
||||
}
|
||||
$imported[] = ['type' => 'bookmark', 'id' => $bm->getId(), 'title' => $bookmark['title'], 'url' => $bookmark['href']];
|
||||
}
|
||||
return ['imported' => $imported, 'errors' => $errors];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
* @param array $folderParams
|
||||
* @param int $parentId
|
||||
* @param array $errors
|
||||
* @return array
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
*/
|
||||
private function importFolder(int $userId, array $folderParams, int $parentId, &$errors = []) {
|
||||
$folder = new Folder();
|
||||
$folder->setUserId($userId);
|
||||
$folder->setTitle($folderParams['title']);
|
||||
$folder->setParentFolder($parentId);
|
||||
$folder = $this->folderMapper->insert($folder);
|
||||
$newFolder = ['type' => 'folder', 'id' => $folder->getId(), 'title' => $folder['title'], 'children' => []];
|
||||
foreach ($folderParams['bookmarks'] as $bookmark) {
|
||||
try {
|
||||
$bm = $this->importBookmark($userId, $folder->getId(), $bookmark);
|
||||
} catch (UrlParseError $e) {
|
||||
$errors[] = 'Failed to parse URL: '.$bookmark['href'];
|
||||
continue;
|
||||
}
|
||||
$newFolder['children'][] = ['type' => 'bookmark', 'id' => $bm->getId(), 'title' => $bookmark['title'], 'url' => $bookmark['href']];
|
||||
}
|
||||
foreach ($folder['children'] as $childFolder) {
|
||||
$newFolder['children'][] = $this->importFolder($userId, $childFolder, $folder->getId(), $errors);
|
||||
}
|
||||
return $newFolder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $userId
|
||||
* @param int $folderId
|
||||
* @param array $bookmark
|
||||
* @return Bookmark|Entity
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws UrlParseError
|
||||
*/
|
||||
private function importBookmark(int $userId, int $folderId, array $bookmark) {
|
||||
$bm = new Bookmark();
|
||||
$bm->setUserId($userId);
|
||||
$bm->setUrl($bookmark['href']);
|
||||
$bm->setTitle($bookmark['title']);
|
||||
$bm->setDescription($bookmark['title']);
|
||||
if (isset($bookmark['add_date'])) $bm->setAdded($bookmark['add_date']->getTimestamp());
|
||||
|
||||
// insert bookmark
|
||||
$bm = $this->bookmarkMapper->insertOrUpdate($bm);
|
||||
// add to folder
|
||||
$this->folderMapper->addToFolders($bm->getId(), [$folderId]);
|
||||
// add tags
|
||||
$this->tagMapper->addTo($bookmark['tags'], $bm->getId());
|
||||
|
||||
return $bm;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,7 @@
|
|||
<?php
|
||||
namespace OCA\Bookmarks;
|
||||
namespace OCA\Bookmarks\Service;
|
||||
|
||||
use Marcelklehr\LinkPreview\Client as LinkPreview;
|
||||
use Marcelklehr\LinkPreview\Exceptions\ConnectionErrorException;
|
||||
use OCP\ILogger;
|
||||
use OCP\IConfig;
|
||||
use OCP\Http\Client\IClientService;
|
||||
|
@ -49,8 +48,6 @@ class LinkExplorer {
|
|||
|
||||
$data = $preview->toArray();
|
||||
|
||||
$this->logger->debug('getImage for URL: '.$url.' '.var_export($data, true), ['app' => 'bookmarks']);
|
||||
|
||||
if (!isset($data)) {
|
||||
return ['url' => $url];
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
<?php
|
||||
namespace OCA\Bookmarks\Service;
|
||||
|
||||
use OCA\Bookmarks\Exception\UrlParseError;
|
||||
use Rowbot\URL\Exception\TypeError;
|
||||
use Rowbot\URL\URL;
|
||||
|
||||
class UrlNormalizer {
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $urlString
|
||||
* @return string
|
||||
* @throws UrlParseError
|
||||
*/
|
||||
public function normalize($urlString) {
|
||||
try {
|
||||
$url = new URL($urlString);
|
||||
} catch (TypeError $e) {
|
||||
throw new UrlParseError();
|
||||
}
|
||||
return $url->href;
|
||||
}
|
||||
}
|
|
@ -1,15 +0,0 @@
|
|||
<?php
|
||||
namespace OCA\Bookmarks;
|
||||
|
||||
use Rowbot\URL\URL;
|
||||
use Rowbot\URL\Exception\TypeError;
|
||||
|
||||
class UrlNormalizer {
|
||||
public function __construct() {
|
||||
}
|
||||
|
||||
public function normalize($urlString) {
|
||||
$url = new URL($urlString);
|
||||
return $url->href;
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ namespace OCA\Bookmarks\Tests;
|
|||
|
||||
use OCA\Bookmarks\Db;
|
||||
use OCA\Bookmarks\Db\Bookmark;
|
||||
use OCA\Bookmarks\Exception\UrlParseError;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
|
@ -45,6 +46,7 @@ class TagMapperTest extends TestCase {
|
|||
* @param array $tags
|
||||
* @param Bookmark $bookmark
|
||||
* @throws MultipleObjectsReturnedException
|
||||
* @throws UrlParseError
|
||||
*/
|
||||
public function testAddToAndFind(array $tags, Bookmark $bookmark) {
|
||||
$bookmark->setUserId($this->userId);
|
||||
|
|
Loading…
Reference in New Issue