bookmarks/lib/Db/TagMapper.php

246 lines
7.5 KiB
PHP

<?php
/*
* Copyright (c) 2020-2024. The Nextcloud Bookmarks contributors.
*
* This file is licensed under the Affero General Public License version 3 or later. See the COPYING file.
*/
namespace OCA\Bookmarks\Db;
use InvalidArgumentException;
use OCP\IDBConnection;
use PDO;
/**
* Class TagMapper
*
* @package OCA\Bookmarks\Db
*/
class TagMapper {
/**
* @var IDBConnection
*/
protected $db;
/**
* TagMapper constructor.
*
* @param IDBConnection $db
*/
public function __construct(IDBConnection $db) {
$this->db = $db;
}
/**
* @param $userId
* @return array
*/
public function findAllWithCount($userId): array {
$qb = $this->db->getQueryBuilder();
$qb
->select('t.tag AS name')
->selectAlias($qb->createFunction('COUNT(DISTINCT ' . $qb->getColumnName('t.bookmark_id') . ')'), 'count')
->from('bookmarks_tags', 't')
->innerJoin('t', 'bookmarks', 'b', $qb->expr()->eq('b.id', 't.bookmark_id'))
->leftJoin('b', 'bookmarks_tree', 'tr', 'b.id = tr.id AND tr.type = '.$qb->createPositionalParameter(TreeMapper::TYPE_BOOKMARK))
->leftJoin('tr', 'bookmarks_shared_folders', 'sf', $qb->expr()->eq('tr.parent_folder', 'sf.folder_id'))
->where($qb->expr()->eq('b.user_id', $qb->createPositionalParameter($userId)))
->orWhere($qb->expr()->andX(
$qb->expr()->eq('sf.user_id', $qb->createPositionalParameter($userId)),
$qb->expr()->eq('tr.type', $qb->createPositionalParameter(TreeMapper::TYPE_BOOKMARK)))
)
->groupBy('t.tag')
->orderBy('count', 'DESC');
return $qb->execute()->fetchAll();
}
/**
* @param $userId
* @return array
*/
public function findAll($userId): array {
$qb = $this->db->getQueryBuilder();
$qb
->select('t.tag')
->from('bookmarks_tags', 't')
->innerJoin('t', 'bookmarks', 'b', $qb->expr()->eq('b.id', 't.bookmark_id'))
->leftJoin('b', 'bookmarks_tree', 'tr', 'b.id = tr.id AND tr.type = '.$qb->createPositionalParameter(TreeMapper::TYPE_BOOKMARK))
->leftJoin('tr', 'bookmarks_shared_folders', 'sf', $qb->expr()->eq('tr.parent_folder', 'sf.folder_id'))
->where($qb->expr()->eq('b.user_id', $qb->createPositionalParameter($userId)))
->orWhere($qb->expr()->andX(
$qb->expr()->eq('sf.user_id', $qb->createPositionalParameter($userId)),
$qb->expr()->eq('tr.type', $qb->createPositionalParameter(TreeMapper::TYPE_SHARE)))
)
->groupBy('t.tag');
return $qb->execute()->fetchAll(PDO::FETCH_COLUMN);
}
/**
* @param int $bookmarkId
* @return array
*/
public function findByBookmark(int $bookmarkId): array {
$qb = $this->db->getQueryBuilder();
$qb->select('tag');
$qb
->from('bookmarks_tags', 't')
->where($qb->expr()->eq('t.bookmark_id', $qb->createPositionalParameter($bookmarkId)));
return $qb->execute()->fetchAll(PDO::FETCH_COLUMN);
}
/**
* @param $userId
* @param string $tag
*/
public function delete($userId, string $tag) {
$qb = $this->db->getQueryBuilder();
$qb
->delete('bookmarks_tags', 'tgs')
->innerJoin('tgs', 'bookmarks', 'bm', $qb->expr()->eq('tgs.bookmark_id', 'bm.id'))
->where($qb->expr()->eq('tgs.tag', $qb->createNamedParameter($tag)))
->andWhere($qb->expr()->eq('bm.user_id', $qb->createNamedParameter($userId)));
return $qb->execute();
}
/**
* @param $userId
*/
public function deleteAll(int $userId) {
$qb = $this->db->getQueryBuilder();
$qb
->delete('bookmarks_tags', 'tgs')
->innerJoin('tgs', 'bookmarks', 'bm', $qb->expr()->eq('tgs.bookmark_id', 'bm.id'))
->where($qb->expr()->eq('bm.user_id', $qb->createNamedParameter($userId)));
return $qb->execute();
}
/**
* @param $tags
* @param int $bookmarkId
*/
public function addTo(array $tags, int $bookmarkId): void {
if (is_string($tags)) {
$tags = [$tags];
} elseif (!is_array($tags)) {
throw new InvalidArgumentException('$tag must be string or array of strings');
}
if (count($tags) === 0) {
return;
}
$currentTags = $this->findByBookmark($bookmarkId);
$tags = array_filter($tags, static function ($tag) use ($currentTags) {
return !in_array($tag, $currentTags, true);
});
foreach ($tags as $tag) {
$tag = trim($tag);
if (empty($tag)) {
//avoid saving white spaces
continue;
}
$qb = $this->db->getQueryBuilder();
$qb
->insert('bookmarks_tags')
->values([
'tag' => $qb->createNamedParameter($tag),
'bookmark_id' => $qb->createNamedParameter($bookmarkId),
]);
$qb->execute();
}
}
/**
* @param int $bookmarkId
*/
public function removeAllFrom(int $bookmarkId): void {
// Remove old tags
$qb = $this->db->getQueryBuilder();
$qb
->delete('bookmarks_tags')
->where($qb->expr()->eq('bookmark_id', $qb->createNamedParameter($bookmarkId)));
$qb->execute();
}
/**
* @param array $tags
* @param int $bookmarkId
*/
public function setOn(array $tags, int $bookmarkId): void {
$this->removeAllFrom($bookmarkId);
$this->addTo($tags, $bookmarkId);
}
/**
* @brief Rename a tag
* @param int $userId UserId
* @param string $old Old Tag Name
* @param string $new New Tag Name
*/
public function renameTag($userId, string $old, string $new): void {
// Remove about-to-be duplicated tags
$qb = $this->db->getQueryBuilder();
$qb
->select('tgs.bookmark_id')
->from('bookmarks_tags', 'tgs')
->innerJoin('tgs', 'bookmarks', 'bm', $qb->expr()->eq('tgs.bookmark_id', 'bm.id'))
->innerJoin('tgs', 'bookmarks_tags', 't', $qb->expr()->eq('tgs.bookmark_id', 't.bookmark_id'))
->where($qb->expr()->eq('tgs.tag', $qb->createNamedParameter($new)))
->andWhere($qb->expr()->eq('bm.user_id', $qb->createNamedParameter($userId)))
->andWhere($qb->expr()->eq('t.tag', $qb->createNamedParameter($old)));
$duplicates = $qb->execute()->fetchAll(PDO::FETCH_COLUMN);
if (count($duplicates) !== 0) {
$qb = $this->db->getQueryBuilder();
$qb
->delete('bookmarks_tags')
->where($qb->expr()->in('bookmark_id', array_map([$qb, 'createNamedParameter'], $duplicates)))
->andWhere($qb->expr()->eq('tag', $qb->createNamedParameter($old)));
$qb->execute();
}
// Update tags to the new label
$qb = $this->db->getQueryBuilder();
$qb
->select('tgs.bookmark_id')
->from('bookmarks_tags', 'tgs')
->innerJoin('tgs', 'bookmarks', 'bm', $qb->expr()->eq('tgs.bookmark_id', 'bm.id'))
->where($qb->expr()->eq('tgs.tag', $qb->createNamedParameter($old)))
->andWhere($qb->expr()->eq('bm.user_id', $qb->createNamedParameter($userId)));
$bookmarks = $qb->execute()->fetchAll(PDO::FETCH_COLUMN);
if (count($bookmarks) !== 0) {
$qb = $this->db->getQueryBuilder();
$qb
->update('bookmarks_tags')
->set('tag', $qb->createNamedParameter($new))
->where($qb->expr()->eq('tag', $qb->createNamedParameter($old)))
->andWhere($qb->expr()->in('bookmark_id', array_map([$qb, 'createNamedParameter'], $bookmarks)));
$qb->execute();
}
}
/**
* @param $userId
* @param string $old
*/
public function deleteTag($userId, string $old): void {
$qb = $this->db->getQueryBuilder();
$qb
->select('t.bookmark_id')
->from('bookmarks_tags', 't')
->innerJoin('t', 'bookmarks', 'bm', $qb->expr()->eq('t.bookmark_id', 'bm.id'))
->where($qb->expr()->eq('t.tag', $qb->createNamedParameter($old)))
->andWhere($qb->expr()->eq('bm.user_id', $qb->createNamedParameter($userId)));
$affectedBookmarks = $qb->execute()->fetchAll(PDO::FETCH_COLUMN);
if (count($affectedBookmarks) !== 0) {
$qb = $this->db->getQueryBuilder();
$qb
->delete('bookmarks_tags')
->where($qb->expr()->in('bookmark_id', array_map([$qb, 'createNamedParameter'], $affectedBookmarks)))
->andWhere($qb->expr()->eq('tag', $qb->createNamedParameter($old)));
$qb->execute();
}
}
}