mirror of
https://github.com/chylex/Nextcloud-News.git
synced 2025-04-08 07:15:43 +02:00
Remove V1 item API
Signed-off-by: Sean Molenaar <sean@seanmolenaar.eu>
This commit is contained in:
parent
ceba810603
commit
b4fa772bc5
CHANGELOG.mdphpunit.xml
lib
AppInfo
Command/Config
Controller
ApiController.phpFeedApiController.phpFeedController.phpFolderApiController.phpFolderController.phpItemApiController.phpItemController.phpPageController.php
Db
DependencyInjection
Explore
Fetcher
Service
tests
@ -5,6 +5,8 @@ The format is almost based on [Keep a Changelog](https://keepachangelog.com/en/1
|
||||
## [Unreleased]
|
||||
|
||||
### Changed
|
||||
- Remove outdated item DB code.
|
||||
- Stop returning all feeds after marking folder as read.
|
||||
|
||||
### Fixed
|
||||
|
||||
|
@ -31,9 +31,6 @@ use OCP\AppFramework\App;
|
||||
use OCP\Files\IRootFolder;
|
||||
use OCP\Files\Node;
|
||||
|
||||
|
||||
use OCA\News\Db\MapperFactory;
|
||||
use OCA\News\Db\ItemMapper;
|
||||
use OCA\News\Fetcher\FeedFetcher;
|
||||
use OCA\News\Fetcher\Fetcher;
|
||||
use OCP\User\Events\BeforeUserDeletedEvent;
|
||||
@ -90,11 +87,6 @@ class Application extends App implements IBootstrap
|
||||
$context->registerParameter('exploreDir', __DIR__ . '/../Explore/feeds');
|
||||
$context->registerParameter('configFile', 'config.ini');
|
||||
|
||||
// factories
|
||||
$context->registerService(ItemMapper::class, function (ContainerInterface $c): ItemMapper {
|
||||
return $c->get(MapperFactory::class)->build();
|
||||
});
|
||||
|
||||
$context->registerService(HTMLPurifier::class, function (ContainerInterface $c): HTMLPurifier {
|
||||
$directory = $c->get(ITempManager::class)->getTempBaseDir() . '/news/cache/purifier';
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace OCA\News\Command\Config;
|
||||
|
||||
use OCA\News\Service\Exceptions\ServiceException;
|
||||
use OCA\News\Service\Exceptions\ServiceValidationException;
|
||||
use OCA\News\Service\FolderServiceV2;
|
||||
use Symfony\Component\Console\Command\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
@ -50,7 +50,7 @@ class FolderDelete extends Command
|
||||
$id = $input->getArgument('folder-id');
|
||||
|
||||
if ($id === null) {
|
||||
throw new ServiceException('Can not remove root folder!');
|
||||
throw new ServiceValidationException('Can not remove root folder!');
|
||||
}
|
||||
|
||||
$this->folderService->delete($user, intval($id));
|
||||
|
@ -77,7 +77,7 @@ class ApiController extends BaseApiController
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function index()
|
||||
public function index(): array
|
||||
{
|
||||
return [
|
||||
'apiLevels' => ['v1-2']
|
||||
|
@ -19,12 +19,12 @@ use Exception;
|
||||
use OCA\News\Service\Exceptions\ServiceConflictException;
|
||||
use OCA\News\Service\Exceptions\ServiceNotFoundException;
|
||||
use OCA\News\Service\FeedServiceV2;
|
||||
use OCA\News\Service\ItemServiceV2;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use \OCP\IRequest;
|
||||
use \OCP\IUserSession;
|
||||
use \OCP\AppFramework\Http;
|
||||
|
||||
use \OCA\News\Service\ItemService;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class FeedApiController extends ApiController
|
||||
@ -32,10 +32,9 @@ class FeedApiController extends ApiController
|
||||
use JSONHttpErrorTrait, ApiPayloadTrait;
|
||||
|
||||
/**
|
||||
* TODO: Remove
|
||||
* @var ItemService
|
||||
* @var ItemServiceV2
|
||||
*/
|
||||
private $oldItemService;
|
||||
private $itemService;
|
||||
|
||||
/**
|
||||
* @var FeedServiceV2
|
||||
@ -51,12 +50,12 @@ class FeedApiController extends ApiController
|
||||
IRequest $request,
|
||||
?IUserSession $userSession,
|
||||
FeedServiceV2 $feedService,
|
||||
ItemService $oldItemService,
|
||||
ItemServiceV2 $itemService,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
parent::__construct($request, $userSession);
|
||||
$this->feedService = $feedService;
|
||||
$this->oldItemService = $oldItemService;
|
||||
$this->itemService = $itemService;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
@ -70,12 +69,12 @@ class FeedApiController extends ApiController
|
||||
{
|
||||
|
||||
$result = [
|
||||
'starredCount' => $this->oldItemService->starredCount($this->getUserId()),
|
||||
'starredCount' => count($this->itemService->starred($this->getUserId())),
|
||||
'feeds' => $this->serialize($this->feedService->findAllForUser($this->getUserId()))
|
||||
];
|
||||
|
||||
try {
|
||||
$result['newestItemId'] = $this->oldItemService->getNewestItemId($this->getUserId());
|
||||
$result['newestItemId'] = $this->itemService->newest($this->getUserId())->getId();
|
||||
} catch (ServiceNotFoundException $ex) {
|
||||
// in case there are no items, ignore
|
||||
}
|
||||
@ -96,9 +95,7 @@ class FeedApiController extends ApiController
|
||||
*/
|
||||
public function create(string $url, ?int $folderId = null)
|
||||
{
|
||||
if ($folderId === 0) {
|
||||
$folderId = null;
|
||||
}
|
||||
$folderId = $folderId === 0 ? null : $folderId;
|
||||
|
||||
try {
|
||||
$this->feedService->purgeDeleted($this->getUserId(), time() - 600);
|
||||
@ -109,7 +106,7 @@ class FeedApiController extends ApiController
|
||||
$this->feedService->fetch($feed);
|
||||
|
||||
try {
|
||||
$result['newestItemId'] = $this->oldItemService->getNewestItemId($this->getUserId());
|
||||
$result['newestItemId'] = $this->itemService->newest($this->getUserId())->getId();
|
||||
} catch (ServiceNotFoundException $ex) {
|
||||
// in case there are no items, ignore
|
||||
}
|
||||
@ -154,7 +151,7 @@ class FeedApiController extends ApiController
|
||||
*/
|
||||
public function read(int $feedId, int $newestItemId): void
|
||||
{
|
||||
$this->oldItemService->readFeed($feedId, $newestItemId, $this->getUserId());
|
||||
$this->itemService->read($this->getUserId(), $feedId, $newestItemId);
|
||||
}
|
||||
|
||||
|
||||
@ -170,9 +167,7 @@ class FeedApiController extends ApiController
|
||||
*/
|
||||
public function move(int $feedId, ?int $folderId)
|
||||
{
|
||||
if ($folderId === 0) {
|
||||
$folderId = null;
|
||||
}
|
||||
$folderId = $folderId === 0 ? null : $folderId;
|
||||
|
||||
try {
|
||||
$feed = $this->feedService->find($this->getUserId(), $feedId);
|
||||
|
@ -18,12 +18,12 @@ use OCA\News\Service\Exceptions\ServiceNotFoundException;
|
||||
use OCA\News\Service\FeedServiceV2;
|
||||
use OCA\News\Service\FolderServiceV2;
|
||||
use OCA\News\Service\ImportService;
|
||||
use OCA\News\Service\ItemServiceV2;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use OCP\IRequest;
|
||||
use OCP\IConfig;
|
||||
use OCP\AppFramework\Http;
|
||||
|
||||
use OCA\News\Service\ItemService;
|
||||
use OCA\News\Db\FeedType;
|
||||
use OCP\IUserSession;
|
||||
|
||||
@ -35,7 +35,9 @@ class FeedController extends Controller
|
||||
* @var FeedServiceV2
|
||||
*/
|
||||
private $feedService;
|
||||
//TODO: Remove
|
||||
/**
|
||||
* @var ItemServiceV2
|
||||
*/
|
||||
private $itemService;
|
||||
/**
|
||||
* @var FolderServiceV2
|
||||
@ -54,7 +56,7 @@ class FeedController extends Controller
|
||||
IRequest $request,
|
||||
FolderServiceV2 $folderService,
|
||||
FeedServiceV2 $feedService,
|
||||
ItemService $itemService,
|
||||
ItemServiceV2 $itemService,
|
||||
ImportService $importService,
|
||||
IConfig $settings,
|
||||
?IUserSession $userSession
|
||||
@ -79,11 +81,11 @@ class FeedController extends Controller
|
||||
// item id which will be used for marking feeds read
|
||||
$params = [
|
||||
'feeds' => $this->feedService->findAllForUser($this->getUserId()),
|
||||
'starred' => $this->itemService->starredCount($this->getUserId())
|
||||
'starred' => count($this->itemService->starred($this->getUserId()))
|
||||
];
|
||||
|
||||
try {
|
||||
$id = $this->itemService->getNewestItemId($this->getUserId());
|
||||
$id = $this->itemService->newest($this->getUserId())->getId();
|
||||
|
||||
// An exception occurs if there is a newest item. If there is none,
|
||||
// simply ignore it and do not add the newestItemId
|
||||
@ -183,7 +185,7 @@ class FeedController extends Controller
|
||||
$this->feedService->fetch($feed);
|
||||
|
||||
try {
|
||||
$id = $this->itemService->getNewestItemId($this->getUserId());
|
||||
$id = $this->itemService->newest($this->getUserId())->getId();
|
||||
// An exception occurs if there is a newest item. If there is none,
|
||||
// simply ignore it and do not add the newestItemId
|
||||
$params['newestItemId'] = $id;
|
||||
@ -261,7 +263,7 @@ class FeedController extends Controller
|
||||
$feed = $this->importService->importArticles($this->getUserId(), $json);
|
||||
|
||||
$params = [
|
||||
'starred' => $this->itemService->starredCount($this->getUserId())
|
||||
'starred' => count($this->itemService->starred($this->getUserId()))
|
||||
];
|
||||
|
||||
if ($feed) {
|
||||
@ -281,7 +283,7 @@ class FeedController extends Controller
|
||||
*/
|
||||
public function read(int $feedId, int $highestItemId): array
|
||||
{
|
||||
$this->itemService->readFeed($feedId, $highestItemId, $this->getUserId());
|
||||
$this->feedService->read($this->getUserId(), $feedId, $highestItemId);
|
||||
|
||||
return [
|
||||
'feeds' => [
|
||||
|
@ -20,7 +20,6 @@ use \OCP\IRequest;
|
||||
use \OCP\IUserSession;
|
||||
use \OCP\AppFramework\Http;
|
||||
|
||||
use \OCA\News\Service\ItemService;
|
||||
use \OCA\News\Service\FolderServiceV2;
|
||||
use \OCA\News\Service\Exceptions\ServiceNotFoundException;
|
||||
use \OCA\News\Service\Exceptions\ServiceConflictException;
|
||||
@ -30,20 +29,19 @@ class FolderApiController extends ApiController
|
||||
{
|
||||
use JSONHttpErrorTrait, ApiPayloadTrait;
|
||||
|
||||
/**
|
||||
* @var FolderServiceV2
|
||||
*/
|
||||
private $folderService;
|
||||
//TODO: Remove
|
||||
private $itemService;
|
||||
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
?IUserSession $userSession,
|
||||
FolderServiceV2 $folderService,
|
||||
ItemService $itemService
|
||||
FolderServiceV2 $folderService
|
||||
) {
|
||||
parent::__construct($request, $userSession);
|
||||
|
||||
$this->folderService = $folderService;
|
||||
$this->itemService = $itemService;
|
||||
}
|
||||
|
||||
|
||||
@ -52,7 +50,7 @@ class FolderApiController extends ApiController
|
||||
* @NoCSRFRequired
|
||||
* @CORS
|
||||
*/
|
||||
public function index()
|
||||
public function index(): array
|
||||
{
|
||||
$folders = $this->folderService->findAllForUser($this->getUserId());
|
||||
return ['folders' => $this->serialize($folders)];
|
||||
@ -142,14 +140,13 @@ class FolderApiController extends ApiController
|
||||
* @NoCSRFRequired
|
||||
* @CORS
|
||||
*
|
||||
* @param int|null $folderId
|
||||
* @param int $newestItemId
|
||||
* @param int|null $folderId ID of the folder
|
||||
* @param int $maxItemId The newest read item
|
||||
*/
|
||||
public function read(?int $folderId, int $newestItemId): void
|
||||
public function read(?int $folderId, int $maxItemId): void
|
||||
{
|
||||
if ($folderId === 0) {
|
||||
$folderId = null;
|
||||
}
|
||||
$this->itemService->readFolder($folderId, $newestItemId, $this->getUserId());
|
||||
$folderId = $folderId === 0 ? null : $folderId;
|
||||
|
||||
$this->folderService->read($this->getUserId(), $folderId, $maxItemId);
|
||||
}
|
||||
}
|
||||
|
@ -14,13 +14,11 @@
|
||||
namespace OCA\News\Controller;
|
||||
|
||||
use OCA\News\Service\Exceptions\ServiceException;
|
||||
use OCA\News\Service\FeedServiceV2;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use \OCP\IRequest;
|
||||
use \OCP\AppFramework\Http;
|
||||
|
||||
use \OCA\News\Service\FolderServiceV2;
|
||||
use \OCA\News\Service\ItemService;
|
||||
use \OCA\News\Service\Exceptions\ServiceNotFoundException;
|
||||
use \OCA\News\Service\Exceptions\ServiceConflictException;
|
||||
use OCP\IUserSession;
|
||||
@ -33,24 +31,14 @@ class FolderController extends Controller
|
||||
* @var FolderServiceV2
|
||||
*/
|
||||
private $folderService;
|
||||
/**
|
||||
* @var FeedServiceV2
|
||||
*/
|
||||
private $feedService;
|
||||
//TODO: Remove
|
||||
private $itemService;
|
||||
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
FolderServiceV2 $folderService,
|
||||
FeedServiceV2 $feedService,
|
||||
ItemService $itemService,
|
||||
?IUserSession $userSession
|
||||
) {
|
||||
parent::__construct($request, $userSession);
|
||||
$this->folderService = $folderService;
|
||||
$this->feedService = $feedService;
|
||||
$this->itemService = $itemService;
|
||||
}
|
||||
|
||||
|
||||
@ -134,12 +122,12 @@ class FolderController extends Controller
|
||||
/**
|
||||
* @NoAdminRequired
|
||||
*
|
||||
* @param string $folderName
|
||||
* @param int|null $folderId
|
||||
* @param int|null $folderId The ID of the folder
|
||||
* @param string $folderName The new name of the folder
|
||||
*
|
||||
* @return array|JSONResponse
|
||||
*/
|
||||
public function rename(string $folderName, ?int $folderId)
|
||||
public function rename(?int $folderId, string $folderName)
|
||||
{
|
||||
if (empty($folderId)) {
|
||||
return new JSONResponse([], Http::STATUS_BAD_REQUEST);
|
||||
@ -159,21 +147,18 @@ class FolderController extends Controller
|
||||
* @NoAdminRequired
|
||||
*
|
||||
* @param int|null $folderId
|
||||
* @param int $highestItemId
|
||||
* @param int $maxItemId
|
||||
*
|
||||
* @return array
|
||||
* @return void
|
||||
*
|
||||
* @throws ServiceConflictException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function read(?int $folderId, int $highestItemId): array
|
||||
public function read(?int $folderId, int $maxItemId): void
|
||||
{
|
||||
$folderId = $folderId === 0 ? null : $folderId;
|
||||
|
||||
$this->itemService->readFolder(
|
||||
$folderId,
|
||||
$highestItemId,
|
||||
$this->getUserId()
|
||||
);
|
||||
$feeds = $this->feedService->findAllForUser($this->getUserId());
|
||||
return ['feeds' => $this->serialize($feeds)];
|
||||
$this->folderService->read($this->getUserId(), $folderId, $maxItemId);
|
||||
}
|
||||
|
||||
|
||||
|
@ -15,7 +15,9 @@
|
||||
|
||||
namespace OCA\News\Controller;
|
||||
|
||||
use OCA\News\Service\ItemService;
|
||||
use OCA\News\Db\FeedType;
|
||||
use OCA\News\Service\Exceptions\ServiceConflictException;
|
||||
use OCA\News\Service\Exceptions\ServiceValidationException;
|
||||
use OCA\News\Service\ItemServiceV2;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use \OCP\IRequest;
|
||||
@ -24,22 +26,27 @@ use \OCP\AppFramework\Http;
|
||||
|
||||
use \OCA\News\Service\Exceptions\ServiceNotFoundException;
|
||||
|
||||
/**
|
||||
* Class ItemApiController
|
||||
*
|
||||
* @package OCA\News\Controller
|
||||
*/
|
||||
class ItemApiController extends ApiController
|
||||
{
|
||||
use JSONHttpErrorTrait, ApiPayloadTrait;
|
||||
|
||||
private $oldItemService;
|
||||
/**
|
||||
* @var ItemServiceV2
|
||||
*/
|
||||
private $itemService;
|
||||
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
?IUserSession $userSession,
|
||||
ItemService $oldItemService,
|
||||
ItemServiceV2 $itemService
|
||||
) {
|
||||
parent::__construct($request, $userSession);
|
||||
|
||||
$this->oldItemService = $oldItemService;
|
||||
$this->itemService = $itemService;
|
||||
}
|
||||
|
||||
@ -64,16 +71,38 @@ class ItemApiController extends ApiController
|
||||
int $batchSize = -1,
|
||||
int $offset = 0,
|
||||
bool $oldestFirst = false
|
||||
) {
|
||||
$items = $this->oldItemService->findAllItems(
|
||||
$id,
|
||||
$type,
|
||||
$batchSize,
|
||||
$offset,
|
||||
$getRead,
|
||||
$oldestFirst,
|
||||
$this->getUserId()
|
||||
);
|
||||
): array {
|
||||
switch ($type) {
|
||||
case FeedType::FEED:
|
||||
$items = $this->itemService->findAllInFeedWithFilters(
|
||||
$this->getUserId(),
|
||||
$id,
|
||||
$batchSize,
|
||||
$offset,
|
||||
!$getRead,
|
||||
$oldestFirst
|
||||
);
|
||||
break;
|
||||
case FeedType::FOLDER:
|
||||
$items = $this->itemService->findAllInFolderWithFilters(
|
||||
$this->getUserId(),
|
||||
$id,
|
||||
$batchSize,
|
||||
$offset,
|
||||
!$getRead,
|
||||
$oldestFirst
|
||||
);
|
||||
break;
|
||||
default:
|
||||
$items = $this->itemService->findAllWithFilters(
|
||||
$this->getUserId(),
|
||||
$type,
|
||||
$batchSize,
|
||||
$offset,
|
||||
$oldestFirst
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
return ['items' => $this->serialize($items)];
|
||||
}
|
||||
@ -88,8 +117,10 @@ class ItemApiController extends ApiController
|
||||
* @param int $id
|
||||
* @param int $lastModified
|
||||
* @return array|JSONResponse
|
||||
*
|
||||
* @throws ServiceValidationException
|
||||
*/
|
||||
public function updated(int $type = 3, int $id = 0, int $lastModified = 0)
|
||||
public function updated(int $type = 3, int $id = 0, int $lastModified = 0): array
|
||||
{
|
||||
// needs to be turned into a millisecond timestamp to work properly
|
||||
if (strlen((string) $lastModified) <= 10) {
|
||||
@ -97,27 +128,33 @@ class ItemApiController extends ApiController
|
||||
} else {
|
||||
$paddedLastModified = $lastModified;
|
||||
}
|
||||
$items = $this->oldItemService->findAllNew(
|
||||
$id,
|
||||
$type,
|
||||
(int) $paddedLastModified,
|
||||
true,
|
||||
$this->getUserId()
|
||||
);
|
||||
|
||||
switch ($type) {
|
||||
case FeedType::FEED:
|
||||
$items = $this->itemService->findAllInFeedAfter($this->getUserId(), $id, $paddedLastModified, false);
|
||||
break;
|
||||
case FeedType::FOLDER:
|
||||
$items = $this->itemService->findAllInFolderAfter($this->getUserId(), $id, $paddedLastModified, false);
|
||||
break;
|
||||
default:
|
||||
$items = $this->itemService->findAllAfter($this->getUserId(), $type, $paddedLastModified);
|
||||
break;
|
||||
}
|
||||
|
||||
return ['items' => $this->serialize($items)];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return JSONResponse|array
|
||||
* @param int $itemId
|
||||
* @param bool $isRead
|
||||
*
|
||||
* @psalm-return JSONResponse|array<empty, empty>
|
||||
* @return array|JSONResponse
|
||||
* @throws ServiceConflictException
|
||||
*/
|
||||
private function setRead(bool $isRead, int $itemId)
|
||||
private function setRead(int $itemId, bool $isRead)
|
||||
{
|
||||
try {
|
||||
$this->oldItemService->read($itemId, $isRead, $this->getUserId());
|
||||
$this->itemService->read($this->getUserId(), $itemId, $isRead);
|
||||
} catch (ServiceNotFoundException $ex) {
|
||||
return $this->error($ex, Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
@ -134,10 +171,11 @@ class ItemApiController extends ApiController
|
||||
* @param int $itemId
|
||||
*
|
||||
* @return array|JSONResponse
|
||||
* @throws ServiceConflictException
|
||||
*/
|
||||
public function read(int $itemId)
|
||||
{
|
||||
return $this->setRead(true, $itemId);
|
||||
return $this->setRead($itemId, true);
|
||||
}
|
||||
|
||||
|
||||
@ -149,27 +187,25 @@ class ItemApiController extends ApiController
|
||||
* @param int $itemId
|
||||
*
|
||||
* @return array|JSONResponse
|
||||
* @throws ServiceConflictException
|
||||
*/
|
||||
public function unread(int $itemId)
|
||||
{
|
||||
return $this->setRead(false, $itemId);
|
||||
return $this->setRead($itemId, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return JSONResponse|array
|
||||
* @param int $feedId
|
||||
* @param string $guidHash
|
||||
* @param bool $isStarred
|
||||
*
|
||||
* @psalm-return JSONResponse|array<empty, empty>
|
||||
* @return array|JSONResponse
|
||||
* @throws ServiceConflictException
|
||||
*/
|
||||
private function setStarred(bool $isStarred, int $feedId, string $guidHash)
|
||||
private function setStarred(int $feedId, string $guidHash, bool $isStarred)
|
||||
{
|
||||
try {
|
||||
$this->oldItemService->star(
|
||||
$feedId,
|
||||
$guidHash,
|
||||
$isStarred,
|
||||
$this->getUserId()
|
||||
);
|
||||
$this->itemService->starByGuid($this->getUserId(), $feedId, $guidHash, $isStarred);
|
||||
} catch (ServiceNotFoundException $ex) {
|
||||
return $this->error($ex, Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
@ -187,10 +223,11 @@ class ItemApiController extends ApiController
|
||||
* @param string $guidHash
|
||||
*
|
||||
* @return array|JSONResponse
|
||||
* @throws ServiceConflictException
|
||||
*/
|
||||
public function star(int $feedId, string $guidHash)
|
||||
{
|
||||
return $this->setStarred(true, $feedId, $guidHash);
|
||||
return $this->setStarred($feedId, $guidHash, true);
|
||||
}
|
||||
|
||||
|
||||
@ -203,10 +240,11 @@ class ItemApiController extends ApiController
|
||||
* @param string $guidHash
|
||||
*
|
||||
* @return array|JSONResponse
|
||||
* @throws ServiceConflictException
|
||||
*/
|
||||
public function unstar(int $feedId, string $guidHash)
|
||||
{
|
||||
return $this->setStarred(false, $feedId, $guidHash);
|
||||
return $this->setStarred($feedId, $guidHash, false);
|
||||
}
|
||||
|
||||
|
||||
@ -223,15 +261,20 @@ class ItemApiController extends ApiController
|
||||
*/
|
||||
public function readAll(int $newestItemId): void
|
||||
{
|
||||
$this->oldItemService->readAll($newestItemId, $this->getUserId());
|
||||
$this->itemService->readAll($this->getUserId(), $newestItemId);
|
||||
}
|
||||
|
||||
|
||||
private function setMultipleRead(bool $isRead, array $items): void
|
||||
/**
|
||||
* @param array $items
|
||||
* @param bool $isRead
|
||||
*
|
||||
* @throws ServiceConflictException
|
||||
*/
|
||||
private function setMultipleRead(array $items, bool $isRead): void
|
||||
{
|
||||
foreach ($items as $id) {
|
||||
try {
|
||||
$this->oldItemService->read($id, $isRead, $this->getUserId());
|
||||
$this->itemService->read($this->getUserId(), $id, $isRead);
|
||||
} catch (ServiceNotFoundException $ex) {
|
||||
continue;
|
||||
}
|
||||
@ -249,10 +292,12 @@ class ItemApiController extends ApiController
|
||||
* @param int[] $items item ids
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws ServiceConflictException
|
||||
*/
|
||||
public function readMultiple(array $items): void
|
||||
{
|
||||
$this->setMultipleRead(true, $items);
|
||||
$this->setMultipleRead($items, true);
|
||||
}
|
||||
|
||||
|
||||
@ -266,30 +311,32 @@ class ItemApiController extends ApiController
|
||||
* @param int[] $items item ids
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @throws ServiceConflictException
|
||||
*/
|
||||
public function unreadMultiple(array $items): void
|
||||
{
|
||||
$this->setMultipleRead(false, $items);
|
||||
$this->setMultipleRead($items, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param bool $isStarred
|
||||
* @param array $items
|
||||
* @param bool $isStarred
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function setMultipleStarred(bool $isStarred, array $items): void
|
||||
private function setMultipleStarred(array $items, bool $isStarred): void
|
||||
{
|
||||
foreach ($items as $item) {
|
||||
try {
|
||||
$this->oldItemService->star(
|
||||
$this->itemService->starByGuid(
|
||||
$this->getUserId(),
|
||||
$item['feedId'],
|
||||
$item['guidHash'],
|
||||
$isStarred,
|
||||
$this->getUserId()
|
||||
$isStarred
|
||||
);
|
||||
} catch (ServiceNotFoundException $ex) {
|
||||
} catch (ServiceNotFoundException | ServiceConflictException $ex) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@ -309,7 +356,7 @@ class ItemApiController extends ApiController
|
||||
*/
|
||||
public function starMultiple(array $items): void
|
||||
{
|
||||
$this->setMultipleStarred(true, $items);
|
||||
$this->setMultipleStarred($items, true);
|
||||
}
|
||||
|
||||
|
||||
@ -326,6 +373,6 @@ class ItemApiController extends ApiController
|
||||
*/
|
||||
public function unstarMultiple(array $items): void
|
||||
{
|
||||
$this->setMultipleStarred(false, $items);
|
||||
$this->setMultipleStarred($items, false);
|
||||
}
|
||||
}
|
||||
|
@ -13,20 +13,31 @@
|
||||
|
||||
namespace OCA\News\Controller;
|
||||
|
||||
use OCA\News\Db\FeedType;
|
||||
use OCA\News\Service\Exceptions\ServiceConflictException;
|
||||
use OCA\News\Service\FeedServiceV2;
|
||||
use OCP\AppFramework\Http\JSONResponse;
|
||||
use \OCP\IRequest;
|
||||
use \OCP\IConfig;
|
||||
use \OCP\AppFramework\Http;
|
||||
|
||||
use \OCA\News\Service\Exceptions\ServiceException;
|
||||
use \OCA\News\Service\Exceptions\ServiceNotFoundException;
|
||||
use \OCA\News\Service\ItemService;
|
||||
use \OCA\News\Service\ItemServiceV2;
|
||||
use OCP\IUserSession;
|
||||
|
||||
/**
|
||||
* Class ItemController
|
||||
*
|
||||
* @package OCA\News\Controller
|
||||
*/
|
||||
class ItemController extends Controller
|
||||
{
|
||||
use JSONHttpErrorTrait;
|
||||
|
||||
/**
|
||||
* @var ItemServiceV2
|
||||
*/
|
||||
private $itemService;
|
||||
/**
|
||||
* @var FeedServiceV2
|
||||
@ -40,7 +51,7 @@ class ItemController extends Controller
|
||||
public function __construct(
|
||||
IRequest $request,
|
||||
FeedServiceV2 $feedService,
|
||||
ItemService $itemService,
|
||||
ItemServiceV2 $itemService,
|
||||
IConfig $settings,
|
||||
?IUserSession $userSession
|
||||
) {
|
||||
@ -71,7 +82,7 @@ class ItemController extends Controller
|
||||
?bool $showAll = null,
|
||||
?bool $oldestFirst = null,
|
||||
string $search = ''
|
||||
) {
|
||||
): array {
|
||||
|
||||
// in case this is called directly and not from the website use the
|
||||
// internal state
|
||||
@ -104,15 +115,14 @@ class ItemController extends Controller
|
||||
$type
|
||||
);
|
||||
|
||||
$params = [];
|
||||
$return = [];
|
||||
|
||||
// split search parameter on url space
|
||||
$search = trim(urldecode($search));
|
||||
$search = preg_replace('/\s+/', ' ', $search); // remove multiple ws
|
||||
if ($search === '') {
|
||||
$search = [];
|
||||
} else {
|
||||
$search = explode(' ', $search);
|
||||
$search_string = trim(urldecode($search));
|
||||
$search_string = preg_replace('/\s+/', ' ', $search_string); // remove multiple ws
|
||||
$search_items = [];
|
||||
if ($search !== '') {
|
||||
$search_items = explode(' ', $search_string);
|
||||
}
|
||||
|
||||
try {
|
||||
@ -120,30 +130,54 @@ class ItemController extends Controller
|
||||
// we need to pass the newest feeds to not let the unread count get
|
||||
// out of sync
|
||||
if ($offset === 0) {
|
||||
$params['newestItemId'] =
|
||||
$this->itemService->getNewestItemId($this->getUserId());
|
||||
$params['feeds'] = $this->feedService->findAllForUser($this->getUserId());
|
||||
$params['starred'] =
|
||||
$this->itemService->starredCount($this->getUserId());
|
||||
$return['newestItemId'] = $this->itemService->newest($this->getUserId())->getId();
|
||||
$return['feeds'] = $this->feedService->findAllForUser($this->getUserId());
|
||||
$return['starred'] = count($this->itemService->starred($this->getUserId()));
|
||||
}
|
||||
|
||||
$params['items'] = $this->itemService->findAllItems(
|
||||
$id,
|
||||
$type,
|
||||
$limit,
|
||||
$offset,
|
||||
$showAll,
|
||||
$oldestFirst,
|
||||
$this->getUserId(),
|
||||
$search
|
||||
);
|
||||
switch ($type) {
|
||||
case FeedType::FEED:
|
||||
$items = $this->itemService->findAllInFeedWithFilters(
|
||||
$this->getUserId(),
|
||||
$id,
|
||||
$limit,
|
||||
$offset,
|
||||
!$showAll,
|
||||
$oldestFirst,
|
||||
$search_items
|
||||
);
|
||||
break;
|
||||
case FeedType::FOLDER:
|
||||
$items = $this->itemService->findAllInFolderWithFilters(
|
||||
$this->getUserId(),
|
||||
$id,
|
||||
$limit,
|
||||
$offset,
|
||||
!$showAll,
|
||||
$oldestFirst,
|
||||
$search_items
|
||||
);
|
||||
break;
|
||||
default:
|
||||
$items = $this->itemService->findAllWithFilters(
|
||||
$this->getUserId(),
|
||||
$type,
|
||||
$limit,
|
||||
$offset,
|
||||
$oldestFirst,
|
||||
$search_items
|
||||
);
|
||||
break;
|
||||
}
|
||||
$return['items'] = $items;
|
||||
|
||||
// this gets thrown if there are no items
|
||||
// in that case just return an empty array
|
||||
} catch (ServiceException $ex) {
|
||||
//NO-OP
|
||||
}
|
||||
|
||||
return $params;
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
@ -155,7 +189,7 @@ class ItemController extends Controller
|
||||
* @param int $lastModified
|
||||
* @return array
|
||||
*/
|
||||
public function newItems($type, $id, $lastModified = 0)
|
||||
public function newItems(int $type, int $id, $lastModified = 0): array
|
||||
{
|
||||
$showAll = $this->settings->getUserValue(
|
||||
$this->getUserId(),
|
||||
@ -163,28 +197,47 @@ class ItemController extends Controller
|
||||
'showAll'
|
||||
) === '1';
|
||||
|
||||
$params = [];
|
||||
$return = [];
|
||||
|
||||
try {
|
||||
$params['newestItemId'] =
|
||||
$this->itemService->getNewestItemId($this->getUserId());
|
||||
$params['feeds'] = $this->feedService->findAllForUser($this->getUserId());
|
||||
$params['starred'] =
|
||||
$this->itemService->starredCount($this->getUserId());
|
||||
$params['items'] = $this->itemService->findAllNew(
|
||||
$id,
|
||||
$type,
|
||||
$lastModified,
|
||||
$showAll,
|
||||
$this->getUserId()
|
||||
);
|
||||
switch ($type) {
|
||||
case FeedType::FEED:
|
||||
$items = $this->itemService->findAllInFeedAfter(
|
||||
$this->getUserId(),
|
||||
$id,
|
||||
$lastModified,
|
||||
!$showAll
|
||||
);
|
||||
break;
|
||||
case FeedType::FOLDER:
|
||||
$items = $this->itemService->findAllInFolderAfter(
|
||||
$this->getUserId(),
|
||||
$id,
|
||||
$lastModified,
|
||||
!$showAll
|
||||
);
|
||||
break;
|
||||
default:
|
||||
$items = $this->itemService->findAllAfter(
|
||||
$this->getUserId(),
|
||||
$type,
|
||||
$lastModified
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
$return['newestItemId'] = $this->itemService->newest($this->getUserId())->getId();
|
||||
$return['feeds'] = $this->feedService->findAllForUser($this->getUserId());
|
||||
$return['starred'] = count($this->itemService->starred($this->getUserId()));
|
||||
$return['items'] = $items;
|
||||
|
||||
// this gets thrown if there are no items
|
||||
// in that case just return an empty array
|
||||
} catch (ServiceException $ex) {
|
||||
//NO-OP
|
||||
}
|
||||
|
||||
return $params;
|
||||
return $return;
|
||||
}
|
||||
|
||||
|
||||
@ -194,16 +247,17 @@ class ItemController extends Controller
|
||||
* @param int $feedId
|
||||
* @param string $guidHash
|
||||
* @param bool $isStarred
|
||||
* @return array|\OCP\AppFramework\Http\JSONResponse
|
||||
*
|
||||
* @return array|JSONResponse
|
||||
*/
|
||||
public function star($feedId, $guidHash, $isStarred)
|
||||
public function star(int $feedId, string $guidHash, bool $isStarred)
|
||||
{
|
||||
try {
|
||||
$this->itemService->star(
|
||||
$this->itemService->starByGuid(
|
||||
$this->getUserId(),
|
||||
$feedId,
|
||||
$guidHash,
|
||||
$isStarred,
|
||||
$this->getUserId()
|
||||
$isStarred
|
||||
);
|
||||
} catch (ServiceException $ex) {
|
||||
return $this->error($ex, Http::STATUS_NOT_FOUND);
|
||||
@ -218,12 +272,13 @@ class ItemController extends Controller
|
||||
*
|
||||
* @param int $itemId
|
||||
* @param bool $isRead
|
||||
* @return array|\OCP\AppFramework\Http\JSONResponse
|
||||
*
|
||||
* @return array|JSONResponse
|
||||
*/
|
||||
public function read($itemId, $isRead = true)
|
||||
public function read(int $itemId, $isRead = true)
|
||||
{
|
||||
try {
|
||||
$this->itemService->read($itemId, $isRead, $this->getUserId());
|
||||
$this->itemService->read($this->getUserId(), $itemId, $isRead);
|
||||
} catch (ServiceException $ex) {
|
||||
return $this->error($ex, Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
@ -236,11 +291,12 @@ class ItemController extends Controller
|
||||
* @NoAdminRequired
|
||||
*
|
||||
* @param int $highestItemId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function readAll($highestItemId)
|
||||
public function readAll(int $highestItemId): array
|
||||
{
|
||||
$this->itemService->readAll($highestItemId, $this->getUserId());
|
||||
$this->itemService->readAll($this->getUserId(), $highestItemId);
|
||||
return ['feeds' => $this->feedService->findAllForUser($this->getUserId())];
|
||||
}
|
||||
|
||||
@ -252,12 +308,12 @@ class ItemController extends Controller
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function readMultiple($itemIds): void
|
||||
public function readMultiple(array $itemIds): void
|
||||
{
|
||||
foreach ($itemIds as $id) {
|
||||
try {
|
||||
$this->itemService->read($id, true, $this->getUserId());
|
||||
} catch (ServiceNotFoundException $ex) {
|
||||
$this->itemService->read($this->getUserId(), $id, true);
|
||||
} catch (ServiceNotFoundException | ServiceConflictException $ex) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
namespace OCA\News\Controller;
|
||||
|
||||
use OCA\News\AppInfo\Application;
|
||||
use OCA\News\Explore\Exceptions\RecommendedSiteNotFoundException;
|
||||
use OCP\IRequest;
|
||||
use OCP\IConfig;
|
||||
use OCP\IL10N;
|
||||
@ -24,7 +25,6 @@ use OCP\AppFramework\Http\ContentSecurityPolicy;
|
||||
|
||||
use OCA\News\Service\StatusService;
|
||||
use OCA\News\Explore\RecommendedSites;
|
||||
use OCA\News\Explore\RecommendedSiteNotFoundException;
|
||||
use OCA\News\Db\FeedType;
|
||||
use OCP\IUserSession;
|
||||
|
||||
|
@ -153,4 +153,28 @@ class FeedMapperV2 extends NewsMapperV2
|
||||
|
||||
return $this->findEntities($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param int $id
|
||||
* @param int|null $maxItemID
|
||||
*/
|
||||
public function read(string $userId, int $id, ?int $maxItemID = null): void
|
||||
{
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
$builder->update(ItemMapperV2::TABLE_NAME, 'items')
|
||||
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
|
||||
->setValue('unread', 0)
|
||||
->andWhere('feeds.user_id = :userId')
|
||||
->andWhere('feeds.id = :feedId')
|
||||
->setParameter('userId', $userId)
|
||||
->setParameter('feedId', $id);
|
||||
|
||||
if ($maxItemID !== null) {
|
||||
$builder->andWhere('items.id =< :maxItemId')
|
||||
->setParameter('maxItemId', $maxItemID);
|
||||
}
|
||||
|
||||
$this->db->executeUpdate($builder->getSQL());
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,11 @@
|
||||
|
||||
namespace OCA\News\Db;
|
||||
|
||||
/**
|
||||
* Enum FeedType
|
||||
*
|
||||
* @package OCA\News\Db
|
||||
*/
|
||||
class FeedType
|
||||
{
|
||||
const FEED = 0;
|
||||
|
@ -95,4 +95,30 @@ class FolderMapperV2 extends NewsMapperV2
|
||||
|
||||
return $this->findEntity($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param int $id
|
||||
* @param int|null $maxItemID
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function read(string $userId, int $id, ?int $maxItemID = null): void
|
||||
{
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
$builder->update(ItemMapperV2::TABLE_NAME, 'items')
|
||||
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
|
||||
->setValue('unread', 0)
|
||||
->andWhere('feeds.user_id = :userId')
|
||||
->andWhere('feeds.folder_id = :folderId')
|
||||
->setParameter('userId', $userId)
|
||||
->setParameter('folderId', $id);
|
||||
|
||||
if ($maxItemID !== null) {
|
||||
$builder->andWhere('items.id =< :maxItemId')
|
||||
->setParameter('maxItemId', $maxItemID);
|
||||
}
|
||||
|
||||
$this->db->executeUpdate($builder->getSQL());
|
||||
}
|
||||
}
|
||||
|
@ -1,586 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Nextcloud - News
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Alessandro Cosentino <cosenal@gmail.com>
|
||||
* @author Bernhard Posselt <dev@bernhard-posselt.com>
|
||||
* @copyright 2012 Alessandro Cosentino
|
||||
* @copyright 2012-2014 Bernhard Posselt
|
||||
*/
|
||||
|
||||
namespace OCA\News\Db;
|
||||
|
||||
use OCA\News\Utility\Time;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
use OCP\AppFramework\Db\Mapper;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
/**
|
||||
* Class LegacyItemMapper
|
||||
*
|
||||
* @package OCA\News\Db
|
||||
* @deprecated use ItemMapper
|
||||
*/
|
||||
class ItemMapper extends Mapper
|
||||
{
|
||||
|
||||
const TABLE_NAME = 'news_items';
|
||||
/**
|
||||
* @var Time
|
||||
*/
|
||||
private $time;
|
||||
|
||||
/**
|
||||
* NewsMapper constructor.
|
||||
*
|
||||
* @param IDBConnection $db Database connection
|
||||
* @param Time $time Time class
|
||||
*/
|
||||
public function __construct(IDBConnection $db, Time $time)
|
||||
{
|
||||
parent::__construct($db, static::TABLE_NAME, Item::class);
|
||||
$this->time = $time;
|
||||
}
|
||||
|
||||
private function makeSelectQuery(
|
||||
string $prependTo = '',
|
||||
bool $oldestFirst = false,
|
||||
bool $distinctFingerprint = false
|
||||
): string {
|
||||
if ($oldestFirst) {
|
||||
$ordering = 'ASC';
|
||||
} else {
|
||||
$ordering = 'DESC';
|
||||
}
|
||||
|
||||
return 'SELECT `items`.* FROM `*PREFIX*news_items` `items` ' .
|
||||
'JOIN `*PREFIX*news_feeds` `feeds` ' .
|
||||
'ON `feeds`.`id` = `items`.`feed_id` ' .
|
||||
'AND `feeds`.`deleted_at` = 0 ' .
|
||||
'AND `feeds`.`user_id` = ? ' .
|
||||
$prependTo .
|
||||
'LEFT OUTER JOIN `*PREFIX*news_folders` `folders` ' .
|
||||
'ON `folders`.`id` = `feeds`.`folder_id` ' .
|
||||
'WHERE `feeds`.`folder_id` IS NULL ' .
|
||||
'OR `folders`.`deleted_at` = 0 ' .
|
||||
'ORDER BY `items`.`id` ' . $ordering;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if type is feed or all items should be shown
|
||||
*
|
||||
* @param bool $showAll
|
||||
* @param int|null $type
|
||||
* @return string
|
||||
*/
|
||||
private function buildStatusQueryPart($showAll, $type = null)
|
||||
{
|
||||
$sql = '';
|
||||
|
||||
if (isset($type) && $type === FeedType::STARRED) {
|
||||
$sql = 'AND `items`.`starred` = ';
|
||||
$sql .= $this->db->quote(true, IQueryBuilder::PARAM_BOOL) . ' ';
|
||||
} elseif (!$showAll || $type === FeedType::UNREAD) {
|
||||
$sql .= 'AND `items`.`unread` = ';
|
||||
$sql .= $this->db->quote(true, IQueryBuilder::PARAM_BOOL) . ' ';
|
||||
}
|
||||
|
||||
return $sql;
|
||||
}
|
||||
|
||||
private function buildSearchQueryPart(array $search = []): string
|
||||
{
|
||||
return str_repeat('AND `items`.`search_index` LIKE ? ', count($search));
|
||||
}
|
||||
|
||||
/**
|
||||
* wrap and escape search parameters in a like statement
|
||||
*
|
||||
* @param string[] $search an array of strings that should be searched
|
||||
* @return array with like parameters
|
||||
*/
|
||||
private function buildLikeParameters($search = [])
|
||||
{
|
||||
return array_map(
|
||||
function ($param) {
|
||||
$param = addcslashes($param, '\\_%');
|
||||
return '%' . mb_strtolower($param, 'UTF-8') . '%';
|
||||
},
|
||||
$search
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $id
|
||||
* @param string $userId
|
||||
* @return \OCA\News\Db\Item|Entity
|
||||
*/
|
||||
public function find(string $userId, int $id)
|
||||
{
|
||||
$sql = $this->makeSelectQuery('AND `items`.`id` = ? ');
|
||||
return $this->findEntity($sql, [$userId, $id]);
|
||||
}
|
||||
|
||||
public function starredCount(string $userId): int
|
||||
{
|
||||
$sql = 'SELECT COUNT(*) AS size FROM `*PREFIX*news_items` `items` ' .
|
||||
'JOIN `*PREFIX*news_feeds` `feeds` ' .
|
||||
'ON `feeds`.`id` = `items`.`feed_id` ' .
|
||||
'AND `feeds`.`deleted_at` = 0 ' .
|
||||
'AND `feeds`.`user_id` = ? ' .
|
||||
'AND `items`.`starred` = ? ' .
|
||||
'LEFT OUTER JOIN `*PREFIX*news_folders` `folders` ' .
|
||||
'ON `folders`.`id` = `feeds`.`folder_id` ' .
|
||||
'WHERE `feeds`.`folder_id` IS NULL ' .
|
||||
'OR `folders`.`deleted_at` = 0';
|
||||
|
||||
$params = [$userId, true];
|
||||
|
||||
$result = $this->execute($sql, $params)->fetch();
|
||||
|
||||
return (int)$result['size'];
|
||||
}
|
||||
|
||||
|
||||
public function readAll(int $highestItemId, string $time, string $userId): void
|
||||
{
|
||||
$sql = 'UPDATE `*PREFIX*news_items` ' .
|
||||
'SET unread = ? ' .
|
||||
', `last_modified` = ? ' .
|
||||
'WHERE `feed_id` IN (' .
|
||||
'SELECT `id` FROM `*PREFIX*news_feeds` ' .
|
||||
'WHERE `user_id` = ? ' .
|
||||
') ' .
|
||||
'AND `id` <= ?';
|
||||
$params = [false, $time, $userId, $highestItemId];
|
||||
$this->execute($sql, $params);
|
||||
}
|
||||
|
||||
|
||||
public function readFolder(?int $folderId, int $highestItemId, string $time, string $userId): void
|
||||
{
|
||||
$folderWhere = is_null($folderId) ? 'IS' : '=';
|
||||
$sql = 'UPDATE `*PREFIX*news_items` ' .
|
||||
'SET unread = ? ' .
|
||||
', `last_modified` = ? ' .
|
||||
'WHERE `feed_id` IN (' .
|
||||
'SELECT `id` FROM `*PREFIX*news_feeds` ' .
|
||||
"WHERE `folder_id` ${folderWhere} ? " .
|
||||
'AND `user_id` = ? ' .
|
||||
') ' .
|
||||
'AND `id` <= ?';
|
||||
$params = [false, $time, $folderId, $userId,
|
||||
$highestItemId];
|
||||
$this->execute($sql, $params);
|
||||
}
|
||||
|
||||
|
||||
public function readFeed(int $feedId, int $highestItemId, string $time, string $userId): void
|
||||
{
|
||||
$sql = 'UPDATE `*PREFIX*news_items` ' .
|
||||
'SET unread = ? ' .
|
||||
', `last_modified` = ? ' .
|
||||
'WHERE `feed_id` = ? ' .
|
||||
'AND `id` <= ? ' .
|
||||
'AND EXISTS (' .
|
||||
'SELECT * FROM `*PREFIX*news_feeds` ' .
|
||||
'WHERE `user_id` = ? ' .
|
||||
'AND `id` = ? ) ';
|
||||
$params = [false, $time, $feedId, $highestItemId,
|
||||
$userId, $feedId];
|
||||
|
||||
$this->execute($sql, $params);
|
||||
}
|
||||
|
||||
|
||||
private function getOperator(bool $oldestFirst): string
|
||||
{
|
||||
if ($oldestFirst) {
|
||||
return '>';
|
||||
} else {
|
||||
return '<';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function findAllNew(int $updatedSince, int $type, bool $showAll, string $userId): array
|
||||
{
|
||||
$sql = $this->buildStatusQueryPart($showAll, $type);
|
||||
|
||||
$sql .= 'AND `items`.`last_modified` >= ? ';
|
||||
$sql = $this->makeSelectQuery($sql);
|
||||
$params = [$userId, $updatedSince];
|
||||
return $this->findEntities($sql, $params);
|
||||
}
|
||||
|
||||
|
||||
public function findAllNewFolder(?int $id, int $updatedSince, bool $showAll, string $userId): array
|
||||
{
|
||||
$sql = $this->buildStatusQueryPart($showAll);
|
||||
|
||||
$folderWhere = is_null($id) ? 'IS' : '=';
|
||||
$sql .= "AND `feeds`.`folder_id` ${folderWhere} ? " .
|
||||
'AND `items`.`last_modified` >= ? ';
|
||||
$sql = $this->makeSelectQuery($sql);
|
||||
$params = [$userId, $id, $updatedSince];
|
||||
return $this->findEntities($sql, $params);
|
||||
}
|
||||
|
||||
|
||||
public function findAllNewFeed(?int $id, int $updatedSince, bool $showAll, string $userId): array
|
||||
{
|
||||
$sql = $this->buildStatusQueryPart($showAll);
|
||||
|
||||
$sql .= 'AND `items`.`feed_id` = ? ' .
|
||||
'AND `items`.`last_modified` >= ? ';
|
||||
$sql = $this->makeSelectQuery($sql);
|
||||
$params = [$userId, $id, $updatedSince];
|
||||
return $this->findEntities($sql, $params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param (int|mixed|null)[] $params
|
||||
*/
|
||||
private function findEntitiesIgnoringNegativeLimit(string $sql, array $params, int $limit): array
|
||||
{
|
||||
// ignore limit if negative to offer a way to return all feeds
|
||||
if ($limit >= 0) {
|
||||
return $this->findEntities($sql, $params, $limit);
|
||||
} else {
|
||||
return $this->findEntities($sql, $params);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function findAllFeed(
|
||||
?int $id,
|
||||
int $limit,
|
||||
int $offset,
|
||||
bool $showAll,
|
||||
bool $oldestFirst,
|
||||
string $userId,
|
||||
array $search = []
|
||||
): array {
|
||||
$params = [$userId];
|
||||
$params = array_merge($params, $this->buildLikeParameters($search));
|
||||
$params[] = $id;
|
||||
|
||||
$sql = $this->buildStatusQueryPart($showAll);
|
||||
$sql .= $this->buildSearchQueryPart($search);
|
||||
|
||||
$sql .= 'AND `items`.`feed_id` = ? ';
|
||||
if ($offset !== 0) {
|
||||
$sql .= 'AND `items`.`id` ' .
|
||||
$this->getOperator($oldestFirst) . ' ? ';
|
||||
$params[] = $offset;
|
||||
}
|
||||
$sql = $this->makeSelectQuery($sql, $oldestFirst);
|
||||
return $this->findEntitiesIgnoringNegativeLimit($sql, $params, $limit);
|
||||
}
|
||||
|
||||
|
||||
public function findAllFolder(
|
||||
?int $id,
|
||||
int $limit,
|
||||
int $offset,
|
||||
bool $showAll,
|
||||
bool $oldestFirst,
|
||||
string $userId,
|
||||
array $search = []
|
||||
): array {
|
||||
$params = [$userId];
|
||||
$params = array_merge($params, $this->buildLikeParameters($search));
|
||||
$params[] = $id;
|
||||
|
||||
$sql = $this->buildStatusQueryPart($showAll);
|
||||
$sql .= $this->buildSearchQueryPart($search);
|
||||
|
||||
$folderWhere = is_null($id) ? 'IS' : '=';
|
||||
$sql .= "AND `feeds`.`folder_id` ${folderWhere} ? ";
|
||||
if ($offset !== 0) {
|
||||
$sql .= 'AND `items`.`id` ' . $this->getOperator($oldestFirst) . ' ? ';
|
||||
$params[] = $offset;
|
||||
}
|
||||
$sql = $this->makeSelectQuery($sql, $oldestFirst);
|
||||
return $this->findEntitiesIgnoringNegativeLimit($sql, $params, $limit);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string[] $search
|
||||
*/
|
||||
public function findAllItems(
|
||||
int $limit,
|
||||
int $offset,
|
||||
int $type,
|
||||
bool $showAll,
|
||||
bool $oldestFirst,
|
||||
string $userId,
|
||||
array $search = []
|
||||
): array {
|
||||
$params = [$userId];
|
||||
$params = array_merge($params, $this->buildLikeParameters($search));
|
||||
$sql = $this->buildStatusQueryPart($showAll, $type);
|
||||
$sql .= $this->buildSearchQueryPart($search);
|
||||
|
||||
if ($offset !== 0) {
|
||||
$sql .= 'AND `items`.`id` ' .
|
||||
$this->getOperator($oldestFirst) . ' ? ';
|
||||
$params[] = $offset;
|
||||
}
|
||||
|
||||
$sql = $this->makeSelectQuery($sql, $oldestFirst);
|
||||
|
||||
return $this->findEntitiesIgnoringNegativeLimit($sql, $params, $limit);
|
||||
}
|
||||
|
||||
|
||||
public function findAllUnreadOrStarred(string $userId): array
|
||||
{
|
||||
$params = [$userId, true, true];
|
||||
$sql = 'AND (`items`.`unread` = ? OR `items`.`starred` = ?) ';
|
||||
$sql = $this->makeSelectQuery($sql);
|
||||
return $this->findEntities($sql, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $guidHash
|
||||
* @param $feedId
|
||||
* @param $userId
|
||||
*
|
||||
* @return Entity|Item
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
*/
|
||||
public function findByGuidHash($guidHash, $feedId, $userId)
|
||||
{
|
||||
$sql = $this->makeSelectQuery(
|
||||
'AND `items`.`guid_hash` = ? ' .
|
||||
'AND `feeds`.`id` = ? '
|
||||
);
|
||||
|
||||
return $this->findEntity($sql, [$userId, $guidHash, $feedId]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete all items for feeds that have over $threshold unread and not
|
||||
* starred items
|
||||
*
|
||||
* @param int $threshold the number of items that should be deleted
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteReadOlderThanThreshold($threshold)
|
||||
{
|
||||
$params = [false, false, $threshold];
|
||||
|
||||
$sql = 'SELECT (COUNT(*) - `feeds`.`articles_per_update`) AS `size`, ' .
|
||||
'`feeds`.`id` AS `feed_id`, `feeds`.`articles_per_update` ' .
|
||||
'FROM `*PREFIX*news_items` `items` ' .
|
||||
'JOIN `*PREFIX*news_feeds` `feeds` ' .
|
||||
'ON `feeds`.`id` = `items`.`feed_id` ' .
|
||||
'AND `items`.`unread` = ? ' .
|
||||
'AND `items`.`starred` = ? ' .
|
||||
'GROUP BY `feeds`.`id`, `feeds`.`articles_per_update` ' .
|
||||
'HAVING COUNT(*) > ?';
|
||||
|
||||
$result = $this->execute($sql, $params);
|
||||
|
||||
while ($row = $result->fetch()) {
|
||||
$size = (int)$row['size'];
|
||||
$limit = $size - $threshold;
|
||||
$feed_id = $row['feed_id'];
|
||||
|
||||
if ($limit > 0) {
|
||||
$params = [false, false, $feed_id, $limit];
|
||||
$sql = 'SELECT `id` FROM `*PREFIX*news_items` ' .
|
||||
'WHERE `unread` = ? ' .
|
||||
'AND `starred` = ? ' .
|
||||
'AND `feed_id` = ? ' .
|
||||
'ORDER BY `id` ASC ' .
|
||||
'LIMIT 1 ' .
|
||||
'OFFSET ? ';
|
||||
}
|
||||
$limit_result = $this->execute($sql, $params);
|
||||
if ($limit_row = $limit_result->fetch()) {
|
||||
$limit_id = (int)$limit_row['id'];
|
||||
$params = [false, false, $feed_id, $limit_id];
|
||||
$sql = 'DELETE FROM `*PREFIX*news_items` ' .
|
||||
'WHERE `unread` = ? ' .
|
||||
'AND `starred` = ? ' .
|
||||
'AND `feed_id` = ? ' .
|
||||
'AND `id` < ? ';
|
||||
$this->execute($sql, $params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function getNewestItemId(string $userId): int
|
||||
{
|
||||
$sql = 'SELECT MAX(`items`.`id`) AS `max_id` ' .
|
||||
'FROM `*PREFIX*news_items` `items` ' .
|
||||
'JOIN `*PREFIX*news_feeds` `feeds` ' .
|
||||
'ON `feeds`.`id` = `items`.`feed_id` ' .
|
||||
'AND `feeds`.`user_id` = ?';
|
||||
$params = [$userId];
|
||||
|
||||
$result = $this->findOneQuery($sql, $params);
|
||||
|
||||
return (int)$result['max_id'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a list of ids and userid of all items
|
||||
*
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
public function findAllIds(?int $limit = null, ?int $offset = null)
|
||||
{
|
||||
$sql = 'SELECT `id` FROM `*PREFIX*news_items`';
|
||||
return $this->execute($sql, [], $limit, $offset)->fetchAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update search indices of all items
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function updateSearchIndices(): void
|
||||
{
|
||||
// update indices in steps to prevent memory issues on larger systems
|
||||
$step = 1000; // update 1000 items at a time
|
||||
$itemCount = 1;
|
||||
$offset = 0;
|
||||
|
||||
// stop condition if there are no previously fetched items
|
||||
while ($itemCount > 0) {
|
||||
$items = $this->findAllIds($step, $offset);
|
||||
$itemCount = count($items);
|
||||
$this->updateSearchIndex($items);
|
||||
$offset += $step;
|
||||
}
|
||||
}
|
||||
|
||||
private function updateSearchIndex(array $items = []): void
|
||||
{
|
||||
foreach ($items as $row) {
|
||||
$sql = 'SELECT * FROM `*PREFIX*news_items` WHERE `id` = ?';
|
||||
$params = [$row['id']];
|
||||
$item = $this->findEntity($sql, $params);
|
||||
$item->generateSearchIndex();
|
||||
$this->update($item);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function readItem(int $itemId, bool $isRead, string $lastModified, string $userId)
|
||||
{
|
||||
$item = $this->find($userId, $itemId);
|
||||
|
||||
// reading an item should set all of the same items as read, whereas
|
||||
// marking an item as unread should only mark the selected instance
|
||||
// as unread
|
||||
if ($isRead) {
|
||||
$sql = 'UPDATE `*PREFIX*news_items`
|
||||
SET `unread` = ?,
|
||||
`last_modified` = ?
|
||||
WHERE `fingerprint` = ?
|
||||
AND `feed_id` IN (
|
||||
SELECT `f`.`id` FROM `*PREFIX*news_feeds` AS `f`
|
||||
WHERE `f`.`user_id` = ?
|
||||
)';
|
||||
$params = [false, $lastModified, $item->getFingerprint(), $userId];
|
||||
$this->execute($sql, $params);
|
||||
} else {
|
||||
$item->setLastModified($lastModified);
|
||||
$item->setUnread(true);
|
||||
$this->update($item);
|
||||
}
|
||||
}
|
||||
|
||||
public function update(Entity $entity): Entity
|
||||
{
|
||||
$entity->setLastModified($this->time->getMicroTime());
|
||||
return parent::update($entity);
|
||||
}
|
||||
|
||||
public function insert(Entity $entity): Entity
|
||||
{
|
||||
$entity->setLastModified($this->time->getMicroTime());
|
||||
return parent::insert($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove deleted items.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function purgeDeleted(): void
|
||||
{
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
$builder->delete($this->tableName)
|
||||
->where('deleted_at != 0')
|
||||
->execute();
|
||||
}
|
||||
/**
|
||||
* Performs a SELECT query with all arguments appended to the WHERE clause
|
||||
* The SELECT will be performed on the current table and takes the entity
|
||||
* that is related for transforming the properties into column names
|
||||
*
|
||||
* Important: This method does not filter marked as deleted rows!
|
||||
*
|
||||
* @param array $search an assoc array from property to filter value
|
||||
* @param int|null $limit Output limit
|
||||
* @param int|null $offset Output offset
|
||||
*
|
||||
* @depreacted Legacy function
|
||||
*
|
||||
* @return Entity[]
|
||||
*/
|
||||
public function where(array $search = [], ?int $limit = null, ?int $offset = null)
|
||||
{
|
||||
$entity = new $this->entityClass();
|
||||
|
||||
// turn keys into sql query filter, e.g. feedId -> feed_id = :feedId
|
||||
$filter = array_map(
|
||||
function ($property) use ($entity) {
|
||||
// check if the property actually exists on the entity to prevent
|
||||
// accidental Sql injection
|
||||
if (!property_exists($entity, $property)) {
|
||||
$msg = 'Property ' . $property . ' does not exist on '
|
||||
. $this->entityClass;
|
||||
throw new \BadFunctionCallException($msg);
|
||||
}
|
||||
|
||||
$column = $entity->propertyToColumn($property);
|
||||
return $column . ' = :' . $property;
|
||||
},
|
||||
array_keys($search)
|
||||
);
|
||||
|
||||
$andStatement = implode(' AND ', $filter);
|
||||
|
||||
$sql = 'SELECT * FROM `' . $this->getTableName() . '`';
|
||||
|
||||
if (count($search) > 0) {
|
||||
$sql .= 'WHERE ' . $andStatement;
|
||||
}
|
||||
|
||||
return $this->findEntities($sql, $search, $limit, $offset);
|
||||
}
|
||||
}
|
@ -12,6 +12,7 @@
|
||||
|
||||
namespace OCA\News\Db;
|
||||
|
||||
use OCA\News\Service\Exceptions\ServiceValidationException;
|
||||
use Doctrine\DBAL\FetchMode;
|
||||
use OCA\News\Utility\Time;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
@ -55,12 +56,11 @@ class ItemMapperV2 extends NewsMapperV2
|
||||
->from($this->tableName, 'items')
|
||||
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
|
||||
->where('feeds.user_id = :user_id')
|
||||
->andWhere('deleted_at = 0')
|
||||
->andWhere('feeds.deleted_at = 0')
|
||||
->setParameter('user_id', $userId, IQueryBuilder::PARAM_STR);
|
||||
|
||||
foreach ($params as $key => $value) {
|
||||
$builder->andWhere("${key} = :${key}")
|
||||
->setParameter($key, $value);
|
||||
$builder->andWhere("${key} = " . $builder->createNamedParameter($value));
|
||||
}
|
||||
|
||||
return $this->findEntities($builder);
|
||||
@ -74,13 +74,17 @@ class ItemMapperV2 extends NewsMapperV2
|
||||
public function findAll(): array
|
||||
{
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
$builder->addSelect('*')
|
||||
$builder->select('*')
|
||||
->from($this->tableName)
|
||||
->andWhere('deleted_at = 0');
|
||||
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
|
||||
->andWhere('feeds.deleted_at = 0');
|
||||
|
||||
return $this->findEntities($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function findFromUser(string $userId, int $id): Entity
|
||||
{
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
@ -89,9 +93,9 @@ class ItemMapperV2 extends NewsMapperV2
|
||||
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
|
||||
->where('feeds.user_id = :user_id')
|
||||
->andWhere('items.id = :item_id')
|
||||
->andWhere('deleted_at = 0')
|
||||
->andWhere('feeds.deleted_at = 0')
|
||||
->setParameter('user_id', $userId, IQueryBuilder::PARAM_STR)
|
||||
->setParameter('item_id', $id, IQueryBuilder::PARAM_STR);
|
||||
->setParameter('item_id', $id, IQueryBuilder::PARAM_INT);
|
||||
|
||||
return $this->findEntity($builder);
|
||||
}
|
||||
@ -102,15 +106,15 @@ class ItemMapperV2 extends NewsMapperV2
|
||||
* @param int $feedId ID of the feed
|
||||
* @param string $guidHash hash to find with
|
||||
*
|
||||
* @return Item
|
||||
* @return Item|Entity
|
||||
*
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
*/
|
||||
public function findByGuidHash(int $feedId, string $guidHash): Item
|
||||
public function findByGuidHash(int $feedId, string $guidHash): Entity
|
||||
{
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
$builder->addSelect('*')
|
||||
$builder->select('*')
|
||||
->from($this->tableName)
|
||||
->andWhere('feed_id = :feed_id')
|
||||
->andWhere('guid_hash = :guid_hash')
|
||||
@ -120,6 +124,34 @@ class ItemMapperV2 extends NewsMapperV2
|
||||
return $this->findEntity($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a user item by a GUID hash.
|
||||
*
|
||||
* @param string $userId
|
||||
* @param int $feedId ID of the feed
|
||||
* @param string $guidHash hash to find with
|
||||
*
|
||||
* @return Item|Entity
|
||||
*
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
*/
|
||||
public function findForUserByGuidHash(string $userId, int $feedId, string $guidHash): Item
|
||||
{
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
$builder->select('items.*')
|
||||
->from($this->tableName, 'items')
|
||||
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
|
||||
->andWhere('feeds.user_id = :user_id')
|
||||
->andWhere('feeds.id = :feed_id')
|
||||
->andWhere('items.guid_hash = :guid_hash')
|
||||
->setParameter('user_id', $userId, IQueryBuilder::PARAM_STR)
|
||||
->setParameter('feed_id', $feedId, IQueryBuilder::PARAM_INT)
|
||||
->setParameter('guid_hash', $guidHash, IQueryBuilder::PARAM_STR);
|
||||
|
||||
return $this->findEntity($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $feedId
|
||||
*
|
||||
@ -128,10 +160,10 @@ class ItemMapperV2 extends NewsMapperV2
|
||||
public function findAllForFeed(int $feedId): array
|
||||
{
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
$builder->addSelect('*')
|
||||
$builder->select('*')
|
||||
->from($this->tableName)
|
||||
->andWhere('feed_id = :feed_id')
|
||||
->setParameter('feed_id', $feedId, IQueryBuilder::PARAM_INT);
|
||||
->where('feed_id = :feed_identifier')
|
||||
->setParameter('feed_identifier', $feedId, IQueryBuilder::PARAM_INT);
|
||||
|
||||
return $this->findEntities($builder);
|
||||
}
|
||||
@ -214,4 +246,312 @@ class ItemMapperV2 extends NewsMapperV2
|
||||
{
|
||||
//NO-OP
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param int $maxItemId
|
||||
*
|
||||
* @TODO: Update this for NC 21
|
||||
*/
|
||||
public function readAll(string $userId, int $maxItemId): void
|
||||
{
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
|
||||
$builder->update($this->tableName, 'items')
|
||||
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
|
||||
->setValue('unread', 0)
|
||||
->andWhere('items.id =< :maxItemId')
|
||||
->andWhere('feeds.user_id = :userId')
|
||||
->setParameter('maxItemId', $maxItemId)
|
||||
->setParameter('userId', $userId);
|
||||
|
||||
$this->db->executeUpdate($builder->getSQL());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
*
|
||||
* @return Entity|Item
|
||||
*
|
||||
* @throws DoesNotExistException The item is not found
|
||||
* @throws MultipleObjectsReturnedException Multiple items found
|
||||
*/
|
||||
public function newest(string $userId): Entity
|
||||
{
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
|
||||
$builder->select('items.*')
|
||||
->from($this->tableName, 'items')
|
||||
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
|
||||
->where('feeds.user_id = :userId')
|
||||
->setParameter('userId', $userId)
|
||||
->orderBy('items.updated_date', 'DESC')
|
||||
->addOrderBy('items.id', 'DESC')
|
||||
->setMaxResults(1);
|
||||
|
||||
return $this->findEntity($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param int $feedId
|
||||
* @param int $updatedSince
|
||||
* @param bool $hideRead
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function findAllInFeedAfter(
|
||||
string $userId,
|
||||
int $feedId,
|
||||
int $updatedSince,
|
||||
bool $hideRead
|
||||
): array {
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
|
||||
$builder->select('items.*')
|
||||
->from($this->tableName, 'items')
|
||||
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
|
||||
->andWhere('items.updated_date >= :updatedSince')
|
||||
->andWhere('feeds.user_id = :userId')
|
||||
->andWhere('feeds.id = :feedId')
|
||||
->setParameters([
|
||||
'updatedSince' => $updatedSince,
|
||||
'feedId' => $feedId,
|
||||
'userId'=> $userId,
|
||||
])
|
||||
->orderBy('items.updated_date', 'DESC')
|
||||
->addOrderBy('items.id', 'DESC');
|
||||
|
||||
if ($hideRead === true) {
|
||||
$builder->andWhere('items.unread = 1');
|
||||
}
|
||||
|
||||
return $this->findEntities($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param int|null $folderId
|
||||
* @param int $updatedSince
|
||||
* @param bool $hideRead
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function findAllInFolderAfter(
|
||||
string $userId,
|
||||
?int $folderId,
|
||||
int $updatedSince,
|
||||
bool $hideRead
|
||||
): array {
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
|
||||
$builder->select('items.*')
|
||||
->from($this->tableName, 'items')
|
||||
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
|
||||
->innerJoin('feeds', FolderMapperV2::TABLE_NAME, 'folders', 'feeds.folder_id = folders.id')
|
||||
->andWhere('items.updated_date >= :updatedSince')
|
||||
->andWhere('feeds.user_id = :userId')
|
||||
->andWhere('folders.id = :folderId')
|
||||
->setParameters(['updatedSince' => $updatedSince, 'folderId' => $folderId, 'userId' => $userId])
|
||||
->orderBy('items.updated_date', 'DESC')
|
||||
->addOrderBy('items.id', 'DESC');
|
||||
|
||||
if ($hideRead === true) {
|
||||
$builder->andWhere('items.unread = 1');
|
||||
}
|
||||
|
||||
return $this->findEntities($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param int $updatedSince
|
||||
* @param int $feedType
|
||||
*
|
||||
* @return Item[]|Entity[]
|
||||
* @throws ServiceValidationException
|
||||
*/
|
||||
public function findAllAfter(string $userId, int $feedType, int $updatedSince): array
|
||||
{
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
|
||||
$builder->select('items.*')
|
||||
->from($this->tableName, 'items')
|
||||
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
|
||||
->andWhere('items.updated_date >= :updatedSince')
|
||||
->andWhere('feeds.user_id = :userId')
|
||||
->setParameters(['updatedSince' => $updatedSince, 'userId' => $userId])
|
||||
->orderBy('items.updated_date', 'DESC')
|
||||
->addOrderBy('items.id', 'DESC');
|
||||
|
||||
switch ($feedType) {
|
||||
case FeedType::STARRED:
|
||||
$builder->andWhere('items.starred = 1');
|
||||
break;
|
||||
case FeedType::UNREAD:
|
||||
$builder->andWhere('items.unread = 1');
|
||||
break;
|
||||
default:
|
||||
throw new ServiceValidationException('Unexpected Feed type in call');
|
||||
}
|
||||
|
||||
return $this->findEntities($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param int $feedId
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @param bool $hideRead
|
||||
* @param bool $oldestFirst
|
||||
* @param array $search
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function findAllFeed(
|
||||
string $userId,
|
||||
int $feedId,
|
||||
int $limit,
|
||||
int $offset,
|
||||
bool $hideRead,
|
||||
bool $oldestFirst,
|
||||
array $search
|
||||
): array {
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
|
||||
$builder->select('items.*')
|
||||
->from($this->tableName, 'items')
|
||||
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
|
||||
->andWhere('feeds.user_id = :userId')
|
||||
->andWhere('items.feed_id = :feedId')
|
||||
->setParameter('userId', $userId)
|
||||
->setParameter('feedId', $feedId)
|
||||
->setMaxResults($limit)
|
||||
->setFirstResult($offset)
|
||||
->orderBy('items.updated_date', ($oldestFirst ? 'ASC' : 'DESC'))
|
||||
->addOrderBy('items.id', ($oldestFirst ? 'ASC' : 'DESC'));
|
||||
|
||||
if ($search !== []) {
|
||||
foreach ($search as $key => $term) {
|
||||
$term = $this->db->escapeLikeParameter($term);
|
||||
$builder->andWhere("items.search_index LIKE :term${key}")
|
||||
->setParameter("term${key}", "%$term%");
|
||||
}
|
||||
}
|
||||
|
||||
if ($hideRead === true) {
|
||||
$builder->andWhere('items.unread = 1');
|
||||
}
|
||||
|
||||
return $this->findEntities($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param int|null $folderId
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @param bool $hideRead
|
||||
* @param bool $oldestFirst
|
||||
* @param array $search
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function findAllFolder(
|
||||
string $userId,
|
||||
?int $folderId,
|
||||
int $limit,
|
||||
int $offset,
|
||||
bool $hideRead,
|
||||
bool $oldestFirst,
|
||||
array $search
|
||||
): array {
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
|
||||
if ($folderId === null) {
|
||||
$folderWhere = $builder->expr()->isNull('feeds.folder_id');
|
||||
} else {
|
||||
$folderWhere = $builder->expr()->eq('feeds.folder_id', $folderId);
|
||||
}
|
||||
|
||||
$builder->select('items.*')
|
||||
->from($this->tableName, 'items')
|
||||
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
|
||||
->andWhere('feeds.user_id = :userId')
|
||||
->andWhere($folderWhere)
|
||||
->setParameter('userId', $userId)
|
||||
->setMaxResults($limit)
|
||||
->setFirstResult($offset)
|
||||
->orderBy('items.updated_date', ($oldestFirst ? 'ASC' : 'DESC'))
|
||||
->addOrderBy('items.id', ($oldestFirst ? 'ASC' : 'DESC'));
|
||||
|
||||
if ($search !== []) {
|
||||
foreach ($search as $key => $term) {
|
||||
$term = $this->db->escapeLikeParameter($term);
|
||||
$builder->andWhere("items.search_index LIKE :term${key}")
|
||||
->setParameter("term${key}", "%$term%");
|
||||
}
|
||||
}
|
||||
|
||||
if ($hideRead === true) {
|
||||
$builder->andWhere('items.unread = 1');
|
||||
}
|
||||
|
||||
return $this->findEntities($builder);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
* @param int $type
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @param bool $oldestFirst
|
||||
* @param array $search
|
||||
*
|
||||
* @return Item[]
|
||||
* @throws ServiceValidationException
|
||||
*/
|
||||
public function findAllItems(
|
||||
string $userId,
|
||||
int $type,
|
||||
int $limit,
|
||||
int $offset,
|
||||
bool $oldestFirst,
|
||||
array $search
|
||||
): array {
|
||||
$builder = $this->db->getQueryBuilder();
|
||||
|
||||
$builder->select('items.*')
|
||||
->from($this->tableName, 'items')
|
||||
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
|
||||
->andWhere('feeds.user_id = :userId')
|
||||
->setParameter('userId', $userId)
|
||||
->setMaxResults($limit)
|
||||
->setFirstResult($offset)
|
||||
->orderBy('items.updated_date', ($oldestFirst ? 'ASC' : 'DESC'))
|
||||
->addOrderBy('items.id', ($oldestFirst ? 'ASC' : 'DESC'));
|
||||
|
||||
if ($search !== []) {
|
||||
foreach ($search as $key => $term) {
|
||||
$term = $this->db->escapeLikeParameter($term);
|
||||
$builder->andWhere("items.search_index LIKE :term${key}")
|
||||
->setParameter("term${key}", "%$term%");
|
||||
}
|
||||
}
|
||||
|
||||
switch ($type) {
|
||||
case FeedType::STARRED:
|
||||
$builder->andWhere('items.starred = 1');
|
||||
break;
|
||||
case FeedType::UNREAD:
|
||||
$builder->andWhere('items.unread = 1');
|
||||
break;
|
||||
default:
|
||||
throw new ServiceValidationException('Unexpected Feed type in call');
|
||||
}
|
||||
|
||||
return $this->findEntities($builder);
|
||||
}
|
||||
}
|
||||
|
@ -1,54 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Nextcloud - News
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Alessandro Cosentino <cosenal@gmail.com>
|
||||
* @author Bernhard Posselt <dev@bernhard-posselt.com>
|
||||
* @copyright 2012 Alessandro Cosentino
|
||||
* @copyright 2012-2014 Bernhard Posselt
|
||||
*/
|
||||
|
||||
namespace OCA\News\Db;
|
||||
|
||||
use OCA\News\Utility\Time;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
use OCA\News\Db\Mysql\ItemMapper as MysqlItemMapper;
|
||||
use OCA\News\DependencyInjection\IFactory;
|
||||
|
||||
/**
|
||||
* Class LegacyMapperFactory
|
||||
*
|
||||
* @package OCA\News\Db
|
||||
* @deprecated not needed in modern system
|
||||
*/
|
||||
class MapperFactory implements IFactory
|
||||
{
|
||||
|
||||
private $dbType;
|
||||
private $db;
|
||||
/**
|
||||
* @var Time
|
||||
*/
|
||||
private $time;
|
||||
|
||||
public function __construct(IDBConnection $db, $databaseType, Time $time)
|
||||
{
|
||||
$this->dbType = $databaseType;
|
||||
$this->db = $db;
|
||||
$this->time = $time;
|
||||
}
|
||||
|
||||
public function build()
|
||||
{
|
||||
switch ($this->dbType) {
|
||||
case 'mysql':
|
||||
return new MysqlItemMapper($this->db, $this->time);
|
||||
default:
|
||||
return new ItemMapper($this->db, $this->time);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,98 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Nextcloud - News
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Alessandro Cosentino <cosenal@gmail.com>
|
||||
* @author Bernhard Posselt <dev@bernhard-posselt.com>
|
||||
* @copyright 2012 Alessandro Cosentino
|
||||
* @copyright 2012-2014 Bernhard Posselt
|
||||
*/
|
||||
|
||||
namespace OCA\News\Db\Mysql;
|
||||
|
||||
use OCA\News\Utility\Time;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
/**
|
||||
* Class LegacyItemMapper
|
||||
*
|
||||
* @package OCA\News\Db\Mysql
|
||||
* @deprecated use normal ItemMapper
|
||||
*/
|
||||
class ItemMapper extends \OCA\News\Db\ItemMapper
|
||||
{
|
||||
|
||||
public function __construct(IDBConnection $db, Time $time)
|
||||
{
|
||||
parent::__construct($db, $time);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete all items for feeds that have over $threshold unread and not
|
||||
* starred items
|
||||
*
|
||||
* @param int $threshold the number of items that should be deleted
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function deleteReadOlderThanThreshold($threshold)
|
||||
{
|
||||
$sql = 'SELECT (COUNT(*) - `feeds`.`articles_per_update`) AS `size`, ' .
|
||||
'`feeds`.`id` AS `feed_id`, `feeds`.`articles_per_update` ' .
|
||||
'FROM `*PREFIX*news_items` `items` ' .
|
||||
'JOIN `*PREFIX*news_feeds` `feeds` ' .
|
||||
'ON `feeds`.`id` = `items`.`feed_id` ' .
|
||||
'AND `items`.`unread` = ? ' .
|
||||
'AND `items`.`starred` = ? ' .
|
||||
'GROUP BY `feeds`.`id`, `feeds`.`articles_per_update` ' .
|
||||
'HAVING COUNT(*) > ?';
|
||||
$params = [false, false, $threshold];
|
||||
$result = $this->execute($sql, $params);
|
||||
|
||||
while ($row = $result->fetch()) {
|
||||
$size = (int) $row['size'];
|
||||
$limit = $size - $threshold;
|
||||
|
||||
if ($limit > 0) {
|
||||
$params = [false, false, $row['feed_id'], $limit];
|
||||
|
||||
$sql = 'DELETE FROM `*PREFIX*news_items` ' .
|
||||
'WHERE `unread` = ? ' .
|
||||
'AND `starred` = ? ' .
|
||||
'AND `feed_id` = ? ' .
|
||||
'ORDER BY `id` ASC ' .
|
||||
'LIMIT ?';
|
||||
|
||||
$this->execute($sql, $params);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function readItem($itemId, $isRead, $lastModified, $userId)
|
||||
{
|
||||
$item = $this->find($itemId, $userId);
|
||||
|
||||
if ($isRead) {
|
||||
$sql = 'UPDATE `*PREFIX*news_items` `items`
|
||||
JOIN `*PREFIX*news_feeds` `feeds`
|
||||
ON `feeds`.`id` = `items`.`feed_id`
|
||||
SET `items`.`unread` = ?,
|
||||
`items`.`last_modified` = ?
|
||||
WHERE `items`.`fingerprint` = ?
|
||||
AND `feeds`.`user_id` = ?';
|
||||
$params = [false, $lastModified, $item->getFingerprint(), $userId];
|
||||
$this->execute($sql, $params);
|
||||
} else {
|
||||
$item->setLastModified($lastModified);
|
||||
$item->setUnread(true);
|
||||
$this->update($item);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Nextcloud - News
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Alessandro Cosentino <cosenal@gmail.com>
|
||||
* @author Bernhard Posselt <dev@bernhard-posselt.com>
|
||||
* @copyright 2012 Alessandro Cosentino
|
||||
* @copyright 2012-2014 Bernhard Posselt
|
||||
*/
|
||||
|
||||
namespace OCA\News\DependencyInjection;
|
||||
|
||||
interface IFactory
|
||||
{
|
||||
|
||||
/**
|
||||
* Method that constructs the object
|
||||
*
|
||||
* @return mixed the constructed object
|
||||
*/
|
||||
public function build();
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
* @copyright 2012-2014 Bernhard Posselt
|
||||
*/
|
||||
|
||||
namespace OCA\News\Explore;
|
||||
namespace OCA\News\Explore\Exceptions;
|
||||
|
||||
use Exception;
|
||||
|
@ -13,6 +13,8 @@
|
||||
|
||||
namespace OCA\News\Explore;
|
||||
|
||||
use OCA\News\Explore\Exceptions\RecommendedSiteNotFoundException;
|
||||
|
||||
class RecommendedSites
|
||||
{
|
||||
|
||||
|
@ -1,28 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Nextcloud - News
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Alessandro Cosentino <cosenal@gmail.com>
|
||||
* @author Bernhard Posselt <dev@bernhard-posselt.com>
|
||||
* @copyright 2012 Alessandro Cosentino
|
||||
* @copyright 2012-2014 Bernhard Posselt
|
||||
*/
|
||||
|
||||
namespace OCA\News\Fetcher;
|
||||
|
||||
class FetcherException extends \Exception
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $msg the error message
|
||||
*/
|
||||
public function __construct(string $msg)
|
||||
{
|
||||
parent::__construct($msg);
|
||||
}
|
||||
}
|
@ -13,16 +13,22 @@
|
||||
|
||||
namespace OCA\News\Service\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use OCP\AppFramework\Db\IMapperException;
|
||||
|
||||
/**
|
||||
* Class ServiceConflictException
|
||||
*
|
||||
* @package OCA\News\Service\Exceptions
|
||||
*/
|
||||
class ServiceConflictException extends ServiceException
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $msg the error message
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __construct(string $msg)
|
||||
public static function from(IMapperException $exception): ServiceException
|
||||
{
|
||||
parent::__construct($msg);
|
||||
return new self($exception->getMessage(), $exception->getCode(), $exception);
|
||||
}
|
||||
}
|
||||
|
@ -13,16 +13,35 @@
|
||||
|
||||
namespace OCA\News\Service\Exceptions;
|
||||
|
||||
class ServiceException extends \Exception
|
||||
use Exception;
|
||||
use OCP\AppFramework\Db\IMapperException;
|
||||
|
||||
/**
|
||||
* Class ServiceException
|
||||
*
|
||||
* @package OCA\News\Service\Exceptions
|
||||
*/
|
||||
abstract class ServiceException extends Exception
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $msg the error message
|
||||
* @param int $code
|
||||
* @param Exception|null $previous
|
||||
*/
|
||||
public function __construct(string $msg)
|
||||
final public function __construct(string $msg, int $code = 0, ?Exception $previous = null)
|
||||
{
|
||||
parent::__construct($msg);
|
||||
parent::__construct($msg, $code, $previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create exception from Mapper exception.
|
||||
*
|
||||
* @param IMapperException|Exception $exception Existing exception
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
abstract public static function from(IMapperException $exception): ServiceException;
|
||||
}
|
||||
|
@ -13,16 +13,21 @@
|
||||
|
||||
namespace OCA\News\Service\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use OCP\AppFramework\Db\IMapperException;
|
||||
|
||||
/**
|
||||
* Class ServiceNotFoundException
|
||||
*
|
||||
* @package OCA\News\Service\Exceptions
|
||||
*/
|
||||
class ServiceNotFoundException extends ServiceException
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $msg the error message
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __construct(string $msg)
|
||||
public static function from(IMapperException $exception): ServiceException
|
||||
{
|
||||
parent::__construct($msg);
|
||||
return new self($exception->getMessage(), $exception->getCode(), $exception);
|
||||
}
|
||||
}
|
||||
|
@ -13,16 +13,22 @@
|
||||
|
||||
namespace OCA\News\Service\Exceptions;
|
||||
|
||||
use Exception;
|
||||
use OCP\AppFramework\Db\IMapperException;
|
||||
|
||||
/**
|
||||
* Class ServiceValidationException
|
||||
*
|
||||
* @package OCA\News\Service\Exceptions
|
||||
*/
|
||||
class ServiceValidationException extends ServiceException
|
||||
{
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param string $msg the error message
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function __construct(string $msg)
|
||||
public static function from(IMapperException $exception): ServiceException
|
||||
{
|
||||
parent::__construct($msg);
|
||||
return new self($exception->getMessage(), $exception->getCode(), $exception);
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ use FeedIo\Reader\ReadErrorException;
|
||||
use HTMLPurifier;
|
||||
|
||||
use OCA\News\Db\FeedMapperV2;
|
||||
use OCA\News\Db\Folder;
|
||||
use OCA\News\Fetcher\FeedFetcher;
|
||||
use OCA\News\Service\Exceptions\ServiceConflictException;
|
||||
use OCA\News\Service\Exceptions\ServiceNotFoundException;
|
||||
@ -119,7 +120,7 @@ class FeedServiceV2 extends Service
|
||||
$feeds = $this->mapper->findAllFromUser($userId);
|
||||
|
||||
foreach ($feeds as &$feed) {
|
||||
$items = $this->itemService->findAllForFeed($feed->getId());
|
||||
$items = $this->itemService->findAllInFeed($userId, $feed->getId());
|
||||
$feed->items = $items;
|
||||
}
|
||||
return $feeds;
|
||||
@ -341,4 +342,21 @@ class FeedServiceV2 extends Service
|
||||
$this->fetch($feed);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a feed as read
|
||||
*
|
||||
* @param string $userId Feed owner
|
||||
* @param int $id Feed ID
|
||||
* @param int|null $maxItemID Highest item ID to mark as read
|
||||
*
|
||||
* @throws ServiceConflictException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function read(string $userId, int $id, ?int $maxItemID = null): void
|
||||
{
|
||||
$feed = $this->find($userId, $id);
|
||||
|
||||
$this->mapper->read($userId, $feed->getId(), $maxItemID);
|
||||
}
|
||||
}
|
||||
|
@ -178,4 +178,21 @@ class FolderServiceV2 extends Service
|
||||
$folder->setOpened($open);
|
||||
return $this->mapper->update($folder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark a folder as read
|
||||
*
|
||||
* @param string $userId Folder owner
|
||||
* @param int $id Folder ID
|
||||
* @param int|null $maxItemID Highest item ID to mark as read
|
||||
*
|
||||
* @throws ServiceConflictException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function read(string $userId, int $id, ?int $maxItemID = null): void
|
||||
{
|
||||
$folder = $this->find($userId, $id);
|
||||
|
||||
$this->mapper->read($userId, $folder->getId(), $maxItemID);
|
||||
}
|
||||
}
|
||||
|
@ -1,352 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Nextcloud - News
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Alessandro Cosentino <cosenal@gmail.com>
|
||||
* @author Bernhard Posselt <dev@bernhard-posselt.com>
|
||||
* @copyright 2012 Alessandro Cosentino
|
||||
* @copyright 2012-2014 Bernhard Posselt
|
||||
*/
|
||||
|
||||
namespace OCA\News\Service;
|
||||
|
||||
use OCA\News\AppInfo\Application;
|
||||
use OCA\News\Db\ItemMapperV2;
|
||||
use OCA\News\Service\Exceptions\ServiceNotFoundException;
|
||||
use OCP\IConfig;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
|
||||
use OCA\News\Db\ItemMapper;
|
||||
use OCA\News\Db\FeedType;
|
||||
use OCA\News\Utility\Time;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* Class LegacyItemService
|
||||
*
|
||||
* @package OCA\News\Service
|
||||
* @deprecated use ItemServiceV2
|
||||
*/
|
||||
class ItemService extends Service
|
||||
{
|
||||
|
||||
/**
|
||||
* @var IConfig
|
||||
*/
|
||||
private $config;
|
||||
/**
|
||||
* @var Time
|
||||
*/
|
||||
private $timeFactory;
|
||||
/**
|
||||
* @var ItemMapper
|
||||
*/
|
||||
private $oldItemMapper;
|
||||
|
||||
public function __construct(
|
||||
ItemMapperV2 $itemMapper,
|
||||
ItemMapper $oldItemMapper,
|
||||
Time $timeFactory,
|
||||
IConfig $config,
|
||||
LoggerInterface $logger
|
||||
) {
|
||||
parent::__construct($itemMapper, $logger);
|
||||
$this->config = $config;
|
||||
$this->timeFactory = $timeFactory;
|
||||
$this->oldItemMapper = $oldItemMapper;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns all new items
|
||||
*
|
||||
* @param int|null $id the id of the feed, 0 for starred or all items
|
||||
* @param int $type the type of the feed
|
||||
* @param int $updatedSince a timestamp with the last modification date
|
||||
* returns only items with a >= modified
|
||||
* timestamp
|
||||
* @param boolean $showAll if unread items should also be returned
|
||||
* @param string $userId the name of the user
|
||||
*
|
||||
* @return array of items
|
||||
*/
|
||||
public function findAllNew(?int $id, $type, int $updatedSince, bool $showAll, string $userId)
|
||||
{
|
||||
switch ($type) {
|
||||
case FeedType::FEED:
|
||||
return $this->oldItemMapper->findAllNewFeed(
|
||||
$id,
|
||||
$updatedSince,
|
||||
$showAll,
|
||||
$userId
|
||||
);
|
||||
case FeedType::FOLDER:
|
||||
return $this->oldItemMapper->findAllNewFolder(
|
||||
$id,
|
||||
$updatedSince,
|
||||
$showAll,
|
||||
$userId
|
||||
);
|
||||
default:
|
||||
return $this->oldItemMapper->findAllNew(
|
||||
$updatedSince,
|
||||
$type,
|
||||
$showAll,
|
||||
$userId
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns all items
|
||||
*
|
||||
* @param int|null $id the id of the feed, 0 for starred or all items
|
||||
* @param int $type the type of the feed
|
||||
* @param int $limit how many items should be returned
|
||||
* @param int $offset the offset
|
||||
* @param boolean $showAll if unread items should also be returned
|
||||
* @param boolean $oldestFirst if it should be ordered by oldest first
|
||||
* @param string $userId the name of the user
|
||||
* @param string[] $search an array of keywords that the result should
|
||||
* contain in either the author, title, link
|
||||
* or body
|
||||
*
|
||||
* @return array of items
|
||||
*/
|
||||
public function findAllItems(
|
||||
?int $id,
|
||||
$type,
|
||||
$limit,
|
||||
$offset,
|
||||
$showAll,
|
||||
$oldestFirst,
|
||||
$userId,
|
||||
$search = []
|
||||
) {
|
||||
switch ($type) {
|
||||
case FeedType::FEED:
|
||||
return $this->oldItemMapper->findAllFeed(
|
||||
$id,
|
||||
$limit,
|
||||
$offset,
|
||||
$showAll,
|
||||
$oldestFirst,
|
||||
$userId,
|
||||
$search
|
||||
);
|
||||
case FeedType::FOLDER:
|
||||
return $this->oldItemMapper->findAllFolder(
|
||||
$id,
|
||||
$limit,
|
||||
$offset,
|
||||
$showAll,
|
||||
$oldestFirst,
|
||||
$userId,
|
||||
$search
|
||||
);
|
||||
default:
|
||||
return $this->oldItemMapper->findAllItems(
|
||||
$limit,
|
||||
$offset,
|
||||
$type,
|
||||
$showAll,
|
||||
$oldestFirst,
|
||||
$userId,
|
||||
$search
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public function findAllForUser(string $userId, array $params = []): array
|
||||
{
|
||||
return $this->mapper->findAllFromUser($userId, $params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Star or unstar an item
|
||||
*
|
||||
* @param int $feedId the id of the item's feed that should be starred
|
||||
* @param string $guidHash the guidHash of the item that should be starred
|
||||
* @param boolean $isStarred if true the item will be marked as starred,
|
||||
* if false unstar
|
||||
* @param string $userId the name of the user for security reasons
|
||||
*
|
||||
* @throws ServiceNotFoundException if the item does not exist
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function star($feedId, $guidHash, $isStarred, $userId): void
|
||||
{
|
||||
try {
|
||||
$item = $this->mapper->findByGuidHash($feedId, $guidHash);
|
||||
|
||||
$item->setStarred($isStarred);
|
||||
|
||||
$this->mapper->update($item);
|
||||
} catch (DoesNotExistException $ex) {
|
||||
throw new ServiceNotFoundException($ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read or unread an item
|
||||
*
|
||||
* @param int $itemId the id of the item that should be read
|
||||
* @param boolean $isRead if true the item will be marked as read,
|
||||
* if false unread
|
||||
* @param string $userId the name of the user for security reasons
|
||||
*
|
||||
* @throws ServiceNotFoundException if the item does not exist
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function read($itemId, $isRead, $userId): void
|
||||
{
|
||||
try {
|
||||
$lastModified = $this->timeFactory->getMicroTime();
|
||||
$this->oldItemMapper->readItem($itemId, $isRead, $lastModified, $userId);
|
||||
} catch (DoesNotExistException $ex) {
|
||||
throw new ServiceNotFoundException($ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set all items read
|
||||
*
|
||||
* @param int $highestItemId all items below that are marked read. This is
|
||||
* used to prevent marking items as read that
|
||||
* the users hasn't seen yet
|
||||
* @param string $userId the name of the user
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function readAll($highestItemId, $userId): void
|
||||
{
|
||||
$time = $this->timeFactory->getMicroTime();
|
||||
$this->oldItemMapper->readAll($highestItemId, $time, $userId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a folder read
|
||||
*
|
||||
* @param int|null $folderId the id of the folder that should be marked read
|
||||
* @param int $highestItemId all items below that are marked read. This is
|
||||
* used to prevent marking items as read that
|
||||
* the users hasn't seen yet
|
||||
* @param string $userId the name of the user
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function readFolder(?int $folderId, $highestItemId, $userId): void
|
||||
{
|
||||
$time = $this->timeFactory->getMicroTime();
|
||||
$this->oldItemMapper->readFolder(
|
||||
$folderId,
|
||||
$highestItemId,
|
||||
$time,
|
||||
$userId
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a feed read
|
||||
*
|
||||
* @param int $feedId the id of the feed that should be marked read
|
||||
* @param int $highestItemId all items below that are marked read. This is
|
||||
* used to prevent marking items as read that
|
||||
* the users hasn't seen yet
|
||||
* @param string $userId the name of the user
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function readFeed($feedId, $highestItemId, $userId): void
|
||||
{
|
||||
$time = $this->timeFactory->getMicroTime();
|
||||
$this->oldItemMapper->readFeed($feedId, $highestItemId, $time, $userId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method deletes all unread feeds that are not starred and over the
|
||||
* count of $this->autoPurgeCount starting by the oldest. This is to clean
|
||||
* up the database so that old entries don't spam your db. As criteria for
|
||||
* old, the id is taken
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function autoPurgeOld(): void
|
||||
{
|
||||
$count = $this->config->getAppValue(
|
||||
Application::NAME,
|
||||
'autoPurgeCount',
|
||||
Application::DEFAULT_SETTINGS['autoPurgeCount']
|
||||
);
|
||||
if ($count >= 0) {
|
||||
$this->oldItemMapper->deleteReadOlderThanThreshold($count);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the newest item id, use this for marking feeds read
|
||||
*
|
||||
* @param string $userId the name of the user
|
||||
* @throws ServiceNotFoundException if there is no newest item
|
||||
* @return int
|
||||
*/
|
||||
public function getNewestItemId($userId)
|
||||
{
|
||||
try {
|
||||
return $this->oldItemMapper->getNewestItemId($userId);
|
||||
} catch (DoesNotExistException $ex) {
|
||||
throw new ServiceNotFoundException($ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the starred count
|
||||
*
|
||||
* @param string $userId the name of the user
|
||||
* @return int the count
|
||||
*/
|
||||
public function starredCount($userId)
|
||||
{
|
||||
return $this->oldItemMapper->starredCount($userId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $userId from which user the items should be taken
|
||||
* @return array of items which are starred or unread
|
||||
*/
|
||||
public function getUnreadOrStarred($userId): array
|
||||
{
|
||||
return $this->oldItemMapper->findAllUnreadOrStarred($userId);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Regenerates the search index for all items
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function generateSearchIndices(): void
|
||||
{
|
||||
$this->oldItemMapper->updateSearchIndices();
|
||||
}
|
||||
|
||||
public function findAll(): array
|
||||
{
|
||||
return $this->mapper->findAll();
|
||||
}
|
||||
}
|
@ -13,10 +13,16 @@
|
||||
namespace OCA\News\Service;
|
||||
|
||||
use OCA\News\AppInfo\Application;
|
||||
use OCA\News\Db\Feed;
|
||||
use OCA\News\Db\FeedType;
|
||||
use OCA\News\Db\Item;
|
||||
use OCA\News\Db\ItemMapperV2;
|
||||
use OCA\News\Service\Exceptions\ServiceConflictException;
|
||||
use OCA\News\Service\Exceptions\ServiceNotFoundException;
|
||||
use OCA\News\Service\Exceptions\ServiceValidationException;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
use OCP\IConfig;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
@ -37,7 +43,7 @@ class ItemServiceV2 extends Service
|
||||
* ItemService constructor.
|
||||
*
|
||||
* @param ItemMapperV2 $mapper
|
||||
* @param IConfig $config
|
||||
* @param IConfig $config
|
||||
* @param LoggerInterface $logger
|
||||
*/
|
||||
public function __construct(
|
||||
@ -53,7 +59,7 @@ class ItemServiceV2 extends Service
|
||||
* Finds all items of a user
|
||||
*
|
||||
* @param string $userId The ID/name of the user
|
||||
* @param array $params Filter parameters
|
||||
* @param array $params Filter parameters
|
||||
*
|
||||
*
|
||||
* @return Item[]
|
||||
@ -83,14 +89,15 @@ class ItemServiceV2 extends Service
|
||||
public function insertOrUpdate(Item $item): Entity
|
||||
{
|
||||
try {
|
||||
$db_item = $this->mapper->findByGuidHash($item->getFeedId(), $item->getGuidHash());
|
||||
$db_item = $this->findByGuidHash($item->getFeedId(), $item->getGuidHash());
|
||||
|
||||
// Transfer user modifications
|
||||
$item->setUnread($db_item->isUnread())
|
||||
->setStarred($db_item->isStarred())
|
||||
->setId($db_item->getId());
|
||||
|
||||
$item->generateSearchIndex();
|
||||
$item->generateSearchIndex();//generates fingerprint
|
||||
|
||||
// We don't want to update the database record if there is no
|
||||
// change in the fetched item
|
||||
if ($db_item->getFingerprint() === $item->getFingerprint()) {
|
||||
@ -104,13 +111,36 @@ class ItemServiceV2 extends Service
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $feedId
|
||||
* Return all starred items
|
||||
*
|
||||
* @return array
|
||||
* @param string $userId
|
||||
*
|
||||
* @return Item[]
|
||||
*/
|
||||
public function findAllForFeed(int $feedId): array
|
||||
public function starred(string $userId): array
|
||||
{
|
||||
return $this->mapper->findAllForFeed($feedId);
|
||||
return $this->findAllForUser($userId, ['starred' => 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark an item as read
|
||||
*
|
||||
* @param string $userId Item owner
|
||||
* @param int $id Item ID
|
||||
* @param bool $read
|
||||
*
|
||||
* @return Item
|
||||
* @throws ServiceNotFoundException
|
||||
* @throws ServiceConflictException
|
||||
*/
|
||||
public function read(string $userId, int $id, bool $read): Entity
|
||||
{
|
||||
/** @var Item $item */
|
||||
$item = $this->find($userId, $id);
|
||||
|
||||
$item->setUnread(!$read);
|
||||
|
||||
return $this->mapper->update($item);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -133,13 +163,232 @@ class ItemServiceV2 extends Service
|
||||
|
||||
return $this->mapper->deleteOverThreshold($threshold, $removeUnread);
|
||||
}
|
||||
/**
|
||||
* Mark an item as starred
|
||||
*
|
||||
* @param string $userId Item owner
|
||||
* @param int $id Item ID
|
||||
* @param bool $starred
|
||||
*
|
||||
* @return Item
|
||||
* @throws ServiceNotFoundException|ServiceConflictException
|
||||
*/
|
||||
public function star(string $userId, int $id, bool $starred): Entity
|
||||
{
|
||||
/** @var Item $item */
|
||||
$item = $this->find($userId, $id);
|
||||
|
||||
$item->setStarred($starred);
|
||||
|
||||
return $this->mapper->update($item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark an item as starred by GUID hash
|
||||
*
|
||||
* @param string $userId Item owner
|
||||
* @param int $feedId Item ID
|
||||
* @param string $guidHash
|
||||
* @param bool $starred
|
||||
*
|
||||
* @return Item
|
||||
* @throws ServiceConflictException
|
||||
* @throws ServiceNotFoundException
|
||||
*/
|
||||
public function starByGuid(string $userId, int $feedId, string $guidHash, bool $starred): Entity
|
||||
{
|
||||
try {
|
||||
$item = $this->mapper->findForUserByGuidHash($userId, $feedId, $guidHash);
|
||||
} catch (DoesNotExistException $ex) {
|
||||
throw ServiceNotFoundException::from($ex);
|
||||
} catch (MultipleObjectsReturnedException $ex) {
|
||||
throw ServiceConflictException::from($ex);
|
||||
}
|
||||
|
||||
$item->setStarred($starred);
|
||||
|
||||
return $this->mapper->update($item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark all items as read
|
||||
*
|
||||
* @param string $userId Item owner
|
||||
* @param int $maxItemId
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function readAll(string $userId, int $maxItemId): void
|
||||
{
|
||||
$this->mapper->readAll($userId, $maxItemId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $userId
|
||||
*
|
||||
* @return Item
|
||||
*/
|
||||
public function newest(string $userId): Entity
|
||||
{
|
||||
try {
|
||||
return $this->mapper->newest($userId);
|
||||
} catch (DoesNotExistException $e) {
|
||||
throw ServiceNotFoundException::from($e);
|
||||
} catch (MultipleObjectsReturnedException $e) {
|
||||
throw ServiceConflictException::from($e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $feedId
|
||||
* @param string $guidHash
|
||||
*
|
||||
* @return Item|Entity
|
||||
*
|
||||
* @throws DoesNotExistException
|
||||
* @throws MultipleObjectsReturnedException
|
||||
*/
|
||||
public function findForGuidHash(int $feedId, string $guidHash)
|
||||
public function findByGuidHash(int $feedId, string $guidHash): Entity
|
||||
{
|
||||
return $this->mapper->findByGuidHash($feedId, $guidHash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convenience method to find all items in a feed.
|
||||
*
|
||||
* @param string $userId
|
||||
* @param int $feedId
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function findAllInFeed(string $userId, int $feedId): array
|
||||
{
|
||||
return $this->findAllInFeedAfter($userId, $feedId, PHP_INT_MIN, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all new items in a feed
|
||||
* @param string $userId the name of the user
|
||||
* @param int $feedId the id of the feed
|
||||
* @param int $updatedSince a timestamp with the minimal modification date
|
||||
* @param boolean $hideRead if unread items should also be returned
|
||||
*
|
||||
* @return array of items
|
||||
*/
|
||||
public function findAllInFeedAfter(string $userId, int $feedId, int $updatedSince, bool $hideRead): array
|
||||
{
|
||||
return $this->mapper->findAllInFeedAfter($userId, $feedId, $updatedSince, $hideRead);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all new items in a folder
|
||||
* @param string $userId the name of the user
|
||||
* @param int|null $folderId the id of the folder
|
||||
* @param int $updatedSince a timestamp with the minimal modification date
|
||||
* @param boolean $hideRead if unread items should also be returned
|
||||
*
|
||||
* @return array of items
|
||||
*/
|
||||
public function findAllInFolderAfter(string $userId, ?int $folderId, int $updatedSince, bool $hideRead): array
|
||||
{
|
||||
return $this->mapper->findAllInFolderAfter($userId, $folderId, $updatedSince, $hideRead);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all new items of a type
|
||||
*
|
||||
* @param string $userId the name of the user
|
||||
* @param int $feedType the type of feed items to fetch. (starred || unread)
|
||||
* @param int $updatedSince a timestamp with the minimal modification date
|
||||
*
|
||||
* @return array of items
|
||||
*
|
||||
* @throws ServiceValidationException
|
||||
*/
|
||||
public function findAllAfter(string $userId, int $feedType, int $updatedSince): array
|
||||
{
|
||||
if (!in_array($feedType, [FeedType::STARRED, FeedType::UNREAD])) {
|
||||
throw new ServiceValidationException('Trying to find in unknown type');
|
||||
}
|
||||
|
||||
return $this->mapper->findAllAfter($userId, $feedType, $updatedSince);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns all items
|
||||
*
|
||||
* @param int $feedId the id of the feed
|
||||
* @param int $limit how many items should be returned
|
||||
* @param int $offset the offset
|
||||
* @param boolean $hideRead if unread items should also be returned
|
||||
* @param boolean $oldestFirst if it should be ordered by oldest first
|
||||
* @param string $userId the name of the user
|
||||
* @param string[] $search an array of keywords that the result should
|
||||
* contain in either the author, title, link
|
||||
* or body
|
||||
*
|
||||
* @return array of items
|
||||
*/
|
||||
public function findAllInFeedWithFilters(
|
||||
string $userId,
|
||||
int $feedId,
|
||||
int $limit,
|
||||
int $offset,
|
||||
bool $hideRead,
|
||||
bool $oldestFirst,
|
||||
array $search = []
|
||||
): array {
|
||||
return $this->mapper->findAllFeed($userId, $feedId, $limit, $offset, $hideRead, $oldestFirst, $search);
|
||||
}
|
||||
/**
|
||||
* Returns all items
|
||||
*
|
||||
* @param int|null $folderId the id of the folder
|
||||
* @param int $limit how many items should be returned
|
||||
* @param int $offset the offset
|
||||
* @param boolean $hideRead if unread items should also be returned
|
||||
* @param boolean $oldestFirst if it should be ordered by oldest first
|
||||
* @param string $userId the name of the user
|
||||
* @param string[] $search an array of keywords that the result should
|
||||
* contain in either the author, title, link
|
||||
* or body
|
||||
*
|
||||
* @return array of items
|
||||
*/
|
||||
public function findAllInFolderWithFilters(
|
||||
string $userId,
|
||||
?int $folderId,
|
||||
int $limit,
|
||||
int $offset,
|
||||
bool $hideRead,
|
||||
bool $oldestFirst,
|
||||
array $search = []
|
||||
): array {
|
||||
return $this->mapper->findAllFolder($userId, $folderId, $limit, $offset, $hideRead, $oldestFirst, $search);
|
||||
}
|
||||
/**
|
||||
* Returns all items
|
||||
*
|
||||
* @param int $type the type of the feed
|
||||
* @param int $limit how many items should be returned
|
||||
* @param int $offset the offset
|
||||
* @param boolean $oldestFirst if it should be ordered by oldest first
|
||||
* @param string $userId the name of the user
|
||||
* @param string[] $search an array of keywords that the result should
|
||||
* contain in either the author, title, link
|
||||
* or body
|
||||
*
|
||||
* @return array of items
|
||||
*/
|
||||
public function findAllWithFilters(
|
||||
string $userId,
|
||||
int $type,
|
||||
int $limit,
|
||||
int $offset,
|
||||
bool $oldestFirst,
|
||||
array $search = []
|
||||
): array {
|
||||
return $this->mapper->findAllItems($userId, $type, $limit, $offset, $oldestFirst, $search);
|
||||
}
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
namespace OCA\News\Service;
|
||||
|
||||
use OCA\News\Db\NewsMapperV2;
|
||||
use OCA\News\Service\Exceptions\ServiceConflictException;
|
||||
use OCA\News\Service\Exceptions\ServiceNotFoundException;
|
||||
use OCP\AppFramework\Db\DoesNotExistException;
|
||||
use OCP\AppFramework\Db\Entity;
|
||||
@ -65,14 +66,13 @@ abstract class Service
|
||||
*/
|
||||
abstract public function findAll(): array;
|
||||
|
||||
|
||||
/**
|
||||
* Delete an entity
|
||||
*
|
||||
* @param int $id the id of the entity
|
||||
* @param string $userId the name of the user for security reasons
|
||||
*
|
||||
* @throws ServiceNotFoundException if the entity does not exist, or there
|
||||
* @throws ServiceNotFoundException|ServiceConflictException if the entity does not exist, or there
|
||||
* are more than one of it
|
||||
*/
|
||||
public function delete(string $userId, int $id): Entity
|
||||
@ -102,7 +102,7 @@ abstract class Service
|
||||
* @param string $userId the name of the user for security reasons
|
||||
* @param Entity $entity the entity
|
||||
*
|
||||
* @throws ServiceNotFoundException if the entity does not exist, or there
|
||||
* @throws ServiceNotFoundException|ServiceConflictException if the entity does not exist, or there
|
||||
* are more than one of it
|
||||
*/
|
||||
public function update(string $userId, Entity $entity): Entity
|
||||
@ -119,7 +119,7 @@ abstract class Service
|
||||
* @param string $userId the name of the user for security reasons
|
||||
*
|
||||
* @return Entity the entity
|
||||
* @throws ServiceNotFoundException if the entity does not exist, or there
|
||||
* @throws ServiceNotFoundException|ServiceConflictException if the entity does not exist, or there
|
||||
* are more than one of it
|
||||
*/
|
||||
public function find(string $userId, int $id): Entity
|
||||
@ -127,9 +127,9 @@ abstract class Service
|
||||
try {
|
||||
return $this->mapper->findFromUser($userId, $id);
|
||||
} catch (DoesNotExistException $ex) {
|
||||
throw new ServiceNotFoundException($ex->getMessage());
|
||||
throw ServiceNotFoundException::from($ex);
|
||||
} catch (MultipleObjectsReturnedException $ex) {
|
||||
throw new ServiceNotFoundException($ex->getMessage());
|
||||
throw ServiceConflictException::from($ex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
<directory>./tests/Unit</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
|
||||
<coverage processUncoveredFiles="true">
|
||||
<include>
|
||||
<directory suffix=".php">./lib/</directory>
|
||||
@ -13,7 +14,10 @@
|
||||
<exclude>
|
||||
<file>./lib/AppInfo/Application.php</file>
|
||||
<file>./lib/Controller/JSONHttpErrorTrait.php</file>
|
||||
<file>./lib/**Exception.php</file>
|
||||
<directory suffix=".php">./lib/*/Exceptions</directory>
|
||||
<directory suffix=".php">./lib/Migration</directory>
|
||||
<file>./lib/Db/FeedType.php</file>
|
||||
<file>./lib/Db/IAPI.php</file>
|
||||
</exclude>
|
||||
<report>
|
||||
<clover outputFile="./build/coverage.xml"/>
|
||||
|
@ -82,7 +82,7 @@ class FolderDeleteTest extends TestCase
|
||||
*/
|
||||
public function testInValid()
|
||||
{
|
||||
$this->expectException('OCA\News\Service\Exceptions\ServiceException');
|
||||
$this->expectException('OCA\News\Service\Exceptions\ServiceValidationException');
|
||||
$this->expectExceptionMessage('Can not remove root folder!');
|
||||
|
||||
$this->consoleInput->expects($this->exactly(2))
|
||||
|
@ -18,7 +18,7 @@ namespace OCA\News\Tests\Unit\Controller;
|
||||
use Exception;
|
||||
use OCA\News\Controller\FeedApiController;
|
||||
use OCA\News\Service\FeedServiceV2;
|
||||
use OCA\News\Service\ItemService;
|
||||
use OCA\News\Service\ItemServiceV2;
|
||||
use \OCP\AppFramework\Http;
|
||||
|
||||
use \OCA\News\Service\Exceptions\ServiceNotFoundException;
|
||||
@ -40,7 +40,7 @@ class FeedApiControllerTest extends TestCase
|
||||
private $feedService;
|
||||
|
||||
/**
|
||||
* @var \PHPUnit\Framework\MockObject\MockObject|ItemService
|
||||
* @var \PHPUnit\Framework\MockObject\MockObject|ItemServiceV2
|
||||
*/
|
||||
private $itemService;
|
||||
|
||||
@ -80,7 +80,7 @@ class FeedApiControllerTest extends TestCase
|
||||
$this->feedService = $this->getMockBuilder(FeedServiceV2::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->itemService = $this->getMockBuilder(ItemService::class)
|
||||
$this->itemService = $this->getMockBuilder(ItemServiceV2::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->class = new FeedApiController(
|
||||
@ -96,18 +96,17 @@ class FeedApiControllerTest extends TestCase
|
||||
|
||||
public function testIndex()
|
||||
{
|
||||
$feeds = [new Feed()];
|
||||
$starredCount = 3;
|
||||
$newestItemId = 2;
|
||||
$feed = Feed::fromParams(['id' => 5]);
|
||||
$feeds = [$feed];
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starredCount')
|
||||
->method('starred')
|
||||
->with($this->equalTo($this->userID))
|
||||
->will($this->returnValue($starredCount));
|
||||
->will($this->returnValue([1, 2, 3]));
|
||||
$this->itemService->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
->method('newest')
|
||||
->with($this->equalTo($this->userID))
|
||||
->will($this->returnValue($newestItemId));
|
||||
->will($this->returnValue($feeds[0]));
|
||||
$this->feedService->expects($this->once())
|
||||
->method('findAllForUser')
|
||||
->with($this->equalTo($this->userID))
|
||||
@ -118,8 +117,8 @@ class FeedApiControllerTest extends TestCase
|
||||
$this->assertEquals(
|
||||
[
|
||||
'feeds' => [$feeds[0]->toAPI()],
|
||||
'starredCount' => $starredCount,
|
||||
'newestItemId' => $newestItemId
|
||||
'starredCount' => 3,
|
||||
'newestItemId' => 5
|
||||
],
|
||||
$response
|
||||
);
|
||||
@ -129,14 +128,13 @@ class FeedApiControllerTest extends TestCase
|
||||
public function testIndexNoNewestItemId()
|
||||
{
|
||||
$feeds = [new Feed()];
|
||||
$starredCount = 3;
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starredCount')
|
||||
->method('starred')
|
||||
->with($this->equalTo($this->userID))
|
||||
->will($this->returnValue($starredCount));
|
||||
->will($this->returnValue([1, 2, 3]));
|
||||
$this->itemService->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
->method('newest')
|
||||
->with($this->equalTo($this->userID))
|
||||
->will($this->throwException(new ServiceNotFoundException('')));
|
||||
$this->feedService->expects($this->once())
|
||||
@ -149,7 +147,7 @@ class FeedApiControllerTest extends TestCase
|
||||
$this->assertEquals(
|
||||
[
|
||||
'feeds' => [$feeds[0]->toAPI()],
|
||||
'starredCount' => $starredCount,
|
||||
'starredCount' => 3,
|
||||
],
|
||||
$response
|
||||
);
|
||||
@ -203,8 +201,8 @@ class FeedApiControllerTest extends TestCase
|
||||
->method('fetch')
|
||||
->with($feeds[0]);
|
||||
$this->itemService->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
->will($this->returnValue(3));
|
||||
->method('newest')
|
||||
->will($this->returnValue(Feed::fromParams(['id' => 3])));
|
||||
|
||||
$response = $this->class->create('url', 3);
|
||||
|
||||
@ -234,7 +232,7 @@ class FeedApiControllerTest extends TestCase
|
||||
->method('fetch')
|
||||
->with($feeds[0]);
|
||||
$this->itemService->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
->method('newest')
|
||||
->will($this->throwException(new ServiceNotFoundException('')));
|
||||
|
||||
$response = $this->class->create('ho', 3);
|
||||
@ -287,12 +285,8 @@ class FeedApiControllerTest extends TestCase
|
||||
public function testRead()
|
||||
{
|
||||
$this->itemService->expects($this->once())
|
||||
->method('readFeed')
|
||||
->with(
|
||||
$this->equalTo(3),
|
||||
$this->equalTo(30),
|
||||
$this->equalTo($this->userID)
|
||||
);
|
||||
->method('read')
|
||||
->with($this->userID,3,30);
|
||||
|
||||
$this->class->read(3, 30);
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ use OCA\News\Db\Folder;
|
||||
use OCA\News\Service\FeedServiceV2;
|
||||
use OCA\News\Service\FolderServiceV2;
|
||||
use OCA\News\Service\ImportService;
|
||||
use OCA\News\Service\ItemService;
|
||||
use OCA\News\Service\ItemServiceV2;
|
||||
use OCP\AppFramework\Http;
|
||||
|
||||
use OCA\News\Db\Feed;
|
||||
@ -55,8 +55,7 @@ class FeedControllerTest extends TestCase
|
||||
*/
|
||||
private $importService;
|
||||
/**
|
||||
* TODO: Remove
|
||||
* @var MockObject|ItemService
|
||||
* @var MockObject|ItemServiceV2
|
||||
*/
|
||||
private $itemService;
|
||||
|
||||
@ -87,7 +86,7 @@ class FeedControllerTest extends TestCase
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->itemService = $this
|
||||
->getMockBuilder(ItemService::class)
|
||||
->getMockBuilder(ItemServiceV2::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->feedService = $this
|
||||
@ -138,20 +137,20 @@ class FeedControllerTest extends TestCase
|
||||
'feeds' => [
|
||||
['a feed'],
|
||||
],
|
||||
'starred' => 13
|
||||
'starred' => 4
|
||||
];
|
||||
$this->feedService->expects($this->once())
|
||||
->method('findAllForUser')
|
||||
->with($this->uid)
|
||||
->will($this->returnValue($result['feeds']));
|
||||
$this->itemService->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
->method('newest')
|
||||
->with($this->uid)
|
||||
->will($this->throwException(new ServiceNotFoundException('')));
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starredCount')
|
||||
->method('starred')
|
||||
->with($this->uid)
|
||||
->will($this->returnValue($result['starred']));
|
||||
->will($this->returnValue([1, 2, 3, 4]));
|
||||
|
||||
$response = $this->class->index();
|
||||
|
||||
@ -165,7 +164,7 @@ class FeedControllerTest extends TestCase
|
||||
'feeds' => [
|
||||
['a feed'],
|
||||
],
|
||||
'starred' => 13,
|
||||
'starred' => 2,
|
||||
'newestItemId' => 5
|
||||
];
|
||||
$this->feedService->expects($this->once())
|
||||
@ -173,13 +172,13 @@ class FeedControllerTest extends TestCase
|
||||
->with($this->uid)
|
||||
->will($this->returnValue($result['feeds']));
|
||||
$this->itemService->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
->method('newest')
|
||||
->with($this->uid)
|
||||
->will($this->returnValue($result['newestItemId']));
|
||||
->will($this->returnValue(Feed::fromParams(['id' => 5])));
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starredCount')
|
||||
->method('starred')
|
||||
->with($this->uid)
|
||||
->will($this->returnValue($result['starred']));
|
||||
->will($this->returnValue([1, 2]));
|
||||
|
||||
$response = $this->class->index();
|
||||
|
||||
@ -224,6 +223,30 @@ class FeedControllerTest extends TestCase
|
||||
}
|
||||
|
||||
|
||||
public function testActiveFeed()
|
||||
{
|
||||
$id = 3;
|
||||
$type = FeedType::FEED;
|
||||
$result = [
|
||||
'activeFeed' => [
|
||||
'id' => $id,
|
||||
'type' => $type
|
||||
]
|
||||
];
|
||||
|
||||
$this->feedService->expects($this->once())
|
||||
->method('find')
|
||||
->with($this->uid, $id)
|
||||
->will($this->returnValue(new Feed()));
|
||||
|
||||
$this->activeInitMocks($id, $type);
|
||||
|
||||
$response = $this->class->active();
|
||||
|
||||
$this->assertEquals($result, $response);
|
||||
}
|
||||
|
||||
|
||||
public function testActiveFeedDoesNotExist()
|
||||
{
|
||||
$id = 3;
|
||||
@ -313,8 +336,8 @@ class FeedControllerTest extends TestCase
|
||||
];
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
->will($this->returnValue($result['newestItemId']));
|
||||
->method('newest')
|
||||
->will($this->returnValue(Feed::fromParams(['id' => 3])));
|
||||
$this->feedService->expects($this->once())
|
||||
->method('purgeDeleted')
|
||||
->with($this->uid, false);
|
||||
@ -341,8 +364,8 @@ class FeedControllerTest extends TestCase
|
||||
];
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
->will($this->returnValue($result['newestItemId']));
|
||||
->method('newest')
|
||||
->will($this->returnValue(Feed::fromParams(['id' => 3])));
|
||||
$this->feedService->expects($this->once())
|
||||
->method('purgeDeleted')
|
||||
->with($this->uid, false);
|
||||
@ -370,7 +393,7 @@ class FeedControllerTest extends TestCase
|
||||
->with($this->uid, false);
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
->method('newest')
|
||||
->will($this->throwException(new ServiceNotFoundException('')));
|
||||
|
||||
$this->feedService->expects($this->once())
|
||||
@ -522,9 +545,9 @@ class FeedControllerTest extends TestCase
|
||||
->will($this->returnValue($feed));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starredCount')
|
||||
->method('starred')
|
||||
->with($this->uid)
|
||||
->will($this->returnValue(3));
|
||||
->will($this->returnValue([1, 2, 3]));
|
||||
|
||||
$response = $this->class->import(['json']);
|
||||
|
||||
@ -540,9 +563,9 @@ class FeedControllerTest extends TestCase
|
||||
->will($this->returnValue(null));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starredCount')
|
||||
->method('starred')
|
||||
->with($this->uid)
|
||||
->will($this->returnValue(3));
|
||||
->will($this->returnValue([1, 2, 3]));
|
||||
|
||||
$response = $this->class->import(['json']);
|
||||
|
||||
@ -561,9 +584,9 @@ class FeedControllerTest extends TestCase
|
||||
]
|
||||
];
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('readFeed')
|
||||
->with(4, 5, $this->uid);
|
||||
$this->feedService->expects($this->once())
|
||||
->method('read')
|
||||
->with($this->uid, 4, 5);
|
||||
|
||||
$response = $this->class->read(4, 5);
|
||||
$this->assertEquals($expected, $response);
|
||||
|
@ -37,7 +37,7 @@ class FolderApiControllerTest extends TestCase
|
||||
|
||||
private $folderService;
|
||||
private $itemService;
|
||||
private $folderAPI;
|
||||
private $class;
|
||||
private $user;
|
||||
private $msg;
|
||||
|
||||
@ -65,7 +65,7 @@ class FolderApiControllerTest extends TestCase
|
||||
$this->itemService = $this->getMockBuilder(ItemService::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->folderAPI = new FolderApiController(
|
||||
$this->class = new FolderApiController(
|
||||
$request,
|
||||
$userSession,
|
||||
$this->folderService,
|
||||
@ -84,7 +84,7 @@ class FolderApiControllerTest extends TestCase
|
||||
->with($this->equalTo($this->user->getUID()))
|
||||
->will($this->returnValue($folders));
|
||||
|
||||
$response = $this->folderAPI->index();
|
||||
$response = $this->class->index();
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
@ -108,7 +108,7 @@ class FolderApiControllerTest extends TestCase
|
||||
->with($this->user->getUID(), $folderName)
|
||||
->will($this->returnValue($folder));
|
||||
|
||||
$response = $this->folderAPI->create($folderName);
|
||||
$response = $this->class->create($folderName);
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
@ -129,7 +129,7 @@ class FolderApiControllerTest extends TestCase
|
||||
->method('create')
|
||||
->will($this->throwException(new ServiceConflictException($msg)));
|
||||
|
||||
$response = $this->folderAPI->create('hi');
|
||||
$response = $this->class->create('hi');
|
||||
|
||||
$data = $response->getData();
|
||||
$this->assertEquals($msg, $data['message']);
|
||||
@ -148,7 +148,7 @@ class FolderApiControllerTest extends TestCase
|
||||
->method('create')
|
||||
->will($this->throwException(new ServiceValidationException($msg)));
|
||||
|
||||
$response = $this->folderAPI->create('hi');
|
||||
$response = $this->class->create('hi');
|
||||
|
||||
$data = $response->getData();
|
||||
$this->assertEquals($msg, $data['message']);
|
||||
@ -164,7 +164,7 @@ class FolderApiControllerTest extends TestCase
|
||||
->method('delete')
|
||||
->with($this->user->getUID(), 23);
|
||||
|
||||
$this->folderAPI->delete(23);
|
||||
$this->class->delete(23);
|
||||
}
|
||||
|
||||
|
||||
@ -180,7 +180,7 @@ class FolderApiControllerTest extends TestCase
|
||||
)
|
||||
);
|
||||
|
||||
$response = $this->folderAPI->delete($folderId);
|
||||
$response = $this->class->delete($folderId);
|
||||
|
||||
$data = $response->getData();
|
||||
$this->assertEquals($this->msg, $data['message']);
|
||||
@ -197,7 +197,7 @@ class FolderApiControllerTest extends TestCase
|
||||
->method('rename')
|
||||
->with($this->user->getUID(), $folderId, $folderName);
|
||||
|
||||
$this->folderAPI->update($folderId, $folderName);
|
||||
$this->class->update($folderId, $folderName);
|
||||
}
|
||||
|
||||
public function testUpdateDoesNotExist()
|
||||
@ -213,7 +213,7 @@ class FolderApiControllerTest extends TestCase
|
||||
)
|
||||
);
|
||||
|
||||
$response = $this->folderAPI->update($folderId, $folderName);
|
||||
$response = $this->class->update($folderId, $folderName);
|
||||
|
||||
$data = $response->getData();
|
||||
$this->assertEquals($this->msg, $data['message']);
|
||||
@ -234,7 +234,7 @@ class FolderApiControllerTest extends TestCase
|
||||
)
|
||||
);
|
||||
|
||||
$response = $this->folderAPI->update($folderId, $folderName);
|
||||
$response = $this->class->update($folderId, $folderName);
|
||||
|
||||
$data = $response->getData();
|
||||
$this->assertEquals($this->msg, $data['message']);
|
||||
@ -255,7 +255,7 @@ class FolderApiControllerTest extends TestCase
|
||||
)
|
||||
);
|
||||
|
||||
$response = $this->folderAPI->update($folderId, $folderName);
|
||||
$response = $this->class->update($folderId, $folderName);
|
||||
|
||||
$data = $response->getData();
|
||||
$this->assertEquals($this->msg, $data['message']);
|
||||
@ -267,15 +267,25 @@ class FolderApiControllerTest extends TestCase
|
||||
|
||||
public function testRead()
|
||||
{
|
||||
$this->itemService->expects($this->once())
|
||||
->method('readFolder')
|
||||
->with(
|
||||
$this->equalTo(3),
|
||||
$this->equalTo(30),
|
||||
$this->equalTo($this->user->getUID())
|
||||
);
|
||||
$this->folderService->expects($this->once())
|
||||
->method('read')
|
||||
->with($this->user->getUID(), 3, 30);
|
||||
|
||||
$this->class->read(3, 30);
|
||||
}
|
||||
|
||||
public function testUpdateRoot()
|
||||
{
|
||||
$response = $this->class->update(null, '');
|
||||
$this->assertSame(400, $response->getStatus());
|
||||
|
||||
}
|
||||
|
||||
public function testDeleteRoot()
|
||||
{
|
||||
$response = $this->class->delete(null);
|
||||
$this->assertSame(400, $response->getStatus());
|
||||
|
||||
$this->folderAPI->read(3, 30);
|
||||
}
|
||||
|
||||
|
||||
|
@ -84,8 +84,6 @@ class FolderControllerTest extends TestCase
|
||||
$this->class = new FolderController(
|
||||
$request,
|
||||
$this->folderService,
|
||||
$this->feedService,
|
||||
$this->itemService,
|
||||
$this->userSession
|
||||
);
|
||||
$this->msg = 'ron';
|
||||
@ -162,6 +160,16 @@ class FolderControllerTest extends TestCase
|
||||
$this->class->delete(5);
|
||||
}
|
||||
|
||||
public function testDeleteRoot()
|
||||
{
|
||||
$this->folderService->expects($this->never())
|
||||
->method('markDelete')
|
||||
->with('jack', 5, true);
|
||||
|
||||
$response = $this->class->delete(null);
|
||||
$this->assertEquals(400, $response->getStatus());
|
||||
}
|
||||
|
||||
public function testDeleteDoesNotExist()
|
||||
{
|
||||
$this->folderService->expects($this->once())
|
||||
@ -176,6 +184,20 @@ class FolderControllerTest extends TestCase
|
||||
$this->assertEquals($response->getStatus(), Http::STATUS_NOT_FOUND);
|
||||
}
|
||||
|
||||
public function testDeleteConflict()
|
||||
{
|
||||
$this->folderService->expects($this->once())
|
||||
->method('markDelete')
|
||||
->will($this->throwException(new ServiceConflictException($this->msg)));
|
||||
|
||||
$response = $this->class->delete(5);
|
||||
|
||||
$params = json_decode($response->render(), true);
|
||||
|
||||
$this->assertEquals($this->msg, $params['message']);
|
||||
$this->assertEquals($response->getStatus(), Http::STATUS_CONFLICT);
|
||||
}
|
||||
|
||||
public function testRename()
|
||||
{
|
||||
$folder = new Folder();
|
||||
@ -186,11 +208,21 @@ class FolderControllerTest extends TestCase
|
||||
->with('jack', 4, 'tech')
|
||||
->will($this->returnValue($folder));
|
||||
|
||||
$response = $this->class->rename('tech', 4);
|
||||
$response = $this->class->rename(4, 'tech');
|
||||
|
||||
$this->assertEquals($result, $response);
|
||||
}
|
||||
|
||||
public function testRenameRoot()
|
||||
{
|
||||
$this->folderService->expects($this->never())
|
||||
->method('rename');
|
||||
|
||||
$response = $this->class->rename(null, 'tech');
|
||||
|
||||
$this->assertEquals(400, $response->getStatus());
|
||||
}
|
||||
|
||||
public function testRenameDoesNotExist()
|
||||
{
|
||||
$msg = 'except';
|
||||
@ -199,7 +231,7 @@ class FolderControllerTest extends TestCase
|
||||
->method('rename')
|
||||
->will($this->throwException($ex));
|
||||
|
||||
$response = $this->class->rename('tech', 5);
|
||||
$response = $this->class->rename(5, 'tech');
|
||||
$params = json_decode($response->render(), true);
|
||||
|
||||
$this->assertEquals($response->getStatus(), Http::STATUS_NOT_FOUND);
|
||||
@ -215,7 +247,7 @@ class FolderControllerTest extends TestCase
|
||||
->method('rename')
|
||||
->will($this->throwException($ex));
|
||||
|
||||
$response = $this->class->rename('tech', 1);
|
||||
$response = $this->class->rename(1, 'tech');
|
||||
$params = json_decode($response->render(), true);
|
||||
|
||||
$this->assertEquals($response->getStatus(), Http::STATUS_CONFLICT);
|
||||
@ -226,19 +258,11 @@ class FolderControllerTest extends TestCase
|
||||
|
||||
public function testRead()
|
||||
{
|
||||
$feed = new Feed();
|
||||
$expected = ['feeds' => [$feed->toAPI()]];
|
||||
$this->folderService->expects($this->once())
|
||||
->method('read')
|
||||
->with('jack', 4, 5);
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('readFolder')
|
||||
->with(4, 5, 'jack');
|
||||
$this->feedService->expects($this->once())
|
||||
->method('findAllForUser')
|
||||
->with('jack')
|
||||
->will($this->returnValue([$feed]));
|
||||
|
||||
$response = $this->class->read(4, 5);
|
||||
$this->assertEquals($expected, $response);
|
||||
$this->class->read(4, 5);
|
||||
}
|
||||
|
||||
|
||||
@ -267,4 +291,20 @@ class FolderControllerTest extends TestCase
|
||||
$this->assertEquals($this->msg, $params['message']);
|
||||
}
|
||||
|
||||
|
||||
public function testRestoreConflict()
|
||||
{
|
||||
$this->folderService->expects($this->once())
|
||||
->method('markDelete')
|
||||
->with('jack', 5, false)
|
||||
->will($this->throwException(new ServiceConflictException($this->msg)));
|
||||
|
||||
$response = $this->class->restore(5);
|
||||
|
||||
$params = json_decode($response->render(), true);
|
||||
|
||||
$this->assertEquals(Http::STATUS_CONFLICT, $response->getStatus());
|
||||
$this->assertEquals($this->msg, $params['message']);
|
||||
}
|
||||
|
||||
}
|
@ -16,7 +16,6 @@
|
||||
namespace OCA\News\Tests\Unit\Controller;
|
||||
|
||||
use OCA\News\Controller\ItemApiController;
|
||||
use OCA\News\Service\ItemService;
|
||||
use OCA\News\Service\ItemServiceV2;
|
||||
use \OCP\AppFramework\Http;
|
||||
|
||||
@ -31,18 +30,28 @@ use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ItemApiControllerTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ItemServiceV2|\PHPUnit\Framework\MockObject\MockObject
|
||||
*/
|
||||
private $itemService;
|
||||
private $oldItemService;
|
||||
private $class;
|
||||
/**
|
||||
* @var IUserSession|\PHPUnit\Framework\MockObject\MockObject
|
||||
*/
|
||||
private $userSession;
|
||||
/**
|
||||
* @var IUser|\PHPUnit\Framework\MockObject\MockObject
|
||||
*/
|
||||
private $user;
|
||||
/**
|
||||
* @var IRequest|\PHPUnit\Framework\MockObject\MockObject
|
||||
*/
|
||||
private $request;
|
||||
private $msg;
|
||||
private $uid = 'tom';
|
||||
private $class;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->user = 'tom';
|
||||
$this->appName = 'news';
|
||||
$this->request = $this->getMockBuilder(IRequest::class)
|
||||
->disableOriginalConstructor()
|
||||
@ -58,24 +67,20 @@ class ItemApiControllerTest extends TestCase
|
||||
->will($this->returnValue($this->user));
|
||||
$this->user->expects($this->any())
|
||||
->method('getUID')
|
||||
->will($this->returnValue('123'));
|
||||
$this->oldItemService = $this->getMockBuilder(ItemService::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
->will($this->returnValue($this->uid));
|
||||
$this->itemService = $this->getMockBuilder(ItemServiceV2::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->class = new ItemApiController(
|
||||
$this->request,
|
||||
$this->userSession,
|
||||
$this->oldItemService,
|
||||
$this->itemService
|
||||
);
|
||||
$this->msg = 'hi';
|
||||
}
|
||||
|
||||
|
||||
public function testIndex()
|
||||
public function testIndexForFeed()
|
||||
{
|
||||
$item = new Item();
|
||||
$item->setId(5);
|
||||
@ -83,26 +88,52 @@ class ItemApiControllerTest extends TestCase
|
||||
$item->setGuidHash('guidhash');
|
||||
$item->setFeedId(123);
|
||||
|
||||
$this->oldItemService->expects($this->once())
|
||||
->method('findAllItems')
|
||||
->with(
|
||||
$this->equalTo(2),
|
||||
$this->equalTo(1),
|
||||
$this->equalTo(30),
|
||||
$this->equalTo(20),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo($this->user->getUID())
|
||||
)
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllInFeedWithFilters')
|
||||
->with($this->uid, 2, 30, 20, false, true)
|
||||
->will($this->returnValue([$item]));
|
||||
|
||||
$response = $this->class->index(0, 2, true, 30, 20, true);
|
||||
|
||||
$this->assertEquals(['items' => [$item->toApi()]], $response);
|
||||
}
|
||||
|
||||
|
||||
public function testIndexForFolder()
|
||||
{
|
||||
$item = new Item();
|
||||
$item->setId(5);
|
||||
$item->setGuid('guid');
|
||||
$item->setGuidHash('guidhash');
|
||||
$item->setFeedId(123);
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllInFolderWithFilters')
|
||||
->with($this->uid, 2, 30, 20, false, true)
|
||||
->will($this->returnValue([$item]));
|
||||
|
||||
$response = $this->class->index(1, 2, true, 30, 20, true);
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
'items' => [$item->toApi()]
|
||||
], $response
|
||||
);
|
||||
$this->assertEquals(['items' => [$item->toApi()]], $response);
|
||||
}
|
||||
|
||||
|
||||
public function testIndexForItems()
|
||||
{
|
||||
$item = new Item();
|
||||
$item->setId(5);
|
||||
$item->setGuid('guid');
|
||||
$item->setGuidHash('guidhash');
|
||||
$item->setFeedId(123);
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllWithFilters')
|
||||
->with($this->uid, 3, 30, 20, true)
|
||||
->will($this->returnValue([$item]));
|
||||
|
||||
$response = $this->class->index(3, 2, true, 30, 20, true);
|
||||
|
||||
$this->assertEquals(['items' => [$item->toApi()]], $response);
|
||||
}
|
||||
|
||||
|
||||
@ -114,30 +145,18 @@ class ItemApiControllerTest extends TestCase
|
||||
$item->setGuidHash('guidhash');
|
||||
$item->setFeedId(123);
|
||||
|
||||
$this->oldItemService->expects($this->once())
|
||||
->method('findAllItems')
|
||||
->with(
|
||||
$this->equalTo(2),
|
||||
$this->equalTo(1),
|
||||
$this->equalTo(-1),
|
||||
$this->equalTo(0),
|
||||
$this->equalTo(false),
|
||||
$this->equalTo(false),
|
||||
$this->equalTo($this->user->getUID())
|
||||
)
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllInFolderWithFilters')
|
||||
->with($this->uid, 2, -1, 0, true, false)
|
||||
->will($this->returnValue([$item]));
|
||||
|
||||
$response = $this->class->index(1, 2, false);
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
'items' => [$item->toApi()]
|
||||
], $response
|
||||
);
|
||||
$this->assertEquals(['items' => [$item->toApi()]], $response);
|
||||
}
|
||||
|
||||
|
||||
public function testUpdated()
|
||||
public function testUpdatedFeed()
|
||||
{
|
||||
$item = new Item();
|
||||
$item->setId(5);
|
||||
@ -145,36 +164,78 @@ class ItemApiControllerTest extends TestCase
|
||||
$item->setGuidHash('guidhash');
|
||||
$item->setFeedId(123);
|
||||
|
||||
$this->oldItemService->expects($this->once())
|
||||
->method('findAllNew')
|
||||
->with(
|
||||
$this->equalTo(2),
|
||||
$this->equalTo(1),
|
||||
$this->equalTo(30000000),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo($this->user->getUID())
|
||||
)
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllInFeedAfter')
|
||||
->with($this->uid, 2, 30000000, false)
|
||||
->will($this->returnValue([$item]));
|
||||
|
||||
$response = $this->class->updated(0, 2, 30);
|
||||
|
||||
$this->assertEquals(['items' => [$item->toApi()]], $response);
|
||||
}
|
||||
|
||||
|
||||
public function testUpdatedFolder()
|
||||
{
|
||||
$item = new Item();
|
||||
$item->setId(5);
|
||||
$item->setGuid('guid');
|
||||
$item->setGuidHash('guidhash');
|
||||
$item->setFeedId(123);
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllInFolderAfter')
|
||||
->with($this->uid, 2, 30000000, false)
|
||||
->will($this->returnValue([$item]));
|
||||
|
||||
$response = $this->class->updated(1, 2, 30);
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
'items' => [$item->toApi()]
|
||||
], $response
|
||||
);
|
||||
$this->assertEquals(['items' => [$item->toApi()]], $response);
|
||||
}
|
||||
|
||||
|
||||
public function testUpdatedItems()
|
||||
{
|
||||
$item = new Item();
|
||||
$item->setId(5);
|
||||
$item->setGuid('guid');
|
||||
$item->setGuidHash('guidhash');
|
||||
$item->setFeedId(123);
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllAfter')
|
||||
->with($this->uid, 3, 30000000)
|
||||
->will($this->returnValue([$item]));
|
||||
|
||||
$response = $this->class->updated(3, 2, 30);
|
||||
|
||||
$this->assertEquals(['items' => [$item->toApi()]], $response);
|
||||
}
|
||||
|
||||
public function testUpdatedFeedFullTimestamp()
|
||||
{
|
||||
$item = new Item();
|
||||
$item->setId(5);
|
||||
$item->setGuid('guid');
|
||||
$item->setGuidHash('guidhash');
|
||||
$item->setFeedId(123);
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllInFeedAfter')
|
||||
->with($this->uid, 2, 1609598359000000, false)
|
||||
->will($this->returnValue([$item]));
|
||||
|
||||
$response = $this->class->updated(0, 2, '1609598359000000');
|
||||
|
||||
$this->assertEquals(['items' => [$item->toApi()]], $response);
|
||||
}
|
||||
|
||||
|
||||
public function testRead()
|
||||
{
|
||||
$this->oldItemService->expects($this->once())
|
||||
$this->itemService->expects($this->once())
|
||||
->method('read')
|
||||
->with(
|
||||
$this->equalTo(2),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo($this->user->getUID())
|
||||
);
|
||||
->with($this->user->getUID(), 2, true);
|
||||
|
||||
$this->class->read(2);
|
||||
}
|
||||
@ -182,7 +243,7 @@ class ItemApiControllerTest extends TestCase
|
||||
|
||||
public function testReadDoesNotExist()
|
||||
{
|
||||
$this->oldItemService->expects($this->once())
|
||||
$this->itemService->expects($this->once())
|
||||
->method('read')
|
||||
->will(
|
||||
$this->throwException(
|
||||
@ -200,12 +261,12 @@ class ItemApiControllerTest extends TestCase
|
||||
|
||||
public function testUnread()
|
||||
{
|
||||
$this->oldItemService->expects($this->once())
|
||||
$this->itemService->expects($this->once())
|
||||
->method('read')
|
||||
->with(
|
||||
$this->equalTo($this->user->getUID()),
|
||||
$this->equalTo(2),
|
||||
$this->equalTo(false),
|
||||
$this->equalTo($this->user->getUID())
|
||||
$this->equalTo(false)
|
||||
);
|
||||
|
||||
$this->class->unread(2);
|
||||
@ -214,7 +275,7 @@ class ItemApiControllerTest extends TestCase
|
||||
|
||||
public function testUnreadDoesNotExist()
|
||||
{
|
||||
$this->oldItemService->expects($this->once())
|
||||
$this->itemService->expects($this->once())
|
||||
->method('read')
|
||||
->will(
|
||||
$this->throwException(
|
||||
@ -232,14 +293,9 @@ class ItemApiControllerTest extends TestCase
|
||||
|
||||
public function testStar()
|
||||
{
|
||||
$this->oldItemService->expects($this->once())
|
||||
->method('star')
|
||||
->with(
|
||||
$this->equalTo(2),
|
||||
$this->equalTo('hash'),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo($this->user->getUID())
|
||||
);
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starByGuid')
|
||||
->with('tom', 2, 'hash', true);
|
||||
|
||||
$this->class->star(2, 'hash');
|
||||
}
|
||||
@ -247,13 +303,9 @@ class ItemApiControllerTest extends TestCase
|
||||
|
||||
public function testStarDoesNotExist()
|
||||
{
|
||||
$this->oldItemService->expects($this->once())
|
||||
->method('star')
|
||||
->will(
|
||||
$this->throwException(
|
||||
new ServiceNotFoundException($this->msg)
|
||||
)
|
||||
);
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starByGuid')
|
||||
->will($this->throwException(new ServiceNotFoundException($this->msg)));
|
||||
|
||||
$response = $this->class->star(2, 'test');
|
||||
|
||||
@ -265,14 +317,9 @@ class ItemApiControllerTest extends TestCase
|
||||
|
||||
public function testUnstar()
|
||||
{
|
||||
$this->oldItemService->expects($this->once())
|
||||
->method('star')
|
||||
->with(
|
||||
$this->equalTo(2),
|
||||
$this->equalTo('hash'),
|
||||
$this->equalTo(false),
|
||||
$this->equalTo($this->user->getUID())
|
||||
);
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starByGuid')
|
||||
->with($this->uid, 2, 'hash', false);
|
||||
|
||||
$this->class->unstar(2, 'hash');
|
||||
}
|
||||
@ -280,8 +327,8 @@ class ItemApiControllerTest extends TestCase
|
||||
|
||||
public function testUnstarDoesNotExist()
|
||||
{
|
||||
$this->oldItemService->expects($this->once())
|
||||
->method('star')
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starByGuid')
|
||||
->will(
|
||||
$this->throwException(
|
||||
new ServiceNotFoundException($this->msg)
|
||||
@ -298,12 +345,9 @@ class ItemApiControllerTest extends TestCase
|
||||
|
||||
public function testReadAll()
|
||||
{
|
||||
$this->oldItemService->expects($this->once())
|
||||
$this->itemService->expects($this->once())
|
||||
->method('readAll')
|
||||
->with(
|
||||
$this->equalTo(30),
|
||||
$this->equalTo($this->user->getUID())
|
||||
);
|
||||
->with($this->user->getUID(), 30);
|
||||
|
||||
$this->class->readAll(30);
|
||||
}
|
||||
@ -312,11 +356,11 @@ class ItemApiControllerTest extends TestCase
|
||||
|
||||
public function testReadMultiple()
|
||||
{
|
||||
$this->oldItemService->expects($this->exactly(2))
|
||||
$this->itemService->expects($this->exactly(2))
|
||||
->method('read')
|
||||
->withConsecutive(
|
||||
[2, true, $this->user->getUID()],
|
||||
[4, true, $this->user->getUID()]
|
||||
[$this->user->getUID(), 2, true],
|
||||
[$this->user->getUID(), 4, true]
|
||||
);
|
||||
$this->class->readMultiple([2, 4]);
|
||||
}
|
||||
@ -324,24 +368,24 @@ class ItemApiControllerTest extends TestCase
|
||||
|
||||
public function testReadMultipleDoesntCareAboutException()
|
||||
{
|
||||
$this->oldItemService->expects($this->exactly(2))
|
||||
$this->itemService->expects($this->exactly(2))
|
||||
->method('read')
|
||||
->withConsecutive(
|
||||
[2, true, $this->user->getUID()],
|
||||
[4, true, $this->user->getUID()]
|
||||
[$this->user->getUID(), 2, true],
|
||||
[$this->user->getUID(), 4, true]
|
||||
)
|
||||
->willReturnOnConsecutiveCalls($this->throwException(new ServiceNotFoundException('')), null);
|
||||
->willReturnOnConsecutiveCalls($this->throwException(new ServiceNotFoundException('')), new Item());
|
||||
$this->class->readMultiple([2, 4]);
|
||||
}
|
||||
|
||||
|
||||
public function testUnreadMultiple()
|
||||
{
|
||||
$this->oldItemService->expects($this->exactly(2))
|
||||
$this->itemService->expects($this->exactly(2))
|
||||
->method('read')
|
||||
->withConsecutive(
|
||||
[2, false, $this->user->getUID()],
|
||||
[4, false, $this->user->getUID()]
|
||||
[$this->user->getUID(), 2, false],
|
||||
[$this->user->getUID(), 4, false]
|
||||
);
|
||||
$this->class->unreadMultiple([2, 4]);
|
||||
}
|
||||
@ -360,11 +404,11 @@ class ItemApiControllerTest extends TestCase
|
||||
]
|
||||
];
|
||||
|
||||
$this->oldItemService->expects($this->exactly(2))
|
||||
->method('star')
|
||||
$this->itemService->expects($this->exactly(2))
|
||||
->method('starByGuid')
|
||||
->withConsecutive(
|
||||
[2, 'a', true, $this->user->getUID()],
|
||||
[4, 'b', true, $this->user->getUID()]
|
||||
[$this->user->getUID(), 2, 'a', true],
|
||||
[$this->user->getUID(), 4, 'b', true]
|
||||
);
|
||||
$this->class->starMultiple($ids);
|
||||
}
|
||||
@ -383,13 +427,13 @@ class ItemApiControllerTest extends TestCase
|
||||
]
|
||||
];
|
||||
|
||||
$this->oldItemService->expects($this->exactly(2))
|
||||
->method('star')
|
||||
$this->itemService->expects($this->exactly(2))
|
||||
->method('starByGuid')
|
||||
->withConsecutive(
|
||||
[2, 'a', true, $this->user->getUID()],
|
||||
[4, 'b', true, $this->user->getUID()]
|
||||
[$this->user->getUID(), 2, 'a', true],
|
||||
[$this->user->getUID(), 4, 'b', true]
|
||||
)
|
||||
->willReturnOnConsecutiveCalls($this->throwException(new ServiceNotFoundException('')), null);
|
||||
->willReturnOnConsecutiveCalls($this->throwException(new ServiceNotFoundException('')), new Item());
|
||||
|
||||
$this->class->starMultiple($ids);
|
||||
}
|
||||
@ -408,11 +452,11 @@ class ItemApiControllerTest extends TestCase
|
||||
]
|
||||
];
|
||||
|
||||
$this->oldItemService->expects($this->exactly(2))
|
||||
->method('star')
|
||||
$this->itemService->expects($this->exactly(2))
|
||||
->method('starByGuid')
|
||||
->withConsecutive(
|
||||
[2, 'a', false, $this->user->getUID()],
|
||||
[4, 'b', false, $this->user->getUID()]
|
||||
[$this->user->getUID(), 2, 'a', false],
|
||||
[$this->user->getUID(), 4, 'b', false]
|
||||
);
|
||||
|
||||
$this->class->unstarMultiple($ids);
|
||||
|
@ -15,7 +15,7 @@ namespace OCA\News\Tests\Unit\Controller;
|
||||
|
||||
use OCA\News\Controller\ItemController;
|
||||
use OCA\News\Service\FeedServiceV2;
|
||||
use OCA\News\Service\ItemService;
|
||||
use OCA\News\Service\ItemServiceV2;
|
||||
use \OCP\AppFramework\Http;
|
||||
|
||||
use \OCA\News\Db\Item;
|
||||
@ -39,7 +39,7 @@ class ItemControllerTest extends TestCase
|
||||
*/
|
||||
private $settings;
|
||||
/**
|
||||
* @var \PHPUnit\Framework\MockObject\MockObject|ItemService
|
||||
* @var \PHPUnit\Framework\MockObject\MockObject|ItemServiceV2
|
||||
*/
|
||||
private $itemService;
|
||||
/**
|
||||
@ -72,7 +72,7 @@ class ItemControllerTest extends TestCase
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->itemService =
|
||||
$this->getMockBuilder(ItemService::class)
|
||||
$this->getMockBuilder(ItemServiceV2::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->feedService =
|
||||
@ -106,7 +106,7 @@ class ItemControllerTest extends TestCase
|
||||
{
|
||||
$this->itemService->expects($this->once())
|
||||
->method('read')
|
||||
->with(4, true, 'user');
|
||||
->with('user', 4, true);
|
||||
|
||||
$this->controller->read(4, true);
|
||||
}
|
||||
@ -133,8 +133,8 @@ class ItemControllerTest extends TestCase
|
||||
$this->itemService->expects($this->exactly(2))
|
||||
->method('read')
|
||||
->withConsecutive(
|
||||
[2, true, 'user'],
|
||||
[4, true, 'user']
|
||||
['user', 2, true],
|
||||
['user', 4, true]
|
||||
);
|
||||
|
||||
$this->controller->readMultiple([2, 4]);
|
||||
@ -147,10 +147,10 @@ class ItemControllerTest extends TestCase
|
||||
$this->itemService->expects($this->exactly(2))
|
||||
->method('read')
|
||||
->withConsecutive(
|
||||
[2, true, 'user'],
|
||||
[4, true, 'user']
|
||||
['user', 2, true],
|
||||
['user', 4, true]
|
||||
)
|
||||
->willReturnOnConsecutiveCalls($this->throwException(new ServiceNotFoundException('yo')), null);
|
||||
->willReturnOnConsecutiveCalls($this->throwException(new ServiceNotFoundException('yo')), new Item());
|
||||
$this->controller->readMultiple([2, 4]);
|
||||
}
|
||||
|
||||
@ -158,8 +158,8 @@ class ItemControllerTest extends TestCase
|
||||
public function testStar()
|
||||
{
|
||||
$this->itemService->expects($this->once())
|
||||
->method('star')
|
||||
->with(4, 'test', true, 'user');
|
||||
->method('starByGuid')
|
||||
->with('user', 4, 'test', true);
|
||||
|
||||
$this->controller->star(4, 'test', true);
|
||||
}
|
||||
@ -170,7 +170,7 @@ class ItemControllerTest extends TestCase
|
||||
$msg = 'ho';
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('star')
|
||||
->method('starByGuid')
|
||||
->will($this->throwException(new ServiceNotFoundException($msg)));
|
||||
|
||||
$response = $this->controller->star(4, 'test', false);
|
||||
@ -189,7 +189,7 @@ class ItemControllerTest extends TestCase
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('readAll')
|
||||
->with(5, 'user');
|
||||
->with('user', 5);
|
||||
$this->feedService->expects($this->once())
|
||||
->method('findAllForUser')
|
||||
->with('user')
|
||||
@ -199,8 +199,14 @@ class ItemControllerTest extends TestCase
|
||||
$this->assertEquals($expected, $response);
|
||||
}
|
||||
|
||||
|
||||
private function itemsApiExpects($id, $type, $oldestFirst = '1')
|
||||
/**
|
||||
* Setup expectations for settings
|
||||
*
|
||||
* @param $id
|
||||
* @param $type
|
||||
* @param string $oldestFirst
|
||||
*/
|
||||
private function itemsApiExpects($id, $type, $oldestFirst = '1'): void
|
||||
{
|
||||
$this->settings->expects($this->exactly(2))
|
||||
->method('getUserValue')
|
||||
@ -218,14 +224,14 @@ class ItemControllerTest extends TestCase
|
||||
}
|
||||
|
||||
|
||||
public function testIndex()
|
||||
public function testIndexForFeed()
|
||||
{
|
||||
$feeds = [new Feed()];
|
||||
$result = [
|
||||
'items' => [new Item()],
|
||||
'feeds' => $feeds,
|
||||
'newestItemId' => $this->newestItemId,
|
||||
'starred' => 3111
|
||||
'starred' => 3
|
||||
];
|
||||
|
||||
$this->itemsApiExpects(2, FeedType::FEED, '0');
|
||||
@ -236,18 +242,18 @@ class ItemControllerTest extends TestCase
|
||||
->will($this->returnValue($feeds));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
->method('newest')
|
||||
->with('user')
|
||||
->will($this->returnValue($this->newestItemId));
|
||||
->will($this->returnValue(Item::fromParams(['id' => $this->newestItemId])));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starredCount')
|
||||
->method('starred')
|
||||
->with('user')
|
||||
->will($this->returnValue(3111));
|
||||
->will($this->returnValue([1, 2, 3]));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllItems')
|
||||
->with(2, FeedType::FEED, 3, 0, true, false, 'user', [])
|
||||
->method('findAllInFeedWithFilters')
|
||||
->with('user', 2, 3, 0, false, false, [])
|
||||
->will($this->returnValue($result['items']));
|
||||
|
||||
$response = $this->controller->index(FeedType::FEED, 2, 3);
|
||||
@ -255,14 +261,88 @@ class ItemControllerTest extends TestCase
|
||||
}
|
||||
|
||||
|
||||
public function testIndexSearch()
|
||||
public function testIndexForFolder()
|
||||
{
|
||||
$feeds = [new Feed()];
|
||||
$result = [
|
||||
'items' => [new Item()],
|
||||
'feeds' => $feeds,
|
||||
'newestItemId' => $this->newestItemId,
|
||||
'starred' => 3111
|
||||
'starred' => 3
|
||||
];
|
||||
|
||||
$this->itemsApiExpects(2, FeedType::FOLDER, '0');
|
||||
|
||||
$this->feedService->expects($this->once())
|
||||
->method('findAllForUser')
|
||||
->with('user')
|
||||
->will($this->returnValue($feeds));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('newest')
|
||||
->with('user')
|
||||
->will($this->returnValue(Item::fromParams(['id' => $this->newestItemId])));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starred')
|
||||
->with('user')
|
||||
->will($this->returnValue([1, 2, 3]));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllInFolderWithFilters')
|
||||
->with('user', 2, 3, 0, false, false, [])
|
||||
->will($this->returnValue($result['items']));
|
||||
|
||||
$response = $this->controller->index(FeedType::FOLDER, 2, 3);
|
||||
$this->assertEquals($result, $response);
|
||||
}
|
||||
|
||||
|
||||
public function testIndexForOther()
|
||||
{
|
||||
$feeds = [new Feed()];
|
||||
$result = [
|
||||
'items' => [new Item()],
|
||||
'feeds' => $feeds,
|
||||
'newestItemId' => $this->newestItemId,
|
||||
'starred' => 3
|
||||
];
|
||||
|
||||
$this->itemsApiExpects(2, FeedType::STARRED, '0');
|
||||
|
||||
$this->feedService->expects($this->once())
|
||||
->method('findAllForUser')
|
||||
->with('user')
|
||||
->will($this->returnValue($feeds));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('newest')
|
||||
->with('user')
|
||||
->will($this->returnValue(Item::fromParams(['id' => $this->newestItemId])));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starred')
|
||||
->with('user')
|
||||
->will($this->returnValue([1, 2, 3]));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllWithFilters')
|
||||
->with('user', 2, 3, 0, false, [])
|
||||
->will($this->returnValue($result['items']));
|
||||
|
||||
$response = $this->controller->index(FeedType::STARRED, 2, 3);
|
||||
$this->assertEquals($result, $response);
|
||||
}
|
||||
|
||||
|
||||
public function testIndexSearchFeed()
|
||||
{
|
||||
$feeds = [new Feed()];
|
||||
$result = [
|
||||
'items' => [new Item()],
|
||||
'feeds' => $feeds,
|
||||
'newestItemId' => $this->newestItemId,
|
||||
'starred' => 3
|
||||
];
|
||||
|
||||
$this->itemsApiExpects(2, FeedType::FEED, '0');
|
||||
@ -273,18 +353,18 @@ class ItemControllerTest extends TestCase
|
||||
->will($this->returnValue($feeds));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
->method('newest')
|
||||
->with('user')
|
||||
->will($this->returnValue($this->newestItemId));
|
||||
->will($this->returnValue(Item::fromParams(['id' => $this->newestItemId])));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starredCount')
|
||||
->method('starred')
|
||||
->with('user')
|
||||
->will($this->returnValue(3111));
|
||||
->will($this->returnValue([1, 2, 3]));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllItems')
|
||||
->with(2, FeedType::FEED, 3, 0, true, false, 'user', ['test', 'search'])
|
||||
->method('findAllInFeedWithFilters')
|
||||
->with('user', 2, 3, 0, false, false, ['test', 'search'])
|
||||
->will($this->returnValue($result['items']));
|
||||
|
||||
$response = $this->controller->index(FeedType::FEED, 2, 3, 0, null, null, 'test%20%20search%20');
|
||||
@ -299,8 +379,8 @@ class ItemControllerTest extends TestCase
|
||||
$this->itemsApiExpects(2, FeedType::FEED);
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllItems')
|
||||
->with(2, FeedType::FEED, 3, 10, true, true, 'user')
|
||||
->method('findAllInFeedWithFilters')
|
||||
->with('user', 2, 3, 10, false, true)
|
||||
->will($this->returnValue($result['items']));
|
||||
|
||||
$this->feedService->expects($this->never())
|
||||
@ -316,7 +396,7 @@ class ItemControllerTest extends TestCase
|
||||
$this->itemsApiExpects(2, FeedType::FEED);
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
->method('newest')
|
||||
->with('user')
|
||||
->will($this->throwException(new ServiceNotFoundException('')));
|
||||
|
||||
@ -325,14 +405,14 @@ class ItemControllerTest extends TestCase
|
||||
}
|
||||
|
||||
|
||||
public function testNewItems()
|
||||
public function testNewItemsFeed()
|
||||
{
|
||||
$feeds = [new Feed()];
|
||||
$result = [
|
||||
'items' => [new Item()],
|
||||
'feeds' => $feeds,
|
||||
'newestItemId' => $this->newestItemId,
|
||||
'starred' => 3111
|
||||
'starred' => 3
|
||||
];
|
||||
|
||||
$this->settings->expects($this->once())
|
||||
@ -346,18 +426,18 @@ class ItemControllerTest extends TestCase
|
||||
->will($this->returnValue($feeds));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
->method('newest')
|
||||
->with('user')
|
||||
->will($this->returnValue($this->newestItemId));
|
||||
->will($this->returnValue(Item::fromParams(['id' => $this->newestItemId])));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starredCount')
|
||||
->method('starred')
|
||||
->with('user')
|
||||
->will($this->returnValue(3111));
|
||||
->will($this->returnValue([1, 2, 3]));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllNew')
|
||||
->with(2, FeedType::FEED, 3, true, 'user')
|
||||
->method('findAllInFeedAfter')
|
||||
->with('user', 2, 3, false)
|
||||
->will($this->returnValue($result['items']));
|
||||
|
||||
$response = $this->controller->newItems(FeedType::FEED, 2, 3);
|
||||
@ -365,6 +445,86 @@ class ItemControllerTest extends TestCase
|
||||
}
|
||||
|
||||
|
||||
public function testNewItemsFolder()
|
||||
{
|
||||
$feeds = [new Feed()];
|
||||
$result = [
|
||||
'items' => [new Item()],
|
||||
'feeds' => $feeds,
|
||||
'newestItemId' => $this->newestItemId,
|
||||
'starred' => 3
|
||||
];
|
||||
|
||||
$this->settings->expects($this->once())
|
||||
->method('getUserValue')
|
||||
->with('user', $this->appName, 'showAll')
|
||||
->will($this->returnValue('1'));
|
||||
|
||||
$this->feedService->expects($this->once())
|
||||
->method('findAllForUser')
|
||||
->with('user')
|
||||
->will($this->returnValue($feeds));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('newest')
|
||||
->with('user')
|
||||
->will($this->returnValue(Item::fromParams(['id' => $this->newestItemId])));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starred')
|
||||
->with('user')
|
||||
->will($this->returnValue([1, 2, 3]));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllInFolderAfter')
|
||||
->with('user', 2, 3, false)
|
||||
->will($this->returnValue($result['items']));
|
||||
|
||||
$response = $this->controller->newItems(FeedType::FOLDER, 2, 3);
|
||||
$this->assertEquals($result, $response);
|
||||
}
|
||||
|
||||
|
||||
public function testNewItemsOther()
|
||||
{
|
||||
$feeds = [new Feed()];
|
||||
$result = [
|
||||
'items' => [new Item()],
|
||||
'feeds' => $feeds,
|
||||
'newestItemId' => $this->newestItemId,
|
||||
'starred' => 3
|
||||
];
|
||||
|
||||
$this->settings->expects($this->once())
|
||||
->method('getUserValue')
|
||||
->with('user', $this->appName, 'showAll')
|
||||
->will($this->returnValue('1'));
|
||||
|
||||
$this->feedService->expects($this->once())
|
||||
->method('findAllForUser')
|
||||
->with('user')
|
||||
->will($this->returnValue($feeds));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('newest')
|
||||
->with('user')
|
||||
->will($this->returnValue(Item::fromParams(['id' => $this->newestItemId])));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('starred')
|
||||
->with('user')
|
||||
->will($this->returnValue([1, 2, 3]));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('findAllAfter')
|
||||
->with('user', 6, 3)
|
||||
->will($this->returnValue($result['items']));
|
||||
|
||||
$response = $this->controller->newItems(FeedType::UNREAD, 2, 3);
|
||||
$this->assertEquals($result, $response);
|
||||
}
|
||||
|
||||
|
||||
public function testGetNewItemsNoNewestItemsId()
|
||||
{
|
||||
$this->settings->expects($this->once())
|
||||
@ -373,7 +533,7 @@ class ItemControllerTest extends TestCase
|
||||
->will($this->returnValue('1'));
|
||||
|
||||
$this->itemService->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
->method('newest')
|
||||
->with('user')
|
||||
->will($this->throwException(new ServiceNotFoundException('')));
|
||||
|
||||
|
@ -16,6 +16,7 @@ namespace OCA\News\Tests\Unit\Controller;
|
||||
use OC\L10N\L10N;
|
||||
use OCA\News\Controller\PageController;
|
||||
use \OCA\News\Db\FeedType;
|
||||
use OCA\News\Explore\Exceptions\RecommendedSiteNotFoundException;
|
||||
use OCA\News\Explore\RecommendedSites;
|
||||
use OCA\News\Service\StatusService;
|
||||
use OCP\IConfig;
|
||||
@ -26,7 +27,6 @@ use OCP\IUser;
|
||||
use OCP\IUserSession;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
|
||||
class PageControllerTest extends TestCase
|
||||
{
|
||||
|
||||
@ -278,4 +278,24 @@ class PageControllerTest extends TestCase
|
||||
|
||||
}
|
||||
|
||||
public function testExploreError()
|
||||
{
|
||||
$this->settings->expects($this->exactly(2))
|
||||
->method('setUserValue')
|
||||
->withConsecutive(
|
||||
['becka', 'news', 'lastViewedFeedId', 0],
|
||||
['becka', 'news', 'lastViewedFeedType', FeedType::EXPLORE]
|
||||
);
|
||||
|
||||
$this->recommended->expects($this->once())
|
||||
->method('forLanguage')
|
||||
->with('nl')
|
||||
->will($this->throwException(new RecommendedSiteNotFoundException('error')));
|
||||
|
||||
$out = $this->controller->explore('nl');
|
||||
|
||||
$this->assertEquals(404, $out->getStatus());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -69,7 +69,7 @@ class FeedMapperTest extends MapperTestUtility
|
||||
->getMock();
|
||||
|
||||
$func = $this->getMockBuilder(IQueryFunction::class)
|
||||
->getMock();
|
||||
->getMock();
|
||||
|
||||
$funcbuilder->expects($this->once())
|
||||
->method('count')
|
||||
@ -451,4 +451,94 @@ class FeedMapperTest extends MapperTestUtility
|
||||
$result = $this->class->findAllFromFolder(null);
|
||||
$this->assertEquals($this->feeds, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \OCA\News\Db\FeedMapperV2::read
|
||||
*/
|
||||
public function testRead()
|
||||
{
|
||||
$this->db->expects($this->once())
|
||||
->method('getQueryBuilder')
|
||||
->willReturn($this->builder);
|
||||
|
||||
$this->builder->expects($this->once())
|
||||
->method('update')
|
||||
->with('news_items', 'items')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->once())
|
||||
->method('innerJoin')
|
||||
->with('items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->once())
|
||||
->method('setValue')
|
||||
->with('unread', 0)
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->exactly(2))
|
||||
->method('andWhere')
|
||||
->withConsecutive(['feeds.user_id = :userId'], ['feeds.id = :feedId'])
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->exactly(2))
|
||||
->method('setParameter')
|
||||
->withConsecutive(['userId', 'admin'], ['feedId', 1])
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->exactly(1))
|
||||
->method('getSQL')
|
||||
->will($this->returnValue('QUERY'));
|
||||
|
||||
$this->db->expects($this->exactly(1))
|
||||
->method('executeUpdate')
|
||||
->with('QUERY');
|
||||
|
||||
$this->class->read('admin', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \OCA\News\Db\FeedMapperV2::read
|
||||
*/
|
||||
public function testReadWithMaxId()
|
||||
{
|
||||
$this->db->expects($this->once())
|
||||
->method('getQueryBuilder')
|
||||
->willReturn($this->builder);
|
||||
|
||||
$this->builder->expects($this->once())
|
||||
->method('update')
|
||||
->with('news_items', 'items')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->once())
|
||||
->method('innerJoin')
|
||||
->with('items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->once())
|
||||
->method('setValue')
|
||||
->with('unread', 0)
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->exactly(3))
|
||||
->method('andWhere')
|
||||
->withConsecutive(['feeds.user_id = :userId'], ['feeds.id = :feedId'], ['items.id =< :maxItemId'])
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->exactly(3))
|
||||
->method('setParameter')
|
||||
->withConsecutive(['userId', 'admin'], ['feedId', 1], ['maxItemId', 4])
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->exactly(1))
|
||||
->method('getSQL')
|
||||
->will($this->returnValue('QUERY'));
|
||||
|
||||
$this->db->expects($this->exactly(1))
|
||||
->method('executeUpdate')
|
||||
->with('QUERY');
|
||||
|
||||
$this->class->read('admin', 1, 4);
|
||||
}
|
||||
}
|
@ -279,4 +279,94 @@ class FolderMapperTest extends MapperTestUtility
|
||||
$result = $this->class->findAll();
|
||||
$this->assertEquals($this->folders, $result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \OCA\News\Db\FolderMapperV2::read
|
||||
*/
|
||||
public function testRead()
|
||||
{
|
||||
$this->db->expects($this->once())
|
||||
->method('getQueryBuilder')
|
||||
->willReturn($this->builder);
|
||||
|
||||
$this->builder->expects($this->once())
|
||||
->method('update')
|
||||
->with('news_items', 'items')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->once())
|
||||
->method('innerJoin')
|
||||
->with('items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->once())
|
||||
->method('setValue')
|
||||
->with('unread', 0)
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->exactly(2))
|
||||
->method('andWhere')
|
||||
->withConsecutive(['feeds.user_id = :userId'], ['feeds.folder_id = :folderId'])
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->exactly(2))
|
||||
->method('setParameter')
|
||||
->withConsecutive(['userId', 'admin'], ['folderId', 1])
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->exactly(1))
|
||||
->method('getSQL')
|
||||
->will($this->returnValue('QUERY'));
|
||||
|
||||
$this->db->expects($this->exactly(1))
|
||||
->method('executeUpdate')
|
||||
->with('QUERY');
|
||||
|
||||
$this->class->read('admin', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \OCA\News\Db\FolderMapperV2::read
|
||||
*/
|
||||
public function testReadWithMaxId()
|
||||
{
|
||||
$this->db->expects($this->once())
|
||||
->method('getQueryBuilder')
|
||||
->willReturn($this->builder);
|
||||
|
||||
$this->builder->expects($this->once())
|
||||
->method('update')
|
||||
->with('news_items', 'items')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->once())
|
||||
->method('innerJoin')
|
||||
->with('items', 'news_feeds', 'feeds', 'items.feed_id = feeds.id')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->once())
|
||||
->method('setValue')
|
||||
->with('unread', 0)
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->exactly(3))
|
||||
->method('andWhere')
|
||||
->withConsecutive(['feeds.user_id = :userId'], ['feeds.folder_id = :folderId'], ['items.id =< :maxItemId'])
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->exactly(3))
|
||||
->method('setParameter')
|
||||
->withConsecutive(['userId', 'admin'], ['folderId', 1], ['maxItemId', 4])
|
||||
->will($this->returnSelf());
|
||||
|
||||
$this->builder->expects($this->exactly(1))
|
||||
->method('getSQL')
|
||||
->will($this->returnValue('QUERY'));
|
||||
|
||||
$this->db->expects($this->exactly(1))
|
||||
->method('executeUpdate')
|
||||
->with('QUERY');
|
||||
|
||||
$this->class->read('admin', 1, 4);
|
||||
}
|
||||
}
|
2360
tests/Unit/Db/ItemMapperTest.php
Normal file
2360
tests/Unit/Db/ItemMapperTest.php
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,59 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Nextcloud - News
|
||||
*
|
||||
* This file is licensed under the Affero General Public License version 3 or
|
||||
* later. See the COPYING file.
|
||||
*
|
||||
* @author Alessandro Cosentino <cosenal@gmail.com>
|
||||
* @author Bernhard Posselt <dev@bernhard-posselt.com>
|
||||
* @copyright 2012 Alessandro Cosentino
|
||||
* @copyright 2012-2014 Bernhard Posselt
|
||||
*/
|
||||
|
||||
namespace OCA\News\Tests\Unit\Db;
|
||||
|
||||
use OCA\News\Db\ItemMapper;
|
||||
use OCA\News\Db\MapperFactory;
|
||||
use OCA\News\Utility\Time;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
use OCP\IDBConnection;
|
||||
|
||||
use OCA\News\Db\Mysql\ItemMapper as MysqlMapper;
|
||||
|
||||
|
||||
class MapperFactoryTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \PHPUnit\Framework\MockObject\MockObject|IDBConnection
|
||||
*/
|
||||
private $db;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->db = $this->getMockBuilder(IDBConnection::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
}
|
||||
|
||||
public function testGetItemMapperSqlite()
|
||||
{
|
||||
$factory = new MapperFactory($this->db, 'sqlite', new Time());
|
||||
$this->assertTrue($factory->build() instanceof ItemMapper);
|
||||
}
|
||||
|
||||
public function testGetItemMapperPostgres()
|
||||
{
|
||||
$factory = new MapperFactory($this->db, 'pgsql', new Time());
|
||||
$this->assertTrue($factory->build() instanceof ItemMapper);
|
||||
}
|
||||
|
||||
public function testGetItemMapperMysql()
|
||||
{
|
||||
$factory = new MapperFactory($this->db, 'mysql', new Time());
|
||||
$this->assertTrue($factory->build() instanceof MysqlMapper);
|
||||
}
|
||||
|
||||
}
|
@ -24,6 +24,7 @@
|
||||
namespace OCA\News\Tests\Unit\Db;
|
||||
|
||||
use Doctrine\DBAL\Driver\Statement;
|
||||
use OC\DB\QueryBuilder\QueryBuilder;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
use OCP\IDBConnection;
|
||||
|
||||
@ -74,6 +75,7 @@ abstract class MapperTestUtility extends TestCase
|
||||
->getMock();
|
||||
|
||||
$this->builder = $this->getMockBuilder(IQueryBuilder::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->cursor = $this->getMockBuilder(Statement::class)
|
||||
|
@ -815,8 +815,8 @@ class FeedServiceTest extends TestCase
|
||||
->will($this->returnValue([$feed1, $feed2]));
|
||||
|
||||
$this->itemService->expects($this->exactly(2))
|
||||
->method('findAllForFeed')
|
||||
->withConsecutive([1], [2])
|
||||
->method('findAllInFeed')
|
||||
->withConsecutive(['jack', 1], ['jack', 2])
|
||||
->willReturn(['a']);
|
||||
|
||||
$feeds = $this->class->findAllForUserRecursive($this->uid);
|
||||
@ -824,4 +824,21 @@ class FeedServiceTest extends TestCase
|
||||
$this->assertEquals(['a'], $feeds[1]->items);
|
||||
}
|
||||
|
||||
public function testRead()
|
||||
{
|
||||
$feed1 = new Feed();
|
||||
$feed1->setId(1);
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findFromUser')
|
||||
->with($this->uid, 1)
|
||||
->will($this->returnValue($feed1));
|
||||
|
||||
$this->mapper->expects($this->exactly(1))
|
||||
->method('read')
|
||||
->withConsecutive(['jack', 1, null]);
|
||||
|
||||
$this->class->read($this->uid, 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -262,4 +262,21 @@ class FolderServiceTest extends TestCase
|
||||
}
|
||||
|
||||
|
||||
public function testRead()
|
||||
{
|
||||
$folder = new Folder();
|
||||
$folder->setId(1);
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findFromUser')
|
||||
->with('jack', 1)
|
||||
->will($this->returnValue($folder));
|
||||
|
||||
$this->mapper->expects($this->exactly(1))
|
||||
->method('read')
|
||||
->withConsecutive(['jack', 1, null]);
|
||||
|
||||
$this->class->read('jack', 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,84 +13,63 @@
|
||||
|
||||
namespace OCA\News\Tests\Unit\Service;
|
||||
|
||||
use OC\Log;
|
||||
use OCA\News\Db\ItemMapper;
|
||||
use OCA\News\Db\ItemMapperV2;
|
||||
use OCA\News\Service\ItemService;
|
||||
use OCA\News\Service\Exceptions\ServiceConflictException;
|
||||
use OCA\News\Service\Exceptions\ServiceValidationException;
|
||||
use OCA\News\Service\Exceptions\ServiceNotFoundException;
|
||||
use OCA\News\Utility\PsrLogger;
|
||||
use OCA\News\Utility\Time;
|
||||
use OCA\News\Service\ItemServiceV2;
|
||||
use \OCP\AppFramework\Db\DoesNotExistException;
|
||||
|
||||
use \OCA\News\Db\Item;
|
||||
use \OCA\News\Db\FeedType;
|
||||
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
|
||||
use OCP\IConfig;
|
||||
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
|
||||
/**
|
||||
* Class ItemServiceTest
|
||||
*
|
||||
* @package OCA\News\Tests\Unit\Service
|
||||
*/
|
||||
class ItemServiceTest extends TestCase
|
||||
{
|
||||
|
||||
/**
|
||||
* @var \PHPUnit\Framework\MockObject\MockObject|ItemMapper
|
||||
*/
|
||||
private $oldItemMapper;
|
||||
|
||||
/**
|
||||
* @var \PHPUnit\Framework\MockObject\MockObject|ItemMapperV2
|
||||
* @var MockObject|ItemMapperV2
|
||||
*/
|
||||
private $mapper;
|
||||
/**
|
||||
* @var ItemService
|
||||
* @var ItemServiceV2
|
||||
*/
|
||||
private $itemService;
|
||||
private $class;
|
||||
|
||||
/**
|
||||
* @var \PHPUnit\Framework\MockObject\MockObject|IConfig
|
||||
* @var MockObject|IConfig
|
||||
*/
|
||||
private $config;
|
||||
|
||||
/**
|
||||
* @var \PHPUnit\Framework\MockObject\MockObject|LoggerInterface
|
||||
* @var MockObject|LoggerInterface
|
||||
*/
|
||||
private $logger;
|
||||
|
||||
/**
|
||||
* @var \PHPUnit\Framework\MockObject\MockObject|Time
|
||||
*/
|
||||
private $timeFactory;
|
||||
|
||||
/**
|
||||
* @var int
|
||||
*/
|
||||
private $newestItemId;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $time;
|
||||
private $user;
|
||||
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->time = '222';
|
||||
$this->timeFactory = $this->getMockBuilder(Time::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->timeFactory->expects($this->any())
|
||||
->method('getTime')
|
||||
->will($this->returnValue($this->time));
|
||||
$this->timeFactory->expects($this->any())
|
||||
->method('getMicroTime')
|
||||
->will($this->returnValue($this->time));
|
||||
$this->mapper = $this->getMockBuilder(ItemMapperV2::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->oldItemMapper = $this->getMockBuilder(ItemMapper::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
$this->config = $this->getMockBuilder(IConfig::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
@ -99,10 +78,8 @@ class ItemServiceTest extends TestCase
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$this->itemService = new ItemService(
|
||||
$this->class = new ItemServiceV2(
|
||||
$this->mapper,
|
||||
$this->oldItemMapper,
|
||||
$this->timeFactory,
|
||||
$this->config,
|
||||
$this->logger
|
||||
);
|
||||
@ -115,164 +92,126 @@ class ItemServiceTest extends TestCase
|
||||
$this->newestItemId = 4;
|
||||
}
|
||||
|
||||
|
||||
public function testFindAllNewFeed()
|
||||
{
|
||||
$type = FeedType::FEED;
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
->method('findAllNewFeed')
|
||||
->with(
|
||||
$this->equalTo(3),
|
||||
$this->equalTo(20333),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo('jack')
|
||||
)
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findAllInFeedAfter')
|
||||
->with('jack', 2, 20333, true)
|
||||
->will($this->returnValue([]));
|
||||
|
||||
$result = $this->itemService->findAllNew(3, $type, 20333, true, 'jack');
|
||||
$result = $this->class->findAllInFeedAfter($this->user, 2, 20333, true);
|
||||
$this->assertEquals([], $result);
|
||||
}
|
||||
|
||||
|
||||
public function testFindAllNewFolder()
|
||||
{
|
||||
$type = FeedType::FOLDER;
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
->method('findAllNewFolder')
|
||||
->with(
|
||||
$this->equalTo(3),
|
||||
$this->equalTo(20333),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo('jack')
|
||||
)
|
||||
->will($this->returnValue(['val']));
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findAllInFolderAfter')
|
||||
->with('jack', 2, 20333, true)
|
||||
->will($this->returnValue([]));
|
||||
|
||||
$result = $this->itemService->findAllNew(3, $type, 20333, true, 'jack');
|
||||
$this->assertEquals(['val'], $result);
|
||||
$result = $this->class->findAllInFolderAfter($this->user, 2, 20333, true);
|
||||
$this->assertEquals([], $result);
|
||||
}
|
||||
|
||||
|
||||
public function testFindAllNew()
|
||||
public function testFindAllNewItem()
|
||||
{
|
||||
$type = FeedType::STARRED;
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
->method('findAllNew')
|
||||
->with(
|
||||
$this->equalTo(20333),
|
||||
$this->equalTo($type),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo('jack')
|
||||
)
|
||||
->will($this->returnValue(['val']));
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findAllAfter')
|
||||
->with('jack', 2, 20333)
|
||||
->will($this->returnValue([]));
|
||||
|
||||
$result = $this->itemService->findAllNew(
|
||||
3, $type, 20333, true,
|
||||
'jack'
|
||||
);
|
||||
$this->assertEquals(['val'], $result);
|
||||
$result = $this->class->findAllAfter($this->user, 2, 20333);
|
||||
$this->assertEquals([], $result);
|
||||
}
|
||||
|
||||
public function testFindAllNewItemWrongType()
|
||||
{
|
||||
$this->expectException(ServiceValidationException::class);
|
||||
$this->expectExceptionMessage('Trying to find in unknown type');
|
||||
|
||||
$this->mapper->expects($this->never())
|
||||
->method('findAllAfter');
|
||||
|
||||
$result = $this->class->findAllAfter($this->user, 3, 20333);
|
||||
$this->assertEquals([], $result);
|
||||
}
|
||||
|
||||
public function testFindAllFeed()
|
||||
{
|
||||
$type = FeedType::FEED;
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findAllFeed')
|
||||
->with(
|
||||
$this->equalTo(3),
|
||||
$this->equalTo(20),
|
||||
$this->equalTo(5),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo(false),
|
||||
$this->equalTo('jack'),
|
||||
$this->equalTo([])
|
||||
)
|
||||
->with('jack', 3, 20, 5, true, false, [])
|
||||
->will($this->returnValue(['val']));
|
||||
|
||||
$result = $this->itemService->findAllItems(
|
||||
3, $type, 20, 5,
|
||||
true, false, 'jack'
|
||||
$result = $this->class->findAllInFeedWithFilters(
|
||||
'jack',
|
||||
3,
|
||||
20,
|
||||
5,
|
||||
true,
|
||||
false
|
||||
);
|
||||
$this->assertEquals(['val'], $result);
|
||||
}
|
||||
|
||||
|
||||
public function testFindAllFolder()
|
||||
{
|
||||
$type = FeedType::FOLDER;
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findAllFolder')
|
||||
->with(
|
||||
$this->equalTo(3),
|
||||
$this->equalTo(20),
|
||||
$this->equalTo(5),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo('jack'),
|
||||
$this->equalTo([])
|
||||
)
|
||||
->with('jack', 3, 20, 5, true, true, [])
|
||||
->will($this->returnValue(['val']));
|
||||
|
||||
$result = $this->itemService->findAllItems(
|
||||
3, $type, 20, 5,
|
||||
true, true, 'jack'
|
||||
$result = $this->class->findAllInFolderWithFilters(
|
||||
'jack',
|
||||
3,
|
||||
20,
|
||||
5,
|
||||
true,
|
||||
true,
|
||||
[]
|
||||
);
|
||||
$this->assertEquals(['val'], $result);
|
||||
}
|
||||
|
||||
|
||||
public function testFindAll()
|
||||
public function testFindAllItems()
|
||||
{
|
||||
$type = FeedType::STARRED;
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findAllItems')
|
||||
->with(
|
||||
$this->equalTo(20),
|
||||
$this->equalTo(5),
|
||||
$this->equalTo($type),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo('jack'),
|
||||
$this->equalTo([])
|
||||
)
|
||||
->with('jack', $type, 20, 5, true, [])
|
||||
->will($this->returnValue(['val']));
|
||||
|
||||
$result = $this->itemService->findAllItems(
|
||||
3, $type, 20, 5,
|
||||
true, true, 'jack'
|
||||
);
|
||||
$result = $this->class->findAllWithFilters('jack', $type, 20, 5, true);
|
||||
$this->assertEquals(['val'], $result);
|
||||
}
|
||||
|
||||
|
||||
public function testFindAllSearch()
|
||||
{
|
||||
$type = FeedType::STARRED;
|
||||
$search = ['test'];
|
||||
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findAllItems')
|
||||
->with(
|
||||
$this->equalTo(20),
|
||||
$this->equalTo(5),
|
||||
$this->equalTo($type),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo('jack'),
|
||||
$this->equalTo($search)
|
||||
)
|
||||
->with('jack', $type, 20, 5, true, $search)
|
||||
->will($this->returnValue(['val']));
|
||||
|
||||
$result = $this->itemService->findAllItems(
|
||||
3, $type, 20, 5,
|
||||
true, true, 'jack', $search
|
||||
);
|
||||
$result = $this->class->findAllWithFilters('jack', $type, 20, 5, true, $search);
|
||||
$this->assertEquals(['val'], $result);
|
||||
}
|
||||
|
||||
public function testFindAll()
|
||||
{
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findAll')
|
||||
->will($this->returnValue(['val']));
|
||||
|
||||
$result = $this->class->findAll();
|
||||
$this->assertEquals(['val'], $result);
|
||||
}
|
||||
|
||||
public function testStar()
|
||||
public function testStarByGuid()
|
||||
{
|
||||
$itemId = 3;
|
||||
$feedId = 5;
|
||||
@ -287,20 +226,19 @@ class ItemServiceTest extends TestCase
|
||||
$expectedItem->setId($itemId);
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findByGuidHash')
|
||||
->with($feedId, $guidHash)
|
||||
->method('findForUserByGuidHash')
|
||||
->with('jack', $feedId, $guidHash)
|
||||
->will($this->returnValue($item));
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('update')
|
||||
->with($this->equalTo($expectedItem));
|
||||
|
||||
$this->itemService->star($feedId, $guidHash, true, 'jack');
|
||||
$this->class->starByGuid('jack', $feedId, $guidHash, true);
|
||||
|
||||
$this->assertTrue($item->isStarred());
|
||||
}
|
||||
|
||||
|
||||
public function testUnstar()
|
||||
{
|
||||
$itemId = 3;
|
||||
@ -317,162 +255,111 @@ class ItemServiceTest extends TestCase
|
||||
$expectedItem->setId($itemId);
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findByGuidHash')
|
||||
->with($feedId, $guidHash)
|
||||
->method('findForUserByGuidHash')
|
||||
->with('jack', $feedId, $guidHash)
|
||||
->will($this->returnValue($item));
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('update')
|
||||
->with($this->equalTo($expectedItem));
|
||||
|
||||
$this->itemService->star($feedId, $guidHash, false, 'jack');
|
||||
$this->class->starByGuid('jack', $feedId, $guidHash, false);
|
||||
|
||||
$this->assertFalse($item->isStarred());
|
||||
}
|
||||
|
||||
public function testRead()
|
||||
{
|
||||
$itemId = 3;
|
||||
$item = new Item();
|
||||
$item->setId($itemId);
|
||||
$item->setUnread(true);
|
||||
$item = $this->getMockBuilder(Item::class)
|
||||
->getMock();
|
||||
|
||||
$expectedItem = new Item();
|
||||
$expectedItem->setUnread(false);
|
||||
$expectedItem->setId($itemId);
|
||||
$expectedItem->setLastModified($this->time);
|
||||
$item->expects($this->once())
|
||||
->method('setUnread')
|
||||
->with(false);
|
||||
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
->method('readItem')
|
||||
->with(
|
||||
$this->equalTo($itemId),
|
||||
$this->equalTo(true),
|
||||
$this->equalTo($this->time),
|
||||
$this->equalTo('jack')
|
||||
)
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findFromUser')
|
||||
->with('jack', 3)
|
||||
->will($this->returnValue($item));
|
||||
|
||||
$this->itemService->read($itemId, true, 'jack');
|
||||
$this->mapper->expects($this->once())
|
||||
->method('update')
|
||||
->with($item)
|
||||
->will($this->returnValue($item));
|
||||
|
||||
$this->class->read('jack', 3, true);
|
||||
}
|
||||
|
||||
|
||||
public function testReadDoesNotExist()
|
||||
public function testStar()
|
||||
{
|
||||
$item = $this->getMockBuilder(Item::class)
|
||||
->getMock();
|
||||
|
||||
$this->expectException(ServiceNotFoundException::class);
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
->method('readItem')
|
||||
->will($this->throwException(new DoesNotExistException('')));
|
||||
$item->expects($this->once())
|
||||
->method('setStarred')
|
||||
->with(true);
|
||||
|
||||
$this->itemService->read(1, true, 'jack');
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findFromUser')
|
||||
->with('jack', 3)
|
||||
->will($this->returnValue($item));
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('update')
|
||||
->with($item)
|
||||
->will($this->returnValue($item));
|
||||
|
||||
$this->class->star('jack', 3, true);
|
||||
}
|
||||
|
||||
public function testStarDoesNotExist()
|
||||
public function testStarByGuidDoesNotExist()
|
||||
{
|
||||
|
||||
$this->expectException(ServiceNotFoundException::class);
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findByGuidHash')
|
||||
->method('findForUserByGuidHash')
|
||||
->will($this->throwException(new DoesNotExistException('')));
|
||||
|
||||
$this->itemService->star(1, 'hash', true, 'jack');
|
||||
$this->class->starByGuid('jack', 1, 'hash', true);
|
||||
}
|
||||
|
||||
public function testStarByGuidDuplicate()
|
||||
{
|
||||
|
||||
$this->expectException(ServiceConflictException::class);
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findForUserByGuidHash')
|
||||
->will($this->throwException(new MultipleObjectsReturnedException('')));
|
||||
|
||||
$this->class->starByGuid('jack', 1, 'hash', true);
|
||||
}
|
||||
|
||||
public function testReadAll()
|
||||
{
|
||||
$highestItemId = 6;
|
||||
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
$this->mapper->expects($this->once())
|
||||
->method('readAll')
|
||||
->with(
|
||||
$this->equalTo($highestItemId),
|
||||
$this->equalTo($this->time),
|
||||
$this->equalTo('jack')
|
||||
);
|
||||
->with('jack', $highestItemId);
|
||||
|
||||
$this->itemService->readAll($highestItemId, 'jack');
|
||||
$this->class->readAll('jack', $highestItemId);
|
||||
}
|
||||
|
||||
|
||||
public function testReadFolder()
|
||||
{
|
||||
$folderId = 3;
|
||||
$highestItemId = 6;
|
||||
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
->method('readFolder')
|
||||
->with(
|
||||
$this->equalTo($folderId),
|
||||
$this->equalTo($highestItemId),
|
||||
$this->equalTo($this->time),
|
||||
$this->equalTo('jack')
|
||||
);
|
||||
|
||||
$this->itemService->readFolder($folderId, $highestItemId, 'jack');
|
||||
}
|
||||
|
||||
|
||||
public function testReadFeed()
|
||||
{
|
||||
$feedId = 3;
|
||||
$highestItemId = 6;
|
||||
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
->method('readFeed')
|
||||
->with(
|
||||
$this->equalTo($feedId),
|
||||
$this->equalTo($highestItemId),
|
||||
$this->equalTo($this->time),
|
||||
$this->equalTo('jack')
|
||||
);
|
||||
|
||||
$this->itemService->readFeed($feedId, $highestItemId, 'jack');
|
||||
}
|
||||
|
||||
|
||||
public function testAutoPurgeOldWillPurgeOld()
|
||||
{
|
||||
$this->config->expects($this->once())
|
||||
->method('getAppValue')
|
||||
->with('news', 'autoPurgeCount')
|
||||
->will($this->returnValue(2));
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
->method('deleteReadOlderThanThreshold')
|
||||
->with($this->equalTo(2));
|
||||
|
||||
$this->itemService->autoPurgeOld();
|
||||
}
|
||||
|
||||
public function testAutoPurgeOldWontPurgeOld()
|
||||
{
|
||||
$this->config->expects($this->once())
|
||||
->method('getAppValue')
|
||||
->with('news', 'autoPurgeCount')
|
||||
->will($this->returnValue(-1));
|
||||
$this->oldItemMapper->expects($this->never())
|
||||
->method('deleteReadOlderThanThreshold');
|
||||
|
||||
$this->itemService->autoPurgeOld();
|
||||
}
|
||||
|
||||
|
||||
public function testGetNewestItemId()
|
||||
{
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
$this->mapper->expects($this->once())
|
||||
->method('newest')
|
||||
->with($this->equalTo('jack'))
|
||||
->will($this->returnValue(12));
|
||||
->will($this->returnValue(Item::fromParams(['id' => 12])));
|
||||
|
||||
$result = $this->itemService->getNewestItemId('jack');
|
||||
$this->assertEquals(12, $result);
|
||||
$result = $this->class->newest('jack');
|
||||
$this->assertEquals(12, $result->getId());
|
||||
}
|
||||
|
||||
|
||||
public function testGetNewestItemIdDoesNotExist()
|
||||
{
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
->method('getNewestItemId')
|
||||
$this->mapper->expects($this->once())
|
||||
->method('newest')
|
||||
->with($this->equalTo('jack'))
|
||||
->will(
|
||||
$this->throwException(
|
||||
@ -481,37 +368,266 @@ class ItemServiceTest extends TestCase
|
||||
);
|
||||
|
||||
$this->expectException(ServiceNotFoundException::class);
|
||||
$this->itemService->getNewestItemId('jack');
|
||||
$this->class->newest('jack');
|
||||
}
|
||||
|
||||
public function testGetNewestItemDuplicate()
|
||||
{
|
||||
$this->mapper->expects($this->once())
|
||||
->method('newest')
|
||||
->with($this->equalTo('jack'))
|
||||
->will(
|
||||
$this->throwException(
|
||||
new MultipleObjectsReturnedException('There are no items')
|
||||
)
|
||||
);
|
||||
|
||||
$this->expectException(ServiceConflictException::class);
|
||||
$this->class->newest('jack');
|
||||
}
|
||||
|
||||
public function testStarredCount()
|
||||
{
|
||||
$star = 18;
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findAllFromUser')
|
||||
->with('jack', ['starred' => 1])
|
||||
->will($this->returnValue([new Item(), new Item()]));
|
||||
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
->method('starredCount')
|
||||
->with($this->equalTo('jack'))
|
||||
->will($this->returnValue($star));
|
||||
$result = $this->class->starred('jack');
|
||||
|
||||
$result = $this->itemService->starredCount('jack');
|
||||
|
||||
$this->assertEquals($star, $result);
|
||||
$this->assertEquals(2, count($result));
|
||||
}
|
||||
|
||||
|
||||
public function testGetUnreadOrStarred()
|
||||
public function testInsertOrUpdateInserts()
|
||||
{
|
||||
$this->oldItemMapper->expects($this->once())
|
||||
->method('findAllUnreadOrStarred')
|
||||
->with($this->equalTo('jack'))
|
||||
->will($this->returnValue([]));
|
||||
$item = $this->getMockBuilder(Item::class)
|
||||
->getMock();
|
||||
|
||||
$result = $this->itemService->getUnreadOrStarred('jack');
|
||||
$item->expects($this->once())
|
||||
->method('getFeedId')
|
||||
->will($this->returnValue(1));
|
||||
|
||||
$this->assertEquals([], $result);
|
||||
$item->expects($this->once())
|
||||
->method('getGuidHash')
|
||||
->will($this->returnValue('hash'));
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findByGuidHash')
|
||||
->with(1, 'hash')
|
||||
->will($this->throwException(new DoesNotExistException('exception')));
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('insert')
|
||||
->with($item)
|
||||
->will($this->returnValue($item));
|
||||
|
||||
$result = $this->class->insertOrUpdate($item);
|
||||
|
||||
$this->assertEquals($item, $result);
|
||||
}
|
||||
|
||||
public function testInsertOrUpdateUpdates()
|
||||
{
|
||||
$item = $this->getMockBuilder(Item::class)
|
||||
->getMock();
|
||||
$db_item = $this->getMockBuilder(Item::class)
|
||||
->getMock();
|
||||
|
||||
$item->expects($this->once())
|
||||
->method('getFeedId')
|
||||
->will($this->returnValue(1));
|
||||
|
||||
$item->expects($this->once())
|
||||
->method('getGuidHash')
|
||||
->will($this->returnValue('hash'));
|
||||
|
||||
$item->expects($this->once())
|
||||
->method('setUnread')
|
||||
->with(true)
|
||||
->will($this->returnSelf());
|
||||
|
||||
$db_item->expects($this->once())
|
||||
->method('isUnread')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$item->expects($this->once())
|
||||
->method('setStarred')
|
||||
->with(true)
|
||||
->will($this->returnSelf());
|
||||
|
||||
$db_item->expects($this->once())
|
||||
->method('isStarred')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$item->expects($this->once())
|
||||
->method('generateSearchIndex')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$item->expects($this->once())
|
||||
->method('getFingerprint')
|
||||
->will($this->returnValue('fingerA'));
|
||||
|
||||
$db_item->expects($this->once())
|
||||
->method('getFingerprint')
|
||||
->will($this->returnValue('fingerB'));
|
||||
|
||||
$item->expects($this->never())
|
||||
->method('resetUpdatedFields');
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findByGuidHash')
|
||||
->with(1, 'hash')
|
||||
->will($this->returnValue($db_item));
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('update')
|
||||
->with($item)
|
||||
->will($this->returnValue($item));
|
||||
|
||||
$result = $this->class->insertOrUpdate($item);
|
||||
|
||||
$this->assertEquals($item, $result);
|
||||
}
|
||||
|
||||
public function testInsertOrUpdateSkipsSame()
|
||||
{
|
||||
$item = $this->getMockBuilder(Item::class)
|
||||
->getMock();
|
||||
$db_item = $this->getMockBuilder(Item::class)
|
||||
->getMock();
|
||||
|
||||
$item->expects($this->once())
|
||||
->method('getFeedId')
|
||||
->will($this->returnValue(1));
|
||||
|
||||
$item->expects($this->once())
|
||||
->method('getGuidHash')
|
||||
->will($this->returnValue('hash'));
|
||||
|
||||
$item->expects($this->once())
|
||||
->method('setUnread')
|
||||
->with(true)
|
||||
->will($this->returnSelf());
|
||||
|
||||
$db_item->expects($this->once())
|
||||
->method('isUnread')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$item->expects($this->once())
|
||||
->method('setStarred')
|
||||
->with(true)
|
||||
->will($this->returnSelf());
|
||||
|
||||
$db_item->expects($this->once())
|
||||
->method('isStarred')
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$item->expects($this->once())
|
||||
->method('generateSearchIndex')
|
||||
->will($this->returnSelf());
|
||||
|
||||
$item->expects($this->once())
|
||||
->method('getFingerprint')
|
||||
->will($this->returnValue('fingerA'));
|
||||
|
||||
$db_item->expects($this->once())
|
||||
->method('getFingerprint')
|
||||
->will($this->returnValue('fingerA'));
|
||||
|
||||
$item->expects($this->once())
|
||||
->method('resetUpdatedFields');
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findByGuidHash')
|
||||
->with(1, 'hash')
|
||||
->will($this->returnValue($db_item));
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('update')
|
||||
->with($item)
|
||||
->will($this->returnValue($item));
|
||||
|
||||
$result = $this->class->insertOrUpdate($item);
|
||||
|
||||
$this->assertEquals($item, $result);
|
||||
}
|
||||
|
||||
public function testFindByGuidHash()
|
||||
{
|
||||
$item = $this->getMockBuilder(Item::class)
|
||||
->getMock();
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findByGuidHash')
|
||||
->with(1, 'a')
|
||||
->will($this->returnValue($item));
|
||||
|
||||
$result = $this->class->findByGuidHash(1, 'a');
|
||||
|
||||
$this->assertEquals($item, $result);
|
||||
}
|
||||
|
||||
public function testFindAllInFeed()
|
||||
{
|
||||
$items = [new Item(), new Item()];
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('findAllInFeedAfter')
|
||||
->with('jack', 1, PHP_INT_MIN, false)
|
||||
->will($this->returnValue($items));
|
||||
|
||||
$result = $this->class->findAllInFeed('jack', 1);
|
||||
|
||||
$this->assertEquals($items, $result);
|
||||
}
|
||||
|
||||
public function testPurgeOverThreshold()
|
||||
{
|
||||
$this->mapper->expects($this->once())
|
||||
->method('deleteOverThreshold')
|
||||
->with(1, true)
|
||||
->will($this->returnValue(1));
|
||||
|
||||
$result = $this->class->purgeOverThreshold(1, true);
|
||||
|
||||
$this->assertEquals(1, $result);
|
||||
}
|
||||
|
||||
public function testPurgeOverThresholdWithNegative()
|
||||
{
|
||||
$this->mapper->expects($this->never())
|
||||
->method('deleteOverThreshold');
|
||||
|
||||
$result = $this->class->purgeOverThreshold(-1, true);
|
||||
|
||||
$this->assertEquals(null, $result);
|
||||
}
|
||||
|
||||
public function testPurgeOverThresholdNull()
|
||||
{
|
||||
$this->config->expects($this->once())
|
||||
->method('getAppValue')
|
||||
->with('news', 'autoPurgeCount', 200)
|
||||
->will($this->returnValue(200));
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('deleteOverThreshold')
|
||||
->with(200);
|
||||
|
||||
$this->class->purgeOverThreshold();
|
||||
}
|
||||
|
||||
public function testPurgeOverThresholdSet()
|
||||
{
|
||||
$this->config->expects($this->never())
|
||||
->method('getAppValue')
|
||||
->with('news', 'autoPurgeCount', 200);
|
||||
|
||||
$this->mapper->expects($this->once())
|
||||
->method('deleteOverThreshold')
|
||||
->with(5);
|
||||
|
||||
$this->class->purgeOverThreshold(5);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,8 +14,8 @@
|
||||
namespace OCA\News\Tests\Unit\Service;
|
||||
|
||||
use OCA\News\Db\Feed;
|
||||
use OCA\News\Db\ItemMapper;
|
||||
use OCA\News\Db\ItemMapperV2;
|
||||
use OCA\News\Service\Exceptions\ServiceConflictException;
|
||||
use OCA\News\Service\Exceptions\ServiceNotFoundException;
|
||||
use OCA\News\Service\Service;
|
||||
use \OCP\AppFramework\Db\DoesNotExistException;
|
||||
@ -112,7 +112,7 @@ class ServiceTest extends TestCase
|
||||
->method('findFromUser')
|
||||
->will($this->throwException($ex));
|
||||
|
||||
$this->expectException(ServiceNotFoundException::class);
|
||||
$this->expectException(ServiceConflictException::class);
|
||||
$this->class->find('', 1);
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<files psalm-version="4.4.1@9fd7a7d885b3a216cff8dec9d8c21a132f275224">
|
||||
<file src="lib/AppInfo/Application.php">
|
||||
<MissingDependency occurrences="5">
|
||||
<MissingDependency occurrences="4">
|
||||
<code>$fs</code>
|
||||
<code>$fs</code>
|
||||
<code>$fs</code>
|
||||
<code>BeforeUserDeletedEvent</code>
|
||||
<code>IRootFolder</code>
|
||||
</MissingDependency>
|
||||
</file>
|
||||
@ -21,18 +20,30 @@
|
||||
</InvalidReturnType>
|
||||
</file>
|
||||
<file src="lib/Hooks/UserDeleteHook.php">
|
||||
<MissingDependency occurrences="2">
|
||||
<code>BeforeUserDeletedEvent</code>
|
||||
<code>UserDeleteHook</code>
|
||||
</MissingDependency>
|
||||
<MoreSpecificImplementedParamType occurrences="1">
|
||||
<code>$event</code>
|
||||
</MoreSpecificImplementedParamType>
|
||||
</file>
|
||||
<file src="lib/Service/Exceptions/ServiceConflictException.php">
|
||||
<MoreSpecificImplementedParamType occurrences="1">
|
||||
<code>$exception</code>
|
||||
</MoreSpecificImplementedParamType>
|
||||
</file>
|
||||
<file src="lib/Service/Exceptions/ServiceNotFoundException.php">
|
||||
<MoreSpecificImplementedParamType occurrences="1">
|
||||
<code>$exception</code>
|
||||
</MoreSpecificImplementedParamType>
|
||||
</file>
|
||||
<file src="lib/Service/Exceptions/ServiceValidationException.php">
|
||||
<MoreSpecificImplementedParamType occurrences="1">
|
||||
<code>$exception</code>
|
||||
</MoreSpecificImplementedParamType>
|
||||
</file>
|
||||
<file src="lib/Service/FeedServiceV2.php">
|
||||
<UndefinedMethod occurrences="2">
|
||||
<UndefinedMethod occurrences="3">
|
||||
<code>findAllFromFolder</code>
|
||||
<code>findByURL</code>
|
||||
<code>read</code>
|
||||
</UndefinedMethod>
|
||||
</file>
|
||||
<file src="lib/Service/FolderServiceV2.php">
|
||||
@ -43,18 +54,23 @@
|
||||
<code>$this->timeFactory</code>
|
||||
<code>TimeFactory</code>
|
||||
</UndefinedDocblockClass>
|
||||
</file>
|
||||
<file src="lib/Service/ItemService.php">
|
||||
<UndefinedMethod occurrences="1">
|
||||
<code>findByGuidHash</code>
|
||||
<code>read</code>
|
||||
</UndefinedMethod>
|
||||
</file>
|
||||
<file src="lib/Service/ItemServiceV2.php">
|
||||
<UndefinedMethod occurrences="4">
|
||||
<UndefinedMethod occurrences="11">
|
||||
<code>deleteOverThreshold</code>
|
||||
<code>findAllForFeed</code>
|
||||
<code>findByGuidHash</code>
|
||||
<code>findAllAfter</code>
|
||||
<code>findAllFeed</code>
|
||||
<code>findAllFolder</code>
|
||||
<code>findAllInFeedAfter</code>
|
||||
<code>findAllInFolderAfter</code>
|
||||
<code>findAllItems</code>
|
||||
<code>findByGuidHash</code>
|
||||
<code>findForUserByGuidHash</code>
|
||||
<code>newest</code>
|
||||
<code>readAll</code>
|
||||
</UndefinedMethod>
|
||||
</file>
|
||||
</files>
|
||||
|
Loading…
Reference in New Issue
Block a user