summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSean Molenaar <sean@seanmolenaar.eu>2020-08-29 23:39:35 +0200
committerBenjamin Brahmer <info@b-brahmer.de>2020-09-27 15:35:31 +0200
commitd00d1ab2a28f428223e52b17052c072c64784016 (patch)
treec019f85fb7ac67147dd43ca64b4ac3cda99832f7
parent5687baca75d47dbdffd3de74e865ad2f71ef0cb7 (diff)
Create V2 mapper, Service and management commands
Signed-off-by: Sean Molenaar <sean@seanmolenaar.eu>
-rw-r--r--.github/workflows/integration-tests.yml7
-rw-r--r--AUTHORS.md1
-rw-r--r--appinfo/info.xml7
-rw-r--r--composer.json3
-rw-r--r--composer.lock15
-rw-r--r--lib/Command/Config/FeedAdd.php72
-rw-r--r--lib/Command/Config/FeedDelete.php56
-rw-r--r--lib/Command/Config/FeedList.php61
-rw-r--r--lib/Command/Config/FolderAdd.php58
-rw-r--r--lib/Command/Config/FolderDelete.php61
-rw-r--r--lib/Command/Config/FolderList.php62
-rw-r--r--lib/Command/ExploreGenerator.php3
-rw-r--r--lib/Command/ShowFeed.php3
-rw-r--r--lib/Command/Updater/AfterUpdate.php36
-rw-r--r--lib/Command/Updater/AllFeeds.php20
-rw-r--r--lib/Command/Updater/BeforeUpdate.php20
-rw-r--r--lib/Command/Updater/UpdateFeed.php21
-rw-r--r--lib/Controller/ApiPayloadTrait.php36
-rw-r--r--lib/Controller/EntityApiSerializer.php6
-rw-r--r--lib/Controller/FeedApiController.php35
-rw-r--r--lib/Controller/FeedController.php12
-rw-r--r--lib/Controller/FolderApiController.php6
-rw-r--r--lib/Controller/FolderController.php6
-rw-r--r--lib/Controller/ItemApiController.php10
-rw-r--r--lib/Controller/ItemController.php6
-rw-r--r--lib/Controller/JSONHttpError.php7
-rw-r--r--lib/Controller/UtilityApiController.php21
-rw-r--r--lib/Cron/UpdaterJob.php (renamed from lib/Cron/Updater.php)18
-rw-r--r--lib/Db/Feed.php115
-rw-r--r--lib/Db/FeedMapper.php29
-rw-r--r--lib/Db/FeedMapperV2.php141
-rw-r--r--lib/Db/Folder.php7
-rw-r--r--lib/Db/FolderMapper.php38
-rw-r--r--lib/Db/FolderMapperV2.php87
-rw-r--r--lib/Db/Item.php6
-rw-r--r--lib/Db/ItemMapper.php52
-rw-r--r--lib/Db/ItemMapperV2.php124
-rw-r--r--lib/Db/MapperFactory.php6
-rw-r--r--lib/Db/Mysql/ItemMapper.php6
-rw-r--r--lib/Db/NewsMapper.php84
-rw-r--r--lib/Db/NewsMapperV2.php108
-rwxr-xr-xlib/Fetcher/FeedFetcher.php2
-rw-r--r--lib/Fetcher/IFeedFetcher.php2
-rw-r--r--lib/Fetcher/YoutubeFetcher.php8
-rw-r--r--lib/Service/Exceptions/ServiceConflictException.php (renamed from lib/Service/ServiceConflictException.php)2
-rw-r--r--lib/Service/Exceptions/ServiceException.php (renamed from lib/Service/ServiceException.php)2
-rw-r--r--lib/Service/Exceptions/ServiceNotFoundException.php (renamed from lib/Service/ServiceNotFoundException.php)2
-rw-r--r--lib/Service/Exceptions/ServiceValidationException.php (renamed from lib/Service/ServiceValidationException.php)2
-rw-r--r--lib/Service/FeedService.php61
-rw-r--r--lib/Service/FeedServiceV2.php336
-rw-r--r--lib/Service/FolderService.php97
-rw-r--r--lib/Service/FolderServiceV2.php102
-rw-r--r--lib/Service/ItemService.php30
-rw-r--r--lib/Service/ItemServiceV2.php104
-rw-r--r--lib/Service/Service.php70
-rw-r--r--lib/Service/StatusService.php6
-rw-r--r--lib/Service/UpdaterService.php (renamed from lib/Utility/Updater.php)20
-rw-r--r--lib/Utility/OPMLExporter.php15
-rw-r--r--lib/Utility/Time.php4
-rw-r--r--tests/Integration/Db/FeedMapperTest.php16
-rw-r--r--tests/Integration/Db/ItemMapperTest.php52
-rw-r--r--tests/Integration/IntegrationTest.php30
-rw-r--r--tests/Unit/Controller/FeedApiControllerTest.php36
-rw-r--r--tests/Unit/Controller/FeedControllerTest.php16
-rw-r--r--tests/Unit/Controller/FolderApiControllerTest.php23
-rw-r--r--tests/Unit/Controller/FolderControllerTest.php14
-rw-r--r--tests/Unit/Controller/ItemApiControllerTest.php2
-rw-r--r--tests/Unit/Controller/ItemControllerTest.php2
-rw-r--r--tests/Unit/Controller/UtilityApiControllerTest.php57
-rw-r--r--tests/Unit/Db/FeedTest.php25
-rw-r--r--tests/Unit/Db/FolderMapperTest.php6
-rw-r--r--tests/Unit/Db/FolderTest.php9
-rw-r--r--tests/Unit/Db/MapperFactoryTest.php4
-rw-r--r--tests/Unit/Fetcher/FeedFetcherTest.php32
-rw-r--r--tests/Unit/Service/FeedServiceTest.php168
-rw-r--r--tests/Unit/Service/FolderServiceTest.php30
-rw-r--r--tests/Unit/Service/ItemServiceTest.php59
-rw-r--r--tests/Unit/Service/ServiceTest.php39
-rw-r--r--tests/Unit/Service/UpdaterTest.php (renamed from tests/Unit/Utility/UpdaterTest.php)38
79 files changed, 2434 insertions, 561 deletions
diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml
index 14244ab2a..b94f01f8e 100644
--- a/.github/workflows/integration-tests.yml
+++ b/.github/workflows/integration-tests.yml
@@ -100,9 +100,16 @@ jobs:
run: |
cd ../server
./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
run: cd ../server/apps/news && make php-test-dependencies
- name: Integration tests
run: cd ../server/apps/news && make integration-test
+
diff --git a/AUTHORS.md b/AUTHORS.md
index 187c491c4..25264f040 100644
--- a/AUTHORS.md
+++ b/AUTHORS.md
@@ -130,6 +130,7 @@
* [blackcrack](mailto:blackcrack@blackysgate.de)
* [comradekingu](mailto:epost@anotheragency.no)
* [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)
* [kesselb](mailto:mail@danielkesselberg.de)
* [kondou](mailto:kondou@ts.unde.re)
diff --git a/appinfo/info.xml b/appinfo/info.xml
index a9eb039f5..c11dc7f20 100644
--- a/appinfo/info.xml
+++ b/appinfo/info.xml
@@ -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\BeforeUpdate</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>
<settings>
diff --git a/composer.json b/composer.json
index 25d0db908..0acc198ae 100644
--- a/composer.json
+++ b/composer.json
@@ -50,7 +50,8 @@
"ext-json": "*",
"ext-simplexml": "*",
"ext-libxml": "*",
- "andreskrey/readability.php": "^2.1"
+ "andreskrey/readability.php": "^2.1",
+ "ext-dom": "*"
},
"require-dev": {
"phpunit/phpunit": "9.2.6",
diff --git a/composer.lock b/composer.lock
index 7b31b1ac9..ada2160ad 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "d026de8b34993e486d928ef4c509676d",
+ "content-hash": "0f4161d1df33ea0b72224da925f2f6b5",
"packages": [
{
"name": "andreskrey/readability.php",
@@ -826,16 +826,16 @@
},
{
"name": "phpstan/phpstan",
- "version": "0.12.44",
+ "version": "0.12.45",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "330b45776ea77f167b150e24787412414a8fa469"
+ "reference": "90c67259212ed891ee86604a9368ef7d7bead3a4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/330b45776ea77f167b150e24787412414a8fa469",
- "reference": "330b45776ea77f167b150e24787412414a8fa469",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/90c67259212ed891ee86604a9368ef7d7bead3a4",
+ "reference": "90c67259212ed891ee86604a9368ef7d7bead3a4",
"shasum": ""
},
"require": {
@@ -878,7 +878,7 @@
"type": "tidelift"
}
],
- "time": "2020-09-24T15:28:47+00:00"
+ "time": "2020-09-26T19:19:00+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -2422,7 +2422,8 @@
"php": "^7.2",
"ext-json": "*",
"ext-simplexml": "*",
- "ext-libxml": "*"
+ "ext-libxml": "*",
+ "ext-dom": "*"
},
"platform-dev": [],
"plugin-api-version": "1.1.0"
diff --git a/lib/Command/Config/FeedAdd.php b/lib/Command/Config/FeedAdd.php
new file mode 100644
index 000000000..d21f448c0
--- /dev/null
+++ b/lib/Command/Config/FeedAdd.php
@@ -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;
+ }
+}
diff --git a/lib/Command/Config/FeedDelete.php b/lib/Command/Config/FeedDelete.php
new file mode 100644
index 000000000..c848b1fd4
--- /dev/null
+++ b/lib/Command/Config/FeedDelete.php
@@ -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;
+ }
+}
diff --git a/lib/Command/Config/FeedList.php b/lib/Command/Config/FeedList.php
new file mode 100644
index 000000000..57e14d339
--- /dev/null
+++ b/lib/Command/Config/FeedList.php
@@ -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));
+ }
+}
diff --git a/lib/Command/Config/FolderAdd.php b/lib/Command/Config/FolderAdd.php
new file mode 100644
index 000000000..5a7155e0c
--- /dev/null
+++ b/lib/Command/Config/FolderAdd.php
@@ -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');
+