Create V2 mapper, Service and management commands

Signed-off-by: Sean Molenaar <sean@seanmolenaar.eu>
This commit is contained in:
Sean Molenaar 2020-08-29 23:39:35 +02:00 коммит произвёл Benjamin Brahmer
Родитель 5687baca75
Коммит d00d1ab2a2
79 изменённых файлов: 2436 добавлений и 563 удалений

7
.github/workflows/integration-tests.yml поставляемый
Просмотреть файл

@ -100,9 +100,16 @@ jobs:
run: | run: |
cd ../server cd ../server
./occ news:generate-explore --votes 100 "https://nextcloud.com/blog/feed/" ./occ news:generate-explore --votes 100 "https://nextcloud.com/blog/feed/"
./occ news:folder:add 'admin' 'Something'
./occ news:folder:list 'admin' | grep 'Something'
./occ news:folder:delete 'admin' $(./occ news:folder:list 'admin' | grep 'Something' -1 | head -1 | grep -oE '[0-9]*')
./occ news:feed:add 'admin' "https://nextcloud.com/blog/feed/"
./occ news:feed:list 'admin' | grep 'nextcloud\.com'
./occ news:feed:delete 'admin' $(./occ news:feed:list 'admin' | grep 'nextcloud\.com' -1 | head -1 | grep -oE '[0-9]*')
- name: Prep PHP tests - name: Prep PHP tests
run: cd ../server/apps/news && make php-test-dependencies run: cd ../server/apps/news && make php-test-dependencies
- name: Integration tests - name: Integration tests
run: cd ../server/apps/news && make integration-test run: cd ../server/apps/news && make integration-test

Просмотреть файл

@ -130,6 +130,7 @@
* [blackcrack](mailto:blackcrack@blackysgate.de) * [blackcrack](mailto:blackcrack@blackysgate.de)
* [comradekingu](mailto:epost@anotheragency.no) * [comradekingu](mailto:epost@anotheragency.no)
* [e-alfred](mailto:e-alfred@users.noreply.github.com) * [e-alfred](mailto:e-alfred@users.noreply.github.com)
* [fran-penedo](mailto:fran@franpenedo.com)
* [joeplus](mailto:joerg@honululu.Speedport_W_723V_1_32_000) * [joeplus](mailto:joerg@honululu.Speedport_W_723V_1_32_000)
* [kesselb](mailto:mail@danielkesselberg.de) * [kesselb](mailto:mail@danielkesselberg.de)
* [kondou](mailto:kondou@ts.unde.re) * [kondou](mailto:kondou@ts.unde.re)

Просмотреть файл

@ -58,6 +58,13 @@ Before you update to a new version, [check the changelog](https://github.com/nex
<command>OCA\News\Command\Updater\UpdateFeed</command> <command>OCA\News\Command\Updater\UpdateFeed</command>
<command>OCA\News\Command\Updater\BeforeUpdate</command> <command>OCA\News\Command\Updater\BeforeUpdate</command>
<command>OCA\News\Command\Updater\AfterUpdate</command> <command>OCA\News\Command\Updater\AfterUpdate</command>
<command>OCA\News\Command\Config\FolderList</command>
<command>OCA\News\Command\Config\FolderAdd</command>
<command>OCA\News\Command\Config\FolderDelete</command>
<command>OCA\News\Command\Config\FeedList</command>
<command>OCA\News\Command\Config\FeedAdd</command>
<command>OCA\News\Command\Config\FeedDelete</command>
<command>OCA\News\Command\Config\FeedDelete</command>
</commands> </commands>
<settings> <settings>

Просмотреть файл

@ -50,7 +50,8 @@
"ext-json": "*", "ext-json": "*",
"ext-simplexml": "*", "ext-simplexml": "*",
"ext-libxml": "*", "ext-libxml": "*",
"andreskrey/readability.php": "^2.1" "andreskrey/readability.php": "^2.1",
"ext-dom": "*"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "9.2.6", "phpunit/phpunit": "9.2.6",

15
composer.lock сгенерированный
Просмотреть файл

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "d026de8b34993e486d928ef4c509676d", "content-hash": "0f4161d1df33ea0b72224da925f2f6b5",
"packages": [ "packages": [
{ {
"name": "andreskrey/readability.php", "name": "andreskrey/readability.php",
@ -826,16 +826,16 @@
}, },
{ {
"name": "phpstan/phpstan", "name": "phpstan/phpstan",
"version": "0.12.44", "version": "0.12.45",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpstan/phpstan.git", "url": "https://github.com/phpstan/phpstan.git",
"reference": "330b45776ea77f167b150e24787412414a8fa469" "reference": "90c67259212ed891ee86604a9368ef7d7bead3a4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/330b45776ea77f167b150e24787412414a8fa469", "url": "https://api.github.com/repos/phpstan/phpstan/zipball/90c67259212ed891ee86604a9368ef7d7bead3a4",
"reference": "330b45776ea77f167b150e24787412414a8fa469", "reference": "90c67259212ed891ee86604a9368ef7d7bead3a4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@ -878,7 +878,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2020-09-24T15:28:47+00:00" "time": "2020-09-26T19:19:00+00:00"
}, },
{ {
"name": "phpunit/php-code-coverage", "name": "phpunit/php-code-coverage",
@ -2422,7 +2422,8 @@
"php": "^7.2", "php": "^7.2",
"ext-json": "*", "ext-json": "*",
"ext-simplexml": "*", "ext-simplexml": "*",
"ext-libxml": "*" "ext-libxml": "*",
"ext-dom": "*"
}, },
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "1.1.0" "plugin-api-version": "1.1.0"

Просмотреть файл

@ -0,0 +1,72 @@
<?php
declare(strict_types=1);
namespace OCA\News\Command\Config;
use OCA\News\Service\FeedServiceV2;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class FeedAdd extends Command
{
/**
* @var FeedServiceV2 service for the feeds.
*/
protected $feedService;
/**
* FeedAdd constructor.
*
* @param FeedServiceV2 $feedService
*/
public function __construct(FeedServiceV2 $feedService)
{
parent::__construct(null);
$this->feedService = $feedService;
}
/**
* Configure command
*/
protected function configure()
{
$this->setName('news:feed:add')
->setDescription('Add a feed')
->addArgument('userID', InputArgument::REQUIRED, 'User to add the feed for')
->addArgument('feed', InputArgument::REQUIRED, 'Feed to parse')
->addOption('folder', null, InputOption::VALUE_OPTIONAL, 'Folder ID')
->addOption('title', null, InputOption::VALUE_OPTIONAL, 'Feed title')
->addOption('full-text', null, InputOption::VALUE_OPTIONAL, 'Scrape item URLs', false)
->addOption('username', null, InputOption::VALUE_OPTIONAL, 'Basic auth username')
->addOption('password', null, InputOption::VALUE_OPTIONAL, 'Basic auth password');
}
/**
* Execute command
*
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$url = $input->getArgument('feed');
$user = $input->getArgument('userID');
$folder = (int) $input->getOption('folder') ?? 0;
$title = $input->getOption('title');
$username = $input->getOption('username');
$full_text = $input->getOption('full-text');
$password = $input->getOption('password');
$feed = $this->feedService->create($user, $url, $folder, $full_text, $title, $username, $password);
$this->feedService->fetch($feed, true);
$output->writeln(json_encode($feed->toAPI(), JSON_PRETTY_PRINT));
return 0;
}
}

Просмотреть файл

@ -0,0 +1,56 @@
<?php
namespace OCA\News\Command\Config;
use OCA\News\Db\Feed;
use OCA\News\Service\FeedServiceV2;
use OCA\News\Service\FolderServiceV2;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class FeedDelete extends Command
{
/**
* @var FeedServiceV2 service for the feeds.
*/
protected $feedService;
public function __construct(FeedServiceV2 $feedService)
{
parent::__construct(null);
$this->feedService = $feedService;
}
/**
* Configure command
*/
protected function configure()
{
$this->setName('news:feed:delete')
->setDescription('Remove a feed')
->addArgument('userID', InputArgument::REQUIRED, 'User to remove the feed from')
->addArgument('id', InputArgument::REQUIRED, 'Feed ID', null);
}
/**
* Execute command
*
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$user = $input->getArgument('userID');
$id = $input->getArgument('id');
$this->feedService->delete($user, $id);
return 0;
}
}

Просмотреть файл

@ -0,0 +1,61 @@
<?php
namespace OCA\News\Command\Config;
use OCA\News\Controller\ApiPayloadTrait;
use OCA\News\Service\FeedServiceV2;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class FeedList extends Command
{
use ApiPayloadTrait;
/**
* @var FeedServiceV2 service for the feeds.
*/
protected $feedService;
public function __construct(FeedServiceV2 $feedService)
{
parent::__construct(null);
$this->feedService = $feedService;
}
/**
* Configure command
*/
protected function configure()
{
$this->setName('news:feed:list')
->setDescription('List all feeds')
->addArgument('userID', InputArgument::REQUIRED, 'User to list the feeds for')
->addOption('recursive', null, InputOption::VALUE_NONE, 'Fetch the feed recursively');
}
/**
* Execute command
*
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int|void
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$user = $input->getArgument('userID');
$recursive = $input->getOption('recursive');
if ($recursive !== false) {
$feeds = $this->feedService->findAllForUserRecursive($user);
} else {
$feeds = $this->feedService->findAllForUser($user);
}
$output->writeln(json_encode($this->serialize($feeds), JSON_PRETTY_PRINT));
}
}

Просмотреть файл

@ -0,0 +1,58 @@
<?php
namespace OCA\News\Command\Config;
use OCA\News\Db\Feed;
use OCA\News\Service\FeedServiceV2;
use OCA\News\Service\FolderServiceV2;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class FolderAdd extends Command
{
/**
* @var FolderServiceV2 service for the folders.
*/
protected $folderService;
public function __construct(FolderServiceV2 $folderService)
{
parent::__construct(null);
$this->folderService = $folderService;
}
/**
* Configure command
*/
protected function configure()
{
$this->setName('news:folder:add')
->setDescription('Add a folder')
->addArgument('userID', InputArgument::REQUIRED, 'User to add the folder for')
->addArgument('name', InputArgument::REQUIRED, 'Folder name', null)
->addOption('parent', null, InputOption::VALUE_OPTIONAL, 'Parent folder');
}
/**
* Execute command
*
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$user = $input->getArgument('userID');
$name = $input->getArgument('name');
$parent = $input->getOption('parent') ?? 0;
$this->folderService->create($user, $name, $parent);
return 0;
}
}

Просмотреть файл

@ -0,0 +1,61 @@
<?php
namespace OCA\News\Command\Config;
use OCA\News\Db\Feed;
use OCA\News\Service\Exceptions\ServiceException;
use OCA\News\Service\FeedServiceV2;
use OCA\News\Service\FolderServiceV2;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class FolderDelete extends Command
{
/**
* @var FolderServiceV2 service for the folders.
*/
protected $folderService;
public function __construct(FolderServiceV2 $folderService)
{
parent::__construct(null);
$this->folderService = $folderService;
}
/**
* Configure command
*/
protected function configure()
{
$this->setName('news:folder:delete')
->setDescription('Remove a folder')
->addArgument('userID', InputArgument::REQUIRED, 'User to remove the folder from')
->addArgument('id', InputArgument::REQUIRED, 'Folder ID', null);
}
/**
* Execute command
*
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int
*/
protected function execute(InputInterface $input, OutputInterface $output): int
{
$user = $input->getArgument('userID');
$id = $input->getArgument('id');
if ($id === '0') {
throw new ServiceException('Can not remove root folder!');
}
$this->folderService->delete($user, $id);
return 0;
}
}

Просмотреть файл

@ -0,0 +1,62 @@
<?php
namespace OCA\News\Command\Config;
use OCA\News\Controller\ApiPayloadTrait;
use OCA\News\Service\FeedServiceV2;
use OCA\News\Service\FolderServiceV2;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
class FolderList extends Command
{
use ApiPayloadTrait;
/**
* @var FolderServiceV2 service for the folders.
*/
protected $folderService;
public function __construct(FolderServiceV2 $folderService)
{
parent::__construct(null);
$this->folderService = $folderService;
}
/**
* Configure command
*/
protected function configure()
{
$this->setName('news:folder:list')
->setDescription('List all folders')
->addArgument('userID', InputArgument::REQUIRED, 'User to list the folders for')
->addOption('recursive', null, InputOption::VALUE_NONE, 'Fetch the folder recursively');
}
/**
* Execute command
*
* @param InputInterface $input
* @param OutputInterface $output
*
* @return int|void
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$user = $input->getArgument('userID');
$recursive = $input->getOption('recursive');
if ($recursive !== false) {
$folders = $this->folderService->findAllForUserRecursive($user);
} else {
$folders = $this->folderService->findAllForUser($user);
}
$output->writeln(json_encode($this->serialize($folders), JSON_PRETTY_PRINT));
}
}

Просмотреть файл

@ -64,7 +64,7 @@ class ExploreGenerator extends Command
->addOption('votes', null, InputOption::VALUE_OPTIONAL, 'Votes for the feed, defaults to 100'); ->addOption('votes', null, InputOption::VALUE_OPTIONAL, 'Votes for the feed, defaults to 100');
} }
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output): int
{ {
$url = $input->getArgument('feed'); $url = $input->getArgument('feed');
$votes = $input->getOption('votes'); $votes = $input->getOption('votes');
@ -85,6 +85,7 @@ class ExploreGenerator extends Command
]; ];
$output->writeln(json_encode($result, JSON_PRETTY_PRINT)); $output->writeln(json_encode($result, JSON_PRETTY_PRINT));
return 0;
} catch (\Throwable $ex) { } catch (\Throwable $ex) {
$output->writeln('<error>Failed to fetch feed info:</error>'); $output->writeln('<error>Failed to fetch feed info:</error>');
$output->writeln($ex->getMessage()); $output->writeln($ex->getMessage());

Просмотреть файл

@ -60,7 +60,7 @@ class ShowFeed extends Command
->addOption('full-text', 'f', InputOption::VALUE_NONE, 'Usa a scraper to get full text'); ->addOption('full-text', 'f', InputOption::VALUE_NONE, 'Usa a scraper to get full text');
} }
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output): int
{ {
$url = $input->getArgument('feed'); $url = $input->getArgument('feed');
$user = $input->getOption('user'); $user = $input->getOption('user');
@ -71,6 +71,7 @@ class ShowFeed extends Command
list($feed, $items) = $this->feedFetcher->fetch($url, true, null, $fullTextEnabled, $user, $password); list($feed, $items) = $this->feedFetcher->fetch($url, true, null, $fullTextEnabled, $user, $password);
$output->writeln("Feed: " . json_encode($feed, JSON_PRETTY_PRINT)); $output->writeln("Feed: " . json_encode($feed, JSON_PRETTY_PRINT));
$output->writeln("Items: " . json_encode($items, JSON_PRETTY_PRINT)); $output->writeln("Items: " . json_encode($items, JSON_PRETTY_PRINT));
return 0;
} catch (\Throwable $ex) { } catch (\Throwable $ex) {
$output->writeln('<error>Failed to fetch feed info:</error>'); $output->writeln('<error>Failed to fetch feed info:</error>');
$output->writeln($ex->getMessage()); $output->writeln($ex->getMessage());

Просмотреть файл

@ -11,35 +11,43 @@
namespace OCA\News\Command\Updater; namespace OCA\News\Command\Updater;
use Exception; use OCA\News\Service\ItemServiceV2;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use \OCA\News\Utility\Updater;
class AfterUpdate extends Command class AfterUpdate extends Command
{ {
private $updater; /**
* @var ItemServiceV2
*/
private $itemService;
public function __construct(Updater $updater) /**
* AfterUpdate constructor.
*
* @param ItemServiceV2 $itemService
*/
public function __construct(ItemServiceV2 $itemService)
{ {
parent::__construct(); parent::__construct();
$this->updater = $updater; $this->itemService = $itemService;
} }
protected function configure() protected function configure()
{ {
$this->setName('news:updater:after-update') $this->setName('news:updater:after-update')
->setDescription( ->setDescription('removes old read articles which are not starred')
'This is used to clean up the database. It ' . ->addArgument('purge_count', InputArgument::OPTIONAL, 'The amount of items to purge');
'removes old read articles which are not starred'
);
} }
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output): int
{ {
$this->updater->afterUpdate(); $count = $input->getArgument('id');
echo $this->itemService->purgeOverThreshold($count);
return 0;
} }
} }

Просмотреть файл

@ -11,19 +11,24 @@
namespace OCA\News\Command\Updater; namespace OCA\News\Command\Updater;
use Exception; use OCA\News\Service\FeedServiceV2;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use OCA\News\Service\FeedService;
class AllFeeds extends Command class AllFeeds extends Command
{ {
/**
* @var FeedServiceV2 Feed service
*/
private $feedService; private $feedService;
public function __construct(FeedService $feedService) /**
* AllFeeds constructor.
*
* @param FeedServiceV2 $feedService
*/
public function __construct(FeedServiceV2 $feedService)
{ {
parent::__construct(); parent::__construct();
$this->feedService = $feedService; $this->feedService = $feedService;
@ -35,6 +40,7 @@ class AllFeeds extends Command
$this->setName('news:updater:all-feeds') $this->setName('news:updater:all-feeds')
->setDescription( ->setDescription(
'DEPRECATED: use news:feed:list instead.' . PHP_EOL .
'Prints a JSON string which contains all feed ' . 'Prints a JSON string which contains all feed ' .
'ids and user ids, e.g.: ' . $json 'ids and user ids, e.g.: ' . $json
); );
@ -42,7 +48,7 @@ class AllFeeds extends Command
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$feeds = $this->feedService->findAllFromAllUsers(); $feeds = $this->feedService->findAll();
$result = ['feeds' => []]; $result = ['feeds' => []];
foreach ($feeds as $feed) { foreach ($feeds as $feed) {
@ -53,6 +59,6 @@ class AllFeeds extends Command
]; ];
} }
print(json_encode($result)); $output->write(json_encode($result));
} }
} }

Просмотреть файл

@ -11,22 +11,22 @@
namespace OCA\News\Command\Updater; namespace OCA\News\Command\Updater;
use Exception; use OCA\News\Service\UpdaterService;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Output\OutputInterface;
use \OCA\News\Utility\Updater;
class BeforeUpdate extends Command class BeforeUpdate extends Command
{ {
private $updater; /**
* @var UpdaterService Updater
*/
private $updaterService;
public function __construct(Updater $updater) public function __construct(UpdaterService $updater)
{ {
parent::__construct(); parent::__construct();
$this->updater = $updater; $this->updaterService = $updater;
} }
protected function configure() protected function configure()
@ -39,8 +39,10 @@ class BeforeUpdate extends Command
); );
} }
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output): int
{ {
$this->updater->beforeUpdate(); $this->updaterService->beforeUpdate();
return 0;
} }
} }

Просмотреть файл

@ -13,6 +13,7 @@ namespace OCA\News\Command\Updater;
use Exception; use Exception;
use OCA\News\Service\FeedServiceV2;
use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputInterface;
@ -22,9 +23,12 @@ use OCA\News\Service\FeedService;
class UpdateFeed extends Command class UpdateFeed extends Command
{ {
/**
* @var FeedServiceV2 Feed service
*/
private $feedService; private $feedService;
public function __construct(FeedService $feedService) public function __construct(FeedServiceV2 $feedService)
{ {
parent::__construct(); parent::__construct();
$this->feedService = $feedService; $this->feedService = $feedService;
@ -33,25 +37,26 @@ class UpdateFeed extends Command
protected function configure() protected function configure()
{ {
$this->setName('news:updater:update-feed') $this->setName('news:updater:update-feed')
->addArgument(
'feed-id',
InputArgument::REQUIRED,
'feed id, integer'
)
->addArgument( ->addArgument(
'user-id', 'user-id',
InputArgument::REQUIRED, InputArgument::REQUIRED,
'user id of a user, string' 'user id of a user, string'
) )
->addArgument(
'feed-id',
InputArgument::REQUIRED,
'feed id, integer'
)
->setDescription('Console API for updating a single user\'s feed'); ->setDescription('Console API for updating a single user\'s feed');
} }
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output): int
{ {
$feedId = $input->getArgument('feed-id'); $feedId = $input->getArgument('feed-id');
$userId = $input->getArgument('user-id'); $userId = $input->getArgument('user-id');
try { try {
$this->feedService->update($feedId, $userId); $feed = $this->feedService->findForUser($userId, $feedId);
$this->feedService->fetch($feed);
} catch (Exception $e) { } catch (Exception $e) {
$output->writeln( $output->writeln(
'<error>Could not update feed with id ' . $feedId . '<error>Could not update feed with id ' . $feedId .
@ -59,5 +64,7 @@ class UpdateFeed extends Command
'</error> ' '</error> '
); );
} }
return 0;
} }
} }

Просмотреть файл

@ -0,0 +1,36 @@
<?php
namespace OCA\News\Controller;
use OCA\News\Db\IAPI;
trait ApiPayloadTrait
{
/**
* Serialize all data
*
* @param mixed $data IAPI or array,
* anything else will return an empty array
*
* @return array
*/
public function serialize($data): array
{
$return = [];
if ($data instanceof IAPI) {
return [$data->toAPI()];
}
if (!is_array($data)) {
return $return;
}
foreach ($data as $entity) {
if ($entity instanceof IAPI) {
$return[] = $entity->toAPI();
}
}
return $return;
}
}

Просмотреть файл

@ -13,6 +13,12 @@ namespace OCA\News\Controller;
use \OCA\News\Db\IAPI; use \OCA\News\Db\IAPI;
/**
* Class EntityApiSerializer
*
* @package OCA\News\Controller
* @deprecated use ApiPayloadTrait
*/
class EntityApiSerializer class EntityApiSerializer
{ {

Просмотреть файл

@ -15,6 +15,9 @@
namespace OCA\News\Controller; namespace OCA\News\Controller;
use OCA\News\Service\Exceptions\ServiceConflictException;
use OCA\News\Service\Exceptions\ServiceNotFoundException;
use OCA\News\Utility\PsrLogger;
use \OCP\IRequest; use \OCP\IRequest;
use \OCP\ILogger; use \OCP\ILogger;
use \OCP\IUserSession; use \OCP\IUserSession;
@ -22,17 +25,30 @@ use \OCP\AppFramework\Http;
use \OCA\News\Service\FeedService; use \OCA\News\Service\FeedService;
use \OCA\News\Service\ItemService; use \OCA\News\Service\ItemService;
use \OCA\News\Service\ServiceNotFoundException; use Psr\Log\LoggerInterface;
use \OCA\News\Service\ServiceConflictException;
class FeedApiController extends ApiController class FeedApiController extends ApiController
{ {
use JSONHttpError; use JSONHttpError;
/**
* @var ItemService
*/
private $itemService; private $itemService;
/**
* @var FeedService
*/
private $feedService; private $feedService;
/**
* @var LoggerInterface
*/
private $logger; private $logger;
private $loggerParams;
/**
* @var EntityApiSerializer
*/
private $serializer; private $serializer;
public function __construct( public function __construct(
@ -41,14 +57,12 @@ class FeedApiController extends ApiController
IUserSession $userSession, IUserSession $userSession,
FeedService $feedService, FeedService $feedService,
ItemService $itemService, ItemService $itemService,
ILogger $logger, LoggerInterface $logger
$LoggerParameters
) { ) {
parent::__construct($appName, $request, $userSession); parent::__construct($appName, $request, $userSession);
$this->feedService = $feedService; $this->feedService = $feedService;
$this->itemService = $itemService; $this->itemService = $itemService;
$this->logger = $logger; $this->logger = $logger;
$this->loggerParams = $LoggerParameters;
$this->serializer = new EntityApiSerializer('feeds'); $this->serializer = new EntityApiSerializer('feeds');
} }
@ -63,7 +77,7 @@ class FeedApiController extends ApiController
$result = [ $result = [
'starredCount' => $this->itemService->starredCount($this->getUserId()), 'starredCount' => $this->itemService->starredCount($this->getUserId()),
'feeds' => $this->feedService->findAll($this->getUserId()) 'feeds' => $this->feedService->findAllForUser($this->getUserId())
]; ];
@ -226,13 +240,10 @@ class FeedApiController extends ApiController
public function update($userId, $feedId) public function update($userId, $feedId)
{ {
try { try {
$this->feedService->update($feedId, $userId); $this->feedService->update($userId, $feedId);
// ignore update failure // ignore update failure
} catch (\Exception $ex) { } catch (\Exception $ex) {
$this->logger->debug( $this->logger->debug('Could not update feed ' . $ex->getMessage());
'Could not update feed ' . $ex->getMessage(),
$this->loggerParams
);
} }
} }
} }

Просмотреть файл

@ -13,6 +13,8 @@
namespace OCA\News\Controller; namespace OCA\News\Controller;
use OCA\News\Service\Exceptions\ServiceConflictException;
use OCA\News\Service\Exceptions\ServiceNotFoundException;
use OCP\IRequest; use OCP\IRequest;
use OCP\IConfig; use OCP\IConfig;
use OCP\AppFramework\Controller; use OCP\AppFramework\Controller;
@ -21,8 +23,6 @@ use OCP\AppFramework\Http;
use OCA\News\Service\ItemService; use OCA\News\Service\ItemService;
use OCA\News\Service\FeedService; use OCA\News\Service\FeedService;
use OCA\News\Service\FolderService; use OCA\News\Service\FolderService;
use OCA\News\Service\ServiceNotFoundException;
use OCA\News\Service\ServiceConflictException;
use OCA\News\Db\FeedType; use OCA\News\Db\FeedType;
class FeedController extends Controller class FeedController extends Controller
@ -63,7 +63,7 @@ class FeedController extends Controller
// because of this we also pass the starred count and the newest // because of this we also pass the starred count and the newest
// item id which will be used for marking feeds read // item id which will be used for marking feeds read
$params = [ $params = [
'feeds' => $this->feedService->findAll($this->userId), 'feeds' => $this->feedService->findAllForUser($this->userId),
'starred' => $this->itemService->starredCount($this->userId) 'starred' => $this->itemService->starredCount($this->userId)
]; ];
@ -104,9 +104,9 @@ class FeedController extends Controller
// check if feed or folder exists // check if feed or folder exists
try { try {
if ($feedType === FeedType::FOLDER) { if ($feedType === FeedType::FOLDER) {
$this->folderService->find($feedId, $this->userId); $this->folderService->find($this->userId, $feedId);
} elseif ($feedType === FeedType::FEED) { } elseif ($feedType === FeedType::FEED) {
$this->feedService->find($feedId, $this->userId); $this->feedService->find($this->userId, $feedId);
// if its the first launch, those values will be null // if its the first launch, those values will be null
} elseif ($feedType === null) { } elseif ($feedType === null) {
@ -203,7 +203,7 @@ class FeedController extends Controller
public function update($feedId) public function update($feedId)
{ {
try { try {
$feed = $this->feedService->update($feedId, $this->userId); $feed = $this->feedService->update($this->userId, $feedId);
return [ return [
'feeds' => [ 'feeds' => [

Просмотреть файл

@ -21,9 +21,9 @@ use \OCP\AppFramework\Http;
use \OCA\News\Service\FolderService; use \OCA\News\Service\FolderService;
use \OCA\News\Service\ItemService; use \OCA\News\Service\ItemService;
use \OCA\News\Service\ServiceNotFoundException; use \OCA\News\Service\Exceptions\ServiceNotFoundException;
use \OCA\News\Service\ServiceConflictException; use \OCA\News\Service\Exceptions\ServiceConflictException;
use \OCA\News\Service\ServiceValidationException; use \OCA\News\Service\Exceptions\ServiceValidationException;
class FolderApiController extends ApiController class FolderApiController extends ApiController
{ {

Просмотреть файл

@ -20,9 +20,9 @@ use \OCP\AppFramework\Http;
use \OCA\News\Service\FolderService; use \OCA\News\Service\FolderService;
use \OCA\News\Service\FeedService; use \OCA\News\Service\FeedService;
use \OCA\News\Service\ItemService; use \OCA\News\Service\ItemService;
use \OCA\News\Service\ServiceNotFoundException; use \OCA\News\Service\Exceptions\ServiceNotFoundException;
use \OCA\News\Service\ServiceConflictException; use \OCA\News\Service\Exceptions\ServiceConflictException;
use \OCA\News\Service\ServiceValidationException; use \OCA\News\Service\Exceptions\ServiceValidationException;
class FolderController extends Controller class FolderController extends Controller
{ {

Просмотреть файл

@ -20,7 +20,7 @@ use \OCP\IUserSession;
use \OCP\AppFramework\Http; use \OCP\AppFramework\Http;
use \OCA\News\Service\ItemService; use \OCA\News\Service\ItemService;
use \OCA\News\Service\ServiceNotFoundException; use \OCA\News\Service\Exceptions\ServiceNotFoundException;
class ItemApiController extends ApiController class ItemApiController extends ApiController
{ {
@ -223,7 +223,7 @@ class ItemApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @CORS * @CORS
* *
* @param int[] item ids * @param int[] $items item ids
*/ */
public function readMultiple($items) public function readMultiple($items)
{ {
@ -236,7 +236,7 @@ class ItemApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @CORS * @CORS
* *
* @param int[] item ids * @param int[] $items item ids
*/ */
public function unreadMultiple($items) public function unreadMultiple($items)
{ {
@ -266,7 +266,7 @@ class ItemApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @CORS * @CORS
* *
* @param int[] item ids * @param int[] $items item ids
*/ */
public function starMultiple($items) public function starMultiple($items)
{ {
@ -279,7 +279,7 @@ class ItemApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @CORS * @CORS
* *
* @param int[] item ids * @param int[] $items item ids
*/ */
public function unstarMultiple($items) public function unstarMultiple($items)
{ {

Просмотреть файл

@ -18,8 +18,8 @@ use \OCP\IConfig;
use \OCP\AppFramework\Controller; use \OCP\AppFramework\Controller;
use \OCP\AppFramework\Http; use \OCP\AppFramework\Http;
use \OCA\News\Service\ServiceException; use \OCA\News\Service\Exceptions\ServiceException;
use \OCA\News\Service\ServiceNotFoundException; use \OCA\News\Service\Exceptions\ServiceNotFoundException;
use \OCA\News\Service\ItemService; use \OCA\News\Service\ItemService;
use \OCA\News\Service\FeedService; use \OCA\News\Service\FeedService;
@ -245,7 +245,7 @@ class ItemController extends Controller
/** /**
* @NoAdminRequired * @NoAdminRequired
* *
* @param int[] item ids * @param int[] $itemIds item ids
*/ */
public function readMultiple($itemIds) public function readMultiple($itemIds)
{ {

Просмотреть файл

@ -18,10 +18,9 @@ trait JSONHttpError
/** /**
* @param \Exception $exception the message that is returned taken from the * @param \Exception $exception The exception to report
* exception * @param int $code The http error code
* @param int $code the http error code * @return JSONResponse
* @return \OCP\AppFramework\Http\JSONResponse
*/ */
public function error(\Exception $exception, $code) public function error(\Exception $exception, $code)
{ {

Просмотреть файл

@ -15,18 +15,17 @@
namespace OCA\News\Controller; namespace OCA\News\Controller;
use OCA\News\Service\UpdaterService;
use \OCP\IRequest; use \OCP\IRequest;
use \OCP\IConfig; use \OCP\IConfig;
use \OCP\IUserSession; use \OCP\IUserSession;
use \OCP\AppFramework\Http;
use \OCA\News\Utility\Updater;
use \OCA\News\Service\StatusService; use \OCA\News\Service\StatusService;
class UtilityApiController extends ApiController class UtilityApiController extends ApiController
{ {
private $updater; private $updaterService;
private $settings; private $settings;
private $statusService; private $statusService;
@ -34,12 +33,12 @@ class UtilityApiController extends ApiController
$appName, $appName,
IRequest $request, IRequest $request,
IUserSession $userSession, IUserSession $userSession,
Updater $updater, UpdaterService $updater,
IConfig $settings, IConfig $settings,
StatusService $statusService StatusService $statusService
) { ) {
parent::__construct($appName, $request, $userSession); parent::__construct($appName, $request, $userSession);
$this->updater = $updater; $this->updaterService = $updater;
$this->settings = $settings; $this->settings = $settings;
$this->statusService = $statusService; $this->statusService = $statusService;
} }
@ -50,7 +49,7 @@ class UtilityApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @CORS * @CORS
*/ */
public function version() public function version(): array
{ {
$version = $this->settings->getAppValue( $version = $this->settings->getAppValue(
$this->appName, $this->appName,
@ -64,9 +63,9 @@ class UtilityApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @CORS * @CORS
*/ */
public function beforeUpdate() public function beforeUpdate(): void
{ {
$this->updater->beforeUpdate(); $this->updaterService->beforeUpdate();
} }
@ -74,9 +73,9 @@ class UtilityApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @CORS * @CORS
*/ */
public function afterUpdate() public function afterUpdate(): void
{ {
$this->updater->afterUpdate(); $this->updaterService->afterUpdate();
} }
@ -85,7 +84,7 @@ class UtilityApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @NoAdminRequired * @NoAdminRequired
*/ */
public function status() public function status(): array
{ {
return $this->statusService->getStatus(); return $this->statusService->getStatus();
} }

Просмотреть файл

@ -15,10 +15,10 @@ use OC\BackgroundJob\TimedJob;
use OCA\News\AppInfo\Application; use OCA\News\AppInfo\Application;
use OCA\News\Service\StatusService; use OCA\News\Service\StatusService;
use OCA\News\Utility\Updater as UpdaterService; use OCA\News\Service\UpdaterService;
use OCP\IConfig; use OCP\IConfig;
class Updater extends TimedJob class UpdaterJob extends TimedJob
{ {
/** /**
@ -28,7 +28,7 @@ class Updater extends TimedJob
/** /**
* @var StatusService * @var StatusService
*/ */
private $status; private $statusService;
/** /**
* @var UpdaterService * @var UpdaterService
*/ */
@ -40,7 +40,7 @@ class Updater extends TimedJob
UpdaterService $updaterService UpdaterService $updaterService
) { ) {
$this->config = $config; $this->config = $config;
$this->status = $status; $this->statusService = $status;
$this->updaterService = $updaterService; $this->updaterService = $updaterService;
$interval = $this->config->getAppValue( $interval = $this->config->getAppValue(
@ -60,10 +60,12 @@ class Updater extends TimedJob
Application::DEFAULT_SETTINGS['useCronUpdates'] Application::DEFAULT_SETTINGS['useCronUpdates']
); );
if ($uses_cron && $this->status->isProperlyConfigured()) { if (!$uses_cron || !$this->statusService->isProperlyConfigured()) {
$this->updaterService->beforeUpdate(); return;
$this->updaterService->update();
$this->updaterService->afterUpdate();
} }
$this->updaterService->beforeUpdate();
$this->updaterService->update();
$this->updaterService->afterUpdate();
} }
} }

Просмотреть файл

@ -15,6 +15,12 @@ namespace OCA\News\Db;
use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\Entity;
/**
* Class Feed
*
* @package OCA\News\Db
* @Embeddable
*/
class Feed extends Entity implements IAPI, \JsonSerializable class Feed extends Entity implements IAPI, \JsonSerializable
{ {
use EntityJSONSerializer; use EntityJSONSerializer;
@ -67,6 +73,8 @@ class Feed extends Entity implements IAPI, \JsonSerializable
protected $basicAuthUser = ''; protected $basicAuthUser = '';
/** @var string|null */ /** @var string|null */
protected $basicAuthPassword = ''; protected $basicAuthPassword = '';
/** @var Item[] */
public $items = [];
/** /**
* @return int|null * @return int|null
@ -135,7 +143,7 @@ class Feed extends Entity implements IAPI, \JsonSerializable
/** /**
* @return string|null * @return string|null
*/ */
public function getHttpEtag() public function getHttpEtag(): ?string
{ {
return $this->httpEtag; return $this->httpEtag;
} }
@ -143,7 +151,7 @@ class Feed extends Entity implements IAPI, \JsonSerializable
/** /**
* @return string|null * @return string|null
*/ */
public function getHttpLastModified() public function getHttpLastModified(): ?string
{ {
return $this->httpLastModified; return $this->httpLastModified;
} }
@ -313,250 +321,294 @@ class Feed extends Entity implements IAPI, \JsonSerializable
/** /**
* @param int|null $added * @param int|null $added
*/ */
public function setAdded(int $added = null) public function setAdded(int $added = null): Feed
{ {
if ($this->added !== $added) { if ($this->added !== $added) {
$this->added = $added; $this->added = $added;
$this->markFieldUpdated('added'); $this->markFieldUpdated('added');
} }
return $this;
} }
/** /**
* @param int $articlesPerUpdate * @param int $articlesPerUpdate
*/ */
public function setArticlesPerUpdate(int $articlesPerUpdate) public function setArticlesPerUpdate(int $articlesPerUpdate): Feed
{ {
if ($this->articlesPerUpdate !== $articlesPerUpdate) { if ($this->articlesPerUpdate !== $articlesPerUpdate) {
$this->articlesPerUpdate = $articlesPerUpdate; $this->articlesPerUpdate = $articlesPerUpdate;
$this->markFieldUpdated('articlesPerUpdate'); $this->markFieldUpdated('articlesPerUpdate');
} }
return $this;
} }
/** /**
* @param string|null $basicAuthPassword * @param string|null $basicAuthPassword
*/ */
public function setBasicAuthPassword(string $basicAuthPassword = null) public function setBasicAuthPassword(string $basicAuthPassword = null): Feed
{ {
if ($this->basicAuthPassword !== $basicAuthPassword) { if ($this->basicAuthPassword !== $basicAuthPassword) {
$this->basicAuthPassword = $basicAuthPassword; $this->basicAuthPassword = $basicAuthPassword;
$this->markFieldUpdated('basicAuthPassword'); $this->markFieldUpdated('basicAuthPassword');
} }
return $this;
} }
/** /**
* @param string|null $basicAuthUser * @param string|null $basicAuthUser
*/ */
public function setBasicAuthUser(string $basicAuthUser = null) public function setBasicAuthUser(string $basicAuthUser = null): Feed
{ {
if ($this->basicAuthUser !== $basicAuthUser) { if ($this->basicAuthUser !== $basicAuthUser) {
$this->basicAuthUser = $basicAuthUser; $this->basicAuthUser = $basicAuthUser;
$this->markFieldUpdated('basicAuthUser'); $this->markFieldUpdated('basicAuthUser');
} }
return $this;
} }
/** /**
* @param int|null $deletedAt * @param int|null $deletedAt
*/ */
public function setDeletedAt(int $deletedAt = null) public function setDeletedAt(int $deletedAt = null): Feed
{ {
if ($this->deletedAt !== $deletedAt) { if ($this->deletedAt !== $deletedAt) {
$this->deletedAt = $deletedAt; $this->deletedAt = $deletedAt;
$this->markFieldUpdated('deletedAt'); $this->markFieldUpdated('deletedAt');
} }
return $this;
} }
/** /**
* @param string|null $faviconLink * @param string|null $faviconLink
*/ */
public function setFaviconLink(string $faviconLink = null) public function setFaviconLink(string $faviconLink = null): Feed
{ {
if ($this->faviconLink !== $faviconLink) { if ($this->faviconLink !== $faviconLink) {
$this->faviconLink = $faviconLink; $this->faviconLink = $faviconLink;
$this->markFieldUpdated('faviconLink'); $this->markFieldUpdated('faviconLink');
} }
return $this;
} }
/** /**
* @param int $folderId * @param int $folderId
*/ */
public function setFolderId(int $folderId) public function setFolderId(int $folderId): Feed
{ {
if ($this->folderId !== $folderId) { if ($this->folderId !== $folderId) {
$this->folderId = $folderId; $this->folderId = $folderId;
$this->markFieldUpdated('folderId'); $this->markFieldUpdated('folderId');
} }
return $this;
} }
/** /**
* @param bool $fullTextEnabled * @param bool $fullTextEnabled
*/ */
public function setFullTextEnabled(bool $fullTextEnabled) public function setFullTextEnabled(bool $fullTextEnabled): Feed
{ {
if ($this->fullTextEnabled !== $fullTextEnabled) { if ($this->fullTextEnabled !== $fullTextEnabled) {
$this->fullTextEnabled = $fullTextEnabled; $this->fullTextEnabled = $fullTextEnabled;
$this->markFieldUpdated('fullTextEnabled'); $this->markFieldUpdated('fullTextEnabled');
} }
return $this;
} }
/** /**
* @param string|null $httpEtag * @param string|null $httpEtag
*/ */
public function setHttpEtag(string $httpEtag = null) public function setHttpEtag(string $httpEtag = null): Feed
{ {
if ($this->httpEtag !== $httpEtag) { if ($this->httpEtag !== $httpEtag) {
$this->httpEtag = $httpEtag; $this->httpEtag = $httpEtag;
$this->markFieldUpdated('httpEtag'); $this->markFieldUpdated('httpEtag');
} }
return $this;
} }
/** /**
* @param string|null $httpLastModified * @param string|null $httpLastModified
*/ */
public function setHttpLastModified(string $httpLastModified = null) public function setHttpLastModified(string $httpLastModified = null): Feed
{ {
if ($this->httpLastModified !== $httpLastModified) { if ($this->httpLastModified !== $httpLastModified) {
$this->httpLastModified = $httpLastModified; $this->httpLastModified = $httpLastModified;
$this->markFieldUpdated('httpLastModified'); $this->markFieldUpdated('httpLastModified');
} }
return $this;
} }
/** /**
* @param int $id * @param int $id
*/ */
public function setId(int $id) public function setId(int $id): Feed
{ {
if ($this->id !== $id) { if ($this->id !== $id) {
$this->id = $id; $this->id = $id;
$this->markFieldUpdated('id'); $this->markFieldUpdated('id');
} }
return $this;
} }
/** /**
* @param string|null $lastModified * @param string|null $lastModified
*/ */
public function setLastModified(string $lastModified = null) public function setLastModified(string $lastModified = null): Feed
{ {
if ($this->lastModified !== $lastModified) { if ($this->lastModified !== $lastModified) {
$this->lastModified = $lastModified; $this->lastModified = $lastModified;
$this->markFieldUpdated('lastModified'); $this->markFieldUpdated('lastModified');
} }
return $this;
} }
/** /**
* @param string|null $lastUpdateError * @param string|null $lastUpdateError
*/ */
public function setLastUpdateError(string $lastUpdateError = null) public function setLastUpdateError(string $lastUpdateError = null): Feed
{ {
if ($this->lastUpdateError !== $lastUpdateError) { if ($this->lastUpdateError !== $lastUpdateError) {
$this->lastUpdateError = $lastUpdateError; $this->lastUpdateError = $lastUpdateError;
$this->markFieldUpdated('lastUpdateError'); $this->markFieldUpdated('lastUpdateError');
} }
return $this;
} }
/** /**
* @param string|null $link * @param string|null $link
*/ */
public function setLink(string $link = null) public function setLink(string $link = null): Feed
{ {
$link = trim($link); $link = trim($link);
if (strpos($link, 'http') === 0 && $this->link !== $link) { if (strpos($link, 'http') === 0 && $this->link !== $link) {
$this->link = $link; $this->link = $link;
$this->markFieldUpdated('link'); $this->markFieldUpdated('link');
} }
return $this;
} }
/** /**
* @param string|null $location * @param string|null $location
*/ */
public function setLocation(string $location = null) public function setLocation(string $location = null): Feed
{ {
if ($this->location !== $location) { if ($this->location !== $location) {
$this->location = $location; $this->location = $location;
$this->markFieldUpdated('location'); $this->markFieldUpdated('location');
} }
return $this;
} }
/** /**
* @param int $ordering * @param int $ordering
*/ */
public function setOrdering(int $ordering) public function setOrdering(int $ordering): Feed
{ {
if ($this->ordering !== $ordering) { if ($this->ordering !== $ordering) {
$this->ordering = $ordering; $this->ordering = $ordering;
$this->markFieldUpdated('ordering'); $this->markFieldUpdated('ordering');
} }
return $this;
} }
/** /**
* @param bool $pinned * @param bool $pinned
*/ */
public function setPinned(bool $pinned) public function setPinned(bool $pinned): Feed
{ {
if ($this->pinned !== $pinned) { if ($this->pinned !== $pinned) {
$this->pinned = $pinned; $this->pinned = $pinned;
$this->markFieldUpdated('pinned'); $this->markFieldUpdated('pinned');
} }
return $this;
} }
/** /**
* @param bool $preventUpdate * @param bool $preventUpdate
*/ */
public function setPreventUpdate(bool $preventUpdate) public function setPreventUpdate(bool $preventUpdate): Feed
{ {
if ($this->preventUpdate !== $preventUpdate) { if ($this->preventUpdate !== $preventUpdate) {
$this->preventUpdate = $preventUpdate; $this->preventUpdate = $preventUpdate;
$this->markFieldUpdated('preventUpdate'); $this->markFieldUpdated('preventUpdate');
} }
return $this;
} }
/** /**
* @param string $title * @param string $title
*/ */
public function setTitle(string $title) public function setTitle(string $title): Feed
{ {
if ($this->title !== $title) { if ($this->title !== $title) {
$this->title = $title; $this->title = $title;
$this->markFieldUpdated('title'); $this->markFieldUpdated('title');
} }
return $this;
} }
/** /**
* @param int $unreadCount * @param int $unreadCount
*/ */
public function setUnreadCount(int $unreadCount) public function setUnreadCount(int $unreadCount): Feed
{ {
if ($this->unreadCount !== $unreadCount) { if ($this->unreadCount !== $unreadCount) {
$this->unreadCount = $unreadCount; $this->unreadCount = $unreadCount;
$this->markFieldUpdated('unreadCount'); $this->markFieldUpdated('unreadCount');
} }
return $this;
} }
/** /**
* @param int $updateErrorCount * @param int $updateErrorCount
*/ */
public function setUpdateErrorCount(int $updateErrorCount) public function setUpdateErrorCount(int $updateErrorCount): Feed
{ {
if ($this->updateErrorCount !== $updateErrorCount) { if ($this->updateErrorCount !== $updateErrorCount) {
$this->updateErrorCount = $updateErrorCount; $this->updateErrorCount = $updateErrorCount;
$this->markFieldUpdated('updateErrorCount'); $this->markFieldUpdated('updateErrorCount');
} }
return $this;
} }
/** /**
* @param int $updateMode * @param int $updateMode
*/ */
public function setUpdateMode(int $updateMode) public function setUpdateMode(int $updateMode): Feed
{ {
if ($this->updateMode !== $updateMode) { if ($this->updateMode !== $updateMode) {
$this->updateMode = $updateMode; $this->updateMode = $updateMode;
$this->markFieldUpdated('updateMode'); $this->markFieldUpdated('updateMode');
} }
return $this;
} }
/** /**
* @param string $url * @param string $url
*/ */
public function setUrl(string $url) public function setUrl(string $url): Feed
{ {
$url = trim($url); $url = trim($url);
if (strpos($url, 'http') === 0 && $this->url !== $url) { if (strpos($url, 'http') === 0 && $this->url !== $url) {
@ -564,28 +616,34 @@ class Feed extends Entity implements IAPI, \JsonSerializable
$this->setUrlHash(md5($url)); $this->setUrlHash(md5($url));
$this->markFieldUpdated('url'); $this->markFieldUpdated('url');
} }
return $this;
} }
/** /**
* @param string $urlHash * @param string $urlHash
*/ */
public function setUrlHash(string $urlHash) public function setUrlHash(string $urlHash): Feed
{ {
if ($this->urlHash !== $urlHash) { if ($this->urlHash !== $urlHash) {
$this->urlHash = $urlHash; $this->urlHash = $urlHash;
$this->markFieldUpdated('urlHash'); $this->markFieldUpdated('urlHash');
} }
return $this;
} }
/** /**
* @param string $userId * @param string $userId
*/ */
public function setUserId(string $userId) public function setUserId(string $userId): Feed
{ {
if ($this->userId !== $userId) { if ($this->userId !== $userId) {
$this->userId = $userId; $this->userId = $userId;
$this->markFieldUpdated('userId'); $this->markFieldUpdated('userId');
} }
return $this;
} }
public function toAPI(): array public function toAPI(): array
@ -603,7 +661,8 @@ class Feed extends Entity implements IAPI, \JsonSerializable
'link', 'link',
'pinned', 'pinned',
'updateErrorCount', 'updateErrorCount',
'lastUpdateError' 'lastUpdateError',
'items'
] ]
); );
} }

Просмотреть файл

@ -14,20 +14,28 @@
namespace OCA\News\Db; namespace OCA\News\Db;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\IDBConnection; use OCP\IDBConnection;
use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\Entity;
/**
* Class LegacyFeedMapper
*
* @package OCA\News\Db
* @deprecated use FeedMapper
*/
class FeedMapper extends NewsMapper class FeedMapper extends NewsMapper
{ {
const TABLE_NAME = 'news_feeds';
public function __construct(IDBConnection $db, Time $time) public function __construct(IDBConnection $db, Time $time)
{ {
parent::__construct($db, 'news_feeds', Feed::class, $time); parent::__construct($db, $time, Feed::class);
} }
public function find($id, $userId) public function find(string $userId, int $id)
{ {
$sql = 'SELECT `feeds`.*, `item_numbers`.`unread_count` ' . $sql = 'SELECT `feeds`.*, `item_numbers`.`unread_count` ' .
'FROM `*PREFIX*news_feeds` `feeds` ' . 'FROM `*PREFIX*news_feeds` `feeds` ' .
@ -52,7 +60,7 @@ class FeedMapper extends NewsMapper
} }
public function findAllFromUser($userId) public function findAllFromUser(string $userId): array
{ {
$sql = 'SELECT `feeds`.*, `item_numbers`.`unread_count` ' . $sql = 'SELECT `feeds`.*, `item_numbers`.`unread_count` ' .
'FROM `*PREFIX*news_feeds` `feeds` ' . 'FROM `*PREFIX*news_feeds` `feeds` ' .
@ -82,7 +90,7 @@ class FeedMapper extends NewsMapper
} }
public function findAll() public function findAll(): array
{ {
$sql = 'SELECT `feeds`.*, `item_numbers`.`unread_count` ' . $sql = 'SELECT `feeds`.*, `item_numbers`.`unread_count` ' .
'FROM `*PREFIX*news_feeds` `feeds` ' . 'FROM `*PREFIX*news_feeds` `feeds` ' .
@ -135,15 +143,15 @@ class FeedMapper extends NewsMapper
} }
public function delete(Entity $entity) public function delete(Entity $entity): Entity
{ {
parent::delete($entity);
// someone please slap me for doing this manually :P // someone please slap me for doing this manually :P
// we needz CASCADE + FKs please // we needz CASCADE + FKs please
$sql = 'DELETE FROM `*PREFIX*news_items` WHERE `feed_id` = ?'; $sql = 'DELETE FROM `*PREFIX*news_items` WHERE `feed_id` = ?';
$params = [$entity->getId()]; $params = [$entity->getId()];
$this->execute($sql, $params); $this->execute($sql, $params);
return parent::delete($entity);
} }
@ -186,4 +194,9 @@ class FeedMapper extends NewsMapper
$sql = 'DELETE FROM `*PREFIX*news_feeds` WHERE `user_id` = ?'; $sql = 'DELETE FROM `*PREFIX*news_feeds` WHERE `user_id` = ?';
$this->execute($sql, [$userId]); $this->execute($sql, [$userId]);
} }
public function findFromUser(string $userId, int $id): Entity
{
return $this->find($id, $userId);
}
} }

141
lib/Db/FeedMapperV2.php Normal file
Просмотреть файл

@ -0,0 +1,141 @@
<?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\MultipleObjectsReturnedException;
use OCP\IDBConnection;
use OCP\AppFramework\Db\Entity;
/**
* Class FeedMapper
*
* @package OCA\News\Db
*/
class FeedMapperV2 extends NewsMapperV2
{
const TABLE_NAME = 'news_feeds';
/**
* FeedMapper constructor.
*
* @param IDBConnection $db
* @param Time $time
*/
public function __construct(IDBConnection $db, Time $time)
{
parent::__construct($db, $time, Feed::class);
}
/**
* Find all feeds for a user.
*
* @param string $userId The user identifier
*
* @return Entity[]
*/
public function findAllFromUser(string $userId): array
{
$builder = $this->db->getQueryBuilder();
$builder->addSelect('*')
->from($this->tableName)
->where('user_id = :user_id')
->andWhere('deleted_at = 0')
->setParameter(':user_id', $userId);
return $this->findEntities($builder);
}
/**
* Find all feeds for a user.
*
* @param string $userId The user identifier
* @param int $id The feed identifier
*
* @return Entity
*
* @throws DoesNotExistException
* @throws MultipleObjectsReturnedException
*/
public function findFromUser(string $userId, int $id): Entity
{
$builder = $this->db->getQueryBuilder();
$builder->addSelect('*')
->from($this->tableName)
->where('user_id = :user_id')
->where('id = :id')
->setParameter(':user_id', $userId)
->setParameter(':id', $id);
return $this->findEntity($builder);
}
/**
* Find all items
*
* @return Entity[]
*/
public function findAll(): array
{
$builder = $this->db->getQueryBuilder();
$builder->select('*')
->from($this->tableName)
->where('deleted_at = 0');
return $this->findEntities($builder);
}
/**
* Find feed by URL
*
* @param string $userId The user to find in.
* @param string $url The URL to find
*
* @return Entity
*
* @throws DoesNotExistException If not found
* @throws MultipleObjectsReturnedException If multiple found
*/
public function findByURL(string $userId, string $url): Entity
{
$builder = $this->db->getQueryBuilder();
$builder->addSelect('*')
->from($this->tableName)
->where('user_id = :user_id')
->andWhere('url = :url')
->setParameter(':user_id', $userId)
->setParameter(':url', $url);
return $this->findEntity($builder);
}
/**
* Find all feeds in a folder
*
* @param int $id ID of the folder
*
* @return Feed[]
*/
public function findAllFromFolder(int $id): array
{
$builder = $this->db->getQueryBuilder();
$builder->addSelect('*')
->from($this->tableName)
->where('folder_id = :folder_id')
->setParameter(':folder_id', $id);
return $this->findEntities($builder);
}
}

Просмотреть файл

@ -31,6 +31,8 @@ class Folder extends Entity implements IAPI, \JsonSerializable
protected $deletedAt = 0; protected $deletedAt = 0;
/** @var string|null */ /** @var string|null */
protected $lastModified = '0'; protected $lastModified = '0';
/** @var Feed[] */
public $feeds = [];
/** /**
* @return int|null * @return int|null
@ -134,7 +136,7 @@ class Folder extends Entity implements IAPI, \JsonSerializable
} }
} }
public function setParentId(int $parentId = null) public function setParentId(int $parentId = 0)
{ {
if ($this->parentId !== $parentId) { if ($this->parentId !== $parentId) {
$this->parentId = $parentId; $this->parentId = $parentId;
@ -155,7 +157,8 @@ class Folder extends Entity implements IAPI, \JsonSerializable
return $this->serializeFields( return $this->serializeFields(
[ [
'id', 'id',
'name' 'name',
'feeds'
] ]
); );
} }

Просмотреть файл

@ -14,18 +14,28 @@
namespace OCA\News\Db; namespace OCA\News\Db;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\IDBConnection; use OCP\IDBConnection;
use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\Entity;
/**
* Class LegacyFolderMapper
*
* @package OCA\News\Db
* @deprecated use FolderMapper
*/
class FolderMapper extends NewsMapper class FolderMapper extends NewsMapper
{ {
const TABLE_NAME = 'news_folders';
public function __construct(IDBConnection $db, Time $time) public function __construct(IDBConnection $db, Time $time)
{ {
parent::__construct($db, 'news_folders', Folder::class, $time); parent::__construct($db, $time, Folder::class);
} }
public function find($id, $userId) public function find(string $userId, int $id)
{ {
$sql = 'SELECT * FROM `*PREFIX*news_folders` ' . $sql = 'SELECT * FROM `*PREFIX*news_folders` ' .
'WHERE `id` = ? ' . 'WHERE `id` = ? ' .
@ -35,7 +45,7 @@ class FolderMapper extends NewsMapper
} }
public function findAllFromUser($userId) public function findAllFromUser(string $userId): array
{ {
$sql = 'SELECT * FROM `*PREFIX*news_folders` ' . $sql = 'SELECT * FROM `*PREFIX*news_folders` ' .
'WHERE `user_id` = ? ' . 'WHERE `user_id` = ? ' .
@ -46,7 +56,7 @@ class FolderMapper extends NewsMapper
} }
public function findByName($folderName, $userId) public function findByName(string $folderName, string $userId)
{ {
$sql = 'SELECT * FROM `*PREFIX*news_folders` ' . $sql = 'SELECT * FROM `*PREFIX*news_folders` ' .
'WHERE `name` = ? ' . 'WHERE `name` = ? ' .
@ -57,7 +67,7 @@ class FolderMapper extends NewsMapper
} }
public function delete(Entity $entity) public function delete(Entity $entity): Entity
{ {
parent::delete($entity); parent::delete($entity);
@ -73,6 +83,8 @@ class FolderMapper extends NewsMapper
$stmt = $this->execute($sql); $stmt = $this->execute($sql);
$stmt->closeCursor(); $stmt->closeCursor();
return $entity;
} }
@ -109,9 +121,23 @@ class FolderMapper extends NewsMapper
* *
* @param string $userId the name of the user * @param string $userId the name of the user
*/ */
public function deleteUser($userId) public function deleteUser(string $userId)
{ {
$sql = 'DELETE FROM `*PREFIX*news_folders` WHERE `user_id` = ?'; $sql = 'DELETE FROM `*PREFIX*news_folders` WHERE `user_id` = ?';
$this->execute($sql, [$userId]); $this->execute($sql, [$userId]);
} }
/**
* NO-OP
* @return array
*/
public function findAll(): array
{
return [];
}
public function findFromUser(string $userId, int $id): Entity
{
return $this->find($id, $userId);
}
} }

87
lib/Db/FolderMapperV2.php Normal file
Просмотреть файл

@ -0,0 +1,87 @@
<?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\Entity;
use OCP\IDBConnection;
/**
* Class FolderMapper
*
* @package OCA\News\Db
*/
class FolderMapperV2 extends NewsMapperV2
{
const TABLE_NAME = 'news_folders';
/**
* FolderMapper constructor.
*
* @param IDBConnection $db
* @param Time $time
*/
public function __construct(IDBConnection $db, Time $time)
{
parent::__construct($db, $time, Folder::class);
}
/**
* Find all feeds for a user.
*
* @param string $userId The user identifier
*
* @return Entity[]
*/
public function findAllFromUser($userId): array
{
$builder = $this->db->getQueryBuilder();
$builder->select('*')
->from($this->tableName)
->where('user_id = :user_id')
->where('deleted_at = 0')
->setParameter(':user_id', $userId);
return $this->findEntities($builder);
}
/**
* Find all items
*
* @return Entity[]
*/
public function findAll(): array
{
$builder = $this->db->getQueryBuilder();
$builder->select('*')
->from($this->tableName)
->where('deleted_at = 0');
return $this->findEntities($builder);
}
public function findFromUser(string $userId, int $id): Entity
{
$builder = $this->db->getQueryBuilder();
$builder->select('*')
->from($this->tableName)
->where('user_id = :user_id')
->where('id = :id')
->where('deleted_at = 0')
->setParameter(':user_id', $userId)
->setParameter(':id', $id);
return $this->findEntity($builder);
}
}

Просмотреть файл

@ -15,6 +15,12 @@ namespace OCA\News\Db;
use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\Entity;
/**
* Class Item
*
* @package OCA\News\Db
* @Embeddable
*/
class Item extends Entity implements IAPI, \JsonSerializable class Item extends Entity implements IAPI, \JsonSerializable
{ {
use EntityJSONSerializer; use EntityJSONSerializer;

Просмотреть файл

@ -15,15 +15,25 @@ namespace OCA\News\Db;
use Exception; use Exception;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection; use OCP\IDBConnection;
/**
* Class LegacyItemMapper
*
* @package OCA\News\Db
* @deprecated use ItemMapper
*/
class ItemMapper extends NewsMapper class ItemMapper extends NewsMapper
{ {
const TABLE_NAME = 'news_items';
public function __construct(IDBConnection $db, Time $time) public function __construct(IDBConnection $db, Time $time)
{ {
parent::__construct($db, 'news_items', Item::class, $time); parent::__construct($db, $time, Item::class);
} }
private function makeSelectQuery( private function makeSelectQuery(
@ -99,13 +109,13 @@ class ItemMapper extends NewsMapper
* @param string $userId * @param string $userId
* @return \OCA\News\Db\Item * @return \OCA\News\Db\Item
*/ */
public function find($id, $userId) public function find(string $userId, int $id)
{ {
$sql = $this->makeSelectQuery('AND `items`.`id` = ? '); $sql = $this->makeSelectQuery('AND `items`.`id` = ? ');
return $this->findEntity($sql, [$userId, $id]); return $this->findEntity($sql, [$userId, $id]);
} }
public function starredCount($userId) public function starredCount(string $userId)
{ {
$sql = 'SELECT COUNT(*) AS size FROM `*PREFIX*news_items` `items` ' . $sql = 'SELECT COUNT(*) AS size FROM `*PREFIX*news_items` `items` ' .
'JOIN `*PREFIX*news_feeds` `feeds` ' . 'JOIN `*PREFIX*news_feeds` `feeds` ' .
@ -126,7 +136,7 @@ class ItemMapper extends NewsMapper
} }
public function readAll($highestItemId, $time, $userId) public function readAll(int $highestItemId, $time, string $userId)
{ {
$sql = 'UPDATE `*PREFIX*news_items` ' . $sql = 'UPDATE `*PREFIX*news_items` ' .
'SET unread = ? ' . 'SET unread = ? ' .
@ -221,7 +231,7 @@ class ItemMapper extends NewsMapper
} }
private function findEntitiesIgnoringNegativeLimit($sql, $params, $limit) private function findEntitiesIgnoringNegativeLimit($sql, $params, $limit): array
{ {
// ignore limit if negative to offer a way to return all feeds // ignore limit if negative to offer a way to return all feeds
if ($limit >= 0) { if ($limit >= 0) {
@ -286,7 +296,7 @@ class ItemMapper extends NewsMapper
} }
public function findAll( public function findAllItems(
$limit, $limit,
$offset, $offset,
$type, $type,
@ -294,7 +304,7 @@ class ItemMapper extends NewsMapper
$oldestFirst, $oldestFirst,
$userId, $userId,
$search = [] $search = []
) { ): array {
$params = [$userId]; $params = [$userId];
$params = array_merge($params, $this->buildLikeParameters($search)); $params = array_merge($params, $this->buildLikeParameters($search));
$sql = $this->buildStatusQueryPart($showAll, $type); $sql = $this->buildStatusQueryPart($showAll, $type);
@ -457,7 +467,7 @@ class ItemMapper extends NewsMapper
public function readItem($itemId, $isRead, $lastModified, $userId) public function readItem($itemId, $isRead, $lastModified, $userId)
{ {
$item = $this->find($itemId, $userId); $item = $this->find($userId, $itemId);
// reading an item should set all of the same items as read, whereas // reading an item should set all of the same items as read, whereas
// marking an item as unread should only mark the selected instance // marking an item as unread should only mark the selected instance
@ -479,4 +489,30 @@ class ItemMapper extends NewsMapper
$this->update($item); $this->update($item);
} }
} }
/**
* NO-OP
*
* @param string $userId
*
* @return array
*/
public function findAllFromUser(string $userId): array
{
return [];
}
public function findFromUser(string $userId, int $id): Entity
{
return $this->find($id, $userId);
}
/**
* NO-OP
* @return array
*/
public function findAll(): array
{
return [];
}
} }

124
lib/Db/ItemMapperV2.php Normal file
Просмотреть файл

@ -0,0 +1,124 @@
<?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 2020 Sean Molenaar
*/
namespace OCA\News\Db;
use Doctrine\DBAL\FetchMode;
use OCA\News\Utility\Time;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\Entity;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
/**
* Class ItemMapper
*
* @package OCA\News\Db
*/
class ItemMapperV2 extends NewsMapperV2
{
const TABLE_NAME = 'news_items';
/**
* ItemMapper constructor.
*
* @param IDBConnection $db
* @param Time $time
*/
public function __construct(IDBConnection $db, Time $time)
{
parent::__construct($db, $time, Item::class);
}
/**
* Find all feeds for a user.
*
* @param string $userId The user identifier
*
* @return Entity[]
*/
public function findAllFromUser($userId): array
{
$builder = $this->db->getQueryBuilder();
$builder->select('items.*')
->from($this->tableName)
->innerJoin('items', FeedMapperV2::TABLE_NAME, 'feeds', 'items.feed_id = feeds.id')
->where('feeds.user_id = :user_id')
->andWhere('deleted_at = 0')
->setParameter(':user_id', $userId, IQueryBuilder::PARAM_STR);
return $this->findEntities($builder);
}
/**
* Find all items
*
* @return Entity[]
*/
public function findAll(): array
{
$builder = $this->db->getQueryBuilder();
$builder->addSelect('*')
->from($this->tableName)
->andWhere('deleted_at = 0');
return $this->findEntities($builder);
}
public function findFromUser(string $userId, int $id): Entity
{
$builder = $this->db->getQueryBuilder();
$builder->select('items.*')
->from($this->tableName)
->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')
->setParameter(':user_id', $userId, IQueryBuilder::PARAM_STR)
->setParameter(':item_id', $id, IQueryBuilder::PARAM_STR);
return $this->findEntity($builder);
}
public function findByGuidHash(string $getGuidHash): Item
{
throw new DoesNotExistException('fasi');
}
public function findAllForFeed(int $feedId)
{
$builder = $this->db->getQueryBuilder();
$builder->addSelect('*')
->from($this->tableName)
->andWhere('feed_id = :feed_id')
->setParameter(':feed_id', $feedId, IQueryBuilder::PARAM_INT);
return $this->findEntities($builder);
}
/**
* Delete items from feed that are over the max item threshold
*
* @param int $threshold Deletion threshold
*/
public function deleteOverThreshold($threshold)
{
$builder = $this->db->getQueryBuilder();
$query = $builder->addSelect('COUNT(*)')
->from($this->tableName)
->groupBy('feed_id')
->where('');
return $this->db->executeQuery($query)->fetch(FetchMode::ASSOCIATIVE);
}
}

Просмотреть файл

@ -19,6 +19,12 @@ use OCP\IDBConnection;
use OCA\News\Db\Mysql\ItemMapper as MysqlItemMapper; use OCA\News\Db\Mysql\ItemMapper as MysqlItemMapper;
use OCA\News\DependencyInjection\IFactory; use OCA\News\DependencyInjection\IFactory;
/**
* Class LegacyMapperFactory
*
* @package OCA\News\Db
* @deprecated not needed in modern system
*/
class MapperFactory implements IFactory class MapperFactory implements IFactory
{ {

Просмотреть файл

@ -16,6 +16,12 @@ namespace OCA\News\Db\Mysql;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
use OCP\IDBConnection; use OCP\IDBConnection;
/**
* Class LegacyItemMapper
*
* @package OCA\News\Db\Mysql
* @deprecated use normal ItemMapper
*/
class ItemMapper extends \OCA\News\Db\ItemMapper class ItemMapper extends \OCA\News\Db\ItemMapper
{ {

Просмотреть файл

@ -14,47 +14,101 @@
namespace OCA\News\Db; namespace OCA\News\Db;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\AppFramework\Db\QBMapper;
use OCP\IDBConnection; use OCP\IDBConnection;
use OCP\AppFramework\Db\Mapper; use OCP\AppFramework\Db\Mapper;
use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\Entity;
/**
* Class NewsMapper
*
* @package OCA\News\Db
*/
abstract class NewsMapper extends Mapper abstract class NewsMapper extends Mapper
{ {
const TABLE_NAME = '';
/** /**
* @var Time * @var Time
*/ */
private $time; private $time;
/**
* NewsMapper constructor.
*
* @param IDBConnection $db Database connection
* @param Time $time Time class
* @param string $entity Entity class
*/
public function __construct( public function __construct(
IDBConnection $db, IDBConnection $db,
$table, Time $time,
$entity, string $entity
Time $time
) { ) {
parent::__construct($db, $table, $entity); parent::__construct($db, static::TABLE_NAME, $entity);
$this->time = $time; $this->time = $time;
} }
public function update(Entity $entity) public function update(Entity $entity): Entity
{ {
$entity->setLastModified($this->time->getMicroTime()); $entity->setLastModified($this->time->getMicroTime());
return parent::update($entity); return parent::update($entity);
} }
public function insert(Entity $entity) public function insert(Entity $entity): Entity
{ {
$entity->setLastModified($this->time->getMicroTime()); $entity->setLastModified($this->time->getMicroTime());
return parent::insert($entity); return parent::insert($entity);
} }
/** /**
* @param int $id the id of the feed * Remove deleted items.
* @param string $userId the id of the user
* *
* @return \OCP\AppFramework\Db\Entity * @return void
*/ */
abstract public function find($id, $userId); public function purgeDeleted(): void
{
$builder = $this->db->getQueryBuilder();
$builder->delete($this->tableName)
->where('deleted_at != 0')
->execute()
->execute();
}
abstract public function find(string $userId, int $id);
/**
* Find all items.
*
* @return Entity[]
*/
abstract public function findAll(): array;
/**
* Find all items for a user.
*
* @param string $userId ID of the user
*
* @return Entity[]
*/
abstract public function findAllFromUser(string $userId): array;
/**
* Find item for a user.
*
* @param string $userId ID of the user
* @param int $id ID of the item
*
* @return Feed
*
* @throws DoesNotExistException The item is not found
* @throws MultipleObjectsReturnedException Multiple items found
*/
abstract public function findFromUser(string $userId, int $id): Entity;
/** /**
* Performs a SELECT query with all arguments appened to the WHERE clause * Performs a SELECT query with all arguments appened to the WHERE clause
@ -64,12 +118,14 @@ abstract class NewsMapper extends Mapper
* Important: This method does not filter marked as deleted rows! * Important: This method does not filter marked as deleted rows!
* *
* @param array $search an assoc array from property to filter value * @param array $search an assoc array from property to filter value
* @param int $limit * @param int|null $limit Output limit
* @param int|null $offset Output offset
*
* @depreacted Legacy function
* *
* @paran int $offset
* @return array * @return array
*/ */
public function where(array $search = [], $limit = null, $offset = null) public function where(array $search = [], ?int $limit = null, ?int $offset = null)
{ {
$entity = new $this->entityClass(); $entity = new $this->entityClass();
@ -80,7 +136,7 @@ abstract class NewsMapper extends Mapper
// accidental Sql injection // accidental Sql injection
if (!property_exists($entity, $property)) { if (!property_exists($entity, $property)) {
$msg = 'Property ' . $property . ' does not exist on ' $msg = 'Property ' . $property . ' does not exist on '
. $this->entityClass; . $this->entityClass;
throw new \BadFunctionCallException($msg); throw new \BadFunctionCallException($msg);
} }

108
lib/Db/NewsMapperV2.php Normal file
Просмотреть файл

@ -0,0 +1,108 @@
<?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\MultipleObjectsReturnedException;
use OCP\AppFramework\Db\QBMapper;
use OCP\IDBConnection;
use OCP\AppFramework\Db\Mapper;
use OCP\AppFramework\Db\Entity;
/**
* Class NewsMapper
*
* @package OCA\News\Db
*/
abstract class NewsMapperV2 extends QBMapper
{
const TABLE_NAME = '';
/**
* @var Time
*/
private $time;
/**
* NewsMapper constructor.
*
* @param IDBConnection $db Database connection
* @param Time $time Time class
* @param string $entity Entity class
*/
public function __construct(
IDBConnection $db,
Time $time,
string $entity
) {
parent::__construct($db, static::TABLE_NAME, $entity);
$this->time = $time;
}
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()
->execute();
}
/**
* Find all items.
*
* @return Entity[]
*/
abstract public function findAll(): array;
/**
* Find all items for a user.
*
* @param string $userId ID of the user
*
* @return Entity[]
*/
abstract public function findAllFromUser(string $userId): array;
/**
* Find item for a user.
*
* @param string $userId ID of the user
* @param int $id ID of the item
*
* @return Feed
*
* @throws DoesNotExistException The item is not found
* @throws MultipleObjectsReturnedException Multiple items found
*/
abstract public function findFromUser(string $userId, int $id): Entity;
}

Просмотреть файл

@ -64,7 +64,7 @@ class FeedFetcher implements IFeedFetcher
* *
* @return bool * @return bool
*/ */
public function canHandle($url): bool public function canHandle(string $url): bool
{ {
return true; return true;
} }

Просмотреть файл

@ -43,5 +43,5 @@ interface IFeedFetcher
* @return boolean if the fetcher can handle the url. This fetcher will be * @return boolean if the fetcher can handle the url. This fetcher will be
* used exclusively to fetch the feed and the items of the page * used exclusively to fetch the feed and the items of the page
*/ */
public function canHandle($url): bool; public function canHandle(string $url): bool;
} }

Просмотреть файл

@ -37,9 +37,13 @@ class YoutubeFetcher implements IFeedFetcher
/** /**
* This fetcher handles all the remaining urls therefore always returns true * Check if the URL is a youtube URL by reformatting it.
*
* @param string $url the url that should be fetched
*
* @return bool
*/ */
public function canHandle($url): bool public function canHandle(string $url): bool
{ {
return $this->buildUrl($url) !== $url; return $this->buildUrl($url) !== $url;
} }

Просмотреть файл

@ -11,7 +11,7 @@
* @copyright 2012-2014 Bernhard Posselt * @copyright 2012-2014 Bernhard Posselt
*/ */
namespace OCA\News\Service; namespace OCA\News\Service\Exceptions;
class ServiceConflictException extends ServiceException class ServiceConflictException extends ServiceException
{ {

Просмотреть файл

@ -11,7 +11,7 @@
* @copyright 2012-2014 Bernhard Posselt * @copyright 2012-2014 Bernhard Posselt
*/ */
namespace OCA\News\Service; namespace OCA\News\Service\Exceptions;
class ServiceException extends \Exception class ServiceException extends \Exception
{ {

Просмотреть файл

@ -11,7 +11,7 @@
* @copyright 2012-2014 Bernhard Posselt * @copyright 2012-2014 Bernhard Posselt
*/ */
namespace OCA\News\Service; namespace OCA\News\Service\Exceptions;
class ServiceNotFoundException extends ServiceException class ServiceNotFoundException extends ServiceException
{ {

Просмотреть файл

@ -11,7 +11,7 @@
* @copyright 2012-2014 Bernhard Posselt * @copyright 2012-2014 Bernhard Posselt
*/ */
namespace OCA\News\Service; namespace OCA\News\Service\Exceptions;
class ServiceValidationException extends ServiceException class ServiceValidationException extends ServiceException
{ {

Просмотреть файл

@ -18,7 +18,9 @@ use HTMLPurifier;
use OCA\News\AppInfo\Application; use OCA\News\AppInfo\Application;
use OCP\IConfig; use OCP\IConfig;
use OCP\ILogger; use OCA\News\Service\Exceptions\ServiceConflictException;
use OCA\News\Service\Exceptions\ServiceNotFoundException;
use OCP\AppFramework\Db\Entity;
use OCP\IL10N; use OCP\IL10N;
use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\DoesNotExistException;
@ -28,14 +30,20 @@ use OCA\News\Db\FeedMapper;
use OCA\News\Db\ItemMapper; use OCA\News\Db\ItemMapper;
use OCA\News\Fetcher\Fetcher; use OCA\News\Fetcher\Fetcher;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
use Psr\Log\LoggerInterface;
/**
* Class LegacyFeedService
*
* @package OCA\News\Service
* @deprecated use FeedServiceV2
*/
class FeedService extends Service class FeedService extends Service
{ {
private $feedFetcher; private $feedFetcher;
private $itemMapper; private $itemMapper;
private $feedMapper; private $feedMapper;
private $logger;
private $l10n; private $l10n;
private $timeFactory; private $timeFactory;
private $autoPurgeMinimumInterval; private $autoPurgeMinimumInterval;
@ -43,18 +51,19 @@ class FeedService extends Service
private $loggerParams; private $loggerParams;
public function __construct( public function __construct(
FeedMapper $feedMapper, FeedMapper $legacyFeedMapper,
Fetcher $feedFetcher, Fetcher $feedFetcher,
ItemMapper $itemMapper, ItemMapper $legacyItemMapper,
ILogger $logger, LoggerInterface $logger,
IL10N $l10n, IL10N $l10n,
Time $timeFactory, Time $timeFactory,
IConfig $config, IConfig $config,
HTMLPurifier $purifier HTMLPurifier $purifier
) { ) {
parent::__construct($feedMapper); parent::__construct($legacyFeedMapper, $logger);
$this->feedFetcher = $feedFetcher; $this->feedFetcher = $feedFetcher;
$this->itemMapper = $itemMapper; $this->feedMapper = $legacyFeedMapper;
$this->itemMapper = $legacyItemMapper;
$this->logger = $logger; $this->logger = $logger;
$this->l10n = $l10n; $this->l10n = $l10n;
$this->timeFactory = $timeFactory; $this->timeFactory = $timeFactory;
@ -64,7 +73,6 @@ class FeedService extends Service
Application::DEFAULT_SETTINGS['autoPurgeMinimumInterval'] Application::DEFAULT_SETTINGS['autoPurgeMinimumInterval']
); );
$this->purifier = $purifier; $this->purifier = $purifier;
$this->feedMapper = $feedMapper;
$this->loggerParams = ['app' => Application::NAME]; $this->loggerParams = ['app' => Application::NAME];
} }
@ -75,7 +83,7 @@ class FeedService extends Service
* *
* @return Feed[] * @return Feed[]
*/ */
public function findAll($userId) public function findAllForUser($userId): array
{ {
return $this->feedMapper->findAllFromUser($userId); return $this->feedMapper->findAllFromUser($userId);
} }
@ -88,7 +96,7 @@ class FeedService extends Service
*/ */
public function findAllFromAllUsers() public function findAllFromAllUsers()
{ {
return $this->feedMapper->findAll(); return $this->findAll();
} }
@ -202,17 +210,17 @@ class FeedService extends Service
/** /**
* Updates a single feed * Updates a single feed
* *
* @param int $feedId the id of the feed that should be updated
* @param string $userId the id of the user * @param string $userId the id of the user
* @param int $feedId the id of the feed that should be updated
* @param bool $forceUpdate update even if the article exists already * @param bool $forceUpdate update even if the article exists already
* *
* @throws ServiceNotFoundException if the feed does not exist * @throws ServiceNotFoundException if the feed does not exist
* @return Feed the updated feed entity * @return Feed the updated feed entity
*/ */
public function update($feedId, $userId, $forceUpdate = false) public function update(string $userId, int $feedId, $forceUpdate = false)
{ {
/** @var Feed $existingFeed */ /** @var Feed $existingFeed */
$existingFeed = $this->find($feedId, $userId); $existingFeed = $this->find($userId, $feedId);
if ($existingFeed->getPreventUpdate() === true) { if ($existingFeed->getPreventUpdate() === true) {
return $existingFeed; return $existingFeed;
@ -316,7 +324,7 @@ class FeedService extends Service
$this->feedMapper->update($existingFeed); $this->feedMapper->update($existingFeed);
return $this->find($feedId, $userId); return $this->find($userId, $feedId);
} }
/** /**
@ -333,7 +341,7 @@ class FeedService extends Service
$urlHash = md5($url); $urlHash = md5($url);
// build assoc array for fast access // build assoc array for fast access
$feeds = $this->findAll($userId); $feeds = $this->findAllForUser($userId);
$feedsDict = []; $feedsDict = [];
foreach ($feeds as $feed) { foreach ($feeds as $feed) {
$feedsDict[$feed->getLink()] = $feed; $feedsDict[$feed->getLink()] = $feed;
@ -402,9 +410,9 @@ class FeedService extends Service
* *
* @throws ServiceNotFoundException when feed does not exist * @throws ServiceNotFoundException when feed does not exist
*/ */
public function markDeleted($feedId, $userId) public function markDeleted(int $feedId, string $userId)
{ {
$feed = $this->find($feedId, $userId); $feed = $this->find($userId, $feedId);
$feed->setDeletedAt($this->timeFactory->getTime()); $feed->setDeletedAt($this->timeFactory->getTime());
$this->feedMapper->update($feed); $this->feedMapper->update($feed);
} }
@ -418,9 +426,9 @@ class FeedService extends Service
* *
* @throws ServiceNotFoundException when feed does not exist * @throws ServiceNotFoundException when feed does not exist
*/ */
public function unmarkDeleted($feedId, $userId) public function unmarkDeleted(int $feedId, string $userId)
{ {
$feed = $this->find($feedId, $userId); $feed = $this->find($userId, $feedId);
$feed->setDeletedAt(0); $feed->setDeletedAt(0);
$this->feedMapper->update($feed); $this->feedMapper->update($feed);
} }
@ -463,9 +471,9 @@ class FeedService extends Service
} }
/** /**
* @param string $feedId ID of the feed. * @param int $feedId ID of the feed.
* @param string $userId ID of the user. * @param string $userId ID of the user.
* @param array $diff An array containing the fields to update, e.g.: * @param array $diff An array containing the fields to update, e.g.:
* <code> * <code>
* [ * [
* 'ordering' => 1, * 'ordering' => 1,
@ -479,9 +487,9 @@ class FeedService extends Service
* @throws ServiceNotFoundException if feed does not exist * @throws ServiceNotFoundException if feed does not exist
* @return Feed The patched feed * @return Feed The patched feed
*/ */
public function patch($feedId, $userId, $diff = []) public function patch(int $feedId, string $userId, array $diff = [])
{ {
$feed = $this->find($feedId, $userId); $feed = $this->find($userId, $feedId);
foreach ($diff as $attribute => $value) { foreach ($diff as $attribute => $value) {
$method = 'set' . ucfirst($attribute); $method = 'set' . ucfirst($attribute);
@ -494,9 +502,14 @@ class FeedService extends Service
$feed->setHttpEtag(''); $feed->setHttpEtag('');
$feed->setHttpLastModified(0); $feed->setHttpLastModified(0);
$this->feedMapper->update($feed); $this->feedMapper->update($feed);
return $this->update($feedId, $userId, true); return $this->update($userId, $feedId, true);
} }
return $this->feedMapper->update($feed); return $this->feedMapper->update($feed);
} }
public function findAll(): array
{
return $this->feedMapper->findAll();
}
} }

Просмотреть файл

@ -0,0 +1,336 @@
<?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 FeedIo\Reader\ReadErrorException;
use HTMLPurifier;
use OCA\News\Db\FeedMapperV2;
use OCA\News\Fetcher\FeedFetcher;
use OCA\News\Service\Exceptions\ServiceConflictException;
use OCA\News\Service\Exceptions\ServiceNotFoundException;
use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use OCP\ILogger;
use OCP\IL10N;
use OCP\AppFramework\Db\DoesNotExistException;
use OCA\News\Db\Feed;
use OCA\News\Db\Item;
use OCA\News\Db\FeedMapper;
use OCA\News\Db\ItemMapper;
use OCA\News\Fetcher\Fetcher;
use OCA\News\Config\Config;
use OCA\News\Utility\Time;
use Psr\Log\LoggerInterface;
/**
* Class FeedService
*
* @package OCA\News\Service
*/
class FeedServiceV2 extends Service
{
/**
* Class to fetch feeds.
* @var FeedFetcher
*/
protected $feedFetcher;
/**
* Items service.
*
* @var ItemServiceV2
*/
protected $itemService;
/**
* HTML Purifier
* @var HTMLPurifier
*/
protected $purifier;
/**
* FeedService constructor.
*
* @param FeedMapperV2 $mapper DB layer for feeds
* @param FeedFetcher $feedFetcher FeedIO interface
* @param ItemServiceV2 $itemService Service to manage items
* @param HTMLPurifier $purifier HTML Purifier
* @param LoggerInterface $logger Logger
*/
public function __construct(
FeedMapperV2 $mapper,
FeedFetcher $feedFetcher,
ItemServiceV2 $itemService,
HTMLPurifier $purifier,
LoggerInterface $logger
) {
parent::__construct($mapper, $logger);
$this->feedFetcher = $feedFetcher;
$this->itemService = $itemService;
$this->purifier = $purifier;
}
/**
* Finds all feeds of a user
*
* @param string $userId the name of the user
*
* @return Feed[]
*/
public function findAllForUser(string $userId): array
{
return $this->mapper->findAllFromUser($userId);
}
/**
* Finds a feed of a user
*
* @param string $userId the name of the user
* @param string $id the id of the feed
*
* @return Feed
*
* @throws DoesNotExistException
* @throws MultipleObjectsReturnedException
*/
public function findForUser(string $userId, string $id): Feed
{
return $this->mapper->findFromUser($userId, $id);
}
/**
* @param int $id
*
* @return Feed[]
*/
public function findAllFromFolder(int $id): array
{
return $this->mapper->findAllFromFolder($id);
}
/**
* Finds all feeds of a user and all items in it
*
* @param string $userId the name of the user
*
* @return Feed[]
*/
public function findAllForUserRecursive(string $userId): array
{
$feeds = $this->mapper->findAllFromUser($userId);
foreach ($feeds as &$feed) {
$items = $this->itemService->findAllForFeed($feed->getId());
$feed->items = $items;
}
return $feeds;
}
/**
* Finds all feeds
*
* @return Feed[]
*/
public function findAll(): array
{
return $this->mapper->findAll();
}
/**
* Check if a feed exists for a user
*
* @param string $userID the name of the user
* @param string $url the feed URL
*
* @return bool
*/
public function existsForUser(string $userID, string $url): bool
{
try {
$this->mapper->findByURL($userID, $url);
return true;
} catch (DoesNotExistException $e) {
return false;
}
}
/**
* Creates a new feed
*
* @param string $userId Feed owner
* @param string $feedUrl Feed URL
* @param int $folderId Target folder, defaults to root
* @param string|null $title The OPML feed title
* @param string|null $user Basic auth username, if set
* @param string|null $password Basic auth password if username is set
*
* @return Feed the newly created feed
*
* @throws ServiceConflictException The feed already exists
* @throws ServiceNotFoundException The url points to an invalid feed
*/
public function create(
string $userId,
string $feedUrl,
int $folderId = 0,
bool $full_text = false,
?string $title = null,
?string $user = null,
?string $password = null
): Feed {
if ($this->existsForUser($userId, $feedUrl)) {
throw new ServiceConflictException('Feed with this URL exists');
}
try {
/**
* @var Feed $feed
* @var Item[] $items
*/
list($feed, $items) = $this->feedFetcher->fetch($feedUrl, true, $full_text, false, $user, $password);
if ($feed === null) {
throw new ServiceNotFoundException('Failed to fetch feed');
}
$feed->setFolderId($folderId)
->setUserId($userId)
->setArticlesPerUpdate(count($items));
if (!is_null($title)) {
$feed->setTitle($title);
}
if (!is_null($user)) {
$feed->setBasicAuthUser($user)
->setBasicAuthUser($password);
}
$feed = $this->mapper->insert($feed);
return $feed;
} catch (ReadErrorException $ex) {
$this->logger->debug($ex->getMessage());
throw new ServiceNotFoundException($ex->getMessage());
}
}
/**
* Update a feed
*
* @param Feed $feed Feed item
* @param bool $force update even if the article exists already
*
* @return Feed|Entity Database feed entity
*/
public function fetch(Feed $feed, bool $force = false)
{
if ($feed->getPreventUpdate() === true) {
return $feed;
}
// for backwards compability it can be that the location is not set
// yet, if so use the url
$location = $feed->getLocation() ?? $feed->getUrl();
try {
/**
* @var Feed $feed
* @var Item[] $items
*/
list($fetchedFeed, $items) = $this->feedFetcher->fetch(
$location,
false,
$feed->getHttpLastModified(),
$feed->getFullTextEnabled(),
$feed->getBasicAuthUser(),
$feed->getBasicAuthPassword()
);
// if there is no feed it means that no update took place
if (!$fetchedFeed) {
return $feed;
}
// update number of articles on every feed update
$itemCount = count($items);
// this is needed to adjust to updates that add more items
// than when the feed was created. You can't update the count
// if it's lower because it may be due to the caching headers
// that were sent as the request and it might cause unwanted
// deletion and reappearing of feeds
if ($itemCount > $feed->getArticlesPerUpdate()) {
$feed->setArticlesPerUpdate($itemCount);
}
$feed->setHttpLastModified($fetchedFeed->getHttpLastModified());
$feed->setHttpEtag($fetchedFeed->getHttpEtag());
$feed->setLocation($fetchedFeed->getLocation());
// insert items in reverse order because the first one is
// usually the newest item
for ($i = $itemCount - 1; $i >= 0; $i--) {
$item = $items[$i];
$item->setFeedId($feed->getId());
$item->setTitle($item->getTitle());
$item->setUrl($item->getUrl());
$item->setAuthor($item->getAuthor());
$item->setSearchIndex($item->getSearchIndex());
$item->setRtl($item->getRtl());
$item->setLastModified($item->getLastModified());
$item->setPubDate($item->getPubDate());
$item->setUpdatedDate($item->getUpdatedDate());
$item->setEnclosureMime($item->getEnclosureMime());
$item->setEnclosureLink($item->getEnclosureLink());
$item->setBody($this->purifier->purify($item->getBody()));
// update modes: 0 nothing, 1 set unread
if ($feed->getUpdateMode() === 1) {
$item->setUnread(true);
}
$this->itemService->insertOrUpdate($item);
}
// mark feed as successfully updated
$feed->setUpdateErrorCount(0);
$feed->setLastUpdateError(null);
} catch (ReadErrorException $ex) {
$feed->setUpdateErrorCount($feed->getUpdateErrorCount() + 1);
$feed->setLastUpdateError($ex->getMessage());
}
return $this->mapper->update($feed);
}
public function delete(string $user, int $id)
{
$feed = $this->mapper->findFromUser($user, $id);
$this->mapper->delete($feed);
}
public function purgeDeleted()
{
$this->mapper->purgeDeleted();
}
public function fetchAll()
{
return $this->mapper->findAll();
}
}

Просмотреть файл

@ -15,11 +15,23 @@ namespace OCA\News\Service;
use OCA\News\AppInfo\Application; use OCA\News\AppInfo\Application;
use OCP\IConfig; use OCP\IConfig;
use OCA\News\Service\Exceptions\ServiceConflictException;
use OCA\News\Service\Exceptions\ServiceException;
use OCA\News\Service\Exceptions\ServiceNotFoundException;
use OCA\News\Service\Exceptions\ServiceValidationException;
use OCP\AppFramework\Db\Entity;
use OCP\IL10N; use OCP\IL10N;
use OCA\News\Db\Folder; use OCA\News\Db\Folder;
use OCA\News\Db\FolderMapper; use OCA\News\Db\FolderMapper;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
use Psr\Log\LoggerInterface;
/**
* Class LegacyFolderService
*
* @package OCA\News\Service
* @deprecated use FolderServiceV2
*/
class FolderService extends Service class FolderService extends Service
{ {
@ -32,35 +44,37 @@ class FolderService extends Service
FolderMapper $folderMapper, FolderMapper $folderMapper,
IL10N $l10n, IL10N $l10n,
Time $timeFactory, Time $timeFactory,
IConfig $config IConfig $config,
LoggerInterface $logger
) { ) {
parent::__construct($folderMapper); parent::__construct($folderMapper, $logger);
$this->l10n = $l10n; $this->l10n = $l10n;
$this->timeFactory = $timeFactory; $this->timeFactory = $timeFactory;
$this->folderMapper = $folderMapper;
$this->autoPurgeMinimumInterval = $config->getAppValue( $this->autoPurgeMinimumInterval = $config->getAppValue(
Application::NAME, Application::NAME,
'autoPurgeMinimumInterval', 'autoPurgeMinimumInterval',
Application::DEFAULT_SETTINGS['autoPurgeMinimumInterval'] Application::DEFAULT_SETTINGS['autoPurgeMinimumInterval']
); );
$this->folderMapper = $folderMapper;
} }
/** /**
* Returns all folders of a user * Finds all folders of a user
* *
* @param string $userId the name of the user * @param string $userId the name of the user
* @return array of folders *
* @return Folder[]
*/ */
public function findAll($userId) public function findAllForUser(string $userId): array
{ {
return $this->folderMapper->findAllFromUser($userId); return $this->folderMapper->findAllFromUser($userId);
} }
private function validateFolder($folderName, $userId) private function validateFolder(string $folderName, string $userId)
{ {
$existingFolders = $existingFolders
$this->folderMapper->findByName($folderName, $userId); = $this->folderMapper->findByName($folderName, $userId);
if (count($existingFolders) > 0) { if (count($existingFolders) > 0) {
throw new ServiceConflictException( throw new ServiceConflictException(
$this->l10n->t('Can not add folder: Exists already') $this->l10n->t('Can not add folder: Exists already')
@ -78,15 +92,16 @@ class FolderService extends Service
/** /**
* Creates a new folder * Creates a new folder
* *
* @param string $folderName the name of the folder * @param string $folderName the name of the folder
* @param string $userId the name of the user for whom it should be created * @param string $userId the name of the user for whom it should be created
* @param int $parentId the parent folder id, deprecated we don't nest * @param int $parentId the parent folder id, deprecated we don't nest
* folders * folders
* @throws ServiceConflictException if name exists already *
* @return Folder|Entity the newly created folder
* @throws ServiceValidationException if the folder has invalid parameters * @throws ServiceValidationException if the folder has invalid parameters
* @return Folder the newly created folder * @throws ServiceConflictException if name exists already
*/ */
public function create($folderName, $userId, $parentId = 0) public function create(string $folderName, string $userId, int $parentId = 0)
{ {
$this->validateFolder($folderName, $userId); $this->validateFolder($folderName, $userId);
@ -103,9 +118,9 @@ class FolderService extends Service
/** /**
* @throws ServiceException if the folder does not exist * @throws ServiceException if the folder does not exist
*/ */
public function open($folderId, $opened, $userId) public function open(int $folderId, bool $opened, string $userId)
{ {
$folder = $this->find($folderId, $userId); $folder = $this->find($userId, $folderId);
$folder->setOpened($opened); $folder->setOpened($opened);
$this->folderMapper->update($folder); $this->folderMapper->update($folder);
} }
@ -114,19 +129,20 @@ class FolderService extends Service
/** /**
* Renames a folder * Renames a folder
* *
* @param int $folderId the id of the folder that should be deleted * @param int $folderId the id of the folder that should be deleted
* @param string $folderName the new name of the folder * @param string $folderName the new name of the folder
* @param string $userId the name of the user for security reasons * @param string $userId the name of the user for security reasons
* @throws ServiceConflictException if name exists already *
* @return Folder the updated folder
* @throws ServiceValidationException if the folder has invalid parameters * @throws ServiceValidationException if the folder has invalid parameters
* @throws ServiceNotFoundException if the folder does not exist * @throws ServiceNotFoundException if the folder does not exist
* @return Folder the updated folder * @throws ServiceConflictException if name exists already
*/ */
public function rename($folderId, $folderName, $userId) public function rename(int $folderId, string $folderName, string $userId)
{ {
$this->validateFolder($folderName, $userId); $this->validateFolder($folderName, $userId);
$folder = $this->find($folderId, $userId); $folder = $this->find($userId, $folderId);
$folder->setName($folderName); $folder->setName($folderName);
return $this->folderMapper->update($folder); return $this->folderMapper->update($folder);
@ -136,13 +152,14 @@ class FolderService extends Service
/** /**
* Use this to mark a folder as deleted. That way it can be un-deleted * Use this to mark a folder as deleted. That way it can be un-deleted
* *
* @param int $folderId the id of the folder that should be deleted * @param int $folderId the id of the folder that should be deleted
* @param string $userId the name of the user for security reasons * @param string $userId the name of the user for security reasons
*
* @throws ServiceNotFoundException when folder does not exist * @throws ServiceNotFoundException when folder does not exist
*/ */
public function markDeleted($folderId, $userId) public function markDeleted(int $folderId, string $userId)
{ {
$folder = $this->find($folderId, $userId); $folder = $this->find($userId, $folderId);
$folder->setDeletedAt($this->timeFactory->getTime()); $folder->setDeletedAt($this->timeFactory->getTime());
$this->folderMapper->update($folder); $this->folderMapper->update($folder);
} }
@ -151,13 +168,14 @@ class FolderService extends Service
/** /**
* Use this to restore a folder * Use this to restore a folder
* *
* @param int $folderId the id of the folder that should be restored * @param int $folderId the id of the folder that should be restored
* @param string $userId the name of the user for security reasons * @param string $userId the name of the user for security reasons
*
* @throws ServiceNotFoundException when folder does not exist * @throws ServiceNotFoundException when folder does not exist
*/ */
public function unmarkDeleted($folderId, $userId) public function unmarkDeleted(int $folderId, string $userId)
{ {
$folder = $this->find($folderId, $userId); $folder = $this->find($userId, $folderId);
$folder->setDeletedAt(0); $folder->setDeletedAt(0);
$this->folderMapper->update($folder); $this->folderMapper->update($folder);
} }
@ -171,7 +189,7 @@ class FolderService extends Service
* entries in a given interval to give the user a chance to undo the * entries in a given interval to give the user a chance to undo the
* deletion * deletion
*/ */
public function purgeDeleted($userId = null, $useInterval = true) public function purgeDeleted(?string $userId = null, bool $useInterval = true)
{ {
$deleteOlderThan = null; $deleteOlderThan = null;
@ -193,8 +211,13 @@ class FolderService extends Service
* *
* @param string $userId the name of the user * @param string $userId the name of the user
*/ */
public function deleteUser($userId) public function deleteUser(string $userId)
{ {
$this->folderMapper->deleteUser($userId); $this->folderMapper->deleteUser($userId);
} }
public function findAll(): array
{
return $this->mapper->findAll();
}
} }

Просмотреть файл

@ -0,0 +1,102 @@
<?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\Db\Feed;
use OCA\News\Db\FeedMapperV2;
use OCA\News\Db\Folder;
use OCA\News\Db\FolderMapperV2;
use Psr\Log\LoggerInterface;
/**
* Class FolderService
*
* @package OCA\News\Service
*/
class FolderServiceV2 extends Service
{
/**
* @var FeedServiceV2
*/
private $feedService;
public function __construct(
FolderMapperV2 $mapper,
FeedServiceV2 $feedService,
LoggerInterface $logger
) {
parent::__construct($mapper, $logger);
$this->feedService = $feedService;
}
/**
* Finds all folders of a user
*
* @param string $userId the name of the user
*
* @return Folder[]
*/
public function findAllForUser(string $userId): array
{
return $this->mapper->findAllFromUser($userId);
}
/**
* @param string $userId
*
* @return Folder[]
*/
public function findAllForUserRecursive(string $userId): array
{
$folders = $this->findAllForUser($userId);
foreach ($folders as &$folder) {
$feeds = $this->feedService->findAllFromFolder($folder->getId());
$folder->feeds = $feeds;
}
return $folders;
}
/**
* Find all folders.
*
* @return Folder[]
*/
public function findAll(): array
{
return $this->mapper->findAll();
}
public function create(string $userId, string $name, int $parent = 0): void
{
$folder = new Folder();
$folder->setUserId($userId);
$folder->setName($name);
$folder->setParentId($parent);
$this->mapper->insert($folder);
}
public function delete(string $user, int $id)
{
$entity = $this->mapper->findFromUser($user, $id);
$this->mapper->delete($entity);
}
public function purgeDeleted()
{
$this->mapper->purgeDeleted();
}
}

Просмотреть файл

@ -15,13 +15,22 @@ namespace OCA\News\Service;
use OCA\News\AppInfo\Application; use OCA\News\AppInfo\Application;
use OCA\News\Db\Item; use OCA\News\Db\Item;
use OCA\News\Service\Exceptions\ServiceNotFoundException;
use OCP\AppFramework\Db\Entity;
use OCP\IConfig; use OCP\IConfig;
use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\DoesNotExistException;
use OCA\News\Db\ItemMapper; use OCA\News\Db\ItemMapper;
use OCA\News\Db\FeedType; use OCA\News\Db\FeedType;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
use Psr\Log\LoggerInterface;
/**
* Class LegacyItemService
*
* @package OCA\News\Service
* @deprecated use ItemServiceV2
*/
class ItemService extends Service class ItemService extends Service
{ {
@ -32,12 +41,13 @@ class ItemService extends Service
public function __construct( public function __construct(
ItemMapper $itemMapper, ItemMapper $itemMapper,
Time $timeFactory, Time $timeFactory,
IConfig $config IConfig $config,
LoggerInterface $logger
) { ) {
parent::__construct($itemMapper); parent::__construct($itemMapper, $logger);
$this->config = $config;
$this->timeFactory = $timeFactory; $this->timeFactory = $timeFactory;
$this->itemMapper = $itemMapper; $this->itemMapper = $itemMapper;
$this->config = $config;
} }
@ -96,7 +106,7 @@ class ItemService extends Service
* or body * or body
* @return array of items * @return array of items
*/ */
public function findAll( public function findAllItems(
$id, $id,
$type, $type,
$limit, $limit,
@ -128,7 +138,7 @@ class ItemService extends Service
$search $search
); );
default: default:
return $this->itemMapper->findAll( return $this->itemMapper->findAllItems(
$limit, $limit,
$offset, $offset,
$type, $type,
@ -140,6 +150,11 @@ class ItemService extends Service
} }
} }
public function findAllForUser(string $userId): array
{
return $this->itemMapper->findAllFromUser($userId);
}
/** /**
* Star or unstar an item * Star or unstar an item
@ -320,4 +335,9 @@ class ItemService extends Service
{ {
$this->itemMapper->updateSearchIndices(); $this->itemMapper->updateSearchIndices();
} }
public function findAll(): array
{
return $this->mapper->findAll();
}
} }

Просмотреть файл

@ -0,0 +1,104 @@
<?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 2020 Sean Molenaar
*/
namespace OCA\News\Service;
use OCA\News\AppInfo\Application;
use OCA\News\Db\Item;
use OCA\News\Db\ItemMapperV2;
use OCP\AppFramework\Db\DoesNotExistException;
use OCP\IConfig;
use Psr\Log\LoggerInterface;
/**
* Class ItemService
*
* @package OCA\News\Service
*/
class ItemServiceV2 extends Service
{
/**
* @var IConfig
*/
protected $config;
/**
* ItemService constructor.
*
* @param ItemMapperV2 $mapper
* @param IConfig $config
* @param LoggerInterface $logger
*/
public function __construct(
ItemMapperV2 $mapper,
IConfig $config,
LoggerInterface $logger
) {
parent::__construct($mapper, $logger);
$this->config = $config;
}
/**
* Finds all items of a user
*
* @param string $userId the name of the user
*
* @return Item[]
*/
public function findAllForUser($userId): array
{
return $this->mapper->findAllFromUser($userId);
}
/**
* Find all items
*
* @return Item[]
*/
public function findAll(): array
{
return $this->mapper->findAll();
}
public function insertOrUpdate(Item $item)
{
try {
$db_item = $this->mapper->findByGuidHash($item->getGuidHash());
$item->setId($db_item->getId());
$this->mapper->update($item);
} catch (DoesNotExistException $exception) {
$this->mapper->insert($item);
}
}
public function findAllForFeed(int $feedId): array
{
return $this->mapper->findAllForFeed($feedId);
}
public function purgeOverThreshold($threshold = null)
{
$threshold = (int) $threshold ?? $this->config->getAppValue(
Application::NAME,
'autoPurgeCount',
Application::DEFAULT_SETTINGS['autoPurgeCount']
);
if ($threshold === 0) {
return '';
}
return $this->mapper->deleteOverThreshold($threshold);
}
}

Просмотреть файл

@ -13,33 +13,72 @@
namespace OCA\News\Service; namespace OCA\News\Service;
use \OCP\AppFramework\Db\DoesNotExistException; use OCA\News\Db\NewsMapper;
use \OCP\AppFramework\Db\MultipleObjectsReturnedException; use OCA\News\Db\NewsMapperV2;
use OCA\News\Service\Exceptions\ServiceNotFoundException;
use \OCA\News\Db\NewsMapper; use OCP\AppFramework\Db\DoesNotExistException;
use OCP\AppFramework\Db\Entity;
use OCP\AppFramework\Db\MultipleObjectsReturnedException;
use Psr\Log\LoggerInterface;
/**
* Class Service
*
* @package OCA\News\Service
*/
abstract class Service abstract class Service
{ {
/**
* @var NewsMapper|NewsMapperV2
*/
protected $mapper; protected $mapper;
/**
* @var LoggerInterface
*/
protected $logger;
public function __construct(NewsMapper $mapper) /**
* Service constructor.
*
* @param NewsMapper|NewsMapperV2 $mapper
* @param LoggerInterface $logger
*/
public function __construct($mapper, LoggerInterface $logger)
{ {
$this->mapper = $mapper; $this->mapper = $mapper;
$this->logger = $logger;
} }
/**
* Finds all items of a user
*
* @param string $userId the name of the user
*
* @return Entity[]
*/
abstract public function findAllForUser(string $userId): array;
/**
* Finds all items
*
* @return Entity[]
*/
abstract public function findAll(): array;
/** /**
* Delete an entity * Delete an entity
* *
* @param int $id the id of the entity * @param int $id the id of the entity
* @param string $userId the name of the user for security reasons * @param string $userId the name of the user for security reasons
*
* @throws ServiceNotFoundException if the entity does not exist, or there * @throws ServiceNotFoundException if the entity does not exist, or there
* are more than one of it * are more than one of it
*/ */
public function delete($id, $userId) public function delete(string $userId, int $id)
{ {
$entity = $this->find($id, $userId); $entity = $this->find($userId, $id);
$this->mapper->delete($entity); $this->mapper->delete($entity);
} }
@ -47,16 +86,17 @@ abstract class Service
/** /**
* Finds an entity by id * Finds an entity by id
* *
* @param int $id the id of the entity * @param int $id the id of the entity
* @param string $userId the name of the user for security reasons * @param string $userId the name of the user for security reasons
*
* @return \OCP\AppFramework\Db\Entity the entity
* @throws ServiceNotFoundException if the entity does not exist, or there * @throws ServiceNotFoundException if the entity does not exist, or there
* are more than one of it * are more than one of it
* @return \OCP\AppFramework\Db\Entity the entity
*/ */
public function find($id, $userId) public function find(string $userId, int $id): Entity
{ {
try { try {
return $this->mapper->find($id, $userId); return $this->mapper->find($userId, $id);
} catch (DoesNotExistException $ex) { } catch (DoesNotExistException $ex) {
throw new ServiceNotFoundException($ex->getMessage()); throw new ServiceNotFoundException($ex->getMessage());
} catch (MultipleObjectsReturnedException $ex) { } catch (MultipleObjectsReturnedException $ex) {

Просмотреть файл

@ -29,14 +29,14 @@ class StatusService
public function __construct( public function __construct(
IConfig $settings, IConfig $settings,
IDBConnection $connection, IDBConnection $connection,
$AppName string $AppName
) { ) {
$this->settings = $settings; $this->settings = $settings;
$this->appName = $AppName; $this->appName = $AppName;
$this->connection = $connection; $this->connection = $connection;
} }
public function isProperlyConfigured() public function isProperlyConfigured(): bool
{ {
$cronMode = $this->settings->getSystemValue('backgroundjobs_mode'); $cronMode = $this->settings->getSystemValue('backgroundjobs_mode');
$cronOff = !$this->settings->getAppValue( $cronOff = !$this->settings->getAppValue(
@ -50,7 +50,7 @@ class StatusService
} }
public function getStatus() public function getStatus(): array
{ {
$version = $this->settings->getAppValue( $version = $this->settings->getAppValue(
$this->appName, $this->appName,

Просмотреть файл

@ -12,13 +12,17 @@
*/ */
namespace OCA\News\Utility; namespace OCA\News\Service;
use \OCA\News\Service\FolderService; use OCA\News\Db\ItemMapperV2;
use OCA\News\Service\FeedServiceV2;
use OCA\News\Service\FolderServiceV2;
use OCA\News\Service\ItemServiceV2;
use \OCA\News\Service\LegacyFolderService;
use \OCA\News\Service\FeedService; use \OCA\News\Service\FeedService;
use \OCA\News\Service\ItemService; use \OCA\News\Service\ItemService;
class Updater class UpdaterService
{ {
/** /**
@ -37,9 +41,9 @@ class Updater
private $itemService; private $itemService;
public function __construct( public function __construct(
FolderService $folderService, FolderServiceV2 $folderService,
FeedService $feedService, FeedServiceV2 $feedService,
ItemService $itemService ItemServiceV2 $itemService
) { ) {
$this->folderService = $folderService; $this->folderService = $folderService;
$this->feedService = $feedService; $this->feedService = $feedService;
@ -56,12 +60,12 @@ class Updater
public function update() public function update()
{ {
$this->feedService->updateAll(); $this->feedService->fetchAll();
} }
public function afterUpdate() public function afterUpdate()
{ {
$this->itemService->autoPurgeOld(); $this->itemService->purgeOverThreshold(null);
} }
} }

Просмотреть файл

@ -13,6 +13,8 @@
namespace OCA\News\Utility; namespace OCA\News\Utility;
use \DOMDocument;
use \DOMElement;
use OCA\News\Db\Feed; use OCA\News\Db\Feed;
/** /**
@ -26,11 +28,11 @@ class OPMLExporter
* *
* @param \OCA\News\Db\Folder[] $folders * @param \OCA\News\Db\Folder[] $folders
* @param \OCA\News\Db\Feed[] $feeds * @param \OCA\News\Db\Feed[] $feeds
* @return \DomDocument the document * @return DOMDocument the document
*/ */
public function build($folders, $feeds) public function build(array $folders, array $feeds)
{ {
$document = new \DomDocument('1.0', 'UTF-8'); $document = new DOMDocument('1.0', 'UTF-8');
$document->formatOutput = true; $document->formatOutput = true;
$root = $document->createElement('opml'); $root = $document->createElement('opml');
@ -81,10 +83,10 @@ class OPMLExporter
/** /**
* @param Feed $feed * @param Feed $feed
* @param \DOMDocument $document * @param DOMDocument $document
* @return \DOMElement * @return DOMElement
*/ */
protected function createFeedOutline($feed, $document) protected function createFeedOutline(Feed $feed, DOMDocument $document)
{ {
$feedOutline = $document->createElement('outline'); $feedOutline = $document->createElement('outline');
$feedOutline->setAttribute('title', $feed->getTitle()); $feedOutline->setAttribute('title', $feed->getTitle());
@ -92,6 +94,7 @@ class OPMLExporter
$feedOutline->setAttribute('type', 'rss'); $feedOutline->setAttribute('type', 'rss');
$feedOutline->setAttribute('xmlUrl', $feed->getUrl()); $feedOutline->setAttribute('xmlUrl', $feed->getUrl());
$feedOutline->setAttribute('htmlUrl', $feed->getLink()); $feedOutline->setAttribute('htmlUrl', $feed->getLink());
return $feedOutline; return $feedOutline;
} }
} }

Просмотреть файл

@ -13,7 +13,7 @@ namespace OCA\News\Utility;
class Time class Time
{ {
public function getTime() public function getTime(): int
{ {
return time(); return time();
} }
@ -21,7 +21,7 @@ class Time
/** /**
* @return int the current unix time in miliseconds * @return int the current unix time in miliseconds
*/ */
public function getMicroTime() public function getMicroTime(): int
{ {
list($millisecs, $secs) = explode(" ", microtime()); list($millisecs, $secs) = explode(" ", microtime());
return $secs . substr($millisecs, 2, 6); return $secs . substr($millisecs, 2, 6);

Просмотреть файл

@ -25,7 +25,7 @@ class FeedMapperTest extends IntegrationTest
$feed = new FeedFixture(); $feed = new FeedFixture();
$feed = $this->feedMapper->insert($feed); $feed = $this->feedMapper->insert($feed);
$fetched = $this->feedMapper->find($feed->getId(), $this->user); $fetched = $this->feedMapper->find($this->user, $feed->getId());
$this->assertInstanceOf(Feed::class, $fetched); $this->assertInstanceOf(Feed::class, $fetched);
$this->assertEquals($feed->getLink(), $fetched->getLink()); $this->assertEquals($feed->getLink(), $fetched->getLink());
@ -34,7 +34,7 @@ class FeedMapperTest extends IntegrationTest
public function testFindNotExisting() public function testFindNotExisting()
{ {
$this->expectException('OCP\AppFramework\Db\DoesNotExistException'); $this->expectException('OCP\AppFramework\Db\DoesNotExistException');
$this->feedMapper->find(0, $this->user); $this->feedMapper->find($this->user, 0);
} }
@ -252,22 +252,14 @@ class FeedMapperTest extends IntegrationTest
$this->assertCount(4, $this->feedMapper->findAllFromUser($this->user)); $this->assertCount(4, $this->feedMapper->findAllFromUser($this->user));
$items = $this->itemMapper->findAll(100, 0, 0, true, false, $this->user); $items = $this->itemMapper->findAllItems(100, 0, 0, true, false, $this->user);
$this->assertCount(9, $items); $this->assertCount(9, $items);
$this->feedMapper->deleteUser($this->user); $this->feedMapper->deleteUser($this->user);
$this->assertCount(0, $this->feedMapper->findAllFromUser($this->user)); $this->assertCount(0, $this->feedMapper->findAllFromUser($this->user));
$items = $this->itemMapper->findAll(100, 0, 0, true, false, $this->user); $items = $this->itemMapper->findAllItems(100, 0, 0, true, false, $this->user);
$this->assertCount(0, $items); $this->assertCount(0, $items);
} }
/**
* @coversNothing
*/
public function testDeleteUserNotExisting()
{
$this->feedMapper->deleteUser('notexistinguser');
}
} }

Просмотреть файл

@ -27,7 +27,7 @@ class ItemMapperTest extends IntegrationTest
$item = $this->itemMapper->insert($item); $item = $this->itemMapper->insert($item);
$fetched = $this->itemMapper->find($item->getId(), $this->user); $fetched = $this->itemMapper->find($this->user, $item->getId());
$this->assertEquals($item->getTitle(), $fetched->getTitle()); $this->assertEquals($item->getTitle(), $fetched->getTitle());
} }
@ -44,7 +44,7 @@ class ItemMapperTest extends IntegrationTest
} }
/** /**
* @expectedException OCP\AppFramework\Db\DoesNotExistException * @expectedException \OCP\AppFramework\Db\DoesNotExistException
*/ */
public function testFindNotFoundWhenDeletedFeed() public function testFindNotFoundWhenDeletedFeed()
{ {
@ -52,12 +52,12 @@ class ItemMapperTest extends IntegrationTest
$this->loadFixtures('default'); $this->loadFixtures('default');
$id = $this->whereTitleId('not found feed'); $id = $this->whereTitleId('not found feed');
$this->itemMapper->find($id, $this->user); $this->itemMapper->find($this->user, $id);
} }
/** /**
* @expectedException OCP\AppFramework\Db\DoesNotExistException * @expectedException \OCP\AppFramework\Db\DoesNotExistException
*/ */
public function testFindNotFoundWhenDeletedFolder() public function testFindNotFoundWhenDeletedFolder()
{ {
@ -66,7 +66,7 @@ class ItemMapperTest extends IntegrationTest
$id = $this->whereTitleId('not found folder'); $id = $this->whereTitleId('not found folder');
$this->itemMapper->find($id, $this->user); $this->itemMapper->find($this->user, $id);
} }
@ -76,15 +76,15 @@ class ItemMapperTest extends IntegrationTest
$this->itemMapper->deleteReadOlderThanThreshold(1); $this->itemMapper->deleteReadOlderThanThreshold(1);
$this->itemMapper->find($this->whereTitleId('a title1'), $this->user); $this->itemMapper->find($this->user, $this->whereTitleId('a title1'));
$this->itemMapper->find($this->whereTitleId('a title2'), $this->user); $this->itemMapper->find($this->user, $this->whereTitleId('a title2'));
$this->itemMapper->find($this->whereTitleId('a title3'), $this->user); $this->itemMapper->find($this->user, $this->whereTitleId('a title3'));
$this->itemMapper->find($this->whereTitleId('del3'), $this->user); $this->itemMapper->find($this->user, $this->whereTitleId('del3'));
$this->itemMapper->find($this->whereTitleId('del4'), $this->user); $this->itemMapper->find($this->user, $this->whereTitleId('del4'));
} }
/** /**
* @expectedException OCP\AppFramework\Db\DoesNotExistException * @expectedException \OCP\AppFramework\Db\DoesNotExistException
*/ */
public function testDeleteOlderThanThresholdOne() public function testDeleteOlderThanThresholdOne()
{ {
@ -94,11 +94,11 @@ class ItemMapperTest extends IntegrationTest
$this->deleteReadOlderThanThreshold(); $this->deleteReadOlderThanThreshold();
$this->itemMapper->find($id, $this->user); $this->itemMapper->find($this->user, $id);
} }
/** /**
* @expectedException OCP\AppFramework\Db\DoesNotExistException * @expectedException \OCP\AppFramework\Db\DoesNotExistException
*/ */
public function testDeleteOlderThanThresholdTwo() public function testDeleteOlderThanThresholdTwo()
{ {
@ -108,7 +108,7 @@ class ItemMapperTest extends IntegrationTest
$this->deleteReadOlderThanThreshold(); $this->deleteReadOlderThanThreshold();
$this->itemMapper->find($id, $this->user); $this->itemMapper->find($this->user, $id);
} }
@ -127,24 +127,24 @@ class ItemMapperTest extends IntegrationTest
$this->itemMapper->readAll(PHP_INT_MAX, 10, $this->user); $this->itemMapper->readAll(PHP_INT_MAX, 10, $this->user);
$items = $this->itemMapper->findAll( $items = $this->itemMapper->findAllItems(
30, 0, 0, false, false, $this->user 30, 0, 0, false, false, $this->user
); );
$this->assertEquals(0, count($items)); $this->assertEquals(0, count($items));
$itemId = $this->whereTitleId('a title1'); $itemId = $this->whereTitleId('a title1');
$item = $this->itemMapper->find($itemId, $this->user); $item = $this->itemMapper->find($this->user, $itemId);
$this->assertEquals(10, $item->getLastModified()); $this->assertEquals(10, $item->getLastModified());
$itemId = $this->whereTitleId('a title3'); $itemId = $this->whereTitleId('a title3');
$item = $this->itemMapper->find($itemId, $this->user); $item = $this->itemMapper->find($this->user, $itemId);
$this->assertEquals(10, $item->getLastModified()); $this->assertEquals(10, $item->getLastModified());
$itemId = $this->whereTitleId('a title9'); $itemId = $this->whereTitleId('a title9');
$item = $this->itemMapper->find($itemId, $this->user); $item = $this->itemMapper->find($this->user, $itemId);
$this->assertEquals(10, $item->getLastModified()); $this->assertEquals(10, $item->getLastModified());
} }
@ -159,24 +159,24 @@ class ItemMapperTest extends IntegrationTest
$folderId, PHP_INT_MAX, 10, $this->user $folderId, PHP_INT_MAX, 10, $this->user
); );
$items = $this->itemMapper->findAll( $items = $this->itemMapper->findAllItems(
30, 0, 0, false, false, $this->user 30, 0, 0, false, false, $this->user
); );
$this->assertEquals(1, count($items)); $this->assertEquals(1, count($items));
$item = $this->findItemByTitle('a title1'); $item = $this->findItemByTitle('a title1');
$item = $this->itemMapper->find($item->getId(), $this->user); $item = $this->itemMapper->find($this->user, $item->getId());
$this->assertEquals(10, $item->getLastModified()); $this->assertEquals(10, $item->getLastModified());
$item = $this->findItemByTitle('a title3'); $item = $this->findItemByTitle('a title3');
$item = $this->itemMapper->find($item->getId(), $this->user); $item = $this->itemMapper->find($this->user, $item->getId());
$this->assertEquals(10, $item->getLastModified()); $this->assertEquals(10, $item->getLastModified());
$item = $this->findItemByTitle('a title9'); $item = $this->findItemByTitle('a title9');
$item = $this->itemMapper->find($item->getId(), $this->user); $item = $this->itemMapper->find($this->user, $item->getId());
$this->assertTrue($item->isUnread()); $this->assertTrue($item->isUnread());
} }
@ -191,24 +191,24 @@ class ItemMapperTest extends IntegrationTest
$feedId, PHP_INT_MAX, 10, $this->user $feedId, PHP_INT_MAX, 10, $this->user
); );
$items = $this->itemMapper->findAll( $items = $this->itemMapper->findAllItems(
30, 0, 0, false, false, $this->user 30, 0, 0, false, false, $this->user
); );
$this->assertEquals(2, count($items)); $this->assertEquals(2, count($items));
$item = $this->findItemByTitle('a title9'); $item = $this->findItemByTitle('a title9');
$item = $this->itemMapper->find($item->getId(), $this->user); $item = $this->itemMapper->find($this->user, $item->getId());
$this->assertEquals(10, $item->getLastModified()); $this->assertEquals(10, $item->getLastModified());
$item = $this->findItemByTitle('a title3'); $item = $this->findItemByTitle('a title3');
$item = $this->itemMapper->find($item->getId(), $this->user); $item = $this->itemMapper->find($this->user, $item->getId());
$this->assertTrue($item->isUnread()); $this->assertTrue($item->isUnread());
$item = $this->findItemByTitle('a title1'); $item = $this->findItemByTitle('a title1');
$item = $this->itemMapper->find($item->getId(), $this->user); $item = $this->itemMapper->find($this->user, $item->getId());
$this->assertTrue($item->isUnread()); $this->assertTrue($item->isUnread());
} }

Просмотреть файл

@ -131,7 +131,7 @@ abstract class IntegrationTest extends \Test\TestCase
} }
} }
protected function loadFolderFixtures(array $folderFixtures=[]) protected function loadFolderFixtures(array $folderFixtures = [])
{ {
foreach ($folderFixtures as $folderFixture) { foreach ($folderFixtures as $folderFixture) {
$folder = new FolderFixture($folderFixture); $folder = new FolderFixture($folderFixture);
@ -140,7 +140,7 @@ abstract class IntegrationTest extends \Test\TestCase
} }
} }
protected function loadFeedFixtures(array $feedFixtures=[], $folderId=0) protected function loadFeedFixtures(array $feedFixtures = [], $folderId = 0)
{ {
foreach ($feedFixtures as $feedFixture) { foreach ($feedFixtures as $feedFixture) {
$feed = new FeedFixture($feedFixture); $feed = new FeedFixture($feedFixture);
@ -153,7 +153,7 @@ abstract class IntegrationTest extends \Test\TestCase
} }
} }
protected function loadItemFixtures(array $itemFixtures=[], $feedId) protected function loadItemFixtures(array $itemFixtures, $feedId)
{ {
foreach ($itemFixtures as $itemFixture) { foreach ($itemFixtures as $itemFixture) {
$item = new ItemFixture($itemFixture); $item = new ItemFixture($itemFixture);

Просмотреть файл

@ -18,10 +18,11 @@ namespace OCA\News\Tests\Unit\Controller;
use OCA\News\Controller\FeedApiController; use OCA\News\Controller\FeedApiController;
use OCA\News\Service\FeedService; use OCA\News\Service\FeedService;
use OCA\News\Service\ItemService; use OCA\News\Service\ItemService;
use OCA\News\Utility\PsrLogger;
use \OCP\AppFramework\Http; use \OCP\AppFramework\Http;
use \OCA\News\Service\ServiceNotFoundException; use \OCA\News\Service\Exceptions\ServiceNotFoundException;
use \OCA\News\Service\ServiceConflictException; use \OCA\News\Service\Exceptions\ServiceConflictException;
use \OCA\News\Db\Feed; use \OCA\News\Db\Feed;
use OCP\ILogger; use OCP\ILogger;
use OCP\IRequest; use OCP\IRequest;
@ -29,6 +30,7 @@ use OCP\IUser;
use OCP\IUserSession; use OCP\IUserSession;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
class FeedApiControllerTest extends TestCase class FeedApiControllerTest extends TestCase
{ {
@ -36,10 +38,7 @@ class FeedApiControllerTest extends TestCase
private $feedService; private $feedService;
private $itemService; private $itemService;
private $feedAPI; private $feedAPI;
private $appName;
private $userSession;
private $user; private $user;
private $request;
private $msg; private $msg;
private $logger; private $logger;
private $loggerParams; private $loggerParams;
@ -47,20 +46,20 @@ class FeedApiControllerTest extends TestCase
protected function setUp(): void protected function setUp(): void
{ {
$this->loggerParams = ['hi']; $this->loggerParams = ['hi'];
$this->logger = $this->getMockBuilder(ILogger::class) $this->logger = $this->getMockBuilder(LoggerInterface::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->appName = 'news'; $appName = 'news';
$this->request = $this->getMockBuilder(IRequest::class) $request = $this->getMockBuilder(IRequest::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->userSession = $this->getMockBuilder(IUserSession::class) $userSession = $this->getMockBuilder(IUserSession::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->user = $this->getMockBuilder(IUser::class) $this->user = $this->getMockBuilder(IUser::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->userSession->expects($this->any()) $userSession->expects($this->any())
->method('getUser') ->method('getUser')
->will($this->returnValue($this->user)); ->will($this->returnValue($this->user));
$this->user->expects($this->any()) $this->user->expects($this->any())
@ -73,9 +72,9 @@ class FeedApiControllerTest extends TestCase
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->feedAPI = new FeedApiController( $this->feedAPI = new FeedApiController(
$this->appName, $appName,
$this->request, $request,
$this->userSession, $userSession,
$this->feedService, $this->feedService,
$this->itemService, $this->itemService,
$this->logger, $this->logger,
@ -100,7 +99,7 @@ class FeedApiControllerTest extends TestCase
->with($this->equalTo($this->user->getUID())) ->with($this->equalTo($this->user->getUID()))
->will($this->returnValue($newestItemId)); ->will($this->returnValue($newestItemId));
$this->feedService->expects($this->once()) $this->feedService->expects($this->once())
->method('findAll') ->method('findAllForUser')
->with($this->equalTo($this->user->getUID())) ->with($this->equalTo($this->user->getUID()))
->will($this->returnValue($feeds)); ->will($this->returnValue($feeds));
@ -130,7 +129,7 @@ class FeedApiControllerTest extends TestCase
->with($this->equalTo($this->user->getUID())) ->with($this->equalTo($this->user->getUID()))
->will($this->throwException(new ServiceNotFoundException(''))); ->will($this->throwException(new ServiceNotFoundException('')));
$this->feedService->expects($this->once()) $this->feedService->expects($this->once())
->method('findAll') ->method('findAllForUser')
->with($this->equalTo($this->user->getUID())) ->with($this->equalTo($this->user->getUID()))
->will($this->returnValue($feeds)); ->will($this->returnValue($feeds));
@ -377,7 +376,7 @@ class FeedApiControllerTest extends TestCase
$this->feedService->expects($this->once()) $this->feedService->expects($this->once())
->method('update') ->method('update')
->with($this->equalTo($feedId), $this->equalTo($userId)); ->with($userId, $feedId);
$this->feedAPI->update($userId, $feedId); $this->feedAPI->update($userId, $feedId);
} }
@ -392,10 +391,7 @@ class FeedApiControllerTest extends TestCase
->will($this->throwException(new \Exception($this->msg))); ->will($this->throwException(new \Exception($this->msg)));
$this->logger->expects($this->once()) $this->logger->expects($this->once())
->method('debug') ->method('debug')
->with( ->with('Could not update feed ' . $this->msg);
$this->equalTo('Could not update feed ' . $this->msg),
$this->equalTo($this->loggerParams)
);
$this->feedAPI->update($userId, $feedId); $this->feedAPI->update($userId, $feedId);

Просмотреть файл

@ -21,8 +21,8 @@ use OCP\AppFramework\Http;
use OCA\News\Db\Feed; use OCA\News\Db\Feed;
use OCA\News\Db\FeedType; use OCA\News\Db\FeedType;
use OCA\News\Service\ServiceNotFoundException; use OCA\News\Service\Exceptions\ServiceNotFoundException;
use OCA\News\Service\ServiceConflictException; use OCA\News\Service\Exceptions\ServiceConflictException;
use OCP\IConfig; use OCP\IConfig;
use OCP\IRequest; use OCP\IRequest;
@ -93,7 +93,7 @@ class FeedControllerTest extends TestCase
'starred' => 13 'starred' => 13
]; ];
$this->feedService->expects($this->once()) $this->feedService->expects($this->once())
->method('findAll') ->method('findAllForUser')
->with($this->equalTo($this->user)) ->with($this->equalTo($this->user))
->will($this->returnValue($result['feeds'])); ->will($this->returnValue($result['feeds']));
$this->itemService->expects($this->once()) $this->itemService->expects($this->once())
@ -121,7 +121,7 @@ class FeedControllerTest extends TestCase
'newestItemId' => 5 'newestItemId' => 5
]; ];
$this->feedService->expects($this->once()) $this->feedService->expects($this->once())
->method('findAll') ->method('findAllForUser')
->with($this->equalTo($this->user)) ->with($this->equalTo($this->user))
->will($this->returnValue($result['feeds'])); ->will($this->returnValue($result['feeds']));
$this->itemService->expects($this->once()) $this->itemService->expects($this->once())
@ -189,7 +189,7 @@ class FeedControllerTest extends TestCase
$this->feedService->expects($this->once()) $this->feedService->expects($this->once())
->method('find') ->method('find')
->with($this->equalTo($id), $this->equalTo($this->user)) ->with($this->user, $id)
->will($this->throwException($ex)); ->will($this->throwException($ex));
$this->activeInitMocks($id, $type); $this->activeInitMocks($id, $type);
@ -209,7 +209,7 @@ class FeedControllerTest extends TestCase
$this->folderService->expects($this->once()) $this->folderService->expects($this->once())
->method('find') ->method('find')
->with($this->equalTo($id), $this->equalTo($this->user)) ->with($this->user, $id)
->will($this->throwException($ex)); ->will($this->throwException($ex));
$this->activeInitMocks($id, $type); $this->activeInitMocks($id, $type);
@ -374,7 +374,7 @@ class FeedControllerTest extends TestCase
$this->feedService->expects($this->once()) $this->feedService->expects($this->once())
->method('update') ->method('update')
->with($this->equalTo(4), $this->equalTo($this->user)) ->with($this->equalTo($this->user), $this->equalTo(4))
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$response = $this->controller->update(4); $response = $this->controller->update(4);
@ -387,7 +387,7 @@ class FeedControllerTest extends TestCase
{ {
$this->feedService->expects($this->once()) $this->feedService->expects($this->once())
->method('update') ->method('update')
->with($this->equalTo(4), $this->equalTo($this->user)) ->with($this->equalTo($this->user), $this->equalTo(4))
->will($this->throwException(new ServiceNotFoundException('NO!'))); ->will($this->throwException(new ServiceNotFoundException('NO!')));
$response = $this->controller->update(4); $response = $this->controller->update(4);

Просмотреть файл

@ -20,9 +20,9 @@ use OCA\News\Service\FolderService;
use OCA\News\Service\ItemService; use OCA\News\Service\ItemService;
use \OCP\AppFramework\Http; use \OCP\AppFramework\Http;
use \OCA\News\Service\ServiceNotFoundException; use \OCA\News\Service\Exceptions\ServiceNotFoundException;
use \OCA\News\Service\ServiceConflictException; use \OCA\News\Service\Exceptions\ServiceConflictException;
use \OCA\News\Service\ServiceValidationException; use \OCA\News\Service\Exceptions\ServiceValidationException;
use \OCA\News\Db\Folder; use \OCA\News\Db\Folder;
use OCP\IRequest; use OCP\IRequest;
@ -38,25 +38,22 @@ class FolderApiControllerTest extends TestCase
private $folderService; private $folderService;
private $itemService; private $itemService;
private $folderAPI; private $folderAPI;
private $appName;
private $userSession;
private $user; private $user;
private $request;
private $msg; private $msg;
protected function setUp(): void protected function setUp(): void
{ {
$this->appName = 'news'; $appName = 'news';
$this->request = $this->getMockBuilder(IRequest::class) $request = $this->getMockBuilder(IRequest::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->userSession = $this->getMockBuilder(IUserSession::class) $userSession = $this->getMockBuilder(IUserSession::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->user = $this->getMockBuilder(IUser::class) $this->user = $this->getMockBuilder(IUser::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->userSession->expects($this->any()) $userSession->expects($this->any())
->method('getUser') ->method('getUser')
->will($this->returnValue($this->user)); ->will($this->returnValue($this->user));
$this->user->expects($this->any()) $this->user->expects($this->any())
@ -69,9 +66,9 @@ class FolderApiControllerTest extends TestCase
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->folderAPI = new FolderApiController( $this->folderAPI = new FolderApiController(
$this->appName, $appName,
$this->request, $request,
$this->userSession, $userSession,
$this->folderService, $this->folderService,
$this->itemService $this->itemService
); );

Просмотреть файл

@ -21,9 +21,9 @@ use \OCP\AppFramework\Http;
use \OCA\News\Db\Folder; use \OCA\News\Db\Folder;
use \OCA\News\Db\Feed; use \OCA\News\Db\Feed;
use \OCA\News\Service\ServiceNotFoundException; use \OCA\News\Service\Exceptions\ServiceNotFoundException;
use \OCA\News\Service\ServiceConflictException; use \OCA\News\Service\Exceptions\ServiceConflictException;
use \OCA\News\Service\ServiceValidationException; use \OCA\News\Service\Exceptions\ServiceValidationException;
use OCP\IRequest; use OCP\IRequest;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
@ -32,11 +32,9 @@ use PHPUnit\Framework\TestCase;
class FolderControllerTest extends TestCase class FolderControllerTest extends TestCase
{ {
private $appName;
private $folderService; private $folderService;
private $itemService; private $itemService;
private $feedService; private $feedService;
private $request;
private $controller; private $controller;
private $msg; private $msg;
@ -46,7 +44,7 @@ class FolderControllerTest extends TestCase
*/ */
public function setUp(): void public function setUp(): void
{ {
$this->appName = 'news'; $appName = 'news';
$this->user = 'jack'; $this->user = 'jack';
$this->folderService = $this->getMockBuilder(FolderService::class) $this->folderService = $this->getMockBuilder(FolderService::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
@ -57,11 +55,11 @@ class FolderControllerTest extends TestCase
$this->itemService = $this->getMockBuilder(ItemService::class) $this->itemService = $this->getMockBuilder(ItemService::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->request = $this->getMockBuilder(IRequest::class) $request = $this->getMockBuilder(IRequest::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->controller = new FolderController( $this->controller = new FolderController(
$this->appName, $this->request, $appName, $request,
$this->folderService, $this->folderService,
$this->feedService, $this->feedService,
$this->itemService, $this->itemService,

Просмотреть файл

@ -19,7 +19,7 @@ use OCA\News\Controller\ItemApiController;
use OCA\News\Service\ItemService; use OCA\News\Service\ItemService;
use \OCP\AppFramework\Http; use \OCP\AppFramework\Http;
use \OCA\News\Service\ServiceNotFoundException; use \OCA\News\Service\Exceptions\ServiceNotFoundException;
use \OCA\News\Db\Item; use \OCA\News\Db\Item;
use OCP\IRequest; use OCP\IRequest;
use OCP\IUser; use OCP\IUser;

Просмотреть файл

@ -21,7 +21,7 @@ use \OCP\AppFramework\Http;
use \OCA\News\Db\Item; use \OCA\News\Db\Item;
use \OCA\News\Db\Feed; use \OCA\News\Db\Feed;
use \OCA\News\Db\FeedType; use \OCA\News\Db\FeedType;
use \OCA\News\Service\ServiceNotFoundException; use \OCA\News\Service\Exceptions\ServiceNotFoundException;
use OCP\IConfig; use OCP\IConfig;
use OCP\IRequest; use OCP\IRequest;

Просмотреть файл

@ -17,7 +17,7 @@ namespace OCA\News\Tests\Unit\Controller;
use OCA\News\Controller\UtilityApiController; use OCA\News\Controller\UtilityApiController;
use OCA\News\Service\StatusService; use OCA\News\Service\StatusService;
use OCA\News\Utility\Updater; use OCA\News\Service\UpdaterService;
use OCP\IConfig; use OCP\IConfig;
use OCP\IRequest; use OCP\IRequest;
use OCP\IUser; use OCP\IUser;
@ -28,21 +28,52 @@ use PHPUnit\Framework\TestCase;
class UtilityApiControllerTest extends TestCase class UtilityApiControllerTest extends TestCase
{ {
/**
* @var \PHPUnit\Framework\MockObject\MockObject|IConfig
*/
private $settings; private $settings;
/**
* @var \PHPUnit\Framework\MockObject\MockObject|IRequest
*/
private $request; private $request;
/**
* @var \PHPUnit\Framework\MockObject\MockObject|IUserSession
*/
private $userSession; private $userSession;
/**
* @var \PHPUnit\Framework\MockObject\MockObject|IUser
*/
private $user; private $user;
/**
* @var UtilityApiController
*/
private $newsAPI; private $newsAPI;
private $updater;
/**
* @var string
*/
private $appName; private $appName;
/**
* @var \PHPUnit\Framework\MockObject\MockObject|StatusService
*/
private $status; private $status;
/**
* @var \PHPUnit\Framework\MockObject\MockObject|UpdaterService
*/
private $updateService;
protected function setUp(): void protected function setUp(): void
{ {
$this->appName = 'news'; $this->appName = 'news';
$this->settings = $this->getMockBuilder(IConfig::class) $this->settings = $this->getMockBuilder(IConfig::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->request = $this->getMockBuilder(IRequest::class) $this->request = $this->getMockBuilder(IRequest::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
@ -55,15 +86,19 @@ class UtilityApiControllerTest extends TestCase
$this->userSession->expects($this->any()) $this->userSession->expects($this->any())
->method('getUser') ->method('getUser')
->will($this->returnValue($this->user)); ->will($this->returnValue($this->user));
$this->updater = $this->getMockBuilder(Updater::class)
->disableOriginalConstructor()
->getMock();
$this->status = $this->getMockBuilder(StatusService::class) $this->status = $this->getMockBuilder(StatusService::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->updateService = $this->getMockBuilder(UpdaterService::class)
->disableOriginalConstructor()
->getMock();
$this->newsAPI = new UtilityApiController( $this->newsAPI = new UtilityApiController(
$this->appName, $this->request, $this->userSession, $this->appName,
$this->updater, $this->settings, $this->status $this->request,
$this->userSession,
$this->updateService,
$this->settings,
$this->status
); );
} }
@ -87,7 +122,7 @@ class UtilityApiControllerTest extends TestCase
public function testBeforeUpdate() public function testBeforeUpdate()
{ {
$this->updater->expects($this->once()) $this->updateService->expects($this->once())
->method('beforeUpdate'); ->method('beforeUpdate');
$this->newsAPI->beforeUpdate(); $this->newsAPI->beforeUpdate();
} }
@ -95,7 +130,7 @@ class UtilityApiControllerTest extends TestCase
public function testAfterUpdate() public function testAfterUpdate()
{ {
$this->updater->expects($this->once()) $this->updateService->expects($this->once())
->method('afterUpdate'); ->method('afterUpdate');
$this->newsAPI->afterUpdate(); $this->newsAPI->afterUpdate();
} }
@ -103,7 +138,7 @@ class UtilityApiControllerTest extends TestCase
public function testStatus() public function testStatus()
{ {
$in = 'hi'; $in = ['hi'];
$this->status->expects($this->once()) $this->status->expects($this->once())
->method('getStatus') ->method('getStatus')
->will($this->returnValue($in)); ->will($this->returnValue($in));

Просмотреть файл

@ -51,18 +51,19 @@ class FeedTest extends TestCase
$this->assertEquals( $this->assertEquals(
[ [
'id' => 3, 'id' => 3,
'url' => 'http://google.com/some/weird/path', 'url' => 'http://google.com/some/weird/path',
'title' => 'title', 'title' => 'title',
'faviconLink' => 'favicon', 'faviconLink' => 'favicon',
'added' => 123, 'added' => 123,
'folderId' => 1, 'folderId' => 1,
'unreadCount' => 321, 'unreadCount' => 321,
'ordering' => 2, 'ordering' => 2,
'pinned' => true, 'pinned' => true,
'link' => 'https://www.google.com/some/weird/path', 'link' => 'https://www.google.com/some/weird/path',
'updateErrorCount' => 2, 'updateErrorCount' => 2,
'lastUpdateError' => 'hi' 'lastUpdateError' => 'hi',
'items' => [],
], $feed->toAPI() ], $feed->toAPI()
); );
} }

Просмотреть файл

@ -62,7 +62,7 @@ class FolderMapperTest extends MapperTestUtility
$this->setMapperResult($sql, [$id, $userId], $rows); $this->setMapperResult($sql, [$id, $userId], $rows);
$result = $this->folderMapper->find($id, $userId); $result = $this->folderMapper->find($userId, $id);
$this->assertEquals($this->folders[0], $result); $this->assertEquals($this->folders[0], $result);
} }
@ -79,7 +79,7 @@ class FolderMapperTest extends MapperTestUtility
$this->setMapperResult($sql, [$id, $userId]); $this->setMapperResult($sql, [$id, $userId]);
$this->expectException(DoesNotExistException::class); $this->expectException(DoesNotExistException::class);
$this->folderMapper->find($id, $userId); $this->folderMapper->find($userId, $id);
} }
@ -95,7 +95,7 @@ class FolderMapperTest extends MapperTestUtility
$this->setMapperResult($sql, [$id, $userId], $rows); $this->setMapperResult($sql, [$id, $userId], $rows);
$this->expectException(MultipleObjectsReturnedException::class); $this->expectException(MultipleObjectsReturnedException::class);
$this->folderMapper->find($id, $userId); $this->folderMapper->find($userId, $id);
} }

Просмотреть файл

@ -28,8 +28,9 @@ class FolderTest extends TestCase
$this->assertEquals( $this->assertEquals(
[ [
'id' => 3, 'id' => 3,
'name' => 'name' 'name' => 'name',
'feeds' => [],
], $folder->toAPI() ], $folder->toAPI()
); );
} }

Просмотреть файл

@ -26,8 +26,10 @@ use OCA\News\Db\Mysql\ItemMapper as MysqlMapper;
class MapperFactoryTest extends TestCase class MapperFactoryTest extends TestCase
{ {
/**
* @var \PHPUnit\Framework\MockObject\MockObject|IDBConnection
*/
private $db; private $db;
private $settings;
public function setUp(): void public function setUp(): void
{ {

Просмотреть файл

@ -14,18 +14,22 @@
namespace OCA\News\Tests\Unit\Fetcher; namespace OCA\News\Tests\Unit\Fetcher;
use DateTime; use DateTime;
use Favicon\Favicon;
use FeedIo\Adapter\ResponseInterface;
use FeedIo\Feed\Item\Author; use FeedIo\Feed\Item\Author;
use FeedIo\Feed\Item\MediaInterface; use FeedIo\Feed\Item\MediaInterface;
use FeedIo\Feed\ItemInterface; use FeedIo\Feed\ItemInterface;
use FeedIo\FeedInterface; use FeedIo\FeedInterface;
use FeedIo\FeedIo;
use FeedIo\Reader\Result;
use OC\L10N\L10N; use OC\L10N\L10N;
use \OCA\News\Db\Feed; use \OCA\News\Db\Feed;
use \OCA\News\Db\Item; use \OCA\News\Db\Item;
use OCA\News\Scraper\Scraper; use OCA\News\Scraper\Scraper;
use OCA\News\Fetcher\FeedFetcher; use OCA\News\Fetcher\FeedFetcher;
use OCA\News\Utility\PsrLogger;
use OCP\ILogger; use OCA\News\Utility\Time;
use OCP\IL10N;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
@ -46,26 +50,26 @@ class FeedFetcherTest extends TestCase
/** /**
* Feed reader * Feed reader
* *
* @var \FeedIo\FeedIo * @var FeedIo
*/ */
private $reader; private $reader;
/** /**
* Feed reader result * Feed reader result
* *
* @var \FeedIo\Reader\Result * @var Result
*/ */
private $result; private $result;
/** /**
* Feed reader result object * Feed reader result object
* *
* @var \FeedIo\Adapter\ResponseInterface * @var ResponseInterface
*/ */
private $response; private $response;
/** /**
* @var \Favicon\Favicon * @var Favicon
*/ */
private $favicon; private $favicon;
@ -132,32 +136,32 @@ class FeedFetcherTest extends TestCase
protected function setUp(): void protected function setUp(): void
{ {
$this->l10n = $this->getMockBuilder(\OCP\IL10N::class) $this->l10n = $this->getMockBuilder(IL10N::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->reader = $this->getMockBuilder(\FeedIo\FeedIo::class) $this->reader = $this->getMockBuilder(FeedIo::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->favicon = $this->getMockBuilder(\Favicon\Favicon::class) $this->favicon = $this->getMockBuilder(Favicon::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->result = $this->getMockBuilder(\FeedIo\Reader\Result::class) $this->result = $this->getMockBuilder(Result::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->response = $this->getMockBuilder(\FeedIo\Adapter\ResponseInterface::class) $this->response = $this->getMockBuilder(ResponseInterface::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->item_mock = $this->getMockBuilder(\FeedIo\Feed\ItemInterface::class) $this->item_mock = $this->getMockBuilder(ItemInterface::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->feed_mock = $this->getMockBuilder(\FeedIo\FeedInterface::class) $this->feed_mock = $this->getMockBuilder(FeedInterface::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->time = 2323; $this->time = 2323;
$timeFactory = $this->getMockBuilder(\OCA\News\Utility\Time::class) $timeFactory = $this->getMockBuilder(Time::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$timeFactory->expects($this->any()) $timeFactory->expects($this->any())

Просмотреть файл

@ -20,7 +20,7 @@ use OC\L10N\L10N;
use OCA\News\Db\FeedMapper; use OCA\News\Db\FeedMapper;
use OCA\News\Db\ItemMapper; use OCA\News\Db\ItemMapper;
use OCA\News\Service\FeedService; use OCA\News\Service\FeedService;
use OCA\News\Service\ServiceNotFoundException; use OCA\News\Service\Exceptions\ServiceNotFoundException;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Db\DoesNotExistException;
@ -30,9 +30,9 @@ use OCA\News\Fetcher\Fetcher;
use OCA\News\Fetcher\FetcherException; use OCA\News\Fetcher\FetcherException;
use OCP\IConfig; use OCP\IConfig;
use OCP\IL10N; use OCP\IL10N;
use OCP\ILogger;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
class FeedServiceTest extends TestCase class FeedServiceTest extends TestCase
@ -82,16 +82,15 @@ class FeedServiceTest extends TestCase
private $l10n; private $l10n;
/** /**
* @var \PHPUnit\Framework\MockObject\MockObject|ILogger * @var \PHPUnit\Framework\MockObject\MockObject|LoggerInterface
*/ */
private $logger; private $logger;
protected function setUp(): void protected function setUp(): void
{ {
$this->logger = $this->getMockBuilder(ILogger::class) $this->logger = $this->getMockBuilder(LoggerInterface::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$loggerParams = ['hi'];
$this->time = 222; $this->time = 222;
$this->autoPurgeMinimumInterval = 10; $this->autoPurgeMinimumInterval = 10;
$timeFactory = $this->getMockBuilder(Time::class) $timeFactory = $this->getMockBuilder(Time::class)
@ -130,7 +129,7 @@ class FeedServiceTest extends TestCase
$this->feedService = new FeedService( $this->feedService = new FeedService(
$this->feedMapper, $this->feedMapper,
$this->fetcher, $this->itemMapper, $this->logger, $this->l10n, $this->fetcher, $this->itemMapper, $this->logger, $this->l10n,
$timeFactory, $config, $this->purifier, $loggerParams $timeFactory, $config, $this->purifier
); );
$this->user = 'jack'; $this->user = 'jack';
} }
@ -140,12 +139,13 @@ class FeedServiceTest extends TestCase
*/ */
public function testFindAll() public function testFindAll()
{ {
$this->response = [];
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('findAllFromUser') ->method('findAllFromUser')
->with($this->user) ->with($this->user)
->will($this->returnValue([])); ->will($this->returnValue([]));
$result = $this->feedService->findAll($this->user); $result = $this->feedService->findAllForUser($this->user);
$this->assertEquals([], $result); $this->assertEquals([], $result);
} }
@ -199,10 +199,14 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('insert') ->method('insert')
->with($this->equalTo($createdFeed)) ->with($this->equalTo($createdFeed))
->will($this->returnCallback(function() use ($createdFeed) { ->will(
$createdFeed->setId(4); $this->returnCallback(
return $createdFeed; function () use ($createdFeed) {
})); $createdFeed->setId(4);
return $createdFeed;
}
)
);
$this->itemMapper->expects($this->at(0)) $this->itemMapper->expects($this->at(0))
->method('findByGuidHash') ->method('findByGuidHash')
->with( ->with(
@ -281,10 +285,14 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('insert') ->method('insert')
->with($this->equalTo($createdFeed)) ->with($this->equalTo($createdFeed))
->will($this->returnCallback(function() use ($createdFeed) { ->will(
$createdFeed->setId(5); $this->returnCallback(
return $createdFeed; function () use ($createdFeed) {
})); $createdFeed->setId(5);
return $createdFeed;
}
)
);
$this->itemMapper->expects($this->at(0)) $this->itemMapper->expects($this->at(0))
->method('findByGuidHash') ->method('findByGuidHash')
->with( ->with(
@ -358,10 +366,7 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->at(0)) $this->feedMapper->expects($this->at(0))
->method('find') ->method('find')
->with( ->with($this->user, $feed->getId())
$this->equalTo($feed->getId()),
$this->equalTo($this->user)
)
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$this->fetcher->expects($this->once()) $this->fetcher->expects($this->once())
->method('fetch') ->method('fetch')
@ -394,11 +399,11 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->at(2)) $this->feedMapper->expects($this->at(2))
->method('find') ->method('find')
->with($feed->getId(), $this->user) ->with($this->user, $feed->getId())
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$return = $this->feedService->update($feed->getId(), $this->user); $return = $this->feedService->update($this->user, $feed->getId());
$this->assertEquals($return, $feed); $this->assertEquals($return, $feed);
} }
@ -425,10 +430,7 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->at(0)) $this->feedMapper->expects($this->at(0))
->method('find') ->method('find')
->with( ->with($this->user, $feed->getId())
$this->equalTo($feed->getId()),
$this->equalTo($this->user)
)
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$this->fetcher->expects($this->once()) $this->fetcher->expects($this->once())
->method('fetch') ->method('fetch')
@ -461,11 +463,11 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->at(2)) $this->feedMapper->expects($this->at(2))
->method('find') ->method('find')
->with($feed->getId(), $this->user) ->with($this->user, $feed->getId())
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$return = $this->feedService->update($feed->getId(), $this->user, true); $return = $this->feedService->update($this->user, $feed->getId(), true);
$this->assertEquals($return, $feed); $this->assertEquals($return, $feed);
} }
@ -543,7 +545,7 @@ class FeedServiceTest extends TestCase
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$return = $this->feedService->update($feed->getId(), $this->user); $return = $this->feedService->update($this->user, $feed->getId());
$this->assertEquals($return, $feed); $this->assertEquals($return, $feed);
} }
@ -583,7 +585,7 @@ class FeedServiceTest extends TestCase
->method('find') ->method('find')
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$return = $this->feedService->update($feed->getId(), $this->user); $return = $this->feedService->update($this->user, $feed->getId());
$this->assertEquals($return, $feed); $this->assertEquals($return, $feed);
@ -622,7 +624,7 @@ class FeedServiceTest extends TestCase
->method('findByGuidHash') ->method('findByGuidHash')
->will($this->returnValue($item)); ->will($this->returnValue($item));
$this->feedService->update($feed->getId(), $this->user); $this->feedService->update($this->user, $feed->getId());
} }
public function testUpdateFails() public function testUpdateFails()
@ -643,10 +645,7 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->at(0)) $this->feedMapper->expects($this->at(0))
->method('find') ->method('find')
->with( ->with($this->user, $feed->getId())
$this->equalTo($feed->getId()),
$this->equalTo($this->user)
)
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$this->fetcher->expects($this->once()) $this->fetcher->expects($this->once())
->method('fetch') ->method('fetch')
@ -661,10 +660,10 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->at(2)) $this->feedMapper->expects($this->at(2))
->method('find') ->method('find')
->with($feed->getId(), $this->user) ->with($this->user, $feed->getId())
->will($this->returnValue($exptectedFeed)); ->will($this->returnValue($exptectedFeed));
$return = $this->feedService->update($feed->getId(), $this->user); $return = $this->feedService->update($this->user, $feed->getId());
$this->assertEquals($return, $exptectedFeed); $this->assertEquals($return, $exptectedFeed);
} }
@ -679,14 +678,11 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->at(0)) $this->feedMapper->expects($this->at(0))
->method('find') ->method('find')
->with( ->with($this->user, $feed->getId())
$this->equalTo($feed->getId()),
$this->equalTo($this->user)
)
->will($this->throwException($ex)); ->will($this->throwException($ex));
$this->expectException(ServiceNotFoundException::class); $this->expectException(ServiceNotFoundException::class);
$this->feedService->update($feed->getId(), $this->user); $this->feedService->update($this->user, $feed->getId());
} }
@ -702,10 +698,7 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->at(0)) $this->feedMapper->expects($this->at(0))
->method('find') ->method('find')
->with( ->with($this->user, $feed->getId())
$this->equalTo($feed->getId()),
$this->equalTo($this->user)
)
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$this->fetcher->expects($this->once()) $this->fetcher->expects($this->once())
@ -719,7 +712,7 @@ class FeedServiceTest extends TestCase
->will($this->throwException($ex)); ->will($this->throwException($ex));
$this->expectException(DoesNotExistException::class); $this->expectException(DoesNotExistException::class);
$this->feedService->update($feed->getId(), $this->user); $this->feedService->update($this->user, $feed->getId());
} }
@ -744,10 +737,7 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->at(0)) $this->feedMapper->expects($this->at(0))
->method('find') ->method('find')
->with( ->with($this->user, $feed->getId())
$this->equalTo($feed->getId()),
$this->equalTo($this->user)
)
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$this->feedMapper->expects($this->at(1)) $this->feedMapper->expects($this->at(1))
->method('update') ->method('update')
@ -766,14 +756,11 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->at(2)) $this->feedMapper->expects($this->at(2))
->method('find') ->method('find')
->with( ->with($this->user, $feed->getId())
$this->equalTo($feed->getId()),
$this->equalTo($this->user)
)
->will($this->throwException($ex)); ->will($this->throwException($ex));
$this->expectException(ServiceNotFoundException::class); $this->expectException(ServiceNotFoundException::class);
$this->feedService->update($feed->getId(), $this->user); $this->feedService->update($this->user, $feed->getId());
} }
@ -787,15 +774,12 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('find') ->method('find')
->with( ->with($this->user, $feed->getId())
$this->equalTo($feedId),
$this->equalTo($this->user)
)
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$this->fetcher->expects($this->never()) $this->fetcher->expects($this->never())
->method('fetch'); ->method('fetch');
$this->feedService->update($feedId, $this->user); $this->feedService->update($this->user, $feedId);
} }
@ -809,16 +793,13 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('find') ->method('find')
->with( ->with($this->user, $feed->getId())
$this->equalTo($feedId),
$this->equalTo($this->user)
)
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$this->fetcher->expects($this->once()) $this->fetcher->expects($this->once())
->method('fetch') ->method('fetch')
->will($this->returnValue([null, null])); ->will($this->returnValue([null, null]));
$return = $this->feedService->update($feedId, $this->user); $return = $this->feedService->update($this->user, $feedId);
$this->assertEquals($feed, $return); $this->assertEquals($feed, $return);
} }
@ -833,14 +814,16 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('find') ->method('find')
->with($this->equalTo($feedId), $this->equalTo($this->user)) ->with($this->user, $feedId)
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('update') ->method('update')
->with($this->equalTo($feed)); ->with($this->equalTo($feed));
$this->feedService->patch($feedId, $this->user, ['folderId' => $folderId]); $this->feedService->patch(
$feedId, $this->user, ['folderId' => $folderId]
);
$this->assertEquals($folderId, $feed->getFolderId()); $this->assertEquals($folderId, $feed->getFolderId());
} }
@ -856,14 +839,16 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('find') ->method('find')
->with($this->equalTo($feedId), $this->equalTo($this->user)) ->with($this->equalTo($this->user), $this->equalTo($feedId))
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('update') ->method('update')
->with($this->equalTo($feed)); ->with($this->equalTo($feed));
$this->feedService->patch($feedId, $this->user, ['title' => $feedTitle]); $this->feedService->patch(
$feedId, $this->user, ['title' => $feedTitle]
);
$this->assertEquals($feedTitle, $feed->getTitle()); $this->assertEquals($feedTitle, $feed->getTitle());
} }
@ -982,10 +967,14 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('insert') ->method('insert')
->with($this->equalTo($insertFeed)) ->with($this->equalTo($insertFeed))
->will($this->returnCallback(function() use ($insertFeed) { ->will(
$insertFeed->setId(3); $this->returnCallback(
return $insertFeed; function () use ($insertFeed) {
})); $insertFeed->setId(3);
return $insertFeed;
}
)
);
$this->itemMapper->expects($this->at(0)) $this->itemMapper->expects($this->at(0))
@ -1025,7 +1014,7 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('find') ->method('find')
->with($this->equalTo($id), $this->equalTo($this->user)) ->with($this->equalTo($this->user), $this->equalTo($id))
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('update') ->method('update')
@ -1044,7 +1033,7 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('find') ->method('find')
->with($this->equalTo($id), $this->equalTo($this->user)) ->with($this->equalTo($this->user), $this->equalTo($id))
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('update') ->method('update')
@ -1103,7 +1092,7 @@ class FeedServiceTest extends TestCase
public function testfindAllFromAllUsers() public function testfindAllFromAllUsers()
{ {
$expected = 'hi'; $expected = ['hi'];
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('findAll') ->method('findAll')
->will($this->returnValue($expected)); ->will($this->returnValue($expected));
@ -1128,8 +1117,8 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('find') ->method('find')
->with( ->with(
$this->equalTo($feed->getId()), $this->equalTo($this->user),
$this->equalTo($this->user) $this->equalTo($feed->getId())
) )
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
@ -1146,18 +1135,18 @@ class FeedServiceTest extends TestCase
{ {
$feed = Feed::fromRow( $feed = Feed::fromRow(
[ [
'id' => 3, 'id' => 3,
'http_etag' => 'a', 'http_etag' => 'a',
'http_last_modified' => 1, 'http_last_modified' => 1,
'full_text_enabled' => false 'full_text_enabled' => false
] ]
); );
$feed2 = Feed::fromRow(['id' => 3]); $feed2 = Feed::fromRow(['id' => 3]);
$this->feedMapper->expects($this->at(0)) $this->feedMapper->expects($this->at(0))
->method('find') ->method('find')
->with( ->with(
$this->equalTo($feed->getId()), $this->equalTo($this->user),
$this->equalTo($this->user) $this->equalTo($feed->getId())
) )
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
@ -1171,8 +1160,8 @@ class FeedServiceTest extends TestCase
$this->feedMapper->expects($this->at(2)) $this->feedMapper->expects($this->at(2))
->method('find') ->method('find')
->with( ->with(
$this->equalTo($feed->getId()), $this->equalTo($this->user),
$this->equalTo($this->user) $this->equalTo($feed->getId())
) )
->will($this->throwException(new DoesNotExistException(''))); ->will($this->throwException(new DoesNotExistException('')));
@ -1183,7 +1172,7 @@ class FeedServiceTest extends TestCase
public function testPatchDoesNotExist() public function testPatchDoesNotExist()
{ {
$this->expectException('OCA\News\Service\ServiceNotFoundException'); $this->expectException('OCA\News\Service\Exceptions\ServiceNotFoundException');
$feed = Feed::fromRow(['id' => 3]); $feed = Feed::fromRow(['id' => 3]);
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('find') ->method('find')
@ -1198,10 +1187,7 @@ class FeedServiceTest extends TestCase
$feed = Feed::fromRow(['id' => 3, 'pinned' => false]); $feed = Feed::fromRow(['id' => 3, 'pinned' => false]);
$this->feedMapper->expects($this->once()) $this->feedMapper->expects($this->once())
->method('find') ->method('find')
->with( ->with($this->user, $feed->getId())
$this->equalTo($feed->getId()),
$this->equalTo($this->user)
)
->will($this->returnValue($feed)); ->will($this->returnValue($feed));
$feed->setPinned(true); $feed->setPinned(true);

Просмотреть файл

@ -17,13 +17,14 @@ use OC\L10N\L10N;
use \OCA\News\Db\Folder; use \OCA\News\Db\Folder;
use OCA\News\Db\FolderMapper; use OCA\News\Db\FolderMapper;
use OCA\News\Service\FolderService; use OCA\News\Service\FolderService;
use OCA\News\Service\ServiceConflictException; use OCA\News\Service\Exceptions\ServiceConflictException;
use OCA\News\Service\ServiceValidationException; use OCA\News\Service\Exceptions\ServiceValidationException;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
use OCP\IConfig; use OCP\IConfig;
use OCP\IL10N; use OCP\IL10N;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
class FolderServiceTest extends TestCase class FolderServiceTest extends TestCase
@ -49,6 +50,11 @@ class FolderServiceTest extends TestCase
*/ */
private $user; private $user;
/**
* @var \PHPUnit\Framework\MockObject\MockObject|LoggerInterface
*/
private $logger;
/** /**
* @var int * @var int
*/ */
@ -78,12 +84,15 @@ class FolderServiceTest extends TestCase
$config = $this->getMockBuilder(IConfig::class) $config = $this->getMockBuilder(IConfig::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->logger = $this->getMockBuilder(LoggerInterface::class)
->disableOriginalConstructor()
->getMock();
$config->expects($this->any()) $config->expects($this->any())
->method('getAppValue') ->method('getAppValue')
->with('news', 'autoPurgeMinimumInterval') ->with('news', 'autoPurgeMinimumInterval')
->will($this->returnValue($this->autoPurgeMinimumInterval)); ->will($this->returnValue($this->autoPurgeMinimumInterval));
$this->folderService = new FolderService( $this->folderService = new FolderService(
$this->folderMapper, $this->l10n, $timeFactory, $config $this->folderMapper, $this->l10n, $timeFactory, $config, $this->logger
); );
$this->user = 'hi'; $this->user = 'hi';
} }
@ -92,13 +101,13 @@ class FolderServiceTest extends TestCase
public function testFindAll() public function testFindAll()
{ {
$userId = 'jack'; $userId = 'jack';
$return = 'hi'; $return = [];
$this->folderMapper->expects($this->once()) $this->folderMapper->expects($this->once())
->method('findAllFromUser') ->method('findAllFromUser')
->with($this->equalTo($userId)) ->with($this->equalTo($userId))
->will($this->returnValue($return)); ->will($this->returnValue($return));
$result = $this->folderService->findAll($userId); $result = $this->folderService->findAllForUser($userId);
$this->assertEquals($return, $result); $this->assertEquals($return, $result);
} }
@ -146,8 +155,7 @@ class FolderServiceTest extends TestCase
public function testCreateThrowsExWhenFolderNameEmpty() public function testCreateThrowsExWhenFolderNameEmpty()
{ {
$this->expectException('OCA\News\Service\ServiceValidationException'); $this->expectException('\OCA\News\Service\Exceptions\ServiceValidationException');
$folderName = ''; $folderName = '';
$this->folderMapper->expects($this->once()) $this->folderMapper->expects($this->once())
@ -165,7 +173,7 @@ class FolderServiceTest extends TestCase
$this->folderMapper->expects($this->once()) $this->folderMapper->expects($this->once())
->method('find') ->method('find')
->with($this->equalTo(3)) ->with('', 3)
->will($this->returnValue($folder)); ->will($this->returnValue($folder));
$this->folderMapper->expects($this->once()) $this->folderMapper->expects($this->once())
@ -186,7 +194,7 @@ class FolderServiceTest extends TestCase
$this->folderMapper->expects($this->once()) $this->folderMapper->expects($this->once())
->method('find') ->method('find')
->with($this->equalTo(3)) ->with('', 3)
->will($this->returnValue($folder)); ->will($this->returnValue($folder));
$this->folderMapper->expects($this->once()) $this->folderMapper->expects($this->once())
@ -244,7 +252,7 @@ class FolderServiceTest extends TestCase
$this->folderMapper->expects($this->once()) $this->folderMapper->expects($this->once())
->method('find') ->method('find')
->with($this->equalTo($id), $this->equalTo($this->user)) ->with($this->equalTo($this->user), $this->equalTo($id))
->will($this->returnValue($folder)); ->will($this->returnValue($folder));
$this->folderMapper->expects($this->once()) $this->folderMapper->expects($this->once())
->method('update') ->method('update')
@ -263,7 +271,7 @@ class FolderServiceTest extends TestCase
$this->folderMapper->expects($this->once()) $this->folderMapper->expects($this->once())
->method('find') ->method('find')
->with($this->equalTo($id), $this->equalTo($this->user)) ->with($this->equalTo($this->user), $this->equalTo($id))
->will($this->returnValue($folder)); ->will($this->returnValue($folder));
$this->folderMapper->expects($this->once()) $this->folderMapper->expects($this->once())
->method('update') ->method('update')

Просмотреть файл

@ -13,9 +13,11 @@
namespace OCA\News\Tests\Unit\Service; namespace OCA\News\Tests\Unit\Service;
use OC\Log;
use OCA\News\Db\ItemMapper; use OCA\News\Db\ItemMapper;
use OCA\News\Service\ItemService; use OCA\News\Service\ItemService;
use OCA\News\Service\ServiceNotFoundException; use OCA\News\Service\Exceptions\ServiceNotFoundException;
use OCA\News\Utility\PsrLogger;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
use \OCP\AppFramework\Db\DoesNotExistException; use \OCP\AppFramework\Db\DoesNotExistException;
@ -24,6 +26,7 @@ use \OCA\News\Db\FeedType;
use OCP\IConfig; use OCP\IConfig;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
class ItemServiceTest extends TestCase class ItemServiceTest extends TestCase
@ -38,15 +41,31 @@ class ItemServiceTest extends TestCase
*/ */
private $itemService; private $itemService;
/**
* @var \PHPUnit\Framework\MockObject\MockObject|IConfig
*/
private $config;
/**
* @var \PHPUnit\Framework\MockObject\MockObject|LoggerInterface
*/
private $logger;
/**
* @var \PHPUnit\Framework\MockObject\MockObject|Time
*/
private $timeFactory;
/**
* @var int
*/
private $newestItemId;
/** /**
* @var int * @var int
*/ */
private $time; private $time;
/**
* @var \PHPUnit\Framework\MockObject\MockObject|IConfig
*/
private $config;
protected function setUp(): void protected function setUp(): void
{ {
@ -66,7 +85,24 @@ class ItemServiceTest extends TestCase
$this->config = $this->getMockBuilder(IConfig::class) $this->config = $this->getMockBuilder(IConfig::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->itemService = new ItemService($this->mapper, $this->timeFactory, $this->config);
$this->logger = $this->getMockBuilder(LoggerInterface::class)
->disableOriginalConstructor()
->getMock();
$this->itemService = new ItemService(
$this->mapper,
$this->timeFactory,
$this->config,
$this->logger
);
$this->user = 'jack';
$this->id = 3;
$this->updatedSince = 20333;
$this->showAll = true;
$this->offset = 5;
$this->limit = 20;
$this->newestItemId = 4;
} }
@ -143,7 +179,7 @@ class ItemServiceTest extends TestCase
) )
->will($this->returnValue(['val'])); ->will($this->returnValue(['val']));
$result = $this->itemService->findAll( $result = $this->itemService->findAllItems(
3, $type, 20, 5, 3, $type, 20, 5,
true, false, 'jack' true, false, 'jack'
); );
@ -167,7 +203,7 @@ class ItemServiceTest extends TestCase
) )
->will($this->returnValue(['val'])); ->will($this->returnValue(['val']));
$result = $this->itemService->findAll( $result = $this->itemService->findAllItems(
3, $type, 20, 5, 3, $type, 20, 5,
true, true, 'jack' true, true, 'jack'
); );
@ -179,7 +215,7 @@ class ItemServiceTest extends TestCase
{ {
$type = FeedType::STARRED; $type = FeedType::STARRED;
$this->mapper->expects($this->once()) $this->mapper->expects($this->once())
->method('findAll') ->method('findAllItems')
->with( ->with(
$this->equalTo(20), $this->equalTo(20),
$this->equalTo(5), $this->equalTo(5),
@ -191,7 +227,7 @@ class ItemServiceTest extends TestCase
) )
->will($this->returnValue(['val'])); ->will($this->returnValue(['val']));
$result = $this->itemService->findAll( $result = $this->itemService->findAllItems(
3, $type, 20, 5, 3, $type, 20, 5,
true, true, 'jack' true, true, 'jack'
); );
@ -203,8 +239,9 @@ class ItemServiceTest extends TestCase
{ {
$type = FeedType::STARRED; $type = FeedType::STARRED;
$search = ['test']; $search = ['test'];
$this->mapper->expects($this->once()) $this->mapper->expects($this->once())
->method('findAll') ->method('findAllItems')
->with( ->with(
$this->equalTo(20), $this->equalTo(20),
$this->equalTo(5), $this->equalTo(5),
@ -216,7 +253,7 @@ class ItemServiceTest extends TestCase
) )
->will($this->returnValue(['val'])); ->will($this->returnValue(['val']));
$result = $this->itemService->findAll( $result = $this->itemService->findAllItems(
3, $type, 20, 5, 3, $type, 20, 5,
true, true, 'jack', $search true, true, 'jack', $search
); );

Просмотреть файл

@ -13,21 +13,33 @@
namespace OCA\News\Tests\Unit\Service; namespace OCA\News\Tests\Unit\Service;
use OCA\News\Db\Feed;
use OCA\News\Db\ItemMapper; use OCA\News\Db\ItemMapper;
use OCA\News\Service\Exceptions\ServiceNotFoundException;
use OCA\News\Service\Service; use OCA\News\Service\Service;
use OCA\News\Service\ServiceNotFoundException;
use \OCP\AppFramework\Db\DoesNotExistException; use \OCP\AppFramework\Db\DoesNotExistException;
use \OCP\AppFramework\Db\MultipleObjectsReturnedException; use \OCP\AppFramework\Db\MultipleObjectsReturnedException;
use \OCA\News\Db\Folder; use \OCA\News\Db\Folder;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
use Psr\Log\LoggerInterface;
class TestService extends Service class TestLegacyService extends Service
{ {
public function __construct($mapper) public function __construct($mapper, $logger)
{ {
parent::__construct($mapper); parent::__construct($mapper, $logger);
}
public function findAllForUser(string $userId): array
{
// TODO: Implement findAllForUser() method.
}
public function findAll(): array
{
// TODO: Implement findAll() method.
} }
} }
@ -35,6 +47,7 @@ class ServiceTest extends TestCase
{ {
protected $mapper; protected $mapper;
protected $logger;
protected $newsService; protected $newsService;
protected function setUp(): void protected function setUp(): void
@ -42,7 +55,10 @@ class ServiceTest extends TestCase
$this->mapper = $this->getMockBuilder(ItemMapper::class) $this->mapper = $this->getMockBuilder(ItemMapper::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->newsService = new TestService($this->mapper); $this->logger = $this->getMockBuilder(LoggerInterface::class)
->disableOriginalConstructor()
->getMock();
$this->newsService = new TestLegacyService($this->mapper, $this->logger);
} }
@ -58,10 +74,10 @@ class ServiceTest extends TestCase
->with($this->equalTo($folder)); ->with($this->equalTo($folder));
$this->mapper->expects($this->once()) $this->mapper->expects($this->once())
->method('find') ->method('find')
->with($this->equalTo($id), $this->equalTo($user)) ->with($this->equalTo($user), $this->equalTo($id))
->will($this->returnValue($folder)); ->will($this->returnValue($folder));
$this->newsService->delete($id, $user); $this->newsService->delete($user, $id);
} }
@ -72,9 +88,10 @@ class ServiceTest extends TestCase
$this->mapper->expects($this->once()) $this->mapper->expects($this->once())
->method('find') ->method('find')
->with($this->equalTo($id), $this->equalTo($user)); ->with($this->equalTo($user), $this->equalTo($id))
->will($this->returnValue(new Feed()));
$this->newsService->find($id, $user); $this->newsService->find($user, $id);
} }
@ -87,7 +104,7 @@ class ServiceTest extends TestCase
->will($this->throwException($ex)); ->will($this->throwException($ex));
$this->expectException(ServiceNotFoundException::class); $this->expectException(ServiceNotFoundException::class);
$this->newsService->find(1, ''); $this->newsService->find('', 1);
} }
@ -100,7 +117,7 @@ class ServiceTest extends TestCase
->will($this->throwException($ex)); ->will($this->throwException($ex));
$this->expectException(ServiceNotFoundException::class); $this->expectException(ServiceNotFoundException::class);
$this->newsService->find(1, ''); $this->newsService->find('', 1);
} }
} }

Просмотреть файл

@ -11,35 +11,49 @@
* @copyright 2012-2014 Bernhard Posselt * @copyright 2012-2014 Bernhard Posselt
*/ */
namespace OCA\News\Tests\Unit\Utility; namespace OCA\News\Tests\Unit\Service;
use OCA\News\Service\FeedServiceV2;
use OCA\News\Service\FeedService; use OCA\News\Service\FolderServiceV2;
use OCA\News\Service\FolderService; use OCA\News\Service\ItemServiceV2;
use OCA\News\Service\ItemService; use OCA\News\Service\UpdaterService;
use OCA\News\Utility\Updater;
use PHPUnit\Framework\TestCase; use PHPUnit\Framework\TestCase;
class UpdaterTest extends TestCase class UpdaterTest extends TestCase
{ {
/**
* @var \PHPUnit\Framework\MockObject\MockObject|FolderServiceV2
*/
private $folderService; private $folderService;
/**
* @var \PHPUnit\Framework\MockObject\MockObject|FeedServiceV2
*/
private $feedService; private $feedService;
/**
* @var \PHPUnit\Framework\MockObject\MockObject|ItemServiceV2
*/
private $itemService; private $itemService;
/**
* @var UpdaterService
*/
private $updater; private $updater;
protected function setUp(): void protected function setUp(): void
{ {
$this->folderService = $this->getMockBuilder(FolderService::class) $this->folderService = $this->getMockBuilder(FolderServiceV2::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->feedService = $this->getMockBuilder(FeedService::class) $this->feedService = $this->getMockBuilder(FeedServiceV2::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->itemService = $this->getMockBuilder(ItemService::class) $this->itemService = $this->getMockBuilder(ItemServiceV2::class)
->disableOriginalConstructor() ->disableOriginalConstructor()
->getMock(); ->getMock();
$this->updater = new Updater( $this->updater = new UpdaterService(
$this->folderService, $this->folderService,
$this->feedService, $this->feedService,
$this->itemService $this->itemService
@ -59,14 +73,14 @@ class UpdaterTest extends TestCase
public function testAfterUpdate() public function testAfterUpdate()
{ {
$this->itemService->expects($this->once()) $this->itemService->expects($this->once())
->method('autoPurgeOld'); ->method('purgeOverThreshold');
$this->updater->afterUpdate(); $this->updater->afterUpdate();
} }
public function testUpdate() public function testUpdate()
{ {
$this->feedService->expects($this->once()) $this->feedService->expects($this->once())
->method('updateAll'); ->method('fetchAll');
$this->updater->update(); $this->updater->update();
} }
} }