From ec602f3e15b6aa1cb4f26fffa4227a05e654dee2 Mon Sep 17 00:00:00 2001 From: Raul Ferreira Fuentes Date: Mon, 11 Apr 2022 18:24:41 +0200 Subject: [PATCH 01/10] Update `DeckMapper` to extend `QBMapper` instead of deprecated `Mapper` Signed-off-by: Raul Ferreira Fuentes --- lib/Db/AclMapper.php | 62 +++++++++++++++--- lib/Db/DeckMapper.php | 18 +++-- lib/Db/LabelMapper.php | 145 +++++++++++++++++++++++++++++++++-------- lib/Db/StackMapper.php | 101 +++++++++++++++++++++------- 4 files changed, 255 insertions(+), 71 deletions(-) diff --git a/lib/Db/AclMapper.php b/lib/Db/AclMapper.php index 5cf188aa0..5a200c09e 100644 --- a/lib/Db/AclMapper.php +++ b/lib/Db/AclMapper.php @@ -29,22 +29,54 @@ use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; class AclMapper extends DeckMapper implements IPermissionMapper { + + /** + * @param IDBConnection $db + */ public function __construct(IDBConnection $db) { - parent::__construct($db, 'deck_board_acl', Acl::class); + parent::__construct($db, 'deck_boards', Board::class); } + /** + * @param int $boardId + * @param int|null $limit + * @param int|null $offset + * @return Acl[] + * @throws \OCP\DB\Exception + */ public function findAll($boardId, $limit = null, $offset = null) { - $sql = 'SELECT id, board_id, type, participant, permission_edit, permission_share, permission_manage FROM `*PREFIX*deck_board_acl` WHERE `board_id` = ? '; - return $this->findEntities($sql, [$boardId], $limit, $offset); + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->getTableName()) + ->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT))) + ->setMaxResults($limit) + ->setFirstResult($offset); + + return $this->findEntities($qb); } + /** + * @param int $userId + * @param int $aclId + * @return bool + * @throws \OCP\DB\Exception + */ public function isOwner($userId, $aclId): bool { - $sql = 'SELECT owner FROM `*PREFIX*deck_boards` WHERE `id` IN (SELECT board_id FROM `*PREFIX*deck_board_acl` WHERE id = ?)'; - $stmt = $this->execute($sql, [$aclId]); - $row = $stmt->fetch(); - return ($row['owner'] === $userId); + $qb = $this->db->getQueryBuilder(); + + $qb->select('owner') + ->from($this->getTableName()) + ->innerJoin('acl', 'deck_boards','b', 'acl.board_id = b.id') + ->where($qb->expr()->eq('owner.id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_INT))) + ->andWhere($qb->expr()->eq('acl.id', $qb->createNamedParameter($aclId, IQueryBuilder::PARAM_INT))); + + return $qb->executeQuery()->rowCount() > 0; } + /** + * @param int $id + * @return int|null + */ public function findBoardId($id): ?int { try { $entity = $this->find($id); @@ -54,9 +86,21 @@ class AclMapper extends DeckMapper implements IPermissionMapper { return null; } + /** + * @param int $type + * @param string $participant + * @return Acl[] + * @throws \OCP\DB\Exception + */ public function findByParticipant($type, $participant): array { - $sql = 'SELECT * from *PREFIX*deck_board_acl WHERE type = ? AND participant = ?'; - return $this->findEntities($sql, [$type, $participant]); + $qb = $this->db->getQueryBuilder(); + + $qb->select('*') + ->from($this->getTableName()) + ->where($qb->expr()->eq('type', $qb->createNamedParameter($type, IQueryBuilder::PARAM_INT))) + ->andWhere($qb->expr()->eq('participant', $qb->createNamedParameter($participant, IQueryBuilder::PARAM_STR))); + + return $this->findEntities($qb); } /** diff --git a/lib/Db/DeckMapper.php b/lib/Db/DeckMapper.php index 2dd0dd990..0aa0e7d96 100644 --- a/lib/Db/DeckMapper.php +++ b/lib/Db/DeckMapper.php @@ -23,17 +23,15 @@ namespace OCA\Deck\Db; -use OCP\AppFramework\Db\Mapper; +use OCP\AppFramework\Db\QBMapper; +use OCP\DB\QueryBuilder\IQueryBuilder; /** * Class DeckMapper * * @package OCA\Deck\Db - * @deprecated use QBMapper - * - * TODO: Move to QBMapper once Nextcloud 14 is a minimum requirement */ -class DeckMapper extends Mapper { +class DeckMapper extends QBMapper { /** * @param $id @@ -42,11 +40,11 @@ class DeckMapper extends Mapper { * @throws \OCP\AppFramework\Db\DoesNotExistException */ public function find($id) { - $sql = 'SELECT * FROM `' . $this->tableName . '` ' . 'WHERE `id` = ?'; - return $this->findEntity($sql, [$id]); - } + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->getTableName()) + ->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT))); - protected function execute($sql, array $params = [], $limit = null, $offset = null) { - return parent::execute($sql, $params, $limit, $offset); + return $this->findEntity($qb); } } diff --git a/lib/Db/LabelMapper.php b/lib/Db/LabelMapper.php index 1aa2bc98f..e613dd2af 100644 --- a/lib/Db/LabelMapper.php +++ b/lib/Db/LabelMapper.php @@ -26,48 +26,115 @@ namespace OCA\Deck\Db; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\MultipleObjectsReturnedException; +use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; class LabelMapper extends DeckMapper implements IPermissionMapper { + /** + * @param IDBConnection $db + */ public function __construct(IDBConnection $db) { parent::__construct($db, 'deck_labels', Label::class); } - public function findAll($boardId, $limit = null, $offset = null) { - $sql = 'SELECT * FROM `*PREFIX*deck_labels` WHERE `board_id` = ? ORDER BY `id`'; - return $this->findEntities($sql, [$boardId], $limit, $offset); + /** + * @param int $boardId + * @param int|null $limit + * @param int|null $offset + * @return Label[] + * @throws \OCP\DB\Exception + */ + public function findAll($boardId, $limit = null, $offset = null): array { + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->getTableName()) + ->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT))) + ->setMaxResults($limit) + ->setFirstResult($offset); + return $this->findEntities($qb); } - public function delete(\OCP\AppFramework\Db\Entity $entity) { + /** + * @param Entity $entity + * @return Entity + * @throws \OCP\DB\Exception + */ + public function delete(Entity $entity): Entity { // delete assigned labels $this->deleteLabelAssignments($entity->getId()); // delete label return parent::delete($entity); } - public function findAssignedLabelsForCard($cardId, $limit = null, $offset = null) { - $sql = 'SELECT l.*,card_id FROM `*PREFIX*deck_assigned_labels` as al INNER JOIN *PREFIX*deck_labels as l ON l.id = al.label_id WHERE `card_id` = ? ORDER BY l.id'; - return $this->findEntities($sql, [$cardId], $limit, $offset); - } - public function findAssignedLabelsForBoard($boardId, $limit = null, $offset = null) { - $sql = 'SELECT c.id as card_id, l.id as id, l.title as title, l.color as color FROM `*PREFIX*deck_cards` as c ' . - ' INNER JOIN `*PREFIX*deck_assigned_labels` as al ON al.card_id = c.id INNER JOIN `*PREFIX*deck_labels` as l ON al.label_id = l.id WHERE board_id=? ORDER BY l.id'; - return $this->findEntities($sql, [$boardId], $limit, $offset); + /** + * @param int $cardId + * @param int|null $limit + * @param int|null $offset + * @return Label[] + * @throws \OCP\DB\Exception + */ + public function findAssignedLabelsForCard($cardId, $limit = null, $offset = null): array { + $qb = $this->db->getQueryBuilder(); + $qb->select('l.*,card_id') + ->from($this->getTableName(), 'l') + ->innerJoin('l', 'deck_assigned_labels', 'al', 'l.id = al.label_id') + ->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT))) + ->orderBy('l.id') + ->setMaxResults($limit) + ->setFirstResult($offset); + + return $this->findEntities($qb); } - public function insert(Entity $entity) { + /** + * @param int $boardId + * @param int|null $limit + * @param int|null $offset + * @return Label[] + * @throws \OCP\DB\Exception + */ + public function findAssignedLabelsForBoard($boardId, $limit = null, $offset = null): array { + $qb = $this->db->getQueryBuilder(); + $qb->select('c.id as card_id', 'l.id as id', 'l.title as title', 'l.color as color') + ->from($this->getTableName(), 'l') + ->innerJoin('l', 'deck_assigned_labels', 'al', 'al.label_id = l.id') + ->innerJoin('l', 'deck_cards', 'c', 'al.card_id = c.id') + ->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT))) + ->orderBy('l.id') + ->setMaxResults($limit) + ->setFirstResult($offset); + + return $this->findEntities($qb); + } + + /** + * @param Entity $entity + * @return Entity + * @throws \OCP\DB\Exception + */ + public function insert(Entity $entity): Entity { $entity->setLastModified(time()); return parent::insert($entity); } - public function update(Entity $entity, $updateModified = true) { + /** + * @param Entity $entity + * @param bool $updateModified + * @return Entity + * @throws \OCP\DB\Exception + */ + public function update(Entity $entity, $updateModified = true): Entity { if ($updateModified) { $entity->setLastModified(time()); } return parent::update($entity); } - + /** + * @param int $boardId + * @return array + * @throws \OCP\DB\Exception + */ public function getAssignedLabelsForBoard($boardId) { $labels = $this->findAssignedLabelsForBoard($boardId); $result = []; @@ -80,27 +147,51 @@ class LabelMapper extends DeckMapper implements IPermissionMapper { return $result; } + /** + * @param int $labelId + * @return void + * @throws \OCP\DB\Exception + */ public function deleteLabelAssignments($labelId) { - $sql = 'DELETE FROM `*PREFIX*deck_assigned_labels` WHERE label_id = ?'; - $stmt = $this->db->prepare($sql); - $stmt->bindParam(1, $labelId, \PDO::PARAM_INT); - $stmt->execute(); + $qb = $this->db->getQueryBuilder(); + $qb->delete('deck_assigned_labels') + ->where($qb->expr()->eq('label_id', $qb->createNamedParameter($labelId, IQueryBuilder::PARAM_INT))); + $qb->executeStatement(); } + /** + * @param int $cardId + * @return void + * @throws \OCP\DB\Exception + */ public function deleteLabelAssignmentsForCard($cardId) { - $sql = 'DELETE FROM `*PREFIX*deck_assigned_labels` WHERE card_id = ?'; - $stmt = $this->db->prepare($sql); - $stmt->bindParam(1, $cardId, \PDO::PARAM_INT); - $stmt->execute(); + $qb = $this->db->getQueryBuilder(); + $qb->delete('deck_assigned_labels') + ->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT))); + $qb->executeStatement(); } + /** + * @param string $userId + * @param int $labelId + * @return bool + * @throws \OCP\DB\Exception + */ public function isOwner($userId, $labelId): bool { - $sql = 'SELECT owner FROM `*PREFIX*deck_boards` WHERE `id` IN (SELECT board_id FROM `*PREFIX*deck_labels` WHERE id = ?)'; - $stmt = $this->execute($sql, [$labelId]); - $row = $stmt->fetch(); - return ($row['owner'] === $userId); + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->getTableName(), 'l') + ->innerJoin('l', 'deck_boards' , 'b', 'l.board_id = b.id') + ->where($qb->expr()->eq('l.id', $qb->createNamedParameter($labelId, IQueryBuilder::PARAM_INT))) + ->andWhere($qb->expr()->eq('b.owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR))); + + return $qb->executeQuery()->rowCount() > 0; } + /** + * @param int $id + * @return int|null + */ public function findBoardId($id): ?int { try { $entity = $this->find($id); diff --git a/lib/Db/StackMapper.php b/lib/Db/StackMapper.php index 300cfd335..9b719d989 100644 --- a/lib/Db/StackMapper.php +++ b/lib/Db/StackMapper.php @@ -26,6 +26,7 @@ namespace OCA\Deck\Db; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\MultipleObjectsReturnedException; +use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; class StackMapper extends DeckMapper implements IPermissionMapper { @@ -38,62 +39,112 @@ class StackMapper extends DeckMapper implements IPermissionMapper { /** - * @param $id - * @throws MultipleObjectsReturnedException + * @param int $id + * @return Stack * @throws DoesNotExistException + * @throws MultipleObjectsReturnedException + * @throws \OCP\DB\Exception */ public function find($id): Stack { - $sql = 'SELECT * FROM `*PREFIX*deck_stacks` ' . - 'WHERE `id` = ?'; - return $this->findEntity($sql, [$id]); + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->getTableName()) + ->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT))); + + return $this->findEntity($qb); } /** * @param $cardId * @return Stack|null + * @throws \OCP\DB\Exception */ public function findStackFromCardId($cardId): ?Stack { - $sql = <<db->getQueryBuilder(); + $qb->select('*') + ->from($this->getTableName(), 's') + ->innerJoin('s', 'deck_cards', 'c', 's.id = c.stack_id') + ->where($qb->expr()->eq('c.id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT))); + try { - return $this->findEntity($sql, [$cardId]); + return $this->findEntity($qb); } catch (MultipleObjectsReturnedException|DoesNotExistException $e) { } return null; } + /** + * @param int $boardId + * @param int|null $limit + * @param int|null $offset + * @return Stack[] + * @throws \OCP\DB\Exception + */ + public function findAll($boardId, $limit = null, $offset = null): array { + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->getTableName()) + ->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT))) + ->andWhere($qb->expr()->eq('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT))) + ->setFirstResult($offset) + ->setMaxResults($limit); - public function findAll($boardId, $limit = null, $offset = null) { - $sql = 'SELECT * FROM `*PREFIX*deck_stacks` WHERE `board_id` = ? AND deleted_at = 0 ORDER BY `order`, `id`'; - return $this->findEntities($sql, [$boardId], $limit, $offset); + return $this->findEntities($qb); } - + /** + * @param int $boardId + * @param int|null $limit + * @param int|null $offset + * @return Stack[] + * @throws \OCP\DB\Exception + */ public function findDeleted($boardId, $limit = null, $offset = null) { - $sql = 'SELECT * FROM `*PREFIX*deck_stacks` s - WHERE `s`.`board_id` = ? AND NOT s.deleted_at = 0'; - return $this->findEntities($sql, [$boardId], $limit, $offset); + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->getTableName()) + ->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT))) + ->andWhere($qb->expr()->neq('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT))) + ->setFirstResult($offset) + ->setMaxResults($limit); + + return $this->findEntities($qb); } - - public function delete(Entity $entity) { + /** + * @param Entity $entity + * @return Entity + * @throws \OCP\DB\Exception + */ + public function delete(Entity $entity): Entity { // delete cards on stack $this->cardMapper->deleteByStack($entity->getId()); return parent::delete($entity); } + /** + * @param int $userId + * @param int $stackId + * @return bool + * @throws \OCP\DB\Exception + */ public function isOwner($userId, $stackId): bool { - $sql = 'SELECT owner FROM `*PREFIX*deck_boards` WHERE `id` IN (SELECT board_id FROM `*PREFIX*deck_stacks` WHERE id = ?)'; - $stmt = $this->execute($sql, [$stackId]); - $row = $stmt->fetch(); - return ($row['owner'] === $userId); + $qb = $this->db->getQueryBuilder(); + $qb->select('*') + ->from($this->getTableName(), 's') + ->innerJoin('s', 'deck_boards', 'b', 'b.id = s.board_id') + ->where($qb->expr()->eq('s.id', $qb->createNamedParameter($stackId, IQueryBuilder::PARAM_INT))) + ->andWhere($qb->expr()->eq('owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR))); + + return $qb->executeQuery()->rowCount() > 0; } + /** + * @param $id + * @return int|null + * @throws \OCP\DB\Exception + */ public function findBoardId($id): ?int { try { $entity = $this->find($id); From 9244adee30f3b1fadea5086bae5ac47370a7e6fa Mon Sep 17 00:00:00 2001 From: Raul Ferreira Fuentes Date: Mon, 11 Apr 2022 18:44:27 +0200 Subject: [PATCH 02/10] Various small fixes in mapper queries Signed-off-by: Raul Ferreira Fuentes --- lib/Db/AclMapper.php | 4 +-- lib/Db/AttachmentMapper.php | 63 ++++++++++++------------------------- lib/Db/LabelMapper.php | 5 +-- 3 files changed, 25 insertions(+), 47 deletions(-) diff --git a/lib/Db/AclMapper.php b/lib/Db/AclMapper.php index 5a200c09e..95e1af55a 100644 --- a/lib/Db/AclMapper.php +++ b/lib/Db/AclMapper.php @@ -34,7 +34,7 @@ class AclMapper extends DeckMapper implements IPermissionMapper { * @param IDBConnection $db */ public function __construct(IDBConnection $db) { - parent::__construct($db, 'deck_boards', Board::class); + parent::__construct($db, 'deck_board_acl', Board::class); } /** @@ -47,7 +47,7 @@ class AclMapper extends DeckMapper implements IPermissionMapper { public function findAll($boardId, $limit = null, $offset = null) { $qb = $this->db->getQueryBuilder(); $qb->select('*') - ->from($this->getTableName()) + ->from('deck_board_acl') ->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT))) ->setMaxResults($limit) ->setFirstResult($offset); diff --git a/lib/Db/AttachmentMapper.php b/lib/Db/AttachmentMapper.php index 46e63f7c4..6b98b895b 100644 --- a/lib/Db/AttachmentMapper.php +++ b/lib/Db/AttachmentMapper.php @@ -52,10 +52,11 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper { } /** - * @param $id - * @return Entity|Attachment - * @throws \OCP\AppFramework\Db\DoesNotExistException - * @throws \OCP\AppFramework\Db\MultipleObjectsReturnedException + * @param int $id + * @return Attachment + * @throws DoesNotExistException + * @throws MultipleObjectsReturnedException + * @throws \OCP\DB\Exception */ public function find($id) { $qb = $this->db->getQueryBuilder(); @@ -63,43 +64,31 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper { ->from('deck_attachment') ->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT))); - $cursor = $qb->execute(); - $row = $cursor->fetch(PDO::FETCH_ASSOC); - if ($row === false) { - $cursor->closeCursor(); - throw new DoesNotExistException('Did expect one result but found none when executing' . $qb); - } - - $row2 = $cursor->fetch(); - $cursor->closeCursor(); - if ($row2 !== false) { - throw new MultipleObjectsReturnedException('Did not expect more than one result when executing' . $query); - } - - return $this->mapRowToEntity($row); + return $this->findEntity($qb); } + /** + * @param int $cardId + * @param string $data + * @return Attachment + * @throws DoesNotExistException + * @throws MultipleObjectsReturnedException + * @throws \OCP\DB\Exception + */ public function findByData($cardId, $data) { $qb = $this->db->getQueryBuilder(); $qb->select('*') ->from('deck_attachment') ->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT))) ->andWhere($qb->expr()->eq('data', $qb->createNamedParameter($data, IQueryBuilder::PARAM_STR))); - $cursor = $qb->execute(); - $row = $cursor->fetch(PDO::FETCH_ASSOC); - if ($row === false) { - $cursor->closeCursor(); - throw new DoesNotExistException('Did expect one result but found none when executing' . $qb); - } - $cursor->closeCursor(); - return $this->mapRowToEntity($row); + + return $this->findEntity($qb); } /** - * Find all attachments for a card - * * @param $cardId - * @return array + * @return Entity[] + * @throws \OCP\DB\Exception */ public function findAll($cardId) { $qb = $this->db->getQueryBuilder(); @@ -109,13 +98,7 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper { ->andWhere($qb->expr()->eq('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT))); - $entities = []; - $cursor = $qb->execute(); - while ($row = $cursor->fetch()) { - $entities[] = $this->mapRowToEntity($row); - } - $cursor->closeCursor(); - return $entities; + return $this->findEntities($qb); } /** @@ -139,13 +122,7 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper { ->andWhere($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT))); } - $entities = []; - $cursor = $qb->execute(); - while ($row = $cursor->fetch()) { - $entities[] = $this->mapRowToEntity($row); - } - $cursor->closeCursor(); - return $entities; + return $this->findEntities($qb); } diff --git a/lib/Db/LabelMapper.php b/lib/Db/LabelMapper.php index e613dd2af..be1b68c23 100644 --- a/lib/Db/LabelMapper.php +++ b/lib/Db/LabelMapper.php @@ -75,7 +75,7 @@ class LabelMapper extends DeckMapper implements IPermissionMapper { */ public function findAssignedLabelsForCard($cardId, $limit = null, $offset = null): array { $qb = $this->db->getQueryBuilder(); - $qb->select('l.*,card_id') + $qb->select('l.*', 'card_id') ->from($this->getTableName(), 'l') ->innerJoin('l', 'deck_assigned_labels', 'al', 'l.id = al.label_id') ->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT))) @@ -95,7 +95,8 @@ class LabelMapper extends DeckMapper implements IPermissionMapper { */ public function findAssignedLabelsForBoard($boardId, $limit = null, $offset = null): array { $qb = $this->db->getQueryBuilder(); - $qb->select('c.id as card_id', 'l.id as id', 'l.title as title', 'l.color as color') + $qb->select('l.id as id', 'l.title as title', 'l.color as color') + ->selectAlias('c.id', 'card_id') ->from($this->getTableName(), 'l') ->innerJoin('l', 'deck_assigned_labels', 'al', 'al.label_id = l.id') ->innerJoin('l', 'deck_cards', 'c', 'al.card_id = c.id') From 8399b00a104328f64502e146c4591492e84ef2b3 Mon Sep 17 00:00:00 2001 From: Raul Ferreira Fuentes Date: Mon, 11 Apr 2022 19:46:05 +0200 Subject: [PATCH 03/10] Fix Entity class in `AclMapper` Signed-off-by: Raul Ferreira Fuentes --- lib/Db/AclMapper.php | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/lib/Db/AclMapper.php b/lib/Db/AclMapper.php index 95e1af55a..d95f88c46 100644 --- a/lib/Db/AclMapper.php +++ b/lib/Db/AclMapper.php @@ -34,7 +34,7 @@ class AclMapper extends DeckMapper implements IPermissionMapper { * @param IDBConnection $db */ public function __construct(IDBConnection $db) { - parent::__construct($db, 'deck_board_acl', Board::class); + parent::__construct($db, 'deck_board_acl', Acl::class); } /** @@ -46,7 +46,7 @@ class AclMapper extends DeckMapper implements IPermissionMapper { */ public function findAll($boardId, $limit = null, $offset = null) { $qb = $this->db->getQueryBuilder(); - $qb->select('*') + $qb->select('id', 'board_id', 'type', 'participant', 'permission_edit', 'permission_share', 'permission_manage') ->from('deck_board_acl') ->where($qb->expr()->eq('board_id', $qb->createNamedParameter($boardId, IQueryBuilder::PARAM_INT))) ->setMaxResults($limit) @@ -63,11 +63,10 @@ class AclMapper extends DeckMapper implements IPermissionMapper { */ public function isOwner($userId, $aclId): bool { $qb = $this->db->getQueryBuilder(); - - $qb->select('owner') - ->from($this->getTableName()) + $qb->select('*') + ->from($this->getTableName(), 'acl') ->innerJoin('acl', 'deck_boards','b', 'acl.board_id = b.id') - ->where($qb->expr()->eq('owner.id', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_INT))) + ->where($qb->expr()->eq('owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR))) ->andWhere($qb->expr()->eq('acl.id', $qb->createNamedParameter($aclId, IQueryBuilder::PARAM_INT))); return $qb->executeQuery()->rowCount() > 0; From 8c1e53a8dff6f87237508c6f9a1da17ce99ad767 Mon Sep 17 00:00:00 2001 From: Raul Ferreira Fuentes Date: Mon, 11 Apr 2022 20:04:16 +0200 Subject: [PATCH 04/10] Fix test case which relied on `mapper->delete()` returning a bool value Signed-off-by: Raul Ferreira Fuentes --- lib/Service/BoardService.php | 4 +--- tests/unit/Service/BoardServiceTest.php | 2 +- tests/unit/Service/CardServiceTest.php | 1 + 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/lib/Service/BoardService.php b/lib/Service/BoardService.php index e1cfc8023..4dd2b05c3 100644 --- a/lib/Service/BoardService.php +++ b/lib/Service/BoardService.php @@ -625,11 +625,9 @@ class BoardService { } catch (\Exception $e) { } } - $delete = $this->aclMapper->delete($acl); $this->eventDispatcher->dispatchTyped(new AclDeletedEvent($acl)); - - return $delete; + return (bool) $this->aclMapper->delete($acl); } /** diff --git a/tests/unit/Service/BoardServiceTest.php b/tests/unit/Service/BoardServiceTest.php index 0e8bfeb15..702e16cd4 100644 --- a/tests/unit/Service/BoardServiceTest.php +++ b/tests/unit/Service/BoardServiceTest.php @@ -420,7 +420,7 @@ class BoardServiceTest extends TestCase { $this->aclMapper->expects($this->once()) ->method('delete') ->with($acl) - ->willReturn(true); + ->willReturn($acl); $this->assertTrue($this->service->deleteAcl(123)); } } diff --git a/tests/unit/Service/CardServiceTest.php b/tests/unit/Service/CardServiceTest.php index 622b22c5b..ca260dc9b 100644 --- a/tests/unit/Service/CardServiceTest.php +++ b/tests/unit/Service/CardServiceTest.php @@ -160,6 +160,7 @@ class CardServiceTest extends TestCase { $cardExpected->setAssignedUsers(['user1', 'user2']); $cardExpected->setRelatedBoard($boardMock); $cardExpected->setRelatedStack($stackMock); + $cardExpected->setLabels([]); $this->assertEquals($cardExpected, $this->cardService->find(123)); } From 04974d37d6c14494806d5214e82fe9c92392673c Mon Sep 17 00:00:00 2001 From: Raul Date: Wed, 13 Apr 2022 10:38:32 +0200 Subject: [PATCH 05/10] Replace `rowCount()` with explicit count primitive function. This is necessary due to sqlite driver always returning 0 on `rowCount` (this is documented behaviour: https://www.php.net/manual/en/pdostatement.rowcount.php) Signed-off-by: Raul --- lib/Db/AclMapper.php | 4 ++-- lib/Db/LabelMapper.php | 4 ++-- lib/Db/StackMapper.php | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/Db/AclMapper.php b/lib/Db/AclMapper.php index d95f88c46..fd673f678 100644 --- a/lib/Db/AclMapper.php +++ b/lib/Db/AclMapper.php @@ -63,13 +63,13 @@ class AclMapper extends DeckMapper implements IPermissionMapper { */ public function isOwner($userId, $aclId): bool { $qb = $this->db->getQueryBuilder(); - $qb->select('*') + $qb->select('acl.id') ->from($this->getTableName(), 'acl') ->innerJoin('acl', 'deck_boards','b', 'acl.board_id = b.id') ->where($qb->expr()->eq('owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR))) ->andWhere($qb->expr()->eq('acl.id', $qb->createNamedParameter($aclId, IQueryBuilder::PARAM_INT))); - return $qb->executeQuery()->rowCount() > 0; + return count($qb->executeQuery()->fetchAll()) > 0; } /** diff --git a/lib/Db/LabelMapper.php b/lib/Db/LabelMapper.php index be1b68c23..d65b65fd2 100644 --- a/lib/Db/LabelMapper.php +++ b/lib/Db/LabelMapper.php @@ -180,13 +180,13 @@ class LabelMapper extends DeckMapper implements IPermissionMapper { */ public function isOwner($userId, $labelId): bool { $qb = $this->db->getQueryBuilder(); - $qb->select('*') + $qb->select('l.id') ->from($this->getTableName(), 'l') ->innerJoin('l', 'deck_boards' , 'b', 'l.board_id = b.id') ->where($qb->expr()->eq('l.id', $qb->createNamedParameter($labelId, IQueryBuilder::PARAM_INT))) ->andWhere($qb->expr()->eq('b.owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR))); - return $qb->executeQuery()->rowCount() > 0; + return count($qb->executeQuery()->fetchAll()) > 0; } /** diff --git a/lib/Db/StackMapper.php b/lib/Db/StackMapper.php index 9b719d989..9990ad6c5 100644 --- a/lib/Db/StackMapper.php +++ b/lib/Db/StackMapper.php @@ -131,13 +131,13 @@ class StackMapper extends DeckMapper implements IPermissionMapper { */ public function isOwner($userId, $stackId): bool { $qb = $this->db->getQueryBuilder(); - $qb->select('*') + $qb->select('s.id') ->from($this->getTableName(), 's') ->innerJoin('s', 'deck_boards', 'b', 'b.id = s.board_id') ->where($qb->expr()->eq('s.id', $qb->createNamedParameter($stackId, IQueryBuilder::PARAM_INT))) ->andWhere($qb->expr()->eq('owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR))); - return $qb->executeQuery()->rowCount() > 0; + return count($qb->executeQuery()->fetchAll()) > 0; } /** From 53e3a7ae7f8bebd7304a043cdb8152033c5b0966 Mon Sep 17 00:00:00 2001 From: Raul Date: Wed, 13 Apr 2022 10:43:14 +0200 Subject: [PATCH 06/10] Removed redundant phpDoc block from constructors Signed-off-by: Raul --- lib/Db/AclMapper.php | 3 --- lib/Db/LabelMapper.php | 4 +--- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/lib/Db/AclMapper.php b/lib/Db/AclMapper.php index fd673f678..56b7cb5c0 100644 --- a/lib/Db/AclMapper.php +++ b/lib/Db/AclMapper.php @@ -30,9 +30,6 @@ use OCP\IDBConnection; class AclMapper extends DeckMapper implements IPermissionMapper { - /** - * @param IDBConnection $db - */ public function __construct(IDBConnection $db) { parent::__construct($db, 'deck_board_acl', Acl::class); } diff --git a/lib/Db/LabelMapper.php b/lib/Db/LabelMapper.php index d65b65fd2..ba2d34cff 100644 --- a/lib/Db/LabelMapper.php +++ b/lib/Db/LabelMapper.php @@ -30,9 +30,7 @@ use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; class LabelMapper extends DeckMapper implements IPermissionMapper { - /** - * @param IDBConnection $db - */ + public function __construct(IDBConnection $db) { parent::__construct($db, 'deck_labels', Label::class); } From 815b8597d17588b2884ef7547b496e9274ee8794 Mon Sep 17 00:00:00 2001 From: Raul Date: Wed, 13 Apr 2022 12:39:39 +0200 Subject: [PATCH 07/10] Use `numeric` typehint instead of `int` to allow for numeric strings to be passed to find methods. Fixes the psalm check. Signed-off-by: Raul --- lib/Db/AclMapper.php | 8 ++++---- lib/Db/AssignmentMapper.php | 3 --- lib/Db/LabelMapper.php | 16 ++++++++-------- lib/Db/StackMapper.php | 12 ++++++------ 4 files changed, 18 insertions(+), 21 deletions(-) diff --git a/lib/Db/AclMapper.php b/lib/Db/AclMapper.php index 56b7cb5c0..45a3be468 100644 --- a/lib/Db/AclMapper.php +++ b/lib/Db/AclMapper.php @@ -35,7 +35,7 @@ class AclMapper extends DeckMapper implements IPermissionMapper { } /** - * @param int $boardId + * @param numeric $boardId * @param int|null $limit * @param int|null $offset * @return Acl[] @@ -53,8 +53,8 @@ class AclMapper extends DeckMapper implements IPermissionMapper { } /** - * @param int $userId - * @param int $aclId + * @param numeric $userId + * @param numeric $aclId * @return bool * @throws \OCP\DB\Exception */ @@ -70,7 +70,7 @@ class AclMapper extends DeckMapper implements IPermissionMapper { } /** - * @param int $id + * @param numeric $id * @return int|null */ public function findBoardId($id): ?int { diff --git a/lib/Db/AssignmentMapper.php b/lib/Db/AssignmentMapper.php index fdbf80d85..98a2ead71 100644 --- a/lib/Db/AssignmentMapper.php +++ b/lib/Db/AssignmentMapper.php @@ -55,9 +55,6 @@ class AssignmentMapper extends QBMapper implements IPermissionMapper { $this->circleService = $circleService; } - /** - * @return Assignment[] - */ public function findAll(int $cardId): array { $qb = $this->db->getQueryBuilder(); $qb->select('*') diff --git a/lib/Db/LabelMapper.php b/lib/Db/LabelMapper.php index ba2d34cff..2dcf502c4 100644 --- a/lib/Db/LabelMapper.php +++ b/lib/Db/LabelMapper.php @@ -36,7 +36,7 @@ class LabelMapper extends DeckMapper implements IPermissionMapper { } /** - * @param int $boardId + * @param numeric $boardId * @param int|null $limit * @param int|null $offset * @return Label[] @@ -65,7 +65,7 @@ class LabelMapper extends DeckMapper implements IPermissionMapper { } /** - * @param int $cardId + * @param numeric $cardId * @param int|null $limit * @param int|null $offset * @return Label[] @@ -85,7 +85,7 @@ class LabelMapper extends DeckMapper implements IPermissionMapper { } /** - * @param int $boardId + * @param numeric $boardId * @param int|null $limit * @param int|null $offset * @return Label[] @@ -130,7 +130,7 @@ class LabelMapper extends DeckMapper implements IPermissionMapper { } /** - * @param int $boardId + * @param numeric $boardId * @return array * @throws \OCP\DB\Exception */ @@ -147,7 +147,7 @@ class LabelMapper extends DeckMapper implements IPermissionMapper { } /** - * @param int $labelId + * @param numeric $labelId * @return void * @throws \OCP\DB\Exception */ @@ -159,7 +159,7 @@ class LabelMapper extends DeckMapper implements IPermissionMapper { } /** - * @param int $cardId + * @param numeric $cardId * @return void * @throws \OCP\DB\Exception */ @@ -172,7 +172,7 @@ class LabelMapper extends DeckMapper implements IPermissionMapper { /** * @param string $userId - * @param int $labelId + * @param numeric $labelId * @return bool * @throws \OCP\DB\Exception */ @@ -188,7 +188,7 @@ class LabelMapper extends DeckMapper implements IPermissionMapper { } /** - * @param int $id + * @param numeric $id * @return int|null */ public function findBoardId($id): ?int { diff --git a/lib/Db/StackMapper.php b/lib/Db/StackMapper.php index 9990ad6c5..66e3b0689 100644 --- a/lib/Db/StackMapper.php +++ b/lib/Db/StackMapper.php @@ -39,7 +39,7 @@ class StackMapper extends DeckMapper implements IPermissionMapper { /** - * @param int $id + * @param numeric $id * @return Stack * @throws DoesNotExistException * @throws MultipleObjectsReturnedException @@ -75,7 +75,7 @@ class StackMapper extends DeckMapper implements IPermissionMapper { } /** - * @param int $boardId + * @param numeric $boardId * @param int|null $limit * @param int|null $offset * @return Stack[] @@ -94,7 +94,7 @@ class StackMapper extends DeckMapper implements IPermissionMapper { } /** - * @param int $boardId + * @param numeric $boardId * @param int|null $limit * @param int|null $offset * @return Stack[] @@ -124,8 +124,8 @@ class StackMapper extends DeckMapper implements IPermissionMapper { } /** - * @param int $userId - * @param int $stackId + * @param numeric $userId + * @param numeric $stackId * @return bool * @throws \OCP\DB\Exception */ @@ -141,7 +141,7 @@ class StackMapper extends DeckMapper implements IPermissionMapper { } /** - * @param $id + * @param numeric $id * @return int|null * @throws \OCP\DB\Exception */ From 1d5fdef4b4f609e2eda78ff5de40c68a489f418b Mon Sep 17 00:00:00 2001 From: Raul Date: Wed, 13 Apr 2022 12:40:05 +0200 Subject: [PATCH 08/10] Remove redundant `is_array` checks on return result from `LabelMapper::findAll` Signed-off-by: Raul --- lib/Service/LabelService.php | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/lib/Service/LabelService.php b/lib/Service/LabelService.php index b27384760..4e833d94e 100644 --- a/lib/Service/LabelService.php +++ b/lib/Service/LabelService.php @@ -91,14 +91,12 @@ class LabelService { $this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE); $boardLabels = $this->labelMapper->findAll($boardId); - if (\is_array($boardLabels)) { - foreach ($boardLabels as $boardLabel) { - if ($boardLabel->getTitle() === $title) { - throw new BadRequestException('title must be unique'); - break; - } - } - } + foreach ($boardLabels as $boardLabel) { + if ($boardLabel->getTitle() === $title) { + throw new BadRequestException('title must be unique'); + break; + } + } if ($this->boardService->isArchived(null, $boardId)) { throw new StatusException('Operation not allowed. This board is archived.'); @@ -163,17 +161,15 @@ class LabelService { $label = $this->find($id); $boardLabels = $this->labelMapper->findAll($label->getBoardId()); - if (\is_array($boardLabels)) { - foreach ($boardLabels as $boardLabel) { - if ($boardLabel->getId() === $label->getId()) { - continue; - } - if ($boardLabel->getTitle() === $title) { - throw new BadRequestException('title must be unique'); - break; - } - } - } + foreach ($boardLabels as $boardLabel) { + if ($boardLabel->getId() === $label->getId()) { + continue; + } + if ($boardLabel->getTitle() === $title) { + throw new BadRequestException('title must be unique'); + break; + } + } if ($this->boardService->isArchived($this->labelMapper, $id)) { throw new StatusException('Operation not allowed. This board is archived.'); From 0c5b1a88a691f7632226cb4ff3d69da4a3672392 Mon Sep 17 00:00:00 2001 From: Raul Date: Wed, 13 Apr 2022 12:43:00 +0200 Subject: [PATCH 09/10] Run cs:fix Signed-off-by: Raul --- lib/Db/AclMapper.php | 3 +-- lib/Db/AttachmentMapper.php | 1 - lib/Db/LabelMapper.php | 5 ++--- lib/Db/StackMapper.php | 2 +- lib/Service/LabelService.php | 30 +++++++++++++++--------------- 5 files changed, 19 insertions(+), 22 deletions(-) diff --git a/lib/Db/AclMapper.php b/lib/Db/AclMapper.php index 45a3be468..f3d6ea3d9 100644 --- a/lib/Db/AclMapper.php +++ b/lib/Db/AclMapper.php @@ -29,7 +29,6 @@ use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; class AclMapper extends DeckMapper implements IPermissionMapper { - public function __construct(IDBConnection $db) { parent::__construct($db, 'deck_board_acl', Acl::class); } @@ -62,7 +61,7 @@ class AclMapper extends DeckMapper implements IPermissionMapper { $qb = $this->db->getQueryBuilder(); $qb->select('acl.id') ->from($this->getTableName(), 'acl') - ->innerJoin('acl', 'deck_boards','b', 'acl.board_id = b.id') + ->innerJoin('acl', 'deck_boards', 'b', 'acl.board_id = b.id') ->where($qb->expr()->eq('owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR))) ->andWhere($qb->expr()->eq('acl.id', $qb->createNamedParameter($aclId, IQueryBuilder::PARAM_INT))); diff --git a/lib/Db/AttachmentMapper.php b/lib/Db/AttachmentMapper.php index 6b98b895b..269af4131 100644 --- a/lib/Db/AttachmentMapper.php +++ b/lib/Db/AttachmentMapper.php @@ -30,7 +30,6 @@ use OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; use OCP\IUserManager; -use PDO; class AttachmentMapper extends DeckMapper implements IPermissionMapper { private $cardMapper; diff --git a/lib/Db/LabelMapper.php b/lib/Db/LabelMapper.php index 2dcf502c4..61ce03ed3 100644 --- a/lib/Db/LabelMapper.php +++ b/lib/Db/LabelMapper.php @@ -30,7 +30,6 @@ use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; class LabelMapper extends DeckMapper implements IPermissionMapper { - public function __construct(IDBConnection $db) { parent::__construct($db, 'deck_labels', Label::class); } @@ -180,11 +179,11 @@ class LabelMapper extends DeckMapper implements IPermissionMapper { $qb = $this->db->getQueryBuilder(); $qb->select('l.id') ->from($this->getTableName(), 'l') - ->innerJoin('l', 'deck_boards' , 'b', 'l.board_id = b.id') + ->innerJoin('l', 'deck_boards', 'b', 'l.board_id = b.id') ->where($qb->expr()->eq('l.id', $qb->createNamedParameter($labelId, IQueryBuilder::PARAM_INT))) ->andWhere($qb->expr()->eq('b.owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR))); - return count($qb->executeQuery()->fetchAll()) > 0; + return count($qb->executeQuery()->fetchAll()) > 0; } /** diff --git a/lib/Db/StackMapper.php b/lib/Db/StackMapper.php index 66e3b0689..1ae59dd1b 100644 --- a/lib/Db/StackMapper.php +++ b/lib/Db/StackMapper.php @@ -137,7 +137,7 @@ class StackMapper extends DeckMapper implements IPermissionMapper { ->where($qb->expr()->eq('s.id', $qb->createNamedParameter($stackId, IQueryBuilder::PARAM_INT))) ->andWhere($qb->expr()->eq('owner', $qb->createNamedParameter($userId, IQueryBuilder::PARAM_STR))); - return count($qb->executeQuery()->fetchAll()) > 0; + return count($qb->executeQuery()->fetchAll()) > 0; } /** diff --git a/lib/Service/LabelService.php b/lib/Service/LabelService.php index 4e833d94e..f4c95fb66 100644 --- a/lib/Service/LabelService.php +++ b/lib/Service/LabelService.php @@ -91,12 +91,12 @@ class LabelService { $this->permissionService->checkPermission(null, $boardId, Acl::PERMISSION_MANAGE); $boardLabels = $this->labelMapper->findAll($boardId); - foreach ($boardLabels as $boardLabel) { - if ($boardLabel->getTitle() === $title) { - throw new BadRequestException('title must be unique'); - break; - } - } + foreach ($boardLabels as $boardLabel) { + if ($boardLabel->getTitle() === $title) { + throw new BadRequestException('title must be unique'); + break; + } + } if ($this->boardService->isArchived(null, $boardId)) { throw new StatusException('Operation not allowed. This board is archived.'); @@ -161,15 +161,15 @@ class LabelService { $label = $this->find($id); $boardLabels = $this->labelMapper->findAll($label->getBoardId()); - foreach ($boardLabels as $boardLabel) { - if ($boardLabel->getId() === $label->getId()) { - continue; - } - if ($boardLabel->getTitle() === $title) { - throw new BadRequestException('title must be unique'); - break; - } - } + foreach ($boardLabels as $boardLabel) { + if ($boardLabel->getId() === $label->getId()) { + continue; + } + if ($boardLabel->getTitle() === $title) { + throw new BadRequestException('title must be unique'); + break; + } + } if ($this->boardService->isArchived($this->labelMapper, $id)) { throw new StatusException('Operation not allowed. This board is archived.'); From 3f754dc662ac82777aa5c1e6a0c641d3f55c9371 Mon Sep 17 00:00:00 2001 From: Raul Date: Thu, 14 Apr 2022 16:56:22 +0200 Subject: [PATCH 10/10] Update `AttachmentMapper` finder methods to use `$this-getTableName()` instead of explicitly naming the table on the FROM parameters. Signed-off-by: Raul --- lib/Db/AttachmentMapper.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Db/AttachmentMapper.php b/lib/Db/AttachmentMapper.php index 269af4131..727e3cce1 100644 --- a/lib/Db/AttachmentMapper.php +++ b/lib/Db/AttachmentMapper.php @@ -60,7 +60,7 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper { public function find($id) { $qb = $this->db->getQueryBuilder(); $qb->select('*') - ->from('deck_attachment') + ->from($this->getTableName()) ->where($qb->expr()->eq('id', $qb->createNamedParameter($id, IQueryBuilder::PARAM_INT))); return $this->findEntity($qb); @@ -77,7 +77,7 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper { public function findByData($cardId, $data) { $qb = $this->db->getQueryBuilder(); $qb->select('*') - ->from('deck_attachment') + ->from($this->getTableName()) ->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT))) ->andWhere($qb->expr()->eq('data', $qb->createNamedParameter($data, IQueryBuilder::PARAM_STR))); @@ -92,7 +92,7 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper { public function findAll($cardId) { $qb = $this->db->getQueryBuilder(); $qb->select('*') - ->from('deck_attachment') + ->from($this->getTableName()) ->where($qb->expr()->eq('card_id', $qb->createNamedParameter($cardId, IQueryBuilder::PARAM_INT))) ->andWhere($qb->expr()->eq('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT))); @@ -110,7 +110,7 @@ class AttachmentMapper extends DeckMapper implements IPermissionMapper { $timeLimit = time() - (60 * 5); $qb = $this->db->getQueryBuilder(); $qb->select('*') - ->from('deck_attachment') + ->from($this->getTableName()) ->where($qb->expr()->gt('deleted_at', $qb->createNamedParameter(0, IQueryBuilder::PARAM_INT))); if ($withOffset) { $qb