From a4c654f44c5291a09f6ba178edd201b770eed40a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rub=C3=A9n=20D?= Date: Sun, 20 Nov 2022 19:58:16 +0100 Subject: [PATCH] chore: Implement PublicLinkRepository tests. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Rubén D --- lib/SP/DataModel/PublicLinkData.php | 257 ++------ lib/SP/DataModel/PublicLinkListData.php | 70 +-- .../Account/PublicLinkServiceInterface.php | 2 +- .../PublicLinkRepositoryInterface.php | 150 +++++ .../Domain/Account/Services/PublicLinkKey.php | 2 +- .../Account/Services/PublicLinkService.php | 63 +- .../Repositories/PublicLinkRepository.php | 567 +++++++----------- .../Infrastructure/Database/QueryResult.php | 5 +- .../Repositories/PublicLinkRepositoryTest.php | 443 ++++++++++++++ .../Repositories/PublicLinkRepositoryTest.php | 13 +- 10 files changed, 932 insertions(+), 640 deletions(-) create mode 100644 lib/SP/Domain/Account/Repositories/PublicLinkRepositoryInterface.php create mode 100644 tests/SP/Infrastructure/Account/Repositories/PublicLinkRepositoryTest.php diff --git a/lib/SP/DataModel/PublicLinkData.php b/lib/SP/DataModel/PublicLinkData.php index f9641107..db01e5a7 100644 --- a/lib/SP/DataModel/PublicLinkData.php +++ b/lib/SP/DataModel/PublicLinkData.php @@ -27,8 +27,6 @@ namespace SP\DataModel; use SP\Domain\Common\Out\DataModelBase; use SP\Domain\Common\Out\DataModelInterface; -defined('APP_ROOT') || die(); - /** * Class PublicLinkData * @@ -36,75 +34,27 @@ defined('APP_ROOT') || die(); */ class PublicLinkData extends DataModelBase implements DataModelInterface { - /** - * @var int - */ - public $id = 0; - /** - * @var int - */ - public $itemId = 0; - /** - * @var string - */ - public $hash = ''; - /** - * @var int - */ - public $userId = 0; - /** - * @var int - */ - public $typeId = 0; - /** - * @var bool - */ - public $notify = false; - /** - * @var int - */ - public $dateAdd = 0; - /** - * @var int - */ - public $dateUpdate = 0; - /** - * @var int - */ - public $dateExpire = 0; - /** - * @var int - */ - public $countViews = 0; - /** - * @var int - */ - public $totalCountViews = 0; - /** - * @var int - */ - public $maxCountViews = 0; - /** - * @var string - */ - public $useInfo; - /** - * @var string - */ - public $data; + protected ?int $id; + protected ?int $itemId; + protected ?string $hash; + protected ?int $userId; + protected ?int $typeId; + protected ?bool $notify; + protected ?int $dateAdd; + protected ?int $dateUpdate; + protected ?int $dateExpire; + protected ?int $countViews; + protected ?int $totalCountViews; + protected ?int $maxCountViews; + protected ?string $useInfo; + protected ?string $data; - /** - * @return string - */ - public function getData() + public function getData(): ?string { return $this->data; } - /** - * @param string $data - */ - public function setData($data) + public function setData(?string $data): void { $this->data = $data; } @@ -114,216 +64,123 @@ class PublicLinkData extends DataModelBase implements DataModelInterface return (int)$this->id; } - /** - * @param int $id - */ - public function setId($id) - { - $this->id = (int)$id; - } - - /** - * @return string - */ - public function getHash() + public function getHash(): ?string { return $this->hash; } - /** - * @param string $hash - */ - public function setHash($hash) + public function setHash(?string $hash): void { $this->hash = $hash; } - /** - * @return int - */ - public function getItemId() + public function getItemId(): int { return (int)$this->itemId; } - /** - * @param int $itemId - */ - public function setItemId($itemId) + public function setItemId(int $itemId): void { - $this->itemId = (int)$itemId; + $this->itemId = $itemId; } - /** - * @return int - */ - public function getUserId() + public function getUserId(): int { return (int)$this->userId; } - /** - * @param int $userId - */ - public function setUserId($userId) + public function setUserId(int $userId): void { - $this->userId = (int)$userId; + $this->userId = $userId; } - /** - * @return int - */ - public function getTypeId() + public function getTypeId(): ?int { - return (int)$this->typeId; + return $this->typeId; } - /** - * @param int $typeId - */ - public function setTypeId($typeId) + public function setTypeId(int $typeId): void { - $this->typeId = (int)$typeId; + $this->typeId = $typeId; } - /** - * @return boolean - */ - public function isNotify() + public function isNotify(): bool { - return (bool)$this->notify; + return $this->notify; } - /** - * @param boolean $notify - */ - public function setNotify($notify) + public function setNotify(bool $notify): void { - $this->notify = (bool)$notify; + $this->notify = $notify; } - /** - * @return int - */ - public function getDateAdd() + public function getDateAdd(): ?int { - return (int)$this->dateAdd; + return $this->dateAdd; } - /** - * @param int $dateAdd - */ - public function setDateAdd($dateAdd) + public function setDateAdd(int $dateAdd): void { - $this->dateAdd = (int)$dateAdd; + $this->dateAdd = $dateAdd; } - /** - * @return int - */ - public function getDateExpire() + public function getDateExpire(): ?int { - return (int)$this->dateExpire; + return $this->dateExpire; } - /** - * @param int $dateExpire - */ - public function setDateExpire($dateExpire) + public function setDateExpire(int $dateExpire): void { - $this->dateExpire = (int)$dateExpire; + $this->dateExpire = $dateExpire; } - /** - * @return int - */ - public function getCountViews() + public function getCountViews(): ?int { - return (int)$this->countViews; + return $this->countViews; } - /** - * @param int $countViews - */ - public function setCountViews($countViews) + public function setCountViews(int $countViews): void { - $this->countViews = (int)$countViews; + $this->countViews = $countViews; } - /** - * @return int - */ - public function addCountViews() + public function addCountViews(): ?int { return $this->countViews++; } - /** - * @return int - */ - public function getMaxCountViews() + public function getMaxCountViews(): ?int { - return (int)$this->maxCountViews; + return $this->maxCountViews; } - /** - * @param int $maxCountViews - */ - public function setMaxCountViews($maxCountViews) + public function setMaxCountViews(int $maxCountViews): void { - $this->maxCountViews = (int)$maxCountViews; + $this->maxCountViews = $maxCountViews; } - /** - * @return string - */ - public function getUseInfo() + public function getUseInfo(): ?string { return $this->useInfo; } - /** - * @param array $useInfo - */ - public function setUseInfo(array $useInfo) + public function setUseInfo(array $useInfo): void { $this->useInfo = serialize($useInfo); } - /** - * @return int - */ - public function getTotalCountViews() + public function getTotalCountViews(): ?int { - return (int)$this->totalCountViews; + return $this->totalCountViews; } - /** - * @return int - */ - public function addTotalCountViews() + public function getDateUpdate(): ?int { - return $this->totalCountViews++; + return $this->dateUpdate; } public function getName(): ?string { - return ''; + return null; } - - /** - * @return int - */ - public function getDateUpdate(): int - { - return (int)$this->dateUpdate; - } - - /** - * @param int $dateUpdate - */ - public function setDateUpdate(int $dateUpdate) - { - $this->dateUpdate = $dateUpdate; - } -} \ No newline at end of file +} diff --git a/lib/SP/DataModel/PublicLinkListData.php b/lib/SP/DataModel/PublicLinkListData.php index 99c74f4d..6c0ecedb 100644 --- a/lib/SP/DataModel/PublicLinkListData.php +++ b/lib/SP/DataModel/PublicLinkListData.php @@ -4,7 +4,7 @@ * * @author nuxsmin * @link https://syspass.org - * @copyright 2012-2021, Rubén Domínguez nuxsmin@$syspass.org + * @copyright 2012-2022, Rubén Domínguez nuxsmin@$syspass.org * * This file is part of sysPass. * @@ -24,10 +24,6 @@ namespace SP\DataModel; -use SP\Util\DateUtil; - -defined('APP_ROOT') || die(); - /** * Class PublicLinkListData * @@ -35,72 +31,22 @@ defined('APP_ROOT') || die(); */ class PublicLinkListData extends PublicLinkData { - /** - * @var string - */ - public $userName; - /** - * @var string - */ - public $userLogin; - /** - * @var string - */ - public $accountName; + protected ?string $userName; + protected ?string $userLogin; + protected ?string $accountName; - /** - * @return string - */ - public function getName() + public function getName(): ?string { return $this->accountName; } - /** - * @return string - */ - public function getUserName() - { - return $this->userName; - } - - /** - * @return string - */ - public function getUserLogin() + public function getUserLogin(): ?string { return $this->userLogin; } - /** - * @return string - */ - public function getAccountName() + public function getAccountName(): ?string { return $this->accountName; } - - /** - * @return false|string - */ - public function getDateAddFormat() - { - return DateUtil::getDateFromUnix($this->dateAdd); - } - - /** - * @return false|string - */ - public function getDateExpireFormat() - { - return DateUtil::getDateFromUnix($this->dateExpire); - } - - /** - * @return string - */ - public function getCountViewsString() - { - return sprintf('%d/%d/%d', $this->getCountViews(), $this->getMaxCountViews(), $this->getTotalCountViews()); - } -} \ No newline at end of file +} diff --git a/lib/SP/Domain/Account/PublicLinkServiceInterface.php b/lib/SP/Domain/Account/PublicLinkServiceInterface.php index 775ced1c..3dadd19e 100644 --- a/lib/SP/Domain/Account/PublicLinkServiceInterface.php +++ b/lib/SP/Domain/Account/PublicLinkServiceInterface.php @@ -137,5 +137,5 @@ interface PublicLinkServiceInterface * @throws ConstraintException * @throws QueryException */ - public function update(PublicLinkData $itemData): int; + public function update(PublicLinkData $itemData): void; } diff --git a/lib/SP/Domain/Account/Repositories/PublicLinkRepositoryInterface.php b/lib/SP/Domain/Account/Repositories/PublicLinkRepositoryInterface.php new file mode 100644 index 00000000..2f5b9984 --- /dev/null +++ b/lib/SP/Domain/Account/Repositories/PublicLinkRepositoryInterface.php @@ -0,0 +1,150 @@ +. + */ + +namespace SP\Domain\Account\Repositories; + +use SP\Core\Exceptions\ConstraintException; +use SP\Core\Exceptions\QueryException; +use SP\Core\Exceptions\SPException; +use SP\DataModel\ItemSearchData; +use SP\DataModel\PublicLinkData; +use SP\Infrastructure\Common\Repositories\DuplicatedItemException; +use SP\Infrastructure\Database\QueryResult; + +/** + * Class PublicLinkRepository + * + * @package SP\Infrastructure\Common\Repositories\PublicLink + */ +interface PublicLinkRepositoryInterface +{ + /** + * Deletes an item + * + * @param int $id + * + * @return void + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function delete(int $id): void; + + /** + * Returns all the items + * + * @return QueryResult + */ + public function getAll(): QueryResult; + + /** + * Deletes all the items for given ids + * + * @param array $ids + * + * @return int + * @throws ConstraintException + * @throws QueryException + */ + public function deleteByIdBatch(array $ids): int; + + /** + * Searches for items by a given filter + * + * @param ItemSearchData $itemSearchData + * + * @return QueryResult + */ + public function search(ItemSearchData $itemSearchData): QueryResult; + + /** + * Creates an item + * + * @param PublicLinkData $publicLinkData + * + * @return QueryResult + * @throws DuplicatedItemException + * @throws QueryException + * @throws ConstraintException + */ + public function create(PublicLinkData $publicLinkData): QueryResult; + + /** + * Incrementar el contador de visitas de un enlace + * + * @param PublicLinkData $publicLinkData + * + * @return bool + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function addLinkView(PublicLinkData $publicLinkData): bool; + + /** + * Updates an item + * + * @param \SP\DataModel\PublicLinkData $publicLinkData + * + * @return bool + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function update(PublicLinkData $publicLinkData): bool; + + /** + * Refreshes a public link + * + * @param PublicLinkData $publicLinkData + * + * @return bool + * @throws SPException + * @throws ConstraintException + * @throws QueryException + */ + public function refresh(PublicLinkData $publicLinkData): bool; + + /** + * Returns the item for given id + * + * @param int $id + * + * @return QueryResult + */ + public function getById(int $id): QueryResult; + + /** + * @param $hash string + * + * @return QueryResult + */ + public function getByHash(string $hash): QueryResult; + + /** + * Devolver el hash asociado a un elemento + * + * @param int $itemId + * + * @return QueryResult + */ + public function getHashForItem(int $itemId): QueryResult; +} diff --git a/lib/SP/Domain/Account/Services/PublicLinkKey.php b/lib/SP/Domain/Account/Services/PublicLinkKey.php index 38651f20..ae04e4d2 100644 --- a/lib/SP/Domain/Account/Services/PublicLinkKey.php +++ b/lib/SP/Domain/Account/Services/PublicLinkKey.php @@ -66,4 +66,4 @@ final class PublicLinkKey { return $this->salt; } -} \ No newline at end of file +} diff --git a/lib/SP/Domain/Account/Services/PublicLinkService.php b/lib/SP/Domain/Account/Services/PublicLinkService.php index 071a18bd..809e3364 100644 --- a/lib/SP/Domain/Account/Services/PublicLinkService.php +++ b/lib/SP/Domain/Account/Services/PublicLinkService.php @@ -37,15 +37,16 @@ use SP\DataModel\PublicLinkData; use SP\DataModel\PublicLinkListData; use SP\Domain\Account\AccountServiceInterface; use SP\Domain\Account\PublicLinkServiceInterface; +use SP\Domain\Account\Repositories\PublicLinkRepositoryInterface; use SP\Domain\Common\Services\Service; use SP\Domain\Common\Services\ServiceException; use SP\Domain\Common\Services\ServiceItemTrait; use SP\Domain\Config\ConfigInterface; use SP\Http\RequestInterface; use SP\Http\Uri; -use SP\Infrastructure\Account\Repositories\PublicLinkRepository; use SP\Infrastructure\Common\Repositories\NoSuchItemException; use SP\Infrastructure\Database\QueryResult; +use function SP\__u; /** * Class PublicLinkService @@ -61,13 +62,13 @@ final class PublicLinkService extends Service implements PublicLinkServiceInterf */ public const TYPE_ACCOUNT = 1; - private PublicLinkRepository $publicLinkRepository; - private RequestInterface $request; - private AccountServiceInterface $accountService; + private PublicLinkRepositoryInterface $publicLinkRepository; + private RequestInterface $request; + private AccountServiceInterface $accountService; public function __construct( Application $application, - PublicLinkRepository $publicLinkRepository, + PublicLinkRepositoryInterface $publicLinkRepository, RequestInterface $request, AccountServiceInterface $accountService ) { @@ -100,8 +101,9 @@ final class PublicLinkService extends Service implements PublicLinkServiceInterf } /** - * @throws ConstraintException - * @throws QueryException + * @param \SP\DataModel\ItemSearchData $itemSearchData + * + * @return \SP\Infrastructure\Database\QueryResult */ public function search(ItemSearchData $itemSearchData): QueryResult { @@ -138,8 +140,9 @@ final class PublicLinkService extends Service implements PublicLinkServiceInterf } /** - * @throws \SP\Core\Exceptions\ConstraintException - * @throws \SP\Core\Exceptions\QueryException + * @param int $id + * + * @return \SP\DataModel\PublicLinkListData * @throws \SP\Infrastructure\Common\Repositories\NoSuchItemException */ public function getById(int $id): PublicLinkListData @@ -180,7 +183,11 @@ final class PublicLinkService extends Service implements PublicLinkServiceInterf // Desencriptar la clave de la cuenta $accountData->setPass( - Crypt::decrypt($accountData->getPass(), $accountData->getKey(), $this->getMasterKeyFromContext()) + Crypt::decrypt( + $accountData->getPass(), + $accountData->getKey(), + $this->getMasterKeyFromContext() + ) ); $accountData->setKey(null); @@ -196,15 +203,15 @@ final class PublicLinkService extends Service implements PublicLinkServiceInterf } /** + * @param int $id + * + * @return \SP\Domain\Account\PublicLinkServiceInterface * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException - * @throws \SP\Infrastructure\Common\Repositories\NoSuchItemException */ public function delete(int $id): PublicLinkServiceInterface { - if ($this->publicLinkRepository->delete($id) === 0) { - throw new NoSuchItemException(__u('Link not found'), SPException::INFO); - } + $this->publicLinkRepository->delete($id); return $this; } @@ -252,8 +259,6 @@ final class PublicLinkService extends Service implements PublicLinkServiceInterf * Get all items from the service's repository * * @return PublicLinkListData[] - * @throws ConstraintException - * @throws QueryException */ public function getAllBasic(): array { @@ -263,20 +268,19 @@ final class PublicLinkService extends Service implements PublicLinkServiceInterf /** * Incrementar el contador de visitas de un enlace * - * @throws NoSuchItemException - * @throws ConstraintException - * @throws QueryException + * @param \SP\DataModel\PublicLinkData $publicLinkData + * + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException */ public function addLinkView(PublicLinkData $publicLinkData): void { /** @var array $useInfo */ - $useInfo = unserialize($publicLinkData->getUseInfo()); + $useInfo = unserialize($publicLinkData->getUseInfo(), false); $useInfo[] = self::getUseInfo($publicLinkData->getHash(), $this->request); $publicLinkData->setUseInfo($useInfo); - if ($this->publicLinkRepository->addLinkView($publicLinkData) === 0) { - throw new NoSuchItemException(__u('Link not found')); - } + $this->publicLinkRepository->addLinkView($publicLinkData); } /** @@ -310,9 +314,10 @@ final class PublicLinkService extends Service implements PublicLinkServiceInterf /** * Devolver el hash asociado a un elemento * - * @throws ConstraintException - * @throws QueryException - * @throws NoSuchItemException + * @param int $itemId + * + * @return \SP\DataModel\PublicLinkData + * @throws \SP\Infrastructure\Common\Repositories\NoSuchItemException */ public function getHashForItem(int $itemId): PublicLinkData { @@ -332,8 +337,8 @@ final class PublicLinkService extends Service implements PublicLinkServiceInterf * @throws ConstraintException * @throws QueryException */ - public function update(PublicLinkData $itemData): int + public function update(PublicLinkData $itemData): void { - return $this->publicLinkRepository->update($itemData); + $this->publicLinkRepository->update($itemData); } -} \ No newline at end of file +} diff --git a/lib/SP/Infrastructure/Account/Repositories/PublicLinkRepository.php b/lib/SP/Infrastructure/Account/Repositories/PublicLinkRepository.php index b18fb323..97b0fb33 100644 --- a/lib/SP/Infrastructure/Account/Repositories/PublicLinkRepository.php +++ b/lib/SP/Infrastructure/Account/Repositories/PublicLinkRepository.php @@ -24,26 +24,25 @@ namespace SP\Infrastructure\Account\Repositories; -use RuntimeException; use SP\Core\Exceptions\ConstraintException; use SP\Core\Exceptions\QueryException; use SP\Core\Exceptions\SPException; use SP\DataModel\ItemSearchData; use SP\DataModel\PublicLinkData; -use SP\DataModel\PublicLinkListData; -use SP\Domain\Common\In\RepositoryInterface; +use SP\Domain\Account\Repositories\PublicLinkRepositoryInterface; use SP\Infrastructure\Common\Repositories\DuplicatedItemException; use SP\Infrastructure\Common\Repositories\Repository; use SP\Infrastructure\Common\Repositories\RepositoryItemTrait; use SP\Infrastructure\Database\QueryData; use SP\Infrastructure\Database\QueryResult; +use function SP\__u; /** * Class PublicLinkRepository * * @package SP\Infrastructure\Common\Repositories\PublicLink */ -final class PublicLinkRepository extends Repository implements RepositoryInterface +final class PublicLinkRepository extends Repository implements PublicLinkRepositoryInterface { use RepositoryItemTrait; @@ -52,104 +51,55 @@ final class PublicLinkRepository extends Repository implements RepositoryInterfa * * @param int $id * - * @return int + * @return void * @throws \SP\Core\Exceptions\ConstraintException * @throws \SP\Core\Exceptions\QueryException */ - public function delete(int $id): int + public function delete(int $id): void { - $queryData = new QueryData(); - $queryData->setQuery('DELETE FROM PublicLink WHERE id = ? LIMIT 1'); - $queryData->addParam($id); - $queryData->setOnErrorMessage(__u('Error while removing the link')); + $query = $this->queryFactory + ->newDelete() + ->from('PublicLink') + ->where('id = :id') + ->bindValue('id', $id); - return $this->db->doQuery($queryData)->getAffectedNumRows(); + $this->db->doQuery(QueryData::build($query)->setOnErrorMessage(__u('Error while removing the link'))); } /** * Returns all the items * * @return QueryResult - * @throws QueryException - * @throws ConstraintException */ public function getAll(): QueryResult { - $query = /** @lang SQL */ - 'SELECT PL.id, - PL.itemId, - PL.hash, - PL.data, - PL.userId, - PL.typeId, - PL.notify, - PL.dateAdd, - PL.dateExpire, - PL.dateUpdate, - PL.countViews, - PL.maxCountViews, - PL.totalCountViews, - PL.useInfo, - U.name AS userName, - U.login AS userLogin, - A.name AS accountName - FROM PublicLink PL - INNER JOIN User U ON PL.userId = U.id - INNER JOIN Account A ON itemId = A.id - ORDER BY PL.id'; + $query = $this->queryFactory + ->newSelect() + ->cols([ + 'PublicLink.id', + 'PublicLink.itemId', + 'PublicLink.hash', + 'PublicLink.data', + 'PublicLink.userId', + 'PublicLink.typeId', + 'PublicLink.notify', + 'PublicLink.dateAdd', + 'PublicLink.dateExpire', + 'PublicLink.dateUpdate', + 'PublicLink.countViews', + 'PublicLink.maxCountViews', + 'PublicLink.totalCountViews', + 'PublicLink.useInfo', + 'User.name AS userName', + 'User.login AS userLogin', + 'Account.name AS accountName', + ]) + ->from('PublicLink') + ->join('INNER', 'User', 'User.id = PublicLink.userId') + ->join('INNER', 'Account', 'Account.id = PublicLink.itemId') + ->orderBy(['PublicLink.id']); - $queryData = new QueryData(); - $queryData->setMapClassName(PublicLinkListData::class); - $queryData->setQuery($query); - - return $this->db->doSelect($queryData); - } - - /** - * Returns all the items for given ids - * - * @param array $ids - * - * @return QueryResult - * @throws QueryException - * @throws ConstraintException - */ - public function getByIdBatch(array $ids): QueryResult - { - if (count($ids) === 0) { - return new QueryResult(); - } - - $query = /** @lang SQL */ - 'SELECT PL.id, - PL.itemId, - PL.hash, - PL.data, - PL.userId, - PL.typeId, - PL.notify, - PL.dateAdd, - PL.dateExpire, - PL.dateUpdate, - PL.countViews, - PL.maxCountViews, - PL.totalCountViews, - PL.useInfo, - U.name AS userName, - U.login AS userLogin, - A.name AS accountName - FROM PublicLink PL - INNER JOIN User U ON PL.userId = U.id - INNER JOIN Account A ON itemId = A.id - WHERE PL.id IN ('.$this->buildParamsFromArray($ids).') - ORDER BY PL.id'; - - $queryData = new QueryData(); - $queryData->setMapClassName(PublicLinkListData::class); - $queryData->setQuery($query); - $queryData->setParams($ids); - - return $this->db->doSelect($queryData); + return $this->db->doSelect(QueryData::build($query)); } /** @@ -167,23 +117,12 @@ final class PublicLinkRepository extends Repository implements RepositoryInterfa return 0; } - $queryData = new QueryData(); - $queryData->setQuery('DELETE FROM PublicLink WHERE id IN ('.$this->buildParamsFromArray($ids).')'); - $queryData->setParams($ids); + $query = $this->queryFactory + ->newDelete() + ->from('PublicLink') + ->where(sprintf('id IN (%s)', $this->buildParamsFromArray($ids)), ...$ids); - return $this->db->doQuery($queryData)->getAffectedNumRows(); - } - - /** - * Checks whether the item is in use or not - * - * @param $id int - * - * @return void - */ - public function checkInUse(int $id): bool - { - throw new RuntimeException('Not implemented'); + return $this->db->doQuery(QueryData::build($query))->getAffectedNumRows(); } /** @@ -192,99 +131,88 @@ final class PublicLinkRepository extends Repository implements RepositoryInterfa * @param ItemSearchData $itemSearchData * * @return QueryResult - * @throws QueryException - * @throws ConstraintException */ public function search(ItemSearchData $itemSearchData): QueryResult { - $queryData = new QueryData(); - $queryData->setMapClassName(PublicLinkListData::class); - $queryData->setSelect( - 'PublicLink.id, - PublicLink.itemId, - PublicLink.hash, - PublicLink.data, - PublicLink.userId, - PublicLink.typeId, - PublicLink.notify, - PublicLink.dateAdd, - PublicLink.dateExpire, - PublicLink.dateUpdate, - PublicLink.countViews, - PublicLink.maxCountViews, - PublicLink.totalCountViews, - PublicLink.useInfo, - User.name AS userName, - User.login AS userLogin, - Account.name AS accountName, - Client.name AS clientName' - ); - $queryData->setFrom( - 'PublicLink - INNER JOIN User ON PublicLink.userId = User.id - INNER JOIN Account ON PublicLink.itemId = Account.id - INNER JOIN Client ON Account.clientId = Client.id' - ); - $queryData->setOrder('PublicLink.dateExpire DESC'); + $query = $this->queryFactory + ->newSelect() + ->from('PublicLink') + ->cols([ + 'PublicLink.id', + 'PublicLink.itemId', + 'PublicLink.hash', + 'PublicLink.data', + 'PublicLink.userId', + 'PublicLink.typeId', + 'PublicLink.notify', + 'PublicLink.dateAdd', + 'PublicLink.dateExpire', + 'PublicLink.dateUpdate', + 'PublicLink.countViews', + 'PublicLink.maxCountViews', + 'PublicLink.totalCountViews', + 'PublicLink.useInfo', + 'User.name AS userName', + 'User.login AS userLogin', + 'Account.name AS accountName', + 'Client.name AS clientName', + ]) + ->join('INNER', 'User', 'User.id = PublicLink.userId') + ->join('INNER', 'Account', 'Account.id = PublicLink.itemId') + ->join('INNER', 'Client', 'Client.id = Account.clientId') + ->orderBy(['PublicLink.dateExpire DESC']) + ->limit($itemSearchData->getLimitCount()) + ->offset($itemSearchData->getLimitStart()); if (!empty($itemSearchData->getSeachString())) { - $queryData->setWhere('User.login LIKE ? OR Account.name LIKE ? OR Client.name LIKE ?'); + $query->where('User.login LIKE :login') + ->orWhere('Account.name LIKE :accountName') + ->orWhere('Client.name LIKE :clientName'); $search = '%'.$itemSearchData->getSeachString().'%'; - $queryData->addParam($search); - $queryData->addParam($search); - $queryData->addParam($search); + + $query->bindValues([ + 'login' => $search, + 'accountName' => $search, + 'clientName' => $search, + ]); } - $queryData->setLimit( - '?,?', - [$itemSearchData->getLimitStart(), $itemSearchData->getLimitCount()] - ); - - return $this->db->doSelect($queryData, true); + return $this->db->doSelect(QueryData::build($query), true); } /** * Creates an item * - * @param PublicLinkData $itemData + * @param PublicLinkData $publicLinkData * * @return QueryResult * @throws DuplicatedItemException * @throws QueryException * @throws ConstraintException */ - public function create($itemData): QueryResult + public function create(PublicLinkData $publicLinkData): QueryResult { - if ($this->checkDuplicatedOnAdd($itemData)) { + if ($this->checkDuplicatedOnAdd($publicLinkData->getItemId())) { throw new DuplicatedItemException(__u('Link already created')); } - $query = /** @lang SQL */ - 'INSERT INTO PublicLink - SET itemId = ?, - `hash` = ?, - `data` = ?, - userId = ?, - typeId = ?, - notify = ?, - dateAdd = UNIX_TIMESTAMP(), - dateExpire = ?, - maxCountViews = ?'; + $query = $this->queryFactory + ->newInsert() + ->into('PublicLink') + ->cols([ + 'itemId' => $publicLinkData->getItemId(), + 'hash' => $publicLinkData->getHash(), + 'data' => $publicLinkData->getData(), + 'userId' => $publicLinkData->getUserId(), + 'typeId' => $publicLinkData->getTypeId(), + 'notify' => (int)$publicLinkData->isNotify(), + 'dateExpire' => $publicLinkData->getDateExpire(), + 'maxCountViews' => $publicLinkData->getMaxCountViews(), + ]) + ->col('dateAdd = UNIX_TIMESTAMP()'); - $queryData = new QueryData(); - $queryData->setQuery($query); - $queryData->setParams([ - $itemData->getItemId(), - $itemData->getHash(), - $itemData->getData(), - $itemData->getUserId(), - $itemData->getTypeId(), - (int)$itemData->isNotify(), - $itemData->getDateExpire(), - $itemData->getMaxCountViews(), - ]); - $queryData->setOnErrorMessage(__u('Error while creating the link')); + $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while creating the link')); return $this->db->doQuery($queryData); } @@ -292,31 +220,22 @@ final class PublicLinkRepository extends Repository implements RepositoryInterfa /** * Checks whether the item is duplicated on adding * - * @param PublicLinkData $itemData + * @param int $id * * @return bool - * @throws ConstraintException - * @throws QueryException + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException */ - public function checkDuplicatedOnAdd($itemData): bool + private function checkDuplicatedOnAdd(int $id): bool { - $queryData = new QueryData(); - $queryData->setQuery('SELECT id FROM PublicLink WHERE itemId = ? LIMIT 1'); - $queryData->addParam($itemData->getItemId()); + $query = $this->queryFactory + ->newSelect() + ->cols(['id']) + ->from('PublicLink') + ->where('itemId = :itemId') + ->bindValue('itemId', $id); - return $this->db->doQuery($queryData)->getNumRows() === 1; - } - - /** - * Checks whether the item is duplicated on updating - * - * @param mixed $itemData - * - * @return void - */ - public function checkDuplicatedOnUpdate($itemData): bool - { - throw new RuntimeException('Not implemented'); + return $this->db->doQuery(QueryData::build($query))->getNumRows() === 1; } /** @@ -324,76 +243,57 @@ final class PublicLinkRepository extends Repository implements RepositoryInterfa * * @param PublicLinkData $publicLinkData * - * @return int - * @throws ConstraintException - * @throws QueryException + * @return bool + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException */ - public function addLinkView(PublicLinkData $publicLinkData): int + public function addLinkView(PublicLinkData $publicLinkData): bool { - $query = /** @lang SQL */ - 'UPDATE PublicLink - SET countViews = countViews + 1, - totalCountViews = totalCountViews + 1, - useInfo = ? - WHERE `hash` = ? LIMIT 1'; + $query = $this->queryFactory + ->newUpdate() + ->table('PublicLink') + ->set('countViews', '(countViews + 1)') + ->set('totalCountViews', '(totalCountViews + 1)') + ->col('useInfo', $publicLinkData->getUseInfo()) + ->where('hash = :hash') + ->bindValues(['hash' => $publicLinkData->getHash()]); - $queryData = new QueryData(); - $queryData->setQuery($query); - $queryData->setParams([ - $publicLinkData->getUseInfo(), - $publicLinkData->getHash(), - ]); - $queryData->setOnErrorMessage(__u('Error while updating the link')); + $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while updating the link')); - return $this->db->doQuery($queryData)->getAffectedNumRows(); + return $this->db->doQuery($queryData)->getAffectedNumRows() === 1; } /** * Updates an item * - * @param PublicLinkData $itemData + * @param \SP\DataModel\PublicLinkData $publicLinkData * - * @return int - * @throws SPException - * @throws ConstraintException - * @throws QueryException + * @return bool + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException */ - public function update($itemData): int + public function update(PublicLinkData $publicLinkData): bool { - $query = /** @lang SQL */ - 'UPDATE PublicLink - SET itemId = ?, - `hash` = ?, - `data` = ?, - userId = ?, - notify = ?, - dateAdd = ?, - dateExpire = ?, - countViews = ?, - maxCountViews = ?, - useInfo = ?, - typeId = ? - WHERE id = ? LIMIT 1'; + $query = $this->queryFactory + ->newUpdate() + ->table('PublicLink') + ->cols([ + 'itemId' => $publicLinkData->getItemId(), + 'hash' => $publicLinkData->getHash(), + 'data' => $publicLinkData->getData(), + 'userId' => $publicLinkData->getUserId(), + 'typeId' => $publicLinkData->getTypeId(), + 'notify' => (int)$publicLinkData->isNotify(), + 'dateExpire' => $publicLinkData->getDateExpire(), + 'maxCountViews' => $publicLinkData->getMaxCountViews(), + 'useInfo' => $publicLinkData->getUseInfo(), + ]) + ->where('id = :id') + ->bindValues(['id' => $publicLinkData->getId()]); - $queryData = new QueryData(); - $queryData->setQuery($query); - $queryData->setParams([ - $itemData->getItemId(), - $itemData->getHash(), - $itemData->getData(), - $itemData->getUserId(), - (int)$itemData->isNotify(), - $itemData->getDateAdd(), - $itemData->getDateExpire(), - $itemData->getCountViews(), - $itemData->getMaxCountViews(), - $itemData->getUseInfo(), - $itemData->getTypeId(), - $itemData->getId(), - ]); - $queryData->setOnErrorMessage(__u('Error while updating the link')); + $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while updating the link')); - return $this->db->doQuery($queryData)->getAffectedNumRows(); + return $this->db->doQuery($queryData)->getAffectedNumRows() === 1; } /** @@ -401,34 +301,29 @@ final class PublicLinkRepository extends Repository implements RepositoryInterfa * * @param PublicLinkData $publicLinkData * - * @return int + * @return bool * @throws SPException * @throws ConstraintException * @throws QueryException */ - public function refresh(PublicLinkData $publicLinkData): int + public function refresh(PublicLinkData $publicLinkData): bool { - $query = /** @lang SQL */ - 'UPDATE PublicLink - SET `hash` = ?, - `data` = ?, - dateExpire = ?, - countViews = 0, - maxCountViews = ? - WHERE id = ? LIMIT 1'; + $query = $this->queryFactory + ->newUpdate() + ->table('PublicLink') + ->cols([ + 'hash' => $publicLinkData->getHash(), + 'data' => $publicLinkData->getData(), + 'dateExpire' => $publicLinkData->getDateExpire(), + 'countViews' => 0, + 'maxCountViews' => $publicLinkData->getMaxCountViews(), + ]) + ->where('id = :id') + ->bindValues(['id' => $publicLinkData->getId()]); - $queryData = new QueryData(); - $queryData->setQuery($query); - $queryData->setParams([ - $publicLinkData->getHash(), - $publicLinkData->getData(), - $publicLinkData->getDateExpire(), - $publicLinkData->getMaxCountViews(), - $publicLinkData->getId(), - ]); - $queryData->setOnErrorMessage(__u('Error while renewing link')); + $queryData = QueryData::build($query)->setOnErrorMessage(__u('Error while renewing the link')); - return $this->db->doQuery($queryData)->getAffectedNumRows(); + return $this->db->doQuery($queryData)->getAffectedNumRows() === 1; } /** @@ -437,81 +332,74 @@ final class PublicLinkRepository extends Repository implements RepositoryInterfa * @param int $id * * @return QueryResult - * @throws QueryException - * @throws ConstraintException */ public function getById(int $id): QueryResult { - $query = /** @lang SQL */ - 'SELECT PL.id, - PL.itemId, - PL.hash, - PL.data, - PL.userId, - PL.typeId, - PL.notify, - PL.dateAdd, - PL.dateExpire, - PL.countViews, - PL.maxCountViews, - PL.totalCountViews, - PL.useInfo, - U.name AS userName, - U.login AS userLogin, - A.name AS accountName - FROM PublicLink PL - INNER JOIN User U ON PL.userId = U.id - INNER JOIN Account A ON PL.itemId = A.id - WHERE PL.id = ? LIMIT 1'; + $query = $this->queryFactory + ->newSelect() + ->cols([ + 'PublicLink.id', + 'PublicLink.itemId', + 'PublicLink.hash', + 'PublicLink.data', + 'PublicLink.userId', + 'PublicLink.typeId', + 'PublicLink.notify', + 'PublicLink.dateAdd', + 'PublicLink.dateExpire', + 'PublicLink.dateUpdate', + 'PublicLink.countViews', + 'PublicLink.maxCountViews', + 'PublicLink.totalCountViews', + 'PublicLink.useInfo', + 'User.name AS userName', + 'User.login AS userLogin', + 'Account.name AS accountName', + ]) + ->from('PublicLink') + ->join('INNER', 'User', 'User.id = PublicLink.userId') + ->join('INNER', 'Account', 'Account.id = PublicLink.itemId') + ->where('PublicLink.id = :id') + ->bindValue('id', $id); - $queryData = new QueryData(); - $queryData->setMapClassName(PublicLinkListData::class); - $queryData->setQuery($query); - $queryData->addParam($id); - $queryData->setOnErrorMessage(__u('Error while retrieving the link')); - - return $this->db->doSelect($queryData); + return $this->db->doSelect(QueryData::build($query)->setOnErrorMessage(__u('Error while retrieving the link'))); } /** * @param $hash string * * @return QueryResult - * @throws ConstraintException - * @throws QueryException */ public function getByHash(string $hash): QueryResult { - $query = /** @lang SQL */ - 'SELECT PL.id, - PL.itemId, - PL.hash, - PL.data, - PL.userId, - PL.typeId, - PL.notify, - PL.dateAdd, - PL.dateExpire, - PL.dateUpdate, - PL.countViews, - PL.maxCountViews, - PL.totalCountViews, - PL.useInfo, - U.name AS userName, - U.login AS userLogin, - A.name AS accountName - FROM PublicLink PL - INNER JOIN User U ON PL.userId = U.id - INNER JOIN Account A ON itemId = A.id - WHERE PL.hash = ? LIMIT 1'; + $query = $this->queryFactory + ->newSelect() + ->cols([ + 'PublicLink.id', + 'PublicLink.itemId', + 'PublicLink.hash', + 'PublicLink.data', + 'PublicLink.userId', + 'PublicLink.typeId', + 'PublicLink.notify', + 'PublicLink.dateAdd', + 'PublicLink.dateExpire', + 'PublicLink.dateUpdate', + 'PublicLink.countViews', + 'PublicLink.maxCountViews', + 'PublicLink.totalCountViews', + 'PublicLink.useInfo', + 'User.name AS userName', + 'User.login AS userLogin', + 'Account.name AS accountName', + ]) + ->from('PublicLink') + ->join('INNER', 'User', 'User.id = PublicLink.userId') + ->join('INNER', 'Account', 'Account.id = PublicLink.itemId') + ->where('PublicLink.hash = :hash') + ->bindValue('hash', $hash); - $queryData = new QueryData(); - $queryData->setMapClassName(PublicLinkData::class); - $queryData->setQuery($query); - $queryData->addParam($hash); - $queryData->setOnErrorMessage(__u('Error while retrieving the link')); - - return $this->db->doSelect($queryData); + return $this->db->doSelect(QueryData::build($query)->setOnErrorMessage(__u('Error while retrieving the link'))); } /** @@ -520,17 +408,20 @@ final class PublicLinkRepository extends Repository implements RepositoryInterfa * @param int $itemId * * @return QueryResult - * @throws ConstraintException - * @throws QueryException */ public function getHashForItem(int $itemId): QueryResult { - $queryData = new QueryData(); - $queryData->setMapClassName(PublicLinkData::class); - $queryData->setQuery('SELECT id, `hash`, userId FROM PublicLink WHERE itemId = ? LIMIT 1'); - $queryData->addParam($itemId); - $queryData->setOnErrorMessage(__u('Error while retrieving the link')); + $query = $this->queryFactory + ->newSelect() + ->cols([ + 'id', + 'hash', + 'userId', + ]) + ->from('PublicLink') + ->where('itemId = :itemId') + ->bindValue('itemId', $itemId); - return $this->db->doSelect($queryData); + return $this->db->doSelect(QueryData::build($query)->setOnErrorMessage(__u('Error while retrieving the link'))); } -} \ No newline at end of file +} diff --git a/lib/SP/Infrastructure/Database/QueryResult.php b/lib/SP/Infrastructure/Database/QueryResult.php index 7fa603a5..83114ce7 100644 --- a/lib/SP/Infrastructure/Database/QueryResult.php +++ b/lib/SP/Infrastructure/Database/QueryResult.php @@ -67,10 +67,9 @@ final class QueryResult /** * @return mixed|null */ - public function getData() + public function getData(): mixed { return $this->numRows === 1 ? $this->data[0] : null; - } public function getDataAsArray(): array @@ -123,4 +122,4 @@ final class QueryResult return $this; } -} \ No newline at end of file +} diff --git a/tests/SP/Infrastructure/Account/Repositories/PublicLinkRepositoryTest.php b/tests/SP/Infrastructure/Account/Repositories/PublicLinkRepositoryTest.php new file mode 100644 index 00000000..9cb1f2c4 --- /dev/null +++ b/tests/SP/Infrastructure/Account/Repositories/PublicLinkRepositoryTest.php @@ -0,0 +1,443 @@ +. + */ + +namespace SP\Tests\Infrastructure\Account\Repositories; + +use Aura\SqlQuery\QueryFactory; +use PHPUnit\Framework\Constraint\Callback; +use PHPUnit\Framework\MockObject\MockObject; +use SP\DataModel\ItemSearchData; +use SP\DataModel\PublicLinkData; +use SP\Domain\Common\Out\SimpleModel; +use SP\Infrastructure\Account\Repositories\PublicLinkRepository; +use SP\Infrastructure\Common\Repositories\DuplicatedItemException; +use SP\Infrastructure\Database\DatabaseInterface; +use SP\Infrastructure\Database\QueryData; +use SP\Infrastructure\Database\QueryResult; +use SP\Tests\UnitaryTestCase; + +/** + * Class PublicLinkRepositoryTest + */ +class PublicLinkRepositoryTest extends UnitaryTestCase +{ + + private PublicLinkRepository $publicLinkRepository; + private MockObject|DatabaseInterface $database; + + /** + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\ConstraintException + */ + public function testDelete(): void + { + $id = 1; + $expected = new QueryResult(); + $expected->setAffectedNumRows(1); + + $callback = new Callback( + static function (QueryData $arg) use ($id) { + return $arg->getQuery()->getBindValues()['id'] === $id + && !empty($arg->getQuery()->getStatement()); + } + ); + + $this->database->expects(self::once()) + ->method('doQuery') + ->with($callback) + ->willReturn($expected); + + $this->publicLinkRepository->delete($id); + } + + public function testSearch(): void + { + $item = new ItemSearchData(); + $item->seachString = self::$faker->name; + + $callback = new Callback( + static function (QueryData $arg) use ($item) { + $params = $arg->getQuery()->getBindValues(); + $searchStringLike = '%'.$item->seachString.'%'; + + return $params['login'] === $searchStringLike + && $params['accountName'] === $searchStringLike + && $params['clientName'] === $searchStringLike + && $arg->getMapClassName() === SimpleModel::class + && !empty($arg->getQuery()->getStatement()); + } + ); + + $this->database + ->expects(self::once()) + ->method('doSelect') + ->with($callback) + ->willReturn(new QueryResult()); + + $this->publicLinkRepository->search($item); + } + + public function testGetHashForItem(): void + { + $itemId = self::$faker->randomNumber(); + + $callback = new Callback( + static function (QueryData $arg) use ($itemId) { + return $arg->getQuery()->getBindValues()['itemId'] === $itemId + && $arg->getMapClassName() === SimpleModel::class + && !empty($arg->getQuery()->getStatement()); + } + ); + + $this->database->expects(self::once()) + ->method('doSelect') + ->with($callback) + ->willReturn(new QueryResult()); + + $this->publicLinkRepository->getHashForItem($itemId); + } + + public function testGetById(): void + { + $id = self::$faker->randomNumber(); + + $callback = new Callback( + static function (QueryData $arg) use ($id) { + return $arg->getQuery()->getBindValues()['id'] === $id + && $arg->getMapClassName() === SimpleModel::class + && !empty($arg->getQuery()->getStatement()); + } + ); + + $this->database->expects(self::once()) + ->method('doSelect') + ->with($callback) + ->willReturn(new QueryResult()); + + $this->publicLinkRepository->getById($id); + } + + /** + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testAddLinkView(): void + { + $publicLinkData = $this->buildPublicLinkData(); + + $expected = new QueryResult(); + $expected->setAffectedNumRows(1); + + $callback = new Callback( + static function (QueryData $arg) use ($publicLinkData) { + $query = $arg->getQuery(); + $values = $query->getBindValues(); + + return $values['hash'] === $publicLinkData->getHash() + && $values['useInfo'] === $publicLinkData->getUseInfo() + && !empty($query->getStatement()); + } + ); + + $this->database->expects(self::once()) + ->method('doQuery') + ->with($callback) + ->willReturn($expected); + + $this->assertTrue($this->publicLinkRepository->addLinkView($publicLinkData)); + } + + private function buildPublicLinkData(): PublicLinkData + { + $data = [ + 'id' => self::$faker->randomNumber(), + 'itemId' => self::$faker->randomNumber(), + 'hash' => self::$faker->sha1, + 'userId' => self::$faker->randomNumber(), + 'typeId' => self::$faker->randomNumber(), + 'notify' => self::$faker->boolean, + 'dateAdd' => self::$faker->unixTime, + 'dateUpdate' => self::$faker->unixTime, + 'dateExpire' => self::$faker->unixTime, + 'countViews' => self::$faker->randomNumber(), + 'totalCountViews' => self::$faker->randomNumber(), + 'maxCountViews' => self::$faker->randomNumber(), + 'useInfo' => self::$faker->text(), + 'data' => self::$faker->text(), + ]; + + return new PublicLinkData($data); + } + + /** + * @throws \SP\Infrastructure\Common\Repositories\DuplicatedItemException + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testCreate(): void + { + $publicLinkData = $this->buildPublicLinkData(); + + $callbackCheckDuplicate = new Callback( + static function (QueryData $arg) use ($publicLinkData) { + $params = $arg->getQuery()->getBindValues(); + + return $params['itemId'] === $publicLinkData->getItemId() + && !empty($arg->getQuery()->getStatement()); + } + ); + + $callbackCreate = new Callback( + static function (QueryData $arg) use ($publicLinkData) { + $params = $arg->getQuery()->getBindValues(); + + return $params['itemId'] === $publicLinkData->getItemId() + && $params['hash'] === $publicLinkData->getHash() + && $params['data'] === $publicLinkData->getData() + && $params['userId'] === $publicLinkData->getUserId() + && $params['typeId'] === $publicLinkData->getTypeId() + && $params['notify'] === (int)$publicLinkData->isNotify() + && $params['dateExpire'] === $publicLinkData->getDateExpire() + && $params['maxCountViews'] === $publicLinkData->getMaxCountViews() + && !empty($arg->getQuery()->getStatement()); + } + ); + + $this->database->expects(self::exactly(2)) + ->method('doQuery') + ->withConsecutive([$callbackCheckDuplicate], [$callbackCreate]) + ->willReturn(new QueryResult()); + + $this->publicLinkRepository->create($publicLinkData); + } + + /** + * @throws \SP\Infrastructure\Common\Repositories\DuplicatedItemException + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testCreateWithDuplicate(): void + { + $publicLinkData = $this->buildPublicLinkData(); + + $callback = new Callback( + static function (QueryData $arg) use ($publicLinkData) { + $params = $arg->getQuery()->getBindValues(); + + return $params['itemId'] === $publicLinkData->getItemId() + && !empty($arg->getQuery()->getStatement()); + } + ); + + $this->database->expects(self::once()) + ->method('doQuery') + ->with($callback) + ->willReturn(new QueryResult([1])); + + $this->expectException(DuplicatedItemException::class); + $this->expectExceptionMessage('Link already created'); + + $this->publicLinkRepository->create($publicLinkData); + } + + public function testGetAll(): void + { + $callback = new Callback( + static function (QueryData $arg) { + return $arg->getMapClassName() === SimpleModel::class + && !empty($arg->getQuery()->getStatement()); + } + ); + + $this->database + ->expects(self::once()) + ->method('doSelect') + ->with($callback) + ->willReturn(new QueryResult()); + + $this->publicLinkRepository->getAll(); + } + + /** + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\SPException + */ + public function testRefresh(): void + { + $publicLinkData = $this->buildPublicLinkData(); + + $callback = new Callback( + static function (QueryData $arg) use ($publicLinkData) { + $params = $arg->getQuery()->getBindValues(); + + return $params['id'] === $publicLinkData->getId() + && $params['hash'] === $publicLinkData->getHash() + && $params['data'] === $publicLinkData->getData() + && $params['dateExpire'] === $publicLinkData->getDateExpire() + && $params['countViews'] === 0 + && $params['maxCountViews'] === $publicLinkData->getMaxCountViews() + && !empty($arg->getQuery()->getStatement()); + } + ); + + $this->database->expects(self::once()) + ->method('doQuery') + ->with($callback) + ->willReturn(new QueryResult()); + + $this->publicLinkRepository->refresh($publicLinkData); + } + + /** + * @throws \SP\Core\Exceptions\QueryException + * @throws \SP\Core\Exceptions\ConstraintException + */ + public function testDeleteByIdBatch(): void + { + $ids = [self::$faker->randomNumber(), self::$faker->randomNumber(), self::$faker->randomNumber()]; + + $callback = new Callback( + static function (QueryData $arg) use ($ids) { + $values = $arg->getQuery()->getBindValues(); + + return array_shift($values) === array_shift($ids) + && array_shift($values) === array_shift($ids) + && array_shift($values) === array_shift($ids) + && $arg->getMapClassName() === SimpleModel::class + && !empty($arg->getQuery()->getStatement()); + } + ); + + $this->database->expects(self::once()) + ->method('doQuery') + ->with($callback) + ->willReturn(new QueryResult()); + + $this->publicLinkRepository->deleteByIdBatch($ids); + } + + /** + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testDeleteByIdBatchWithNoIds(): void + { + $this->database->expects(self::never()) + ->method('doQuery'); + + $this->assertEquals(0, $this->publicLinkRepository->deleteByIdBatch([])); + } + + public function testGetByHash(): void + { + $hash = self::$faker->sha1; + + $callback = new Callback( + static function (QueryData $arg) use ($hash) { + return $arg->getQuery()->getBindValues()['hash'] === $hash + && $arg->getMapClassName() === SimpleModel::class + && !empty($arg->getQuery()->getStatement()); + } + ); + + $this->database->expects(self::once()) + ->method('doSelect') + ->with($callback) + ->willReturn(new QueryResult()); + + $this->publicLinkRepository->getByHash($hash); + } + + /** + * @throws \SP\Core\Exceptions\ConstraintException + * @throws \SP\Core\Exceptions\QueryException + */ + public function testUpdate(): void + { + $publicLinkData = $this->buildPublicLinkData(); + + $callback = new Callback( + static function (QueryData $arg) use ($publicLinkData) { + $params = $arg->getQuery()->getBindValues(); + + return $params['itemId'] === $publicLinkData->getItemId() + && $params['hash'] === $publicLinkData->getHash() + && $params['data'] === $publicLinkData->getData() + && $params['userId'] === $publicLinkData->getUserId() + && $params['typeId'] === $publicLinkData->getTypeId() + && $params['notify'] === (int)$publicLinkData->isNotify() + && $params['dateExpire'] === $publicLinkData->getDateExpire() + && $params['maxCountViews'] === $publicLinkData->getMaxCountViews() + && $params['useInfo'] === $publicLinkData->getUseInfo() + && $params['id'] === $publicLinkData->getId() + && !empty($arg->getQuery()->getStatement()); + } + ); + + $this->database->expects(self::once()) + ->method('doQuery') + ->with($callback) + ->willReturn(new QueryResult()); + + $this->publicLinkRepository->update($publicLinkData); + } + + public function testSearchWithoutString(): void + { + $callback = new Callback( + static function (QueryData $arg) { + $query = $arg->getQuery(); + + return count($query->getBindValues()) === 0 + && $arg->getMapClassName() === SimpleModel::class + && !empty($query->getStatement()); + } + ); + + $this->database + ->expects(self::once()) + ->method('doSelect') + ->with($callback) + ->willReturn(new QueryResult()); + + $this->publicLinkRepository->search(new ItemSearchData()); + } + + + protected function setUp(): void + { + parent::setUp(); + + $this->database = $this->createMock(DatabaseInterface::class); + $queryFactory = new QueryFactory('mysql'); + + $this->publicLinkRepository = new PublicLinkRepository( + $this->database, + $this->context, + $this->application->getEventDispatcher(), + $queryFactory, + ); + } +} diff --git a/tests/SP/Repositories/PublicLinkRepositoryTest.php b/tests/SP/Repositories/PublicLinkRepositoryTest.php index 2ffa5866..0b2c8019 100644 --- a/tests/SP/Repositories/PublicLinkRepositoryTest.php +++ b/tests/SP/Repositories/PublicLinkRepositoryTest.php @@ -1,10 +1,10 @@ . + * along with sysPass. If not, see . */ namespace SP\Tests\Repositories; @@ -34,6 +34,7 @@ use SP\Core\Exceptions\SPException; use SP\DataModel\ItemSearchData; use SP\DataModel\PublicLinkData; use SP\DataModel\PublicLinkListData; +use SP\Domain\Account\Repositories\PublicLinkRepositoryInterface; use SP\Infrastructure\Account\Repositories\PublicLinkRepository; use SP\Infrastructure\Common\Repositories\DuplicatedItemException; use SP\Tests\DatabaseTestCase; @@ -48,7 +49,7 @@ use function SP\Tests\setupContext; class PublicLinkRepositoryTest extends DatabaseTestCase { /** - * @var \SP\Infrastructure\Account\Repositories\PublicLinkRepository + * @var PublicLinkRepositoryInterface */ private static $repository;