1
0
mirror of https://github.com/chylex/Nextcloud-News.git synced 2025-05-06 07:34:06 +02:00

Define an official codestyle and adhere to it.

This commit is contained in:
Sean Molenaar 2018-11-29 20:59:46 +01:00
parent 0f2645145a
commit becce6b752
68 changed files with 898 additions and 1079 deletions

View File

@ -1,8 +1,8 @@
# Contributing # Contributing
Read this when you want to: Read this when you want to:
* file an issue (bug or feature request) * [file an issue (bug or feature request)](#Issues)
* help translate the News file to your language * [help translate the News file to your language](#Translation)
* start programming and change the way the News app works * start programming and change the way the News app works
* add cool new feeds to the feed explore section * add cool new feeds to the feed explore section
* want to provide additional full text feed rules * want to provide additional full text feed rules
@ -119,16 +119,8 @@ We usually hang out on **irc.freenode.net** in the **#nextcloud-news** and **#ne
### Coding Style Guidelines ### Coding Style Guidelines
* Use 4 spaces for indention. Why spaces? Because it looks the same on every machine and on the web where you can't normally control the tab width. The PHP code should all adhere to [PSR-2](https://www.php-fig.org/psr/psr-2/).
* Place the open curly braces on the same line as the parameter block, e.g.: *Note that this is a different codestyle than nextcloud itself uses.*
```php To test the codestyle you can run `make phpcs`.
if (condition) {
// code
} else {
// code
}
```
* Place a space before and after the parameter block for if, else, for, foreach, function For linting JavaScript, a [jshint file](https://github.com/nextcloud/news/blob/master/js/.jshintrc) is used that is run before compiling the JavaScript
* Everything should be in camelCase except classes which should be in PascalCase
* For linting JavaScript, a [jshint file](https://github.com/nextcloud/news/blob/master/js/.jshintrc) is used that is run before compiling the JavaScript

View File

@ -108,6 +108,11 @@ endif
clean: clean:
rm -rf ./build rm -rf ./build
# Reports PHP codestyle violations
.PHONY: phpcs
phpcs:
./vendor/bin/phpcs --standard=PSR2 lib
# Same as clean but also removes dependencies installed by composer and # Same as clean but also removes dependencies installed by composer and
# npm # npm
.PHONY: distclean .PHONY: distclean
@ -183,3 +188,4 @@ test:
./vendor/phpunit/phpunit/phpunit -c phpunit.xml --coverage-clover build/php-unit.clover ./vendor/phpunit/phpunit/phpunit -c phpunit.xml --coverage-clover build/php-unit.clover
# \Test\TestCase is only allowed to access the db if TRAVIS environment variable is set # \Test\TestCase is only allowed to access the db if TRAVIS environment variable is set
env TRAVIS=1 ./vendor/phpunit/phpunit/phpunit -c phpunit.integration.xml --coverage-clover build/php-unit.clover env TRAVIS=1 ./vendor/phpunit/phpunit/phpunit -c phpunit.integration.xml --coverage-clover build/php-unit.clover
$(MAKE) phpcs

View File

@ -36,7 +36,8 @@
"nicolus/picofeed": "0.1.35" "nicolus/picofeed": "0.1.35"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^6.5" "phpunit/phpunit": "^6.5",
"squizlabs/php_codesniffer": "^3.3"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

359
composer.lock generated
View File

@ -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": "ac4e6dcfaee8b83840050366cacebc4c", "content-hash": "f4a0d96b7e83ec4d9d232412b9e61566",
"packages": [ "packages": [
{ {
"name": "ezyang/htmlpurifier", "name": "ezyang/htmlpurifier",
@ -322,262 +322,6 @@
], ],
"time": "2017-07-22T11:58:36+00:00" "time": "2017-07-22T11:58:36+00:00"
}, },
{
"name": "guzzlehttp/guzzle",
"version": "6.3.3",
"source": {
"type": "git",
"url": "https://github.com/guzzle/guzzle.git",
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba",
"reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba",
"shasum": ""
},
"require": {
"guzzlehttp/promises": "^1.0",
"guzzlehttp/psr7": "^1.4",
"php": ">=5.5"
},
"require-dev": {
"ext-curl": "*",
"phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0",
"psr/log": "^1.0"
},
"suggest": {
"psr/log": "Required for using the Log middleware"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "6.3-dev"
}
},
"autoload": {
"files": [
"src/functions_include.php"
],
"psr-4": {
"GuzzleHttp\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle is a PHP HTTP client library",
"homepage": "http://guzzlephp.org/",
"keywords": [
"client",
"curl",
"framework",
"http",
"http client",
"rest",
"web service"
],
"time": "2018-04-22T15:46:56+00:00"
},
{
"name": "guzzlehttp/promises",
"version": "v1.3.1",
"source": {
"type": "git",
"url": "https://github.com/guzzle/promises.git",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Promise\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Guzzle promises library",
"keywords": [
"promise"
],
"time": "2016-12-20T10:07:11+00:00"
},
{
"name": "guzzlehttp/psr7",
"version": "1.4.2",
"source": {
"type": "git",
"url": "https://github.com/guzzle/psr7.git",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c",
"shasum": ""
},
"require": {
"php": ">=5.4.0",
"psr/http-message": "~1.0"
},
"provide": {
"psr/http-message-implementation": "1.0"
},
"require-dev": {
"phpunit/phpunit": "~4.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.4-dev"
}
},
"autoload": {
"psr-4": {
"GuzzleHttp\\Psr7\\": "src/"
},
"files": [
"src/functions_include.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
},
{
"name": "Tobias Schultze",
"homepage": "https://github.com/Tobion"
}
],
"description": "PSR-7 message implementation that also provides common utility methods",
"keywords": [
"http",
"message",
"request",
"response",
"stream",
"uri",
"url"
],
"time": "2017-03-20T17:10:46+00:00"
},
{
"name": "kevinrob/guzzle-cache-middleware",
"version": "v2.1.1",
"source": {
"type": "git",
"url": "https://github.com/Kevinrob/guzzle-cache-middleware.git",
"reference": "6952064f7747756b0be7b4c234c0fd7535ea4c8c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/Kevinrob/guzzle-cache-middleware/zipball/6952064f7747756b0be7b4c234c0fd7535ea4c8c",
"reference": "6952064f7747756b0be7b4c234c0fd7535ea4c8c",
"shasum": ""
},
"require": {
"php": ">=5.5.0"
},
"require-dev": {
"cache/array-adapter": "^0.4",
"doctrine/cache": "^1.0",
"guzzlehttp/guzzle": "^6.0",
"illuminate/cache": "^5.0",
"league/flysystem": "^1.0",
"phpunit/phpunit": "^4.0 || ^5.0",
"psr/cache": "^1.0"
},
"suggest": {
"doctrine/cache": "This library have a lot of ready-to-use cache storage (to be use with Kevinrob\\GuzzleCache\\Storage\\DoctrineCacheStorage)",
"guzzlehttp/guzzle": "For using this library. It was created for Guzzle6. (but you can use it with any PSR-7 HTTP Client)",
"laravel/framework": "To be use with Kevinrob\\GuzzleCache\\Storage\\LaravelCacheStorage",
"league/flysystem": "To be use with Kevinrob\\GuzzleCache\\Storage\\FlysystemStorage",
"psr/cache": "To be use with Kevinrob\\GuzzleCache\\Storage\\Psr6CacheStorage"
},
"type": "library",
"autoload": {
"psr-4": {
"Kevinrob\\GuzzleCache\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Kevin Robatel",
"email": "kevinrob2@gmail.com",
"homepage": "https://github.com/Kevinrob"
}
],
"description": "A HTTP/1.1 Cache for Guzzle 6. It's a simple Middleware to be added in the HandlerStack. (RFC 7234)",
"homepage": "https://github.com/Kevinrob/guzzle-cache-middleware",
"keywords": [
"Etag",
"Flysystem",
"Guzzle",
"cache",
"cache-control",
"doctrine",
"expiration",
"guzzle6",
"handler",
"http",
"http 1.1",
"middleware",
"performance",
"php",
"promise",
"psr6",
"psr7",
"rfc7234",
"validation"
],
"time": "2017-08-17T12:23:43+00:00"
},
{ {
"name": "myclabs/deep-copy", "name": "myclabs/deep-copy",
"version": "1.8.1", "version": "1.8.1",
@ -1335,56 +1079,6 @@
], ],
"time": "2018-08-09T05:50:03+00:00" "time": "2018-08-09T05:50:03+00:00"
}, },
{
"name": "psr/http-message",
"version": "1.0.1",
"source": {
"type": "git",
"url": "https://github.com/php-fig/http-message.git",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363",
"reference": "f6561bf28d520154e4b0ec72be95418abe6d9363",
"shasum": ""
},
"require": {
"php": ">=5.3.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
}
},
"autoload": {
"psr-4": {
"Psr\\Http\\Message\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "PHP-FIG",
"homepage": "http://www.php-fig.org/"
}
],
"description": "Common interface for HTTP messages",
"homepage": "https://github.com/php-fig/http-message",
"keywords": [
"http",
"http-message",
"psr",
"psr-7",
"request",
"response"
],
"time": "2016-08-06T14:39:51+00:00"
},
{ {
"name": "sebastian/code-unit-reverse-lookup", "name": "sebastian/code-unit-reverse-lookup",
"version": "1.0.1", "version": "1.0.1",
@ -1944,6 +1638,57 @@
"homepage": "https://github.com/sebastianbergmann/version", "homepage": "https://github.com/sebastianbergmann/version",
"time": "2016-10-03T07:35:21+00:00" "time": "2016-10-03T07:35:21+00:00"
}, },
{
"name": "squizlabs/php_codesniffer",
"version": "3.3.2",
"source": {
"type": "git",
"url": "https://github.com/squizlabs/PHP_CodeSniffer.git",
"reference": "6ad28354c04b364c3c71a34e4a18b629cc3b231e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/6ad28354c04b364c3c71a34e4a18b629cc3b231e",
"reference": "6ad28354c04b364c3c71a34e4a18b629cc3b231e",
"shasum": ""
},
"require": {
"ext-simplexml": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "^4.0 || ^5.0 || ^6.0 || ^7.0"
},
"bin": [
"bin/phpcs",
"bin/phpcbf"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.x-dev"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
],
"authors": [
{
"name": "Greg Sherwood",
"role": "lead"
}
],
"description": "PHP_CodeSniffer tokenizes PHP, JavaScript and CSS files and detects violations of a defined set of coding standards.",
"homepage": "http://www.squizlabs.com/php-codesniffer",
"keywords": [
"phpcs",
"standards"
],
"time": "2018-09-23T23:08:17+00:00"
},
{ {
"name": "theseer/tokenizer", "name": "theseer/tokenizer",
"version": "1.1.0", "version": "1.1.0",

View File

@ -1,8 +1,8 @@
# Installation/Update # Installation/Update
## Dependencies ## Dependencies
* PHP >= 5.6 * PHP >= 7.0
* Nextcloud 12 * Nextcloud 14
* libxml >= 2.7.8 (2.9 recommended) * libxml >= 2.7.8 (2.9 recommended)
* php-curl * php-curl
* iconv * iconv

View File

@ -31,7 +31,6 @@ use OCP\ILogger;
use PicoFeed\Config\Config as PicoFeedConfig; use PicoFeed\Config\Config as PicoFeedConfig;
use PicoFeed\Reader\Reader as PicoFeedReader; use PicoFeed\Reader\Reader as PicoFeedReader;
class Application extends App class Application extends App
{ {
@ -80,7 +79,6 @@ class Application extends App
} }
}); });
$container->registerService(Config::class, function (IContainer $c): Config { $container->registerService(Config::class, function (IContainer $c): Config {
$config = new Config( $config = new Config(
$c->query('ConfigView'), $c->query('ConfigView'),
@ -168,8 +166,5 @@ class Application extends App
return $fetcher; return $fetcher;
}); });
} }
} }

View File

@ -23,13 +23,13 @@ class AfterUpdate extends Command
{ {
private $updater; private $updater;
public function __construct(Updater $updater) public function __construct(Updater $updater)
{ {
parent::__construct(); parent::__construct();
$this->updater = $updater; $this->updater = $updater;
} }
protected function configure() protected function configure()
{ {
$this->setName('news:updater:after-update') $this->setName('news:updater:after-update')
->setDescription( ->setDescription(
@ -38,9 +38,8 @@ class AfterUpdate extends Command
); );
} }
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$this->updater->afterUpdate(); $this->updater->afterUpdate();
} }
} }

View File

@ -19,18 +19,17 @@ use Symfony\Component\Console\Output\OutputInterface;
use OCA\News\Service\FeedService; use OCA\News\Service\FeedService;
class AllFeeds extends Command class AllFeeds extends Command
{ {
private $feedService; private $feedService;
public function __construct(FeedService $feedService) public function __construct(FeedService $feedService)
{ {
parent::__construct(); parent::__construct();
$this->feedService = $feedService; $this->feedService = $feedService;
} }
protected function configure() protected function configure()
{ {
$json = '{"feeds": [{"id": 39, "userId": "john"}, // etc ]}'; $json = '{"feeds": [{"id": 39, "userId": "john"}, // etc ]}';
@ -41,7 +40,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->findAllFromAllUsers();
$result = ['feeds' => []]; $result = ['feeds' => []];
@ -55,5 +54,4 @@ class AllFeeds extends Command
print(json_encode($result)); print(json_encode($result));
} }
} }

View File

@ -23,13 +23,13 @@ class BeforeUpdate extends Command
{ {
private $updater; private $updater;
public function __construct(Updater $updater) public function __construct(Updater $updater)
{ {
parent::__construct(); parent::__construct();
$this->updater = $updater; $this->updater = $updater;
} }
protected function configure() protected function configure()
{ {
$this->setName('news:updater:before-update') $this->setName('news:updater:before-update')
->setDescription( ->setDescription(
@ -39,9 +39,8 @@ class BeforeUpdate extends Command
); );
} }
protected function execute(InputInterface $input, OutputInterface $output) protected function execute(InputInterface $input, OutputInterface $output)
{ {
$this->updater->beforeUpdate(); $this->updater->beforeUpdate();
} }
} }

View File

@ -20,18 +20,17 @@ use Symfony\Component\Console\Output\OutputInterface;
use OCA\News\Service\FeedService; use OCA\News\Service\FeedService;
class UpdateFeed extends Command class UpdateFeed extends Command
{ {
private $feedService; private $feedService;
public function __construct(FeedService $feedService) public function __construct(FeedService $feedService)
{ {
parent::__construct(); parent::__construct();
$this->feedService = $feedService; $this->feedService = $feedService;
} }
protected function configure() protected function configure()
{ {
$this->setName('news:updater:update-feed') $this->setName('news:updater:update-feed')
->addArgument( ->addArgument(
@ -47,7 +46,7 @@ class UpdateFeed extends Command
->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)
{ {
$feedId = $input->getArgument('feed-id'); $feedId = $input->getArgument('feed-id');
$userId = $input->getArgument('user-id'); $userId = $input->getArgument('user-id');
@ -61,5 +60,4 @@ class UpdateFeed extends Command
); );
} }
} }
} }

View File

@ -16,7 +16,6 @@ namespace OCA\News\Config;
use OCP\ILogger; use OCP\ILogger;
use OCP\Files\Folder; use OCP\Files\Folder;
class Config class Config
{ {
@ -34,7 +33,8 @@ class Config
private $maxSize; private $maxSize;
private $exploreUrl; private $exploreUrl;
public function __construct(Folder $fileSystem, public function __construct(
Folder $fileSystem,
ILogger $logger, ILogger $logger,
$LoggerParameters $LoggerParameters
) { ) {
@ -42,7 +42,7 @@ class Config
$this->autoPurgeMinimumInterval = 60; $this->autoPurgeMinimumInterval = 60;
$this->autoPurgeCount = 200; $this->autoPurgeCount = 200;
$this->maxRedirects = 10; $this->maxRedirects = 10;
$this->maxSize = 100*1024*1024; // 100Mb $this->maxSize = 100 * 1024 * 1024; // 100Mb
$this->feedFetcherTimeout = 60; $this->feedFetcherTimeout = 60;
$this->useCronUpdates = true; $this->useCronUpdates = true;
$this->logger = $logger; $this->logger = $logger;
@ -50,7 +50,7 @@ class Config
$this->loggerParams = $LoggerParameters; $this->loggerParams = $LoggerParameters;
} }
public function getAutoPurgeMinimumInterval() public function getAutoPurgeMinimumInterval()
{ {
if ($this->autoPurgeMinimumInterval > 60) { if ($this->autoPurgeMinimumInterval > 60) {
return $this->autoPurgeMinimumInterval; return $this->autoPurgeMinimumInterval;
@ -59,103 +59,100 @@ class Config
} }
} }
public function getAutoPurgeCount() public function getAutoPurgeCount()
{ {
return $this->autoPurgeCount; return $this->autoPurgeCount;
} }
public function getMaxRedirects() public function getMaxRedirects()
{ {
return $this->maxRedirects; return $this->maxRedirects;
} }
public function getFeedFetcherTimeout() public function getFeedFetcherTimeout()
{ {
return $this->feedFetcherTimeout; return $this->feedFetcherTimeout;
} }
public function getUseCronUpdates() public function getUseCronUpdates()
{ {
return $this->useCronUpdates; return $this->useCronUpdates;
} }
public function getMaxSize() public function getMaxSize()
{ {
return $this->maxSize; return $this->maxSize;
} }
public function getExploreUrl() public function getExploreUrl()
{ {
return $this->exploreUrl; return $this->exploreUrl;
} }
public function setAutoPurgeMinimumInterval($value) public function setAutoPurgeMinimumInterval($value)
{ {
$this->autoPurgeMinimumInterval = $value; $this->autoPurgeMinimumInterval = $value;
} }
public function setAutoPurgeCount($value) public function setAutoPurgeCount($value)
{ {
$this->autoPurgeCount = $value; $this->autoPurgeCount = $value;
} }
public function setMaxRedirects($value) public function setMaxRedirects($value)
{ {
$this->maxRedirects = $value; $this->maxRedirects = $value;
} }
public function setFeedFetcherTimeout($value) public function setFeedFetcherTimeout($value)
{ {
$this->feedFetcherTimeout = $value; $this->feedFetcherTimeout = $value;
} }
public function setUseCronUpdates($value) public function setUseCronUpdates($value)
{ {
$this->useCronUpdates = $value; $this->useCronUpdates = $value;
} }
public function setMaxSize($value) public function setMaxSize($value)
{ {
$this->maxSize = $value; $this->maxSize = $value;
} }
public function setExploreUrl($value) public function setExploreUrl($value)
{ {
$this->exploreUrl = $value; $this->exploreUrl = $value;
} }
public function read($configPath, $createIfNotExists=false) public function read($configPath, $createIfNotExists = false)
{ {
if($createIfNotExists && !$this->fileSystem->nodeExists($configPath)) { if ($createIfNotExists && !$this->fileSystem->nodeExists($configPath)) {
$this->fileSystem->newFile($configPath); $this->fileSystem->newFile($configPath);
$this->write($configPath); $this->write($configPath);
} else { } else {
$content = $this->fileSystem->get($configPath)->getContent(); $content = $this->fileSystem->get($configPath)->getContent();
$configValues = parse_ini_string($content); $configValues = parse_ini_string($content);
if($configValues === false || count($configValues) === 0) { if ($configValues === false || count($configValues) === 0) {
$this->logger->warning( $this->logger->warning(
'Configuration invalid. Ignoring values.', 'Configuration invalid. Ignoring values.',
$this->loggerParams $this->loggerParams
); );
} else { } else {
foreach ($configValues as $key => $value) {
foreach($configValues as $key => $value) { if (property_exists($this, $key)) {
if(property_exists($this, $key)) {
$type = gettype($this->$key); $type = gettype($this->$key);
settype($value, $type); settype($value, $type);
$this->$key = $value; $this->$key = $value;
@ -167,13 +164,12 @@ class Config
); );
} }
} }
} }
} }
} }
public function write($configPath) public function write($configPath)
{ {
$ini = $ini =
'autoPurgeMinimumInterval = ' . 'autoPurgeMinimumInterval = ' .
@ -194,6 +190,4 @@ class Config
$this->fileSystem->get($configPath)->putContent($ini); $this->fileSystem->get($configPath)->putContent($ini);
} }
} }

View File

@ -26,6 +26,4 @@ class DependencyException extends \Exception
{ {
parent::__construct($msg); parent::__construct($msg);
} }
}
}

View File

@ -28,9 +28,9 @@ use OCA\News\Service\ItemService;
*/ */
class AdminController extends Controller class AdminController extends Controller
{ {
private $_config; private $config;
private $_configPath; private $configPath;
private $_itemService; private $itemService;
/** /**
* AdminController constructor. * AdminController constructor.
@ -41,13 +41,17 @@ class AdminController extends Controller
* @param ItemService $itemService Service for items * @param ItemService $itemService Service for items
* @param string $configFile Path to the config * @param string $configFile Path to the config
*/ */
public function __construct($appName, IRequest $request, Config $config, public function __construct(
ItemService $itemService, $configFile $appName,
IRequest $request,
Config $config,
ItemService $itemService,
$configFile
) { ) {
parent::__construct($appName, $request); parent::__construct($appName, $request);
$this->_config = $config; $this->config = $config;
$this->_configPath = $configFile; $this->configPath = $configFile;
$this->_itemService = $itemService; $this->itemService = $itemService;
} }
/** /**
@ -62,13 +66,13 @@ class AdminController extends Controller
{ {
$data = [ $data = [
'autoPurgeMinimumInterval' => 'autoPurgeMinimumInterval' =>
$this->_config->getAutoPurgeMinimumInterval(), $this->config->getAutoPurgeMinimumInterval(),
'autoPurgeCount' => $this->_config->getAutoPurgeCount(), 'autoPurgeCount' => $this->config->getAutoPurgeCount(),
'maxRedirects' => $this->_config->getMaxRedirects(), 'maxRedirects' => $this->config->getMaxRedirects(),
'feedFetcherTimeout' => $this->_config->getFeedFetcherTimeout(), 'feedFetcherTimeout' => $this->config->getFeedFetcherTimeout(),
'useCronUpdates' => $this->_config->getUseCronUpdates(), 'useCronUpdates' => $this->config->getUseCronUpdates(),
'maxSize' => $this->_config->getMaxSize(), 'maxSize' => $this->config->getMaxSize(),
'exploreUrl' => $this->_config->getExploreUrl(), 'exploreUrl' => $this->config->getExploreUrl(),
]; ];
return new TemplateResponse($this->appName, 'admin', $data, 'blank'); return new TemplateResponse($this->appName, 'admin', $data, 'blank');
} }
@ -87,29 +91,33 @@ class AdminController extends Controller
* *
* @return array with the updated values * @return array with the updated values
*/ */
public function update($autoPurgeMinimumInterval, $autoPurgeCount, public function update(
$maxRedirects, $feedFetcherTimeout, $maxSize, $autoPurgeMinimumInterval,
$useCronUpdates, $exploreUrl $autoPurgeCount,
$maxRedirects,
$feedFetcherTimeout,
$maxSize,
$useCronUpdates,
$exploreUrl
) { ) {
$this->_config->setAutoPurgeMinimumInterval($autoPurgeMinimumInterval); $this->config->setAutoPurgeMinimumInterval($autoPurgeMinimumInterval);
$this->_config->setAutoPurgeCount($autoPurgeCount); $this->config->setAutoPurgeCount($autoPurgeCount);
$this->_config->setMaxRedirects($maxRedirects); $this->config->setMaxRedirects($maxRedirects);
$this->_config->setMaxSize($maxSize); $this->config->setMaxSize($maxSize);
$this->_config->setFeedFetcherTimeout($feedFetcherTimeout); $this->config->setFeedFetcherTimeout($feedFetcherTimeout);
$this->_config->setUseCronUpdates($useCronUpdates); $this->config->setUseCronUpdates($useCronUpdates);
$this->_config->setExploreUrl($exploreUrl); $this->config->setExploreUrl($exploreUrl);
$this->_config->write($this->_configPath); $this->config->write($this->configPath);
return [ return [
'autoPurgeMinimumInterval' => 'autoPurgeMinimumInterval' =>
$this->_config->getAutoPurgeMinimumInterval(), $this->config->getAutoPurgeMinimumInterval(),
'autoPurgeCount' => $this->_config->getAutoPurgeCount(), 'autoPurgeCount' => $this->config->getAutoPurgeCount(),
'maxRedirects' => $this->_config->getMaxRedirects(), 'maxRedirects' => $this->config->getMaxRedirects(),
'maxSize' => $this->_config->getMaxSize(), 'maxSize' => $this->config->getMaxSize(),
'feedFetcherTimeout' => $this->_config->getFeedFetcherTimeout(), 'feedFetcherTimeout' => $this->config->getFeedFetcherTimeout(),
'useCronUpdates' => $this->_config->getUseCronUpdates(), 'useCronUpdates' => $this->config->getUseCronUpdates(),
'exploreUrl' => $this->_config->getExploreUrl(), 'exploreUrl' => $this->config->getExploreUrl(),
]; ];
} }
} }

View File

@ -40,7 +40,8 @@ class ApiController extends BaseApiController
* @param IRequest $request The request * @param IRequest $request The request
* @param IUserSession $userSession The user session * @param IUserSession $userSession The user session
*/ */
public function __construct($appName, IRequest $request, IUserSession $userSession) { public function __construct($appName, IRequest $request, IUserSession $userSession)
{
parent::__construct($appName, $request); parent::__construct($appName, $request);
$this->userSession = $userSession; $this->userSession = $userSession;
} }
@ -48,14 +49,16 @@ class ApiController extends BaseApiController
/** /**
* @return IUser * @return IUser
*/ */
protected function getUser() { protected function getUser()
{
return $this->userSession->getUser(); return $this->userSession->getUser();
} }
/** /**
* @return string * @return string
*/ */
protected function getUserId() { protected function getUserId()
{
return $this->getUser()->getUID(); return $this->getUser()->getUID();
} }
@ -74,5 +77,4 @@ class ApiController extends BaseApiController
'apiLevels' => ['v1-2'] 'apiLevels' => ['v1-2']
]; ];
} }
} }

View File

@ -13,13 +13,12 @@ namespace OCA\News\Controller;
use \OCA\News\Db\IAPI; use \OCA\News\Db\IAPI;
class EntityApiSerializer class EntityApiSerializer
{ {
private $level; private $level;
public function __construct($level) public function __construct($level)
{ {
$this->level = $level; $this->level = $level;
} }
@ -35,16 +34,16 @@ class EntityApiSerializer
* * Response * * Response
* @return array|mixed * @return array|mixed
*/ */
public function serialize($data) public function serialize($data)
{ {
if($data instanceof IAPI) { if ($data instanceof IAPI) {
return [$this->level => [$data->toAPI()]]; return [$this->level => [$data->toAPI()]];
} }
if(is_array($data) && array_key_exists($this->level, $data)) { if (is_array($data) && array_key_exists($this->level, $data)) {
$data[$this->level] = $this->convert($data[$this->level]); $data[$this->level] = $this->convert($data[$this->level]);
} elseif(is_array($data)) { } elseif (is_array($data)) {
$data = [$this->level => $this->convert($data)]; $data = [$this->level => $this->convert($data)];
} }
@ -52,12 +51,12 @@ class EntityApiSerializer
} }
private function convert($entities) private function convert($entities)
{ {
$converted = []; $converted = [];
foreach($entities as $entity) { foreach ($entities as $entity) {
if($entity instanceof IAPI) { if ($entity instanceof IAPI) {
$converted[] = $entity->toAPI(); $converted[] = $entity->toAPI();
// break if it contains anything else than entities // break if it contains anything else than entities
@ -68,5 +67,4 @@ class EntityApiSerializer
return $converted; return $converted;
} }
}
}

View File

@ -33,7 +33,8 @@ class ExportController extends Controller
private $itemService; private $itemService;
private $userId; private $userId;
public function __construct($appName, public function __construct(
$appName,
IRequest $request, IRequest $request,
FolderService $folderService, FolderService $folderService,
FeedService $feedService, FeedService $feedService,
@ -60,7 +61,7 @@ class ExportController extends Controller
$folders = $this->folderService->findAll($this->userId); $folders = $this->folderService->findAll($this->userId);
$opml = $this->opmlExporter->build($folders, $feeds)->saveXML(); $opml = $this->opmlExporter->build($folders, $feeds)->saveXML();
$date = date('Y-m-d'); $date = date('Y-m-d');
$name = "subscriptions-".$date.".opml"; $name = "subscriptions-" . $date . ".opml";
$mimeType = 'text/xml'; $mimeType = 'text/xml';
return new TextDownloadResponse($opml, $name, $mimeType); return new TextDownloadResponse($opml, $name, $mimeType);
} }
@ -77,12 +78,12 @@ class ExportController extends Controller
// build assoc array for fast access // build assoc array for fast access
$feedsDict = []; $feedsDict = [];
foreach($feeds as $feed) { foreach ($feeds as $feed) {
$feedsDict['feed' . $feed->getId()] = $feed; $feedsDict['feed' . $feed->getId()] = $feed;
} }
$articles = []; $articles = [];
foreach($items as $item) { foreach ($items as $item) {
$articles[] = $item->toExport($feedsDict); $articles[] = $item->toExport($feedsDict);
} }
@ -93,6 +94,4 @@ class ExportController extends Controller
); );
return $response; return $response;
} }
}
}

View File

@ -25,10 +25,8 @@ use \OCA\News\Service\ItemService;
use \OCA\News\Service\ServiceNotFoundException; use \OCA\News\Service\ServiceNotFoundException;
use \OCA\News\Service\ServiceConflictException; use \OCA\News\Service\ServiceConflictException;
class FeedApiController extends ApiController class FeedApiController extends ApiController
{ {
use JSONHttpError; use JSONHttpError;
private $itemService; private $itemService;
@ -37,7 +35,8 @@ class FeedApiController extends ApiController
private $loggerParams; private $loggerParams;
private $serializer; private $serializer;
public function __construct($appName, public function __construct(
$appName,
IRequest $request, IRequest $request,
IUserSession $userSession, IUserSession $userSession,
FeedService $feedService, FeedService $feedService,
@ -59,7 +58,7 @@ class FeedApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @CORS * @CORS
*/ */
public function index() public function index()
{ {
$result = [ $result = [
@ -73,7 +72,7 @@ class FeedApiController extends ApiController
$this->itemService->getNewestItemId($this->getUserId()); $this->itemService->getNewestItemId($this->getUserId());
// in case there are no items, ignore // in case there are no items, ignore
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
} }
return $this->serializer->serialize($result); return $this->serializer->serialize($result);
@ -89,7 +88,7 @@ class FeedApiController extends ApiController
* @param int $folderId * @param int $folderId
* @return array|mixed|\OCP\AppFramework\Http\JSONResponse * @return array|mixed|\OCP\AppFramework\Http\JSONResponse
*/ */
public function create($url, $folderId=0) public function create($url, $folderId = 0)
{ {
try { try {
$this->feedService->purgeDeleted($this->getUserId(), false); $this->feedService->purgeDeleted($this->getUserId(), false);
@ -102,14 +101,13 @@ class FeedApiController extends ApiController
$this->itemService->getNewestItemId($this->getUserId()); $this->itemService->getNewestItemId($this->getUserId());
// in case there are no items, ignore // in case there are no items, ignore
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
} }
return $this->serializer->serialize($result); return $this->serializer->serialize($result);
} catch (ServiceConflictException $ex) {
} catch(ServiceConflictException $ex) {
return $this->error($ex, Http::STATUS_CONFLICT); return $this->error($ex, Http::STATUS_CONFLICT);
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
} }
@ -123,11 +121,11 @@ class FeedApiController extends ApiController
* @param int $feedId * @param int $feedId
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function delete($feedId) public function delete($feedId)
{ {
try { try {
$this->feedService->delete($feedId, $this->getUserId()); $this->feedService->delete($feedId, $this->getUserId());
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
@ -143,7 +141,7 @@ class FeedApiController extends ApiController
* @param int $feedId * @param int $feedId
* @param int $newestItemId * @param int $newestItemId
*/ */
public function read($feedId, $newestItemId) public function read($feedId, $newestItemId)
{ {
$this->itemService->readFeed($feedId, $newestItemId, $this->getUserId()); $this->itemService->readFeed($feedId, $newestItemId, $this->getUserId());
} }
@ -158,13 +156,15 @@ class FeedApiController extends ApiController
* @param int $folderId * @param int $folderId
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function move($feedId, $folderId) public function move($feedId, $folderId)
{ {
try { try {
$this->feedService->patch( $this->feedService->patch(
$feedId, $this->getUserId(), ['folderId' => $folderId] $feedId,
$this->getUserId(),
['folderId' => $folderId]
); );
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
@ -181,13 +181,15 @@ class FeedApiController extends ApiController
* @param string $feedTitle * @param string $feedTitle
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function rename($feedId, $feedTitle) public function rename($feedId, $feedTitle)
{ {
try { try {
$this->feedService->patch( $this->feedService->patch(
$feedId, $this->getUserId(), ['title' => $feedTitle] $feedId,
$this->getUserId(),
['title' => $feedTitle]
); );
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
@ -199,7 +201,7 @@ class FeedApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @CORS * @CORS
*/ */
public function fromAllUsers() public function fromAllUsers()
{ {
$feeds = $this->feedService->findAllFromAllUsers(); $feeds = $this->feedService->findAllFromAllUsers();
$result = ['feeds' => []]; $result = ['feeds' => []];
@ -221,18 +223,16 @@ class FeedApiController extends ApiController
* @param string $userId * @param string $userId
* @param int $feedId * @param int $feedId
*/ */
public function update($userId, $feedId) public function update($userId, $feedId)
{ {
try { try {
$this->feedService->update($feedId, $userId); $this->feedService->update($feedId, $userId);
// 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 $this->loggerParams
); );
} }
} }
} }

View File

@ -25,10 +25,8 @@ use OCA\News\Service\ServiceNotFoundException;
use OCA\News\Service\ServiceConflictException; use OCA\News\Service\ServiceConflictException;
use OCA\News\Db\FeedType; use OCA\News\Db\FeedType;
class FeedController extends Controller class FeedController extends Controller
{ {
use JSONHttpError; use JSONHttpError;
private $feedService; private $feedService;
@ -37,7 +35,8 @@ class FeedController extends Controller
private $userId; private $userId;
private $settings; private $settings;
public function __construct($appName, public function __construct(
$appName,
IRequest $request, IRequest $request,
FolderService $folderService, FolderService $folderService,
FeedService $feedService, FeedService $feedService,
@ -88,32 +87,32 @@ class FeedController extends Controller
{ {
$feedId = (int) $this->settings->getUserValue( $feedId = (int) $this->settings->getUserValue(
$this->userId, $this->userId,
$this->appName, 'lastViewedFeedId' $this->appName,
'lastViewedFeedId'
); );
$feedType = $this->settings->getUserValue( $feedType = $this->settings->getUserValue(
$this->userId, $this->appName, $this->userId,
$this->appName,
'lastViewedFeedType' 'lastViewedFeedType'
); );
// cast from null to int is 0 // cast from null to int is 0
if($feedType !== null) { if ($feedType !== null) {
$feedType = (int) $feedType; $feedType = (int) $feedType;
} }
// 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($feedId, $this->userId);
} elseif ($feedType === FeedType::FEED) { } elseif ($feedType === FeedType::FEED) {
$this->feedService->find($feedId, $this->userId); $this->feedService->find($feedId, $this->userId);
// 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) {
throw new ServiceNotFoundException(''); throw new ServiceNotFoundException('');
} }
} catch (ServiceNotFoundException $ex) {
} catch (ServiceNotFoundException $ex){
$feedId = 0; $feedId = 0;
$feedType = FeedType::SUBSCRIPTIONS; $feedType = FeedType::SUBSCRIPTIONS;
} }
@ -137,8 +136,12 @@ class FeedController extends Controller
* @param string $password * @param string $password
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function create($url, $parentFolderId, $title=null, public function create(
$user=null, $password=null $url,
$parentFolderId,
$title = null,
$user = null,
$password = null
) { ) {
try { try {
// we need to purge deleted feeds if a feed is created to // we need to purge deleted feeds if a feed is created to
@ -146,9 +149,12 @@ class FeedController extends Controller
$this->feedService->purgeDeleted($this->userId, false); $this->feedService->purgeDeleted($this->userId, false);
$feed = $this->feedService->create( $feed = $this->feedService->create(
$url, $parentFolderId, $url,
$this->userId, $title, $parentFolderId,
$user, $password $this->userId,
$title,
$user,
$password
); );
$params = ['feeds' => [$feed]]; $params = ['feeds' => [$feed]];
@ -162,13 +168,11 @@ class FeedController extends Controller
} }
return $params; return $params;
} catch (ServiceConflictException $ex) {
} catch(ServiceConflictException $ex) {
return $this->error($ex, Http::STATUS_CONFLICT); return $this->error($ex, Http::STATUS_CONFLICT);
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_UNPROCESSABLE_ENTITY); return $this->error($ex, Http::STATUS_UNPROCESSABLE_ENTITY);
} }
} }
@ -182,7 +186,7 @@ class FeedController extends Controller
{ {
try { try {
$this->feedService->markDeleted($feedId, $this->userId); $this->feedService->markDeleted($feedId, $this->userId);
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
@ -211,11 +215,9 @@ class FeedController extends Controller
] ]
] ]
]; ];
} catch (ServiceNotFoundException $ex) {
} catch(ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
} }
@ -225,7 +227,7 @@ class FeedController extends Controller
* @param array $json * @param array $json
* @return array * @return array
*/ */
public function import($json) public function import($json)
{ {
$feed = $this->feedService->importArticles($json, $this->userId); $feed = $this->feedService->importArticles($json, $this->userId);
@ -233,7 +235,7 @@ class FeedController extends Controller
'starred' => $this->itemService->starredCount($this->userId) 'starred' => $this->itemService->starredCount($this->userId)
]; ];
if($feed) { if ($feed) {
$params['feeds'] = [$feed]; $params['feeds'] = [$feed];
} }
@ -273,7 +275,7 @@ class FeedController extends Controller
{ {
try { try {
$this->feedService->unmarkDeleted($feedId, $this->userId); $this->feedService->unmarkDeleted($feedId, $this->userId);
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
@ -291,9 +293,14 @@ class FeedController extends Controller
* @param int $folderId * @param int $folderId
* @param string $title * @param string $title
*/ */
public function patch($feedId, $pinned=null, $fullTextEnabled=null, public function patch(
$updateMode=null, $ordering=null, $title=null, $feedId,
$folderId=null $pinned = null,
$fullTextEnabled = null,
$updateMode = null,
$ordering = null,
$title = null,
$folderId = null
) { ) {
$attributes = [ $attributes = [
'pinned' => $pinned, 'pinned' => $pinned,
@ -305,18 +312,18 @@ class FeedController extends Controller
]; ];
$diff = array_filter( $diff = array_filter(
$attributes, function ($value) { $attributes,
function ($value) {
return $value !== null; return $value !== null;
} }
); );
try { try {
$this->feedService->patch($feedId, $this->userId, $diff); $this->feedService->patch($feedId, $this->userId, $diff);
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
return []; return [];
} }
} }

View File

@ -25,17 +25,16 @@ use \OCA\News\Service\ServiceNotFoundException;
use \OCA\News\Service\ServiceConflictException; use \OCA\News\Service\ServiceConflictException;
use \OCA\News\Service\ServiceValidationException; use \OCA\News\Service\ServiceValidationException;
class FolderApiController extends ApiController class FolderApiController extends ApiController
{ {
use JSONHttpError; use JSONHttpError;
private $folderService; private $folderService;
private $itemService; private $itemService;
private $serializer; private $serializer;
public function __construct($appName, public function __construct(
$appName,
IRequest $request, IRequest $request,
IUserSession $userSession, IUserSession $userSession,
FolderService $folderService, FolderService $folderService,
@ -53,7 +52,7 @@ class FolderApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @CORS * @CORS
*/ */
public function index() public function index()
{ {
return $this->serializer->serialize( return $this->serializer->serialize(
$this->folderService->findAll($this->getUserId()) $this->folderService->findAll($this->getUserId())
@ -69,16 +68,16 @@ class FolderApiController extends ApiController
* @param string $name * @param string $name
* @return array|mixed|\OCP\AppFramework\Http\JSONResponse * @return array|mixed|\OCP\AppFramework\Http\JSONResponse
*/ */
public function create($name) public function create($name)
{ {
try { try {
$this->folderService->purgeDeleted($this->getUserId(), false); $this->folderService->purgeDeleted($this->getUserId(), false);
return $this->serializer->serialize( return $this->serializer->serialize(
$this->folderService->create($name, $this->getUserId()) $this->folderService->create($name, $this->getUserId())
); );
} catch(ServiceValidationException $ex) { } catch (ServiceValidationException $ex) {
return $this->error($ex, Http::STATUS_UNPROCESSABLE_ENTITY); return $this->error($ex, Http::STATUS_UNPROCESSABLE_ENTITY);
} catch(ServiceConflictException $ex) { } catch (ServiceConflictException $ex) {
return $this->error($ex, Http::STATUS_CONFLICT); return $this->error($ex, Http::STATUS_CONFLICT);
} }
} }
@ -92,11 +91,11 @@ class FolderApiController extends ApiController
* @param int $folderId * @param int $folderId
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function delete($folderId) public function delete($folderId)
{ {
try { try {
$this->folderService->delete($folderId, $this->getUserId()); $this->folderService->delete($folderId, $this->getUserId());
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
@ -112,16 +111,15 @@ class FolderApiController extends ApiController
* @param string $name * @param string $name
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function update($folderId, $name) public function update($folderId, $name)
{ {
try { try {
$this->folderService->rename($folderId, $name, $this->getUserId()); $this->folderService->rename($folderId, $name, $this->getUserId());
} catch (ServiceValidationException $ex) {
} catch(ServiceValidationException $ex) {
return $this->error($ex, Http::STATUS_UNPROCESSABLE_ENTITY); return $this->error($ex, Http::STATUS_UNPROCESSABLE_ENTITY);
} catch(ServiceConflictException $ex) { } catch (ServiceConflictException $ex) {
return $this->error($ex, Http::STATUS_CONFLICT); return $this->error($ex, Http::STATUS_CONFLICT);
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
@ -137,10 +135,8 @@ class FolderApiController extends ApiController
* @param int $folderId * @param int $folderId
* @param int $newestItemId * @param int $newestItemId
*/ */
public function read($folderId, $newestItemId) public function read($folderId, $newestItemId)
{ {
$this->itemService->readFolder($folderId, $newestItemId, $this->getUserId()); $this->itemService->readFolder($folderId, $newestItemId, $this->getUserId());
} }
} }

View File

@ -24,10 +24,8 @@ use \OCA\News\Service\ServiceNotFoundException;
use \OCA\News\Service\ServiceConflictException; use \OCA\News\Service\ServiceConflictException;
use \OCA\News\Service\ServiceValidationException; use \OCA\News\Service\ServiceValidationException;
class FolderController extends Controller class FolderController extends Controller
{ {
use JSONHttpError; use JSONHttpError;
private $folderService; private $folderService;
@ -35,7 +33,8 @@ class FolderController extends Controller
private $itemService; private $itemService;
private $userId; private $userId;
public function __construct($appName, public function __construct(
$appName,
IRequest $request, IRequest $request,
FolderService $folderService, FolderService $folderService,
FeedService $feedService, FeedService $feedService,
@ -53,7 +52,7 @@ class FolderController extends Controller
/** /**
* @NoAdminRequired * @NoAdminRequired
*/ */
public function index() public function index()
{ {
$folders = $this->folderService->findAll($this->userId); $folders = $this->folderService->findAll($this->userId);
return ['folders' => $folders]; return ['folders' => $folders];
@ -67,11 +66,11 @@ class FolderController extends Controller
* @param bool $open * @param bool $open
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function open($folderId, $open) public function open($folderId, $open)
{ {
try { try {
$this->folderService->open($folderId, $open, $this->userId); $this->folderService->open($folderId, $open, $this->userId);
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
@ -85,7 +84,7 @@ class FolderController extends Controller
* @param string $folderName * @param string $folderName
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function create($folderName) public function create($folderName)
{ {
try { try {
// we need to purge deleted folders if a folder is created to // we need to purge deleted folders if a folder is created to
@ -94,13 +93,11 @@ class FolderController extends Controller
$folder = $this->folderService->create($folderName, $this->userId); $folder = $this->folderService->create($folderName, $this->userId);
return ['folders' => [$folder]]; return ['folders' => [$folder]];
} catch (ServiceConflictException $ex) {
} catch(ServiceConflictException $ex) {
return $this->error($ex, Http::STATUS_CONFLICT); return $this->error($ex, Http::STATUS_CONFLICT);
} catch(ServiceValidationException $ex) { } catch (ServiceValidationException $ex) {
return $this->error($ex, Http::STATUS_UNPROCESSABLE_ENTITY); return $this->error($ex, Http::STATUS_UNPROCESSABLE_ENTITY);
} }
} }
@ -110,11 +107,11 @@ class FolderController extends Controller
* @param int $folderId * @param int $folderId
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function delete($folderId) public function delete($folderId)
{ {
try { try {
$this->folderService->markDeleted($folderId, $this->userId); $this->folderService->markDeleted($folderId, $this->userId);
} catch (ServiceNotFoundException $ex){ } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
@ -129,24 +126,23 @@ class FolderController extends Controller
* @param int $folderId * @param int $folderId
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function rename($folderName, $folderId) public function rename($folderName, $folderId)
{ {
try { try {
$folder = $this->folderService->rename( $folder = $this->folderService->rename(
$folderId, $folderName, $folderId,
$folderName,
$this->userId $this->userId
); );
return ['folders' => [$folder]]; return ['folders' => [$folder]];
} catch (ServiceConflictException $ex) {
} catch(ServiceConflictException $ex) {
return $this->error($ex, Http::STATUS_CONFLICT); return $this->error($ex, Http::STATUS_CONFLICT);
} catch(ServiceValidationException $ex) { } catch (ServiceValidationException $ex) {
return $this->error($ex, Http::STATUS_UNPROCESSABLE_ENTITY); return $this->error($ex, Http::STATUS_UNPROCESSABLE_ENTITY);
} catch (ServiceNotFoundException $ex){ } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
} }
/** /**
@ -156,10 +152,12 @@ class FolderController extends Controller
* @param int $highestItemId * @param int $highestItemId
* @return array * @return array
*/ */
public function read($folderId, $highestItemId) public function read($folderId, $highestItemId)
{ {
$this->itemService->readFolder( $this->itemService->readFolder(
$folderId, $highestItemId, $this->userId $folderId,
$highestItemId,
$this->userId
); );
return ['feeds' => $this->feedService->findAll($this->userId)]; return ['feeds' => $this->feedService->findAll($this->userId)];
@ -172,16 +170,14 @@ class FolderController extends Controller
* @param int $folderId * @param int $folderId
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function restore($folderId) public function restore($folderId)
{ {
try { try {
$this->folderService->unmarkDeleted($folderId, $this->userId); $this->folderService->unmarkDeleted($folderId, $this->userId);
} catch (ServiceNotFoundException $ex){ } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
return []; return [];
} }
}
}

View File

@ -24,13 +24,13 @@ use \OCA\News\Service\ServiceNotFoundException;
class ItemApiController extends ApiController class ItemApiController extends ApiController
{ {
use JSONHttpError; use JSONHttpError;
private $itemService; private $itemService;
private $serializer; private $serializer;
public function __construct($appName, public function __construct(
$appName,
IRequest $request, IRequest $request,
IUserSession $userSession, IUserSession $userSession,
ItemService $itemService ItemService $itemService
@ -54,12 +54,22 @@ class ItemApiController extends ApiController
* @param bool $oldestFirst * @param bool $oldestFirst
* @return array|mixed * @return array|mixed
*/ */
public function index($type=3, $id=0, $getRead=true, $batchSize=-1, public function index(
$offset=0, $oldestFirst=false $type = 3,
$id = 0,
$getRead = true,
$batchSize = -1,
$offset = 0,
$oldestFirst = false
) { ) {
return $this->serializer->serialize( return $this->serializer->serialize(
$this->itemService->findAll( $this->itemService->findAll(
$id, $type, $batchSize, $offset, $getRead, $oldestFirst, $id,
$type,
$batchSize,
$offset,
$getRead,
$oldestFirst,
$this->getUserId() $this->getUserId()
) )
); );
@ -76,7 +86,7 @@ class ItemApiController extends ApiController
* @param int $lastModified * @param int $lastModified
* @return array|mixed * @return array|mixed
*/ */
public function updated($type=3, $id=0, $lastModified=0) public function updated($type = 3, $id = 0, $lastModified = 0)
{ {
// needs to be turned into a millisecond timestamp to work properly // needs to be turned into a millisecond timestamp to work properly
if (strlen((string) $lastModified) <= 10) { if (strlen((string) $lastModified) <= 10) {
@ -86,18 +96,21 @@ class ItemApiController extends ApiController
} }
return $this->serializer->serialize( return $this->serializer->serialize(
$this->itemService->findAllNew( $this->itemService->findAllNew(
$id, $type, $paddedLastModified, $id,
true, $this->getUserId() $type,
$paddedLastModified,
true,
$this->getUserId()
) )
); );
} }
private function setRead($isRead, $itemId) private function setRead($isRead, $itemId)
{ {
try { try {
$this->itemService->read($itemId, $isRead, $this->getUserId()); $this->itemService->read($itemId, $isRead, $this->getUserId());
} catch(ServiceNotFoundException $ex){ } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
@ -113,7 +126,7 @@ class ItemApiController extends ApiController
* @param int $itemId * @param int $itemId
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function read($itemId) public function read($itemId)
{ {
return $this->setRead(true, $itemId); return $this->setRead(true, $itemId);
} }
@ -127,19 +140,22 @@ class ItemApiController extends ApiController
* @param int $itemId * @param int $itemId
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function unread($itemId) public function unread($itemId)
{ {
return $this->setRead(false, $itemId); return $this->setRead(false, $itemId);
} }
private function setStarred($isStarred, $feedId, $guidHash) private function setStarred($isStarred, $feedId, $guidHash)
{ {
try { try {
$this->itemService->star( $this->itemService->star(
$feedId, $guidHash, $isStarred, $this->getUserId() $feedId,
$guidHash,
$isStarred,
$this->getUserId()
); );
} catch(ServiceNotFoundException $ex){ } catch (ServiceNotFoundException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
@ -156,7 +172,7 @@ class ItemApiController extends ApiController
* @param string $guidHash * @param string $guidHash
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function star($feedId, $guidHash) public function star($feedId, $guidHash)
{ {
return $this->setStarred(true, $feedId, $guidHash); return $this->setStarred(true, $feedId, $guidHash);
} }
@ -171,7 +187,7 @@ class ItemApiController extends ApiController
* @param string $guidHash * @param string $guidHash
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function unstar($feedId, $guidHash) public function unstar($feedId, $guidHash)
{ {
return $this->setStarred(false, $feedId, $guidHash); return $this->setStarred(false, $feedId, $guidHash);
} }
@ -184,18 +200,18 @@ class ItemApiController extends ApiController
* *
* @param int $newestItemId * @param int $newestItemId
*/ */
public function readAll($newestItemId) public function readAll($newestItemId)
{ {
$this->itemService->readAll($newestItemId, $this->getUserId()); $this->itemService->readAll($newestItemId, $this->getUserId());
} }
private function setMultipleRead($isRead, $items) private function setMultipleRead($isRead, $items)
{ {
foreach($items as $id) { foreach ($items as $id) {
try { try {
$this->itemService->read($id, $isRead, $this->getUserId()); $this->itemService->read($id, $isRead, $this->getUserId());
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
continue; continue;
} }
} }
@ -209,7 +225,7 @@ class ItemApiController extends ApiController
* *
* @param int[] item ids * @param int[] item ids
*/ */
public function readMultiple($items) public function readMultiple($items)
{ {
$this->setMultipleRead(true, $items); $this->setMultipleRead(true, $items);
} }
@ -222,21 +238,23 @@ class ItemApiController extends ApiController
* *
* @param int[] item ids * @param int[] item ids
*/ */
public function unreadMultiple($items) public function unreadMultiple($items)
{ {
$this->setMultipleRead(false, $items); $this->setMultipleRead(false, $items);
} }
private function setMultipleStarred($isStarred, $items) private function setMultipleStarred($isStarred, $items)
{ {
foreach($items as $item) { foreach ($items as $item) {
try { try {
$this->itemService->star( $this->itemService->star(
$item['feedId'], $item['guidHash'], $item['feedId'],
$isStarred, $this->getUserId() $item['guidHash'],
$isStarred,
$this->getUserId()
); );
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
continue; continue;
} }
} }
@ -250,7 +268,7 @@ class ItemApiController extends ApiController
* *
* @param int[] item ids * @param int[] item ids
*/ */
public function starMultiple($items) public function starMultiple($items)
{ {
$this->setMultipleStarred(true, $items); $this->setMultipleStarred(true, $items);
} }
@ -263,10 +281,8 @@ class ItemApiController extends ApiController
* *
* @param int[] item ids * @param int[] item ids
*/ */
public function unstarMultiple($items) public function unstarMultiple($items)
{ {
$this->setMultipleStarred(false, $items); $this->setMultipleStarred(false, $items);
} }
} }

View File

@ -23,10 +23,8 @@ use \OCA\News\Service\ServiceNotFoundException;
use \OCA\News\Service\ItemService; use \OCA\News\Service\ItemService;
use \OCA\News\Service\FeedService; use \OCA\News\Service\FeedService;
class ItemController extends Controller class ItemController extends Controller
{ {
use JSONHttpError; use JSONHttpError;
private $itemService; private $itemService;
@ -34,7 +32,8 @@ class ItemController extends Controller
private $userId; private $userId;
private $settings; private $settings;
public function __construct($appName, public function __construct(
$appName,
IRequest $request, IRequest $request,
FeedService $feedService, FeedService $feedService,
ItemService $itemService, ItemService $itemService,
@ -61,31 +60,45 @@ class ItemController extends Controller
* @param string $search * @param string $search
* @return array * @return array
*/ */
public function index($type=3, $id=0, $limit=50, $offset=0, $showAll=null, public function index(
$oldestFirst=null, $search='' $type = 3,
$id = 0,
$limit = 50,
$offset = 0,
$showAll = null,
$oldestFirst = null,
$search = ''
) { ) {
// in case this is called directly and not from the website use the // in case this is called directly and not from the website use the
// internal state // internal state
if ($showAll === null) { if ($showAll === null) {
$showAll = $this->settings->getUserValue( $showAll = $this->settings->getUserValue(
$this->userId, $this->appName, 'showAll' $this->userId,
$this->appName,
'showAll'
) === '1'; ) === '1';
} }
if ($oldestFirst === null) { if ($oldestFirst === null) {
$oldestFirst = $this->settings->getUserValue( $oldestFirst = $this->settings->getUserValue(
$this->userId, $this->appName, 'oldestFirst' $this->userId,
$this->appName,
'oldestFirst'
) === '1'; ) === '1';
} }
$this->settings->setUserValue( $this->settings->setUserValue(
$this->userId, $this->appName, $this->userId,
'lastViewedFeedId', $id $this->appName,
'lastViewedFeedId',
$id
); );
$this->settings->setUserValue( $this->settings->setUserValue(
$this->userId, $this->appName, $this->userId,
'lastViewedFeedType', $type $this->appName,
'lastViewedFeedType',
$type
); );
$params = []; $params = [];
@ -100,11 +113,10 @@ class ItemController extends Controller
} }
try { try {
// the offset is 0 if the user clicks on a new feed // the offset is 0 if the user clicks on a new feed
// we need to pass the newest feeds to not let the unread count get // we need to pass the newest feeds to not let the unread count get
// out of sync // out of sync
if($offset === 0) { if ($offset === 0) {
$params['newestItemId'] = $params['newestItemId'] =
$this->itemService->getNewestItemId($this->userId); $this->itemService->getNewestItemId($this->userId);
$params['feeds'] = $this->feedService->findAll($this->userId); $params['feeds'] = $this->feedService->findAll($this->userId);
@ -113,13 +125,19 @@ class ItemController extends Controller
} }
$params['items'] = $this->itemService->findAll( $params['items'] = $this->itemService->findAll(
$id, $type, $limit, $offset, $showAll, $oldestFirst, $id,
$this->userId, $search $type,
$limit,
$offset,
$showAll,
$oldestFirst,
$this->userId,
$search
); );
// this gets thrown if there are no items // this gets thrown if there are no items
// in that case just return an empty array // in that case just return an empty array
} catch(ServiceException $ex) { } catch (ServiceException $ex) {
} }
return $params; return $params;
@ -134,10 +152,11 @@ class ItemController extends Controller
* @param int $lastModified * @param int $lastModified
* @return array * @return array
*/ */
public function newItems($type, $id, $lastModified=0) public function newItems($type, $id, $lastModified = 0)
{ {
$showAll = $this->settings->getUserValue( $showAll = $this->settings->getUserValue(
$this->userId, $this->appName, $this->userId,
$this->appName,
'showAll' 'showAll'
) === '1'; ) === '1';
@ -150,13 +169,16 @@ class ItemController extends Controller
$params['starred'] = $params['starred'] =
$this->itemService->starredCount($this->userId); $this->itemService->starredCount($this->userId);
$params['items'] = $this->itemService->findAllNew( $params['items'] = $this->itemService->findAllNew(
$id, $type, $id,
$lastModified, $showAll, $this->userId $type,
$lastModified,
$showAll,
$this->userId
); );
// this gets thrown if there are no items // this gets thrown if there are no items
// in that case just return an empty array // in that case just return an empty array
} catch(ServiceException $ex) { } catch (ServiceException $ex) {
} }
return $params; return $params;
@ -175,10 +197,12 @@ class ItemController extends Controller
{ {
try { try {
$this->itemService->star( $this->itemService->star(
$feedId, $guidHash, $isStarred, $feedId,
$guidHash,
$isStarred,
$this->userId $this->userId
); );
} catch(ServiceException $ex) { } catch (ServiceException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
@ -193,11 +217,11 @@ class ItemController extends Controller
* @param bool $isRead * @param bool $isRead
* @return array|\OCP\AppFramework\Http\JSONResponse * @return array|\OCP\AppFramework\Http\JSONResponse
*/ */
public function read($itemId, $isRead=true) public function read($itemId, $isRead = true)
{ {
try { try {
$this->itemService->read($itemId, $isRead, $this->userId); $this->itemService->read($itemId, $isRead, $this->userId);
} catch(ServiceException $ex) { } catch (ServiceException $ex) {
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
@ -223,16 +247,14 @@ class ItemController extends Controller
* *
* @param int[] item ids * @param int[] item ids
*/ */
public function readMultiple($itemIds) public function readMultiple($itemIds)
{ {
foreach($itemIds as $id) { foreach ($itemIds as $id) {
try { try {
$this->itemService->read($id, true, $this->userId); $this->itemService->read($id, true, $this->userId);
} catch(ServiceNotFoundException $ex) { } catch (ServiceNotFoundException $ex) {
continue; continue;
} }
} }
} }
} }

View File

@ -13,7 +13,6 @@ namespace OCA\News\Controller;
use \OCP\AppFramework\Http\JSONResponse; use \OCP\AppFramework\Http\JSONResponse;
trait JSONHttpError trait JSONHttpError
{ {
@ -24,10 +23,8 @@ trait JSONHttpError
* @param int $code the http error code * @param int $code the http error code
* @return \OCP\AppFramework\Http\JSONResponse * @return \OCP\AppFramework\Http\JSONResponse
*/ */
public function error(\Exception $exception, $code) public function error(\Exception $exception, $code)
{ {
return new JSONResponse(['message' => $exception->getMessage()], $code); return new JSONResponse(['message' => $exception->getMessage()], $code);
} }
}
}

View File

@ -31,6 +31,7 @@ use OCA\News\Db\FeedType;
class PageController extends Controller class PageController extends Controller
{ {
use JSONHttpError;
private $settings; private $settings;
private $l10n; private $l10n;
@ -38,11 +39,11 @@ class PageController extends Controller
private $urlGenerator; private $urlGenerator;
private $config; private $config;
private $recommendedSites; private $recommendedSites;
private $statusService; private $statusService;
use JSONHttpError; public function __construct(
$appName,
public function __construct($appName,
IRequest $request, IRequest $request,
IConfig $settings, IConfig $settings,
IURLGenerator $urlGenerator, IURLGenerator $urlGenerator,
@ -67,20 +68,22 @@ class PageController extends Controller
* @NoAdminRequired * @NoAdminRequired
* @NoCSRFRequired * @NoCSRFRequired
*/ */
public function index() public function index()
{ {
$status = $this->statusService->getStatus(); $status = $this->statusService->getStatus();
$response = new TemplateResponse( $response = new TemplateResponse(
$this->appName, 'index', [ $this->appName,
'warnings' => $status['warnings'], 'index',
'url_generator' => $this->urlGenerator [
'warnings' => $status['warnings'],
'url_generator' => $this->urlGenerator
] ]
); );
$csp = new ContentSecurityPolicy(); $csp = new ContentSecurityPolicy();
$csp->addAllowedImageDomain('*') $csp->addAllowedImageDomain('*')
->addAllowedMediaDomain('*') ->addAllowedMediaDomain('*')
->addAllowedConnectDomain('*') // chrome breaks on audio elements ->addAllowedConnectDomain('*')// chrome breaks on audio elements
->addAllowedFrameDomain('https://youtube.com') ->addAllowedFrameDomain('https://youtube.com')
->addAllowedFrameDomain('https://www.youtube.com') ->addAllowedFrameDomain('https://www.youtube.com')
->addAllowedFrameDomain('https://player.vimeo.com') ->addAllowedFrameDomain('https://player.vimeo.com')
@ -96,7 +99,7 @@ class PageController extends Controller
/** /**
* @NoAdminRequired * @NoAdminRequired
*/ */
public function settings() public function settings()
{ {
$settings = [ $settings = [
'showAll', 'showAll',
@ -110,7 +113,8 @@ class PageController extends Controller
if (trim($exploreUrl) === '') { if (trim($exploreUrl) === '') {
// default url should not feature the sites.en.json // default url should not feature the sites.en.json
$exploreUrl = $this->urlGenerator->linkToRoute( $exploreUrl = $this->urlGenerator->linkToRoute(
'news.page.explore', ['lang' => 'en'] 'news.page.explore',
['lang' => 'en']
); );
$exploreUrl = preg_replace('/feeds\.en\.json$/', '', $exploreUrl); $exploreUrl = preg_replace('/feeds\.en\.json$/', '', $exploreUrl);
} }
@ -122,7 +126,9 @@ class PageController extends Controller
foreach ($settings as $setting) { foreach ($settings as $setting) {
$result[$setting] = $this->settings->getUserValue( $result[$setting] = $this->settings->getUserValue(
$this->userId, $this->appName, $setting $this->userId,
$this->appName,
$setting
) === '1'; ) === '1';
} }
return ['settings' => $result]; return ['settings' => $result];
@ -137,10 +143,15 @@ class PageController extends Controller
* @param bool $preventReadOnScroll * @param bool $preventReadOnScroll
* @param bool $oldestFirst * @param bool $oldestFirst
*/ */
public function updateSettings($showAll, $compact, $preventReadOnScroll, public function updateSettings(
$oldestFirst, $compactExpand $showAll,
$compact,
$preventReadOnScroll,
$oldestFirst,
$compactExpand
) { ) {
$settings = ['showAll', $settings = [
'showAll',
'compact', 'compact',
'preventReadOnScroll', 'preventReadOnScroll',
'oldestFirst', 'oldestFirst',
@ -154,8 +165,10 @@ class PageController extends Controller
$value = '0'; $value = '0';
} }
$this->settings->setUserValue( $this->settings->setUserValue(
$this->userId, $this->appName, $this->userId,
$setting, $value $this->appName,
$setting,
$value
); );
} }
} }
@ -165,15 +178,19 @@ class PageController extends Controller
* *
* @param string $lang * @param string $lang
*/ */
public function explore($lang) public function explore($lang)
{ {
$this->settings->setUserValue( $this->settings->setUserValue(
$this->userId, $this->appName, $this->userId,
'lastViewedFeedId', 0 $this->appName,
'lastViewedFeedId',
0
); );
$this->settings->setUserValue( $this->settings->setUserValue(
$this->userId, $this->appName, $this->userId,
'lastViewedFeedType', FeedType::EXPLORE $this->appName,
'lastViewedFeedType',
FeedType::EXPLORE
); );
try { try {
@ -182,6 +199,4 @@ class PageController extends Controller
return $this->error($ex, Http::STATUS_NOT_FOUND); return $this->error($ex, Http::STATUS_NOT_FOUND);
} }
} }
} }

View File

@ -27,7 +27,8 @@ class UserApiController extends ApiController
private $userSession; private $userSession;
private $rootFolder; private $rootFolder;
public function __construct($appName, public function __construct(
$appName,
IRequest $request, IRequest $request,
IUserSession $userSession, IUserSession $userSession,
IRootFolder $rootFolder IRootFolder $rootFolder
@ -41,7 +42,7 @@ class UserApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @CORS * @CORS
*/ */
public function index() public function index()
{ {
$user = $this->getUser(); $user = $this->getUser();
@ -71,5 +72,4 @@ class UserApiController extends ApiController
'avatar' => $avatar 'avatar' => $avatar
]; ];
} }
} }

View File

@ -23,7 +23,6 @@ use \OCP\AppFramework\Http;
use \OCA\News\Utility\Updater; use \OCA\News\Utility\Updater;
use \OCA\News\Service\StatusService; use \OCA\News\Service\StatusService;
class UtilityApiController extends ApiController class UtilityApiController extends ApiController
{ {
@ -31,7 +30,8 @@ class UtilityApiController extends ApiController
private $settings; private $settings;
private $statusService; private $statusService;
public function __construct($appName, public function __construct(
$appName,
IRequest $request, IRequest $request,
IUserSession $userSession, IUserSession $userSession,
Updater $updater, Updater $updater,
@ -50,7 +50,7 @@ class UtilityApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @CORS * @CORS
*/ */
public function version() public function version()
{ {
$version = $this->settings->getAppValue( $version = $this->settings->getAppValue(
$this->appName, $this->appName,
@ -64,7 +64,7 @@ class UtilityApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @CORS * @CORS
*/ */
public function beforeUpdate() public function beforeUpdate()
{ {
$this->updater->beforeUpdate(); $this->updater->beforeUpdate();
} }
@ -74,7 +74,7 @@ class UtilityApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @CORS * @CORS
*/ */
public function afterUpdate() public function afterUpdate()
{ {
$this->updater->afterUpdate(); $this->updater->afterUpdate();
} }
@ -85,10 +85,8 @@ class UtilityApiController extends ApiController
* @NoCSRFRequired * @NoCSRFRequired
* @NoAdminRequired * @NoAdminRequired
*/ */
public function status() public function status()
{ {
return $this->statusService->getStatus(); return $this->statusService->getStatus();
} }
} }

View File

@ -33,7 +33,9 @@ class Updater extends Job
*/ */
private $updaterService; private $updaterService;
public function __construct(Config $config, StatusService $status, public function __construct(
Config $config,
StatusService $status,
UpdaterService $updaterService UpdaterService $updaterService
) { ) {
$this->config = $config; $this->config = $config;
@ -41,9 +43,9 @@ class Updater extends Job
$this->updaterService = $updaterService; $this->updaterService = $updaterService;
} }
protected function run($argument) protected function run($argument)
{ {
if ($this->config->getUseCronUpdates() if ($this->config->getUseCronUpdates()
&& $this->status->isProperlyConfigured() && $this->status->isProperlyConfigured()
) { ) {
$this->updaterService->beforeUpdate(); $this->updaterService->beforeUpdate();
@ -51,5 +53,4 @@ class Updater extends Job
$this->updaterService->afterUpdate(); $this->updaterService->afterUpdate();
} }
} }
} }

View File

@ -17,14 +17,12 @@ trait EntityJSONSerializer
{ {
public function serializeFields($properties) public function serializeFields($properties)
{ {
$result = []; $result = [];
foreach($properties as $property) { foreach ($properties as $property) {
$result[$property] = $this->$property; $result[$property] = $this->$property;
} }
return $result; return $result;
} }
}
}

View File

@ -17,7 +17,6 @@ use OCP\AppFramework\Db\Entity;
class Feed extends Entity implements IAPI, \JsonSerializable class Feed extends Entity implements IAPI, \JsonSerializable
{ {
use EntityJSONSerializer; use EntityJSONSerializer;
/** @var string */ /** @var string */

View File

@ -17,12 +17,11 @@ use OCA\News\Utility\Time;
use OCP\IDBConnection; use OCP\IDBConnection;
use OCP\AppFramework\Db\Entity; use OCP\AppFramework\Db\Entity;
class FeedMapper extends NewsMapper class FeedMapper extends NewsMapper
{ {
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, 'news_feeds', Feed::class, $time);
} }
@ -52,7 +51,7 @@ class FeedMapper extends NewsMapper
{ {
$sql = 'SELECT `feeds`.*, COUNT(`items`.`id`) AS `unread_count` ' . $sql = 'SELECT `feeds`.*, COUNT(`items`.`id`) AS `unread_count` ' .
'FROM `*PREFIX*news_feeds` `feeds` ' . 'FROM `*PREFIX*news_feeds` `feeds` ' .
'LEFT OUTER JOIN `*PREFIX*news_folders` `folders` '. 'LEFT OUTER JOIN `*PREFIX*news_folders` `folders` ' .
'ON `feeds`.`folder_id` = `folders`.`id` ' . 'ON `feeds`.`folder_id` = `folders`.`id` ' .
'LEFT JOIN `*PREFIX*news_items` `items` ' . 'LEFT JOIN `*PREFIX*news_items` `items` ' .
'ON `feeds`.`id` = `items`.`feed_id` ' . 'ON `feeds`.`id` = `items`.`feed_id` ' .
@ -77,7 +76,7 @@ class FeedMapper extends NewsMapper
{ {
$sql = 'SELECT `feeds`.*, COUNT(`items`.`id`) AS `unread_count` ' . $sql = 'SELECT `feeds`.*, COUNT(`items`.`id`) AS `unread_count` ' .
'FROM `*PREFIX*news_feeds` `feeds` ' . 'FROM `*PREFIX*news_feeds` `feeds` ' .
'LEFT OUTER JOIN `*PREFIX*news_folders` `folders` '. 'LEFT OUTER JOIN `*PREFIX*news_folders` `folders` ' .
'ON `feeds`.`folder_id` = `folders`.`id` ' . 'ON `feeds`.`folder_id` = `folders`.`id` ' .
'LEFT JOIN `*PREFIX*news_items` `items` ' . 'LEFT JOIN `*PREFIX*news_items` `items` ' .
'ON `feeds`.`id` = `items`.`feed_id` ' . 'ON `feeds`.`id` = `items`.`feed_id` ' .
@ -134,7 +133,7 @@ class FeedMapper extends NewsMapper
* @param string $userId if given returns only entries from the given user * @param string $userId if given returns only entries from the given user
* @return array with the database rows * @return array with the database rows
*/ */
public function getToDelete($deleteOlderThan=null, $userId=null) public function getToDelete($deleteOlderThan = null, $userId = null)
{ {
$sql = 'SELECT * FROM `*PREFIX*news_feeds` ' . $sql = 'SELECT * FROM `*PREFIX*news_feeds` ' .
'WHERE `deleted_at` > 0 '; 'WHERE `deleted_at` > 0 ';
@ -147,7 +146,7 @@ class FeedMapper extends NewsMapper
} }
// we need to sometimes only delete feeds of a user // we need to sometimes only delete feeds of a user
if($userId !== null) { if ($userId !== null) {
$sql .= 'AND `user_id` = ?'; $sql .= 'AND `user_id` = ?';
$params[] = $userId; $params[] = $userId;
} }
@ -162,11 +161,9 @@ class FeedMapper 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($userId)
{ {
$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]);
} }
} }

View File

@ -13,7 +13,6 @@
namespace OCA\News\Db; namespace OCA\News\Db;
class FeedType class FeedType
{ {
const FEED = 0; const FEED = 0;
@ -22,4 +21,4 @@ class FeedType
const SUBSCRIPTIONS = 3; const SUBSCRIPTIONS = 3;
const SHARED = 4; const SHARED = 4;
const EXPLORE = 5; const EXPLORE = 5;
} }

View File

@ -17,7 +17,6 @@ use OCP\AppFramework\Db\Entity;
class Folder extends Entity implements IAPI, \JsonSerializable class Folder extends Entity implements IAPI, \JsonSerializable
{ {
use EntityJSONSerializer; use EntityJSONSerializer;
/** @var int|null */ /** @var int|null */

View File

@ -20,7 +20,7 @@ use OCP\AppFramework\Db\Entity;
class FolderMapper extends NewsMapper class FolderMapper extends NewsMapper
{ {
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, 'news_folders', Folder::class, $time);
} }
@ -68,7 +68,7 @@ class FolderMapper extends NewsMapper
$stmt = $this->execute($sql, $params); $stmt = $this->execute($sql, $params);
$stmt->closeCursor(); $stmt->closeCursor();
$sql = 'DELETE FROM `*PREFIX*news_items` WHERE `feed_id` NOT IN '. $sql = 'DELETE FROM `*PREFIX*news_items` WHERE `feed_id` NOT IN ' .
'(SELECT `feeds`.`id` FROM `*PREFIX*news_feeds` `feeds`)'; '(SELECT `feeds`.`id` FROM `*PREFIX*news_feeds` `feeds`)';
$stmt = $this->execute($sql); $stmt = $this->execute($sql);
@ -82,7 +82,7 @@ class FolderMapper extends NewsMapper
* @param string $userId if given returns only entries from the given user * @param string $userId if given returns only entries from the given user
* @return array with the database rows * @return array with the database rows
*/ */
public function getToDelete($deleteOlderThan=null, $userId=null) public function getToDelete($deleteOlderThan = null, $userId = null)
{ {
$sql = 'SELECT * FROM `*PREFIX*news_folders` ' . $sql = 'SELECT * FROM `*PREFIX*news_folders` ' .
'WHERE `deleted_at` > 0 '; 'WHERE `deleted_at` > 0 ';
@ -95,7 +95,7 @@ class FolderMapper extends NewsMapper
} }
// we need to sometimes only delete feeds of a user // we need to sometimes only delete feeds of a user
if($userId !== null) { if ($userId !== null) {
$sql .= 'AND `user_id` = ?'; $sql .= 'AND `user_id` = ?';
$params[] = $userId; $params[] = $userId;
} }
@ -109,11 +109,9 @@ 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($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]);
} }
} }

View File

@ -17,7 +17,6 @@ use OCP\AppFramework\Db\Entity;
class Item extends Entity implements IAPI, \JsonSerializable class Item extends Entity implements IAPI, \JsonSerializable
{ {
use EntityJSONSerializer; use EntityJSONSerializer;
/** @var string|null */ /** @var string|null */
@ -425,8 +424,7 @@ class Item extends Entity implements IAPI, \JsonSerializable
public function setUrl(string $url = null) public function setUrl(string $url = null)
{ {
$url = trim($url); $url = trim($url);
if ( if ((strpos($url, 'http') === 0 || strpos($url, 'magnet') === 0)
(strpos($url, 'http') === 0 || strpos($url, 'magnet') === 0)
&& $this->url !== $url && $this->url !== $url
) { ) {
$this->url = $url; $this->url = $url;

View File

@ -18,16 +18,17 @@ use OCA\News\Utility\Time;
use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection; use OCP\IDBConnection;
class ItemMapper extends NewsMapper class ItemMapper extends NewsMapper
{ {
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, 'news_items', Item::class, $time);
} }
private function makeSelectQuery($prependTo = '', $oldestFirst = false, private function makeSelectQuery(
$prependTo = '',
$oldestFirst = false,
$distinctFingerprint = false $distinctFingerprint = false
) { ) {
if ($oldestFirst) { if ($oldestFirst) {
@ -56,7 +57,7 @@ class ItemMapper extends NewsMapper
* @param int|null $type * @param int|null $type
* @return string * @return string
*/ */
private function buildStatusQueryPart($showAll, $type = null) private function buildStatusQueryPart($showAll, $type = null)
{ {
$sql = ''; $sql = '';
@ -71,7 +72,7 @@ class ItemMapper extends NewsMapper
return $sql; return $sql;
} }
private function buildSearchQueryPart(array $search = []) private function buildSearchQueryPart(array $search = [])
{ {
return str_repeat('AND `items`.`search_index` LIKE ? ', count($search)); return str_repeat('AND `items`.`search_index` LIKE ? ', count($search));
} }
@ -82,13 +83,14 @@ class ItemMapper extends NewsMapper
* @param string[] $search an array of strings that should be searched * @param string[] $search an array of strings that should be searched
* @return array with like parameters * @return array with like parameters
*/ */
private function buildLikeParameters($search = []) private function buildLikeParameters($search = [])
{ {
return array_map( return array_map(
function ($param) { function ($param) {
$param = addcslashes($param, '\\_%'); $param = addcslashes($param, '\\_%');
return '%' . mb_strtolower($param, 'UTF-8') . '%'; return '%' . mb_strtolower($param, 'UTF-8') . '%';
}, $search },
$search
); );
} }
@ -97,13 +99,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($id, $userId)
{ {
$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($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` ' .
@ -124,7 +126,7 @@ class ItemMapper extends NewsMapper
} }
public function readAll($highestItemId, $time, $userId) public function readAll($highestItemId, $time, $userId)
{ {
$sql = 'UPDATE `*PREFIX*news_items` ' . $sql = 'UPDATE `*PREFIX*news_items` ' .
'SET unread = ? ' . 'SET unread = ? ' .
@ -139,7 +141,7 @@ class ItemMapper extends NewsMapper
} }
public function readFolder($folderId, $highestItemId, $time, $userId) public function readFolder($folderId, $highestItemId, $time, $userId)
{ {
$sql = 'UPDATE `*PREFIX*news_items` ' . $sql = 'UPDATE `*PREFIX*news_items` ' .
'SET unread = ? ' . 'SET unread = ? ' .
@ -156,7 +158,7 @@ class ItemMapper extends NewsMapper
} }
public function readFeed($feedId, $highestItemId, $time, $userId) public function readFeed($feedId, $highestItemId, $time, $userId)
{ {
$sql = 'UPDATE `*PREFIX*news_items` ' . $sql = 'UPDATE `*PREFIX*news_items` ' .
'SET unread = ? ' . 'SET unread = ? ' .
@ -174,7 +176,7 @@ class ItemMapper extends NewsMapper
} }
private function getOperator($oldestFirst) private function getOperator($oldestFirst)
{ {
if ($oldestFirst) { if ($oldestFirst) {
return '>'; return '>';
@ -184,7 +186,7 @@ class ItemMapper extends NewsMapper
} }
public function findAllNew($updatedSince, $type, $showAll, $userId) public function findAllNew($updatedSince, $type, $showAll, $userId)
{ {
$sql = $this->buildStatusQueryPart($showAll, $type); $sql = $this->buildStatusQueryPart($showAll, $type);
@ -195,7 +197,7 @@ class ItemMapper extends NewsMapper
} }
public function findAllNewFolder($id, $updatedSince, $showAll, $userId) public function findAllNewFolder($id, $updatedSince, $showAll, $userId)
{ {
$sql = $this->buildStatusQueryPart($showAll); $sql = $this->buildStatusQueryPart($showAll);
@ -207,7 +209,7 @@ class ItemMapper extends NewsMapper
} }
public function findAllNewFeed($id, $updatedSince, $showAll, $userId) public function findAllNewFeed($id, $updatedSince, $showAll, $userId)
{ {
$sql = $this->buildStatusQueryPart($showAll); $sql = $this->buildStatusQueryPart($showAll);
@ -219,7 +221,7 @@ class ItemMapper extends NewsMapper
} }
private function findEntitiesIgnoringNegativeLimit($sql, $params, $limit) private function findEntitiesIgnoringNegativeLimit($sql, $params, $limit)
{ {
// 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) {
@ -230,8 +232,14 @@ class ItemMapper extends NewsMapper
} }
public function findAllFeed($id, $limit, $offset, $showAll, $oldestFirst, public function findAllFeed(
$userId, $search = [] $id,
$limit,
$offset,
$showAll,
$oldestFirst,
$userId,
$search = []
) { ) {
$params = [$userId]; $params = [$userId];
$params = array_merge($params, $this->buildLikeParameters($search)); $params = array_merge($params, $this->buildLikeParameters($search));
@ -251,8 +259,14 @@ class ItemMapper extends NewsMapper
} }
public function findAllFolder($id, $limit, $offset, $showAll, $oldestFirst, public function findAllFolder(
$userId, $search = [] $id,
$limit,
$offset,
$showAll,
$oldestFirst,
$userId,
$search = []
) { ) {
$params = [$userId]; $params = [$userId];
$params = array_merge($params, $this->buildLikeParameters($search)); $params = array_merge($params, $this->buildLikeParameters($search));
@ -272,7 +286,13 @@ class ItemMapper extends NewsMapper
} }
public function findAll($limit, $offset, $type, $showAll, $oldestFirst, $userId, public function findAll(
$limit,
$offset,
$type,
$showAll,
$oldestFirst,
$userId,
$search = [] $search = []
) { ) {
$params = [$userId]; $params = [$userId];
@ -292,7 +312,7 @@ class ItemMapper extends NewsMapper
} }
public function findAllUnreadOrStarred($userId) public function findAllUnreadOrStarred($userId)
{ {
$params = [$userId, true, true]; $params = [$userId, true, true];
$sql = 'AND (`items`.`unread` = ? OR `items`.`starred` = ?) '; $sql = 'AND (`items`.`unread` = ? OR `items`.`starred` = ?) ';
@ -301,7 +321,7 @@ class ItemMapper extends NewsMapper
} }
public function findByGuidHash($guidHash, $feedId, $userId) public function findByGuidHash($guidHash, $feedId, $userId)
{ {
$sql = $this->makeSelectQuery( $sql = $this->makeSelectQuery(
'AND `items`.`guid_hash` = ? ' . 'AND `items`.`guid_hash` = ? ' .
@ -318,7 +338,7 @@ class ItemMapper extends NewsMapper
* *
* @param int $threshold the number of items that should be deleted * @param int $threshold the number of items that should be deleted
*/ */
public function deleteReadOlderThanThreshold($threshold) public function deleteReadOlderThanThreshold($threshold)
{ {
$params = [false, false, $threshold]; $params = [false, false, $threshold];
@ -335,7 +355,6 @@ class ItemMapper extends NewsMapper
$result = $this->execute($sql, $params); $result = $this->execute($sql, $params);
while ($row = $result->fetch()) { while ($row = $result->fetch()) {
$size = (int)$row['size']; $size = (int)$row['size'];
$limit = $size - $threshold; $limit = $size - $threshold;
@ -355,11 +374,10 @@ class ItemMapper extends NewsMapper
$this->execute($sql, $params); $this->execute($sql, $params);
} }
} }
} }
public function getNewestItemId($userId) public function getNewestItemId($userId)
{ {
$sql = 'SELECT MAX(`items`.`id`) AS `max_id` ' . $sql = 'SELECT MAX(`items`.`id`) AS `max_id` ' .
'FROM `*PREFIX*news_items` `items` ' . 'FROM `*PREFIX*news_items` `items` ' .
@ -379,7 +397,7 @@ class ItemMapper 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($userId)
{ {
$sql = 'DELETE FROM `*PREFIX*news_items` ' . $sql = 'DELETE FROM `*PREFIX*news_items` ' .
'WHERE `feed_id` IN (' . 'WHERE `feed_id` IN (' .
@ -394,7 +412,7 @@ class ItemMapper extends NewsMapper
/** /**
* Returns a list of ids and userid of all items * Returns a list of ids and userid of all items
*/ */
public function findAllIds($limit = null, $offset = null) public function findAllIds($limit = null, $offset = null)
{ {
$sql = 'SELECT `id` FROM `*PREFIX*news_items`'; $sql = 'SELECT `id` FROM `*PREFIX*news_items`';
return $this->execute($sql, [], $limit, $offset)->fetchAll(); return $this->execute($sql, [], $limit, $offset)->fetchAll();
@ -403,7 +421,7 @@ class ItemMapper extends NewsMapper
/** /**
* Update search indices of all items * Update search indices of all items
*/ */
public function updateSearchIndices() public function updateSearchIndices()
{ {
// update indices in steps to prevent memory issues on larger systems // update indices in steps to prevent memory issues on larger systems
$step = 1000; // update 1000 items at a time $step = 1000; // update 1000 items at a time
@ -419,7 +437,7 @@ class ItemMapper extends NewsMapper
} }
} }
private function updateSearchIndex(array $items = []) private function updateSearchIndex(array $items = [])
{ {
foreach ($items as $row) { foreach ($items as $row) {
$sql = 'SELECT * FROM `*PREFIX*news_items` WHERE `id` = ?'; $sql = 'SELECT * FROM `*PREFIX*news_items` WHERE `id` = ?';
@ -430,7 +448,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($itemId, $userId);
@ -454,5 +472,4 @@ class ItemMapper extends NewsMapper
$this->update($item); $this->update($item);
} }
} }
} }

View File

@ -19,7 +19,6 @@ 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 MapperFactory implements IFactory class MapperFactory implements IFactory
{ {
@ -30,21 +29,20 @@ class MapperFactory implements IFactory
*/ */
private $time; private $time;
public function __construct(IDBConnection $db, $databaseType, Time $time) public function __construct(IDBConnection $db, $databaseType, Time $time)
{ {
$this->dbType = $databaseType; $this->dbType = $databaseType;
$this->db = $db; $this->db = $db;
$this->time = $time; $this->time = $time;
} }
public function build() public function build()
{ {
switch($this->dbType) { switch ($this->dbType) {
case 'mysql': case 'mysql':
return new MysqlItemMapper($this->db, $this->time); return new MysqlItemMapper($this->db, $this->time);
default: default:
return new ItemMapper($this->db, $this->time); return new ItemMapper($this->db, $this->time);
} }
} }
} }

View File

@ -45,12 +45,11 @@ class ItemMapper extends \OCA\News\Db\ItemMapper
$params = [false, false, $threshold]; $params = [false, false, $threshold];
$result = $this->execute($sql, $params); $result = $this->execute($sql, $params);
while($row = $result->fetch()) { while ($row = $result->fetch()) {
$size = (int) $row['size']; $size = (int) $row['size'];
$limit = $size - $threshold; $limit = $size - $threshold;
if($limit > 0) { if ($limit > 0) {
$params = [false, false, $row['feed_id'], $limit]; $params = [false, false, $row['feed_id'], $limit];
$sql = 'DELETE FROM `*PREFIX*news_items` ' . $sql = 'DELETE FROM `*PREFIX*news_items` ' .
@ -63,10 +62,9 @@ class ItemMapper extends \OCA\News\Db\ItemMapper
$this->execute($sql, $params); $this->execute($sql, $params);
} }
} }
} }
public function readItem($itemId, $isRead, $lastModified, $userId) public function readItem($itemId, $isRead, $lastModified, $userId)
{ {
$item = $this->find($itemId, $userId); $item = $this->find($itemId, $userId);
@ -86,5 +84,4 @@ class ItemMapper extends \OCA\News\Db\ItemMapper
$this->update($item); $this->update($item);
} }
} }
} }

View File

@ -26,20 +26,23 @@ abstract class NewsMapper extends Mapper
*/ */
private $time; private $time;
public function __construct(IDBConnection $db, $table, $entity, public function __construct(
IDBConnection $db,
$table,
$entity,
Time $time Time $time
) { ) {
parent::__construct($db, $table, $entity); parent::__construct($db, $table, $entity);
$this->time = $time; $this->time = $time;
} }
public function update(Entity $entity) public function update(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->setLastModified($this->time->getMicroTime()); $entity->setLastModified($this->time->getMicroTime());
return parent::insert($entity); return parent::insert($entity);
@ -66,9 +69,9 @@ abstract class NewsMapper extends Mapper
* @paran int $offset * @paran int $offset
* @return array * @return array
*/ */
public function where(array $search = [], $limit = null, $offset = null) public function where(array $search = [], $limit = null, $offset = null)
{ {
$entity = new $this->entityClass; $entity = new $this->entityClass();
// turn keys into sql query filter, e.g. feedId -> feed_id = :feedId // turn keys into sql query filter, e.g. feedId -> feed_id = :feedId
$filter = array_map( $filter = array_map(
@ -83,7 +86,8 @@ abstract class NewsMapper extends Mapper
$column = $entity->propertyToColumn($property); $column = $entity->propertyToColumn($property);
return $column . ' = :' . $property; return $column . ' = :' . $property;
}, array_keys($search) },
array_keys($search)
); );
$andStatement = implode(' AND ', $filter); $andStatement = implode(' AND ', $filter);
@ -96,5 +100,4 @@ abstract class NewsMapper extends Mapper
return $this->findEntities($sql, $search, $limit, $offset); return $this->findEntities($sql, $search, $limit, $offset);
} }
} }

View File

@ -22,5 +22,4 @@ interface IFactory
* @return mixed the constructed object * @return mixed the constructed object
*/ */
public function build(); public function build();
} }

View File

@ -22,13 +22,13 @@ class RecommendedSites
* @param string $exploreDir the absolute path to where the recommendation * @param string $exploreDir the absolute path to where the recommendation
* config files lie without a trailing slash * config files lie without a trailing slash
*/ */
public function __construct($exploreDir) public function __construct($exploreDir)
{ {
$this->directory = $exploreDir; $this->directory = $exploreDir;
} }
public function forLanguage($languageCode) public function forLanguage($languageCode)
{ {
$file = $this->directory . '/feeds.' . $languageCode . '.json'; $file = $this->directory . '/feeds.' . $languageCode . '.json';
@ -40,6 +40,4 @@ class RecommendedSites
throw new RecommendedSiteNotFoundException($msg); throw new RecommendedSiteNotFoundException($msg);
} }
} }
} }

View File

@ -47,7 +47,8 @@ class FeedFetcher implements IFeedFetcher
private $time; private $time;
private $clientService; private $clientService;
public function __construct(Reader $reader, public function __construct(
Reader $reader,
PicoFeedFaviconFactory $faviconFactory, PicoFeedFaviconFactory $faviconFactory,
IL10N $l10n, IL10N $l10n,
Time $time, Time $time,
@ -64,7 +65,7 @@ class FeedFetcher implements IFeedFetcher
/** /**
* This fetcher handles all the remaining urls therefore always returns true * This fetcher handles all the remaining urls therefore always returns true
*/ */
public function canHandle($url) public function canHandle($url)
{ {
return true; return true;
} }
@ -73,35 +74,35 @@ class FeedFetcher implements IFeedFetcher
/** /**
* Fetch a feed from remote * Fetch a feed from remote
* *
* @param string $url remote url of the feed * @param string $url remote url of the feed
* @param boolean $getFavicon if the favicon should also be fetched, * @param boolean $getFavicon if the favicon should also be fetched, defaults to true
* defaults to true * @param string $lastModified a last modified value from an http header defaults to false.
* @param string $lastModified a last modified value from an http header * If lastModified matches the http header from the feed no results are fetched
* defaults to false. If lastModified * @param string $etag an etag from an http header.
* matches the http header from the feed no * If lastModified matches the http header from the feed no results are fetched
* results are fetched * @param bool $fullTextEnabled if true tells the fetcher to enhance the articles by fetching more content
* @param string $etag an etag from an http header. * @param string $basicAuthUser if given, basic auth is set for this feed
* If lastModified matches the * @param string $basicAuthPassword if given, basic auth is set for this feed. Ignored if user is empty
* http header from the feed no *
* results are fetched
* @param bool fullTextEnabled if true tells the fetcher to enhance the
* articles by fetching custom enhanced content
* @param string $basicAuthUser if given, basic auth is set for this feed
* @param string $basicAuthPassword if given, basic auth is set for this
* feed. Ignored if user is null or an
* empty string
* @throws FetcherException if it fails * @throws FetcherException if it fails
* @return array an array containing the new feed and its items, first * @return array an array containing the new feed and its items, first
* element being the Feed and second element being an array of Items * element being the Feed and second element being an array of Items
*/ */
public function fetch($url, $getFavicon = true, $lastModified = null, public function fetch(
$etag = null, $fullTextEnabled = false, $url,
$basicAuthUser = null, $basicAuthPassword = null $getFavicon = true,
$lastModified = null,
$etag = null,
$fullTextEnabled = false,
$basicAuthUser = null,
$basicAuthPassword = null
) { ) {
try { try {
if ($basicAuthUser !== null && trim($basicAuthUser) !== '') { if ($basicAuthUser !== null && trim($basicAuthUser) !== '') {
$resource = $this->reader->discover( $resource = $this->reader->discover(
$url, $lastModified, $etag, $url,
$lastModified,
$etag,
$basicAuthUser, $basicAuthUser,
$basicAuthPassword $basicAuthPassword
); );
@ -123,13 +124,24 @@ class FeedFetcher implements IFeedFetcher
if ($fullTextEnabled) { if ($fullTextEnabled) {
$parser->enableContentGrabber(); $parser->enableContentGrabber();
$parser->getItemPostProcessor()->register(new LWNProcessor($basicAuthUser, $basicAuthPassword, $this->clientService)); $parser->getItemPostProcessor()->register(
new LWNProcessor(
$basicAuthUser,
$basicAuthPassword,
$this->clientService
)
);
} }
$parsedFeed = $parser->execute(); $parsedFeed = $parser->execute();
$feed = $this->buildFeed( $feed = $this->buildFeed(
$parsedFeed, $url, $getFavicon, $lastModified, $etag, $location $parsedFeed,
$url,
$getFavicon,
$lastModified,
$etag,
$location
); );
$items = []; $items = [];
@ -138,114 +150,115 @@ class FeedFetcher implements IFeedFetcher
} }
return [$feed, $items]; return [$feed, $items];
} catch (Exception $ex) { } catch (Exception $ex) {
$this->handleError($ex, $url); $this->handleError($ex, $url);
} }
} }
private function handleError(Exception $ex, $url) private function handleError(Exception $ex, $url)
{ {
$msg = $ex->getMessage(); $msg = $ex->getMessage();
if ($ex instanceof MalFormedXmlException) { if ($ex instanceof MalFormedXmlException) {
$msg = $this->l10n->t('Feed contains invalid XML'); $msg = $this->l10n->t('Feed contains invalid XML');
} else if ($ex instanceof SubscriptionNotFoundException) { } elseif ($ex instanceof SubscriptionNotFoundException) {
$msg = $this->l10n->t( $msg = $this->l10n->t(
'Feed not found: Either the website ' . 'Feed not found: Either the website ' .
'does not provide a feed or blocks access. To rule out ' . 'does not provide a feed or blocks access. To rule out ' .
'blocking, try to download the feed on your server\'s ' . 'blocking, try to download the feed on your server\'s ' .
'command line using curl: curl ' . $url 'command line using curl: curl ' . $url
); );
} else if ($ex instanceof UnsupportedFeedFormatException) { } elseif ($ex instanceof UnsupportedFeedFormatException) {
$msg = $this->l10n->t('Detected feed format is not supported'); $msg = $this->l10n->t('Detected feed format is not supported');
} else if ($ex instanceof InvalidCertificateException) { } elseif ($ex instanceof InvalidCertificateException) {
$msg = $this->buildCurlSslErrorMessage($ex->getCode()); $msg = $this->buildCurlSslErrorMessage($ex->getCode());
} else if ($ex instanceof InvalidUrlException) { } elseif ($ex instanceof InvalidUrlException) {
$msg = $this->l10n->t('Website not found'); $msg = $this->l10n->t('Website not found');
} else if ($ex instanceof MaxRedirectException) { } elseif ($ex instanceof MaxRedirectException) {
$msg = $this->l10n->t('More redirects than allowed, aborting'); $msg = $this->l10n->t('More redirects than allowed, aborting');
} else if ($ex instanceof MaxSizeException) { } elseif ($ex instanceof MaxSizeException) {
$msg = $this->l10n->t('Bigger than maximum allowed size'); $msg = $this->l10n->t('Bigger than maximum allowed size');
} else if ($ex instanceof TimeoutException) { } elseif ($ex instanceof TimeoutException) {
$msg = $this->l10n->t('Request timed out'); $msg = $this->l10n->t('Request timed out');
} else if ($ex instanceof UnauthorizedException) { } elseif ($ex instanceof UnauthorizedException) {
$msg = $this->l10n->t( $msg = $this->l10n->t(
'Required credentials for feed were ' . 'Required credentials for feed were ' .
'either missing or incorrect' 'either missing or incorrect'
); );
} else if ($ex instanceof ForbiddenException) { } elseif ($ex instanceof ForbiddenException) {
$msg = $this->l10n->t('Forbidden to access feed'); $msg = $this->l10n->t('Forbidden to access feed');
} }
throw new FetcherException($msg); throw new FetcherException($msg);
} }
private function buildCurlSslErrorMessage($errorCode) private function buildCurlSslErrorMessage($errorCode)
{ {
switch ($errorCode) { switch ($errorCode) {
case 35: // CURLE_SSL_CONNECT_ERROR case 35: // CURLE_SSL_CONNECT_ERROR
return $this->l10n->t( return $this->l10n->t(
'Certificate error: A problem occurred ' . 'Certificate error: A problem occurred ' .
'somewhere in the SSL/TLS handshake. Could be ' . 'somewhere in the SSL/TLS handshake. Could be ' .
'certificates (file formats, paths, permissions), ' . 'certificates (file formats, paths, permissions), ' .
'passwords, and others.' 'passwords, and others.'
); );
case 51: // CURLE_PEER_FAILED_VERIFICATION case 51: // CURLE_PEER_FAILED_VERIFICATION
return $this->l10n->t( return $this->l10n->t(
'Certificate error: The remote server\'s SSL ' . 'Certificate error: The remote server\'s SSL ' .
'certificate or SSH md5 fingerprint was deemed not OK.' 'certificate or SSH md5 fingerprint was deemed not OK.'
); );
case 58: // CURLE_SSL_CERTPROBLEM case 58: // CURLE_SSL_CERTPROBLEM
return $this->l10n->t( return $this->l10n->t(
'Certificate error: Problem with the local client ' . 'Certificate error: Problem with the local client ' .
'certificate.' 'certificate.'
); );
case 59: // CURLE_SSL_CIPHER case 59: // CURLE_SSL_CIPHER
return $this->l10n->t( return $this->l10n->t(
'Certificate error: Couldn\'t use specified cipher.' 'Certificate error: Couldn\'t use specified cipher.'
); );
case 60: // CURLE_SSL_CACERT case 60: // CURLE_SSL_CACERT
return $this->l10n->t( return $this->l10n->t(
'Certificate error: Peer certificate cannot be ' . 'Certificate error: Peer certificate cannot be ' .
'authenticated with known CA certificates.' 'authenticated with known CA certificates.'
); );
case 64: // CURLE_USE_SSL_FAILED case 64: // CURLE_USE_SSL_FAILED
return $this->l10n->t( return $this->l10n->t(
'Certificate error: Requested FTP SSL level failed.' 'Certificate error: Requested FTP SSL level failed.'
); );
case 66: // CURLE_SSL_ENGINE_INITFAILED case 66: // CURLE_SSL_ENGINE_INITFAILED
return $this->l10n->t( return $this->l10n->t(
'Certificate error: Initiating the SSL engine failed.' 'Certificate error: Initiating the SSL engine failed.'
); );
case 77: // CURLE_SSL_CACERT_BADFILE case 77: // CURLE_SSL_CACERT_BADFILE
return $this->l10n->t( return $this->l10n->t(
'Certificate error: Problem with reading the SSL CA ' . 'Certificate error: Problem with reading the SSL CA ' .
'cert (path? access rights?)' 'cert (path? access rights?)'
); );
case 83: // CURLE_SSL_ISSUER_ERROR case 83: // CURLE_SSL_ISSUER_ERROR
return $this->l10n->t( return $this->l10n->t(
'Certificate error: Issuer check failed' 'Certificate error: Issuer check failed'
); );
default: default:
return $this->l10n->t('Unknown SSL certificate error!'); return $this->l10n->t('Unknown SSL certificate error!');
} }
} }
private function decodeTwice($string) private function decodeTwice($string)
{ {
return html_entity_decode( return html_entity_decode(
html_entity_decode( html_entity_decode(
$string, ENT_QUOTES | ENT_HTML5, 'UTF-8' $string,
ENT_QUOTES | ENT_HTML5,
'UTF-8'
), ),
ENT_QUOTES | ENT_HTML5, 'UTF-8' ENT_QUOTES | ENT_HTML5,
'UTF-8'
); );
} }
protected function determineRtl($parsedItem, $parsedFeed) protected function determineRtl($parsedItem, $parsedFeed)
{ {
$itemLang = $parsedItem->getLanguage(); $itemLang = $parsedItem->getLanguage();
$feedLang = $parsedFeed->getLanguage(); $feedLang = $parsedFeed->getLanguage();
@ -258,7 +271,7 @@ class FeedFetcher implements IFeedFetcher
} }
protected function buildItem($parsedItem, $parsedFeed) protected function buildItem($parsedItem, $parsedFeed)
{ {
$item = new Item(); $item = new Item();
$item->setUnread(true); $item->setUnread(true);
@ -276,7 +289,8 @@ class FeedFetcher implements IFeedFetcher
// purification is done in the service layer // purification is done in the service layer
$body = $parsedItem->getContent(); $body = $parsedItem->getContent();
$body = mb_convert_encoding( $body = mb_convert_encoding(
$body, 'HTML-ENTITIES', $body,
'HTML-ENTITIES',
mb_detect_encoding($body) mb_detect_encoding($body)
); );
$item->setBody($body); $item->setBody($body);
@ -284,7 +298,7 @@ class FeedFetcher implements IFeedFetcher
$enclosureUrl = $parsedItem->getEnclosureUrl(); $enclosureUrl = $parsedItem->getEnclosureUrl();
if ($enclosureUrl) { if ($enclosureUrl) {
$enclosureType = $parsedItem->getEnclosureType(); $enclosureType = $parsedItem->getEnclosureType();
if (stripos($enclosureType, 'audio/') !== false if (stripos($enclosureType, 'audio/') !== false
|| stripos($enclosureType, 'video/') !== false || stripos($enclosureType, 'video/') !== false
) { ) {
$item->setEnclosureMime($enclosureType); $item->setEnclosureMime($enclosureType);
@ -298,8 +312,13 @@ class FeedFetcher implements IFeedFetcher
} }
protected function buildFeed($parsedFeed, $url, $getFavicon, $modified, protected function buildFeed(
$etag, $location $parsedFeed,
$url,
$getFavicon,
$modified,
$etag,
$location
) { ) {
$feed = new Feed(); $feed = new Feed();
@ -327,5 +346,4 @@ class FeedFetcher implements IFeedFetcher
return $feed; return $feed;
} }
} }

View File

@ -13,7 +13,6 @@
namespace OCA\News\Fetcher; namespace OCA\News\Fetcher;
class Fetcher class Fetcher
{ {
@ -38,36 +37,38 @@ class Fetcher
/** /**
* Fetch a feed from remote * Fetch a feed from remote
* *
* @param string $url remote url of the feed * @param string $url remote url of the feed
* @param boolean $getFavicon if the favicon should also be fetched, * @param boolean $getFavicon if the favicon should also be fetched, defaults to true
* defaults to true * @param string $lastModified a last modified value from an http header defaults to false.
* @param string $lastModified a last modified value from an http header * If lastModified matches the http header from the feed no results are fetched
* defaults to false. If lastModified * @param string $etag an etag from an http header.
* matches the http header from the feed no * If lastModified matches the http header from the feed no results are fetched
* results are fetched * @param bool $fullTextEnabled if true tells the fetcher to enhance the articles by fetching more content
* @param string $etag an etag from an http header. * @param string $basicAuthUser if given, basic auth is set for this feed
* If lastModified matches the * @param string $basicAuthPassword if given, basic auth is set for this feed. Ignored if user is empty
* http header from the feed no *
* results are fetched
* @param bool fullTextEnabled if true tells the fetcher to enhance the
* articles by fetching custom enhanced content
* @param string $basicAuthUser if given, basic auth is set for this feed
* @param string $basicAuthPassword if given, basic auth is set for this
* feed. Ignored if user is null or an
* empty string
* @throws FetcherException if simple pie fails * @throws FetcherException if simple pie fails
* @return array an array containing the new feed and its items, first * @return array an array containing the new feed and its items, first
* element being the Feed and second element being an array of Items * element being the Feed and second element being an array of Items
*/ */
public function fetch($url, $getFavicon=true, $lastModified=null, public function fetch(
$etag=null, $fullTextEnabled=false, $url,
$basicAuthUser=null, $basicAuthPassword=null $getFavicon = true,
$lastModified = null,
$etag = null,
$fullTextEnabled = false,
$basicAuthUser = null,
$basicAuthPassword = null
) { ) {
foreach($this->fetchers as $fetcher){ foreach ($this->fetchers as $fetcher) {
if($fetcher->canHandle($url)) { if ($fetcher->canHandle($url)) {
return $fetcher->fetch( return $fetcher->fetch(
$url, $getFavicon, $lastModified, $etag, $url,
$fullTextEnabled, $basicAuthUser, $getFavicon,
$lastModified,
$etag,
$fullTextEnabled,
$basicAuthUser,
$basicAuthPassword $basicAuthPassword
); );
} }
@ -75,6 +76,4 @@ class Fetcher
return [null, []]; return [null, []];
} }
} }

View File

@ -25,5 +25,4 @@ class FetcherException extends \Exception
{ {
parent::__construct($msg); parent::__construct($msg);
} }
}
}

View File

@ -17,37 +17,39 @@ interface IFeedFetcher
{ {
/** /**
* @param string $url remote url of the feed * Fetch feed content.
* @param boolean $getFavicon if the favicon should also be fetched, *
* defaults to true * @param string $url remote url of the feed
* @param string $lastModified a last modified value from an http header * @param boolean $getFavicon if the favicon should also be fetched, defaults to true
* defaults to false. If lastModified * @param string $lastModified a last modified value from an http header defaults to false.
* matches the http header from the feed no * If lastModified matches the http header from the feed no results are fetched
* results are fetched * @param string $etag an etag from an http header.
* @param string $etag an etag from an http header. * If lastModified matches the http header from the feed no results are fetched
* If lastModified matches the * @param bool $fullTextEnabled if true tells the fetcher to enhance the articles by fetching more content
* http header from the feed no * @param string $basicAuthUser if given, basic auth is set for this feed
* results are fetched * @param string $basicAuthPassword if given, basic auth is set for this feed. Ignored if user is empty
* @param bool fullTextEnabled if true tells the fetcher to enhance the *
* articles by fetching custom enhanced content
* @param string $basicAuthUser if given, basic auth is set for this feed
* @param string $basicAuthPassword if given, basic auth is set for this
* feed. Ignored if user is null or an
* empty string
* @throws FetcherException if the fetcher encounters a problem * @throws FetcherException if the fetcher encounters a problem
* @return array an array containing the new feed and its items, first * @return array an array containing the new feed and its items, first
* element being the Feed and second element being an array of Items * element being the Feed and second element being an array of Items
*/ */
function fetch($url, $getFavicon=true, $lastModified=null, $etag=null, public function fetch(
$fullTextEnabled=false, $basicAuthUser=null, $url,
$basicAuthPassword=null $getFavicon = true,
$lastModified = null,
$etag = null,
$fullTextEnabled = false,
$basicAuthUser = null,
$basicAuthPassword = null
); );
/** /**
* Can a fetcher handle a feed.
*
* @param string $url the url that should be fetched * @param string $url the url that should be fetched
*
* @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
*/ */
function canHandle($url); public function canHandle($url);
} }

View File

@ -11,7 +11,6 @@
namespace OCA\News\Fetcher; namespace OCA\News\Fetcher;
class YoutubeFetcher implements IFeedFetcher class YoutubeFetcher implements IFeedFetcher
{ {
@ -23,7 +22,7 @@ class YoutubeFetcher implements IFeedFetcher
} }
private function buildUrl($url) private function buildUrl($url)
{ {
$baseRegex = '%(?:https?://|//)?(?:www.)?youtube.com'; $baseRegex = '%(?:https?://|//)?(?:www.)?youtube.com';
$playRegex = $baseRegex . '.*?list=([^&]*)%'; $playRegex = $baseRegex . '.*?list=([^&]*)%';
@ -49,36 +48,39 @@ class YoutubeFetcher implements IFeedFetcher
/** /**
* Fetch a feed from remote * Fetch a feed from remote
* *
* @param string $url remote url of the feed * @param string $url remote url of the feed
* @param boolean $getFavicon if the favicon should also be fetched, * @param boolean $getFavicon if the favicon should also be fetched, defaults to true
* defaults to true * @param string $lastModified a last modified value from an http header defaults to false.
* @param string $lastModified a last modified value from an http header * If lastModified matches the http header from the feed no results are fetched
* defaults to false. If lastModified * @param string $etag an etag from an http header.
* matches the http header from the feed no * If lastModified matches the http header from the feed no results are fetched
* results are fetched * @param bool $fullTextEnabled if true tells the fetcher to enhance the articles by fetching more content
* @param string $etag an etag from an http header. * @param string $basicAuthUser if given, basic auth is set for this feed
* If lastModified matches the * @param string $basicAuthPassword if given, basic auth is set for this feed. Ignored if user is empty
* http header from the feed no *
* results are fetched
* @param bool fullTextEnabled if true tells the fetcher to enhance the
* articles by fetching custom enhanced content
* @param string $basicAuthUser if given, basic auth is set for this feed
* @param string $basicAuthPassword if given, basic auth is set for this
* feed. Ignored if user is null or an
* empty string
* @throws FetcherException if it fails * @throws FetcherException if it fails
* @return array an array containing the new feed and its items, first * @return array an array containing the new feed and its items, first
* element being the Feed and second element being an array of Items * element being the Feed and second element being an array of Items
*/ */
public function fetch($url, $getFavicon=true, $lastModified=null, public function fetch(
$etag=null, $fullTextEnabled=false, $url,
$basicAuthUser=null, $basicAuthPassword=null $getFavicon = true,
$lastModified = null,
$etag = null,
$fullTextEnabled = false,
$basicAuthUser = null,
$basicAuthPassword = null
) { ) {
$transformedUrl = $this->buildUrl($url); $transformedUrl = $this->buildUrl($url);
$result = $this->feedFetcher->fetch( $result = $this->feedFetcher->fetch(
$transformedUrl, $getFavicon, $lastModified, $etag, $transformedUrl,
$fullTextEnabled, $basicAuthUser, $basicAuthPassword $getFavicon,
$lastModified,
$etag,
$fullTextEnabled,
$basicAuthUser,
$basicAuthPassword
); );
// reset feed url so we know the correct added url for the feed // reset feed url so we know the correct added url for the feed
@ -86,6 +88,4 @@ class YoutubeFetcher implements IFeedFetcher
return $result; return $result;
} }
} }

View File

@ -21,7 +21,7 @@ use OCA\News\Service\FolderService;
class User class User
{ {
public static function deleteUser($params) public static function deleteUser($params)
{ {
$userId = $params['uid']; $userId = $params['uid'];
@ -33,5 +33,4 @@ class User
$container->query(FeedService::class)->deleteUser($userId); $container->query(FeedService::class)->deleteUser($userId);
$container->query(FolderService::class)->deleteUser($userId); $container->query(FolderService::class)->deleteUser($userId);
} }
} }

View File

@ -15,7 +15,6 @@ namespace OCA\News\Http;
use \OCP\AppFramework\Http\DownloadResponse; use \OCP\AppFramework\Http\DownloadResponse;
/** /**
* Prompts the user to download the a text file * Prompts the user to download the a text file
*/ */
@ -49,6 +48,4 @@ class TextDownloadResponse extends DownloadResponse
{ {
return $this->content; return $this->content;
} }
} }

View File

@ -30,7 +30,7 @@ class TextResponse extends Response
* @param string $contentType the mimetype. text/ is added automatically so * @param string $contentType the mimetype. text/ is added automatically so
* only plain or html can be added to get text/plain or text/html * only plain or html can be added to get text/plain or text/html
*/ */
public function __construct($content, $contentType='plain') public function __construct($content, $contentType = 'plain')
{ {
$this->content = $content; $this->content = $content;
$this->addHeader('Content-type', 'text/' . $contentType); $this->addHeader('Content-type', 'text/' . $contentType);
@ -46,6 +46,4 @@ class TextResponse extends Response
{ {
return $this->content; return $this->content;
} }
} }

View File

@ -21,12 +21,12 @@ class MigrateStatusFlags implements IRepairStep
{ {
/** /**
* @var IDBConnection * @var IDBConnection
*/ */
private $db; private $db;
/** /**
* @var IConfig * @var IConfig
*/ */
private $config; private $config;
@ -34,18 +34,18 @@ class MigrateStatusFlags implements IRepairStep
* @param IDBConnection $db * @param IDBConnection $db
* @param IConfig $config * @param IConfig $config
*/ */
public function __construct(IDBConnection $db, IConfig $config) public function __construct(IDBConnection $db, IConfig $config)
{ {
$this->db = $db; $this->db = $db;
$this->config = $config; $this->config = $config;
} }
public function getName() public function getName()
{ {
return 'Migrate binary status into separate boolean fields'; return 'Migrate binary status into separate boolean fields';
} }
public function run(IOutput $output) public function run(IOutput $output)
{ {
$version = $this->config->getAppValue('news', 'installed_version', '0.0.0'); $version = $this->config->getAppValue('news', 'installed_version', '0.0.0');
if (version_compare($version, '11.0.6', '>=')) { if (version_compare($version, '11.0.6', '>=')) {
@ -61,4 +61,4 @@ class MigrateStatusFlags implements IRepairStep
throw new \Exception('Could not migrate status'); throw new \Exception('Could not migrate status');
} }
} }
} }

View File

@ -26,24 +26,23 @@ class Plugin
private static $scripts = []; private static $scripts = [];
private static $styles = []; private static $styles = [];
public static function registerStyle($appName, $styleName) public static function registerStyle($appName, $styleName)
{ {
self::$styles[$appName] = $styleName; self::$styles[$appName] = $styleName;
} }
public static function registerScript($appName, $scriptName) public static function registerScript($appName, $scriptName)
{ {
self::$scripts[$appName] = $scriptName; self::$scripts[$appName] = $scriptName;
} }
public static function getStyles() public static function getStyles()
{ {
return self::$styles; return self::$styles;
} }
public static function getScripts() public static function getScripts()
{ {
return self::$scripts; return self::$scripts;
} }
}
}

View File

@ -31,7 +31,7 @@ class LWNProcessor implements ItemProcessorInterface
* @param $user * @param $user
* @param $password * @param $password
*/ */
public function __construct($user, $password, IClientService $clientService) public function __construct($user, $password, IClientService $clientService)
{ {
$this->user = $user; $this->user = $user;
$this->password = $password; $this->password = $password;
@ -39,7 +39,7 @@ class LWNProcessor implements ItemProcessorInterface
$this->cookieJar = new CookieJar(); $this->cookieJar = new CookieJar();
} }
private function login() private function login()
{ {
if ($this->cookieJar->count() > 0) { if ($this->cookieJar->count() > 0) {
return true; return true;
@ -50,7 +50,8 @@ class LWNProcessor implements ItemProcessorInterface
$client = $this->clientService->newClient(); $client = $this->clientService->newClient();
$response = $client->post( $response = $client->post(
'https://lwn.net/login', [ 'https://lwn.net/login',
[
'cookies' => $this->cookieJar, 'cookies' => $this->cookieJar,
'body' => [ 'body' => [
'Username' => $this->user, 'Username' => $this->user,
@ -62,16 +63,18 @@ class LWNProcessor implements ItemProcessorInterface
return ($response->getStatusCode() === 200 && $this->cookieJar->count() > 0); return ($response->getStatusCode() === 200 && $this->cookieJar->count() > 0);
} }
private function getBody($url) private function getBody($url)
{ {
$client = $this->clientService->newClient(); $client = $this->clientService->newClient();
$response = $client->get( $response = $client->get(
$url, [ $url,
[
'cookies' => $this->cookieJar 'cookies' => $this->cookieJar
] ]
); );
$parser = new RuleParser( $parser = new RuleParser(
$response->getBody(), [ $response->getBody(),
[
'body' => array( 'body' => array(
'//div[@class="ArticleText"]', '//div[@class="ArticleText"]',
), ),
@ -85,7 +88,7 @@ class LWNProcessor implements ItemProcessorInterface
return str_replace('href="/', 'href="https://lwn.net/', $articleBody); return str_replace('href="/', 'href="https://lwn.net/', $articleBody);
} }
private function canHandle($url) private function canHandle($url)
{ {
$regex = '%(?:https?://|//)?(?:www.)?lwn.net%'; $regex = '%(?:https?://|//)?(?:www.)?lwn.net%';
@ -100,7 +103,7 @@ class LWNProcessor implements ItemProcessorInterface
* @param Item $item * @param Item $item
* @return bool * @return bool
*/ */
public function execute(Feed $feed, Item $item) public function execute(Feed $feed, Item $item)
{ {
if ($this->canHandle($item->getUrl())) { if ($this->canHandle($item->getUrl())) {
$loggedIn = $this->login(); $loggedIn = $this->login();

View File

@ -28,7 +28,6 @@ use OCA\News\Fetcher\FetcherException;
use OCA\News\Config\Config; use OCA\News\Config\Config;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
class FeedService extends Service class FeedService extends Service
{ {
@ -42,7 +41,8 @@ class FeedService extends Service
private $purifier; private $purifier;
private $loggerParams; private $loggerParams;
public function __construct(FeedMapper $feedMapper, public function __construct(
FeedMapper $feedMapper,
Fetcher $feedFetcher, Fetcher $feedFetcher,
ItemMapper $itemMapper, ItemMapper $itemMapper,
ILogger $logger, ILogger $logger,
@ -82,7 +82,7 @@ class FeedService extends Service
* *
* @return array of feeds * @return array of feeds
*/ */
public function findAllFromAllUsers() public function findAllFromAllUsers()
{ {
return $this->feedMapper->findAll(); return $this->feedMapper->findAll();
} }
@ -103,8 +103,13 @@ class FeedService extends Service
* @throws ServiceNotFoundException if the url points to an invalid feed * @throws ServiceNotFoundException if the url points to an invalid feed
* @return Feed the newly created feed * @return Feed the newly created feed
*/ */
public function create($feedUrl, $folderId, $userId, $title=null, public function create(
$basicAuthUser=null, $basicAuthPassword=null $feedUrl,
$folderId,
$userId,
$title = null,
$basicAuthUser = null,
$basicAuthPassword = null
) { ) {
// first try if the feed exists already // first try if the feed exists already
try { try {
@ -113,8 +118,12 @@ class FeedService extends Service
* @var Item[] $items * @var Item[] $items
*/ */
list($feed, $items) = $this->feedFetcher->fetch( list($feed, $items) = $this->feedFetcher->fetch(
$feedUrl, true, $feedUrl,
null, null, false, $basicAuthUser, true,
null,
null,
false,
$basicAuthUser,
$basicAuthPassword $basicAuthPassword
); );
@ -126,7 +135,7 @@ class FeedService extends Service
); );
// If no matching feed was found everything was ok // If no matching feed was found everything was ok
} catch(DoesNotExistException $ex){ } catch (DoesNotExistException $ex) {
} }
// insert feed // insert feed
@ -146,7 +155,7 @@ class FeedService extends Service
// insert items in reverse order because the first one is usually // insert items in reverse order because the first one is usually
// the newest item // the newest item
$unreadCount = 0; $unreadCount = 0;
for($i=$itemCount-1; $i>=0; $i--){ for ($i = $itemCount - 1; $i >= 0; $i--) {
$item = $items[$i]; $item = $items[$i];
$item->setFeedId($feed->getId()); $item->setFeedId($feed->getId());
@ -154,10 +163,12 @@ class FeedService extends Service
// and ignore it if it does // and ignore it if it does
try { try {
$this->itemMapper->findByGuidHash( $this->itemMapper->findByGuidHash(
$item->getGuidHash(), $item->getFeedId(), $userId $item->getGuidHash(),
$item->getFeedId(),
$userId
); );
continue; continue;
} catch(DoesNotExistException $ex){ } catch (DoesNotExistException $ex) {
$unreadCount += 1; $unreadCount += 1;
$item->setBody($this->purifier->purify($item->getBody())); $item->setBody($this->purifier->purify($item->getBody()));
$this->itemMapper->insert($item); $this->itemMapper->insert($item);
@ -168,7 +179,7 @@ class FeedService extends Service
$feed->setUnreadCount($unreadCount); $feed->setUnreadCount($unreadCount);
return $feed; return $feed;
} catch(FetcherException $ex){ } catch (FetcherException $ex) {
$this->logger->debug($ex->getMessage(), $this->loggerParams); $this->logger->debug($ex->getMessage(), $this->loggerParams);
throw new ServiceNotFoundException($ex->getMessage()); throw new ServiceNotFoundException($ex->getMessage());
} }
@ -182,10 +193,10 @@ class FeedService extends Service
{ {
// TODO: this method is not covered by any tests // TODO: this method is not covered by any tests
$feeds = $this->feedMapper->findAll(); $feeds = $this->feedMapper->findAll();
foreach($feeds as $feed){ foreach ($feeds as $feed) {
try { try {
$this->update($feed->getId(), $feed->getUserId()); $this->update($feed->getId(), $feed->getUserId());
} catch(\Exception $ex){ } catch (\Exception $ex) {
// something is really wrong here, log it // something is really wrong here, log it
$this->logger->error( $this->logger->error(
'Unexpected error when updating feed ' . $ex->getMessage(), 'Unexpected error when updating feed ' . $ex->getMessage(),
@ -205,12 +216,12 @@ class FeedService extends Service
* @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($feedId, $userId, $forceUpdate = false)
{ {
/** @var Feed $existingFeed */ /** @var Feed $existingFeed */
$existingFeed = $this->find($feedId, $userId); $existingFeed = $this->find($feedId, $userId);
if($existingFeed->getPreventUpdate() === true) { if ($existingFeed->getPreventUpdate() === true) {
return $existingFeed; return $existingFeed;
} }
@ -257,20 +268,21 @@ class FeedService extends Service
// insert items in reverse order because the first one is // insert items in reverse order because the first one is
// usually the newest item // usually the newest item
for($i=$itemCount-1; $i>=0; $i--){ for ($i = $itemCount - 1; $i >= 0; $i--) {
$item = $items[$i]; $item = $items[$i];
$item->setFeedId($existingFeed->getId()); $item->setFeedId($existingFeed->getId());
try { try {
$dbItem = $this->itemMapper->findByGuidHash( $dbItem = $this->itemMapper->findByGuidHash(
$item->getGuidHash(), $feedId, $userId $item->getGuidHash(),
$feedId,
$userId
); );
// in case of update // in case of update
if ($forceUpdate if ($forceUpdate
|| $item->getUpdatedDate() > $dbItem->getUpdatedDate() || $item->getUpdatedDate() > $dbItem->getUpdatedDate()
) { ) {
$dbItem->setTitle($item->getTitle()); $dbItem->setTitle($item->getTitle());
$dbItem->setUrl($item->getUrl()); $dbItem->setUrl($item->getUrl());
$dbItem->setAuthor($item->getAuthor()); $dbItem->setAuthor($item->getAuthor());
@ -292,7 +304,7 @@ class FeedService extends Service
$this->itemMapper->update($dbItem); $this->itemMapper->update($dbItem);
} }
} catch(DoesNotExistException $ex){ } catch (DoesNotExistException $ex) {
$item->setBody( $item->setBody(
$this->purifier->purify($item->getBody()) $this->purifier->purify($item->getBody())
); );
@ -303,10 +315,9 @@ class FeedService extends Service
// mark feed as successfully updated // mark feed as successfully updated
$existingFeed->setUpdateErrorCount(0); $existingFeed->setUpdateErrorCount(0);
$existingFeed->setLastUpdateError(''); $existingFeed->setLastUpdateError('');
} catch (FetcherException $ex) {
} catch(FetcherException $ex){
$existingFeed->setUpdateErrorCount( $existingFeed->setUpdateErrorCount(
$existingFeed->getUpdateErrorCount()+1 $existingFeed->getUpdateErrorCount() + 1
); );
$existingFeed->setLastUpdateError($ex->getMessage()); $existingFeed->setLastUpdateError($ex->getMessage());
} }
@ -323,7 +334,7 @@ class FeedService extends Service
* @param string $userId the username * @param string $userId the username
* @return Feed if one had to be created for nonexistent feeds * @return Feed if one had to be created for nonexistent feeds
*/ */
public function importArticles($json, $userId) public function importArticles($json, $userId)
{ {
$url = 'http://nextcloud/nofeed'; $url = 'http://nextcloud/nofeed';
$urlHash = md5($url); $urlHash = md5($url);
@ -331,7 +342,7 @@ class FeedService extends Service
// build assoc array for fast access // build assoc array for fast access
$feeds = $this->findAll($userId); $feeds = $this->findAll($userId);
$feedsDict = []; $feedsDict = [];
foreach($feeds as $feed) { foreach ($feeds as $feed) {
$feedsDict[$feed->getLink()] = $feed; $feedsDict[$feed->getLink()] = $feed;
} }
@ -343,10 +354,10 @@ class FeedService extends Service
$item = Item::fromImport($entry); $item = Item::fromImport($entry);
$feedLink = $entry['feedLink']; // this is not set on the item yet $feedLink = $entry['feedLink']; // this is not set on the item yet
if(array_key_exists($feedLink, $feedsDict)) { if (array_key_exists($feedLink, $feedsDict)) {
$feed = $feedsDict[$feedLink]; $feed = $feedsDict[$feedLink];
$item->setFeedId($feed->getId()); $item->setFeedId($feed->getId());
} elseif(array_key_exists($url, $feedsDict)) { } elseif (array_key_exists($url, $feedsDict)) {
$feed = $feedsDict[$url]; $feed = $feedsDict[$url];
$item->setFeedId($feed->getId()); $item->setFeedId($feed->getId());
} else { } else {
@ -369,18 +380,20 @@ class FeedService extends Service
try { try {
// if item exists, copy the status // if item exists, copy the status
$existingItem = $this->itemMapper->findByGuidHash( $existingItem = $this->itemMapper->findByGuidHash(
$item->getGuidHash(), $feed->getId(), $userId $item->getGuidHash(),
$feed->getId(),
$userId
); );
$existingItem->setStatus($item->getStatus()); $existingItem->setStatus($item->getStatus());
$this->itemMapper->update($existingItem); $this->itemMapper->update($existingItem);
} catch(DoesNotExistException $ex){ } catch (DoesNotExistException $ex) {
$item->setBody($this->purifier->purify($item->getBody())); $item->setBody($this->purifier->purify($item->getBody()));
$item->generateSearchIndex(); $item->generateSearchIndex();
$this->itemMapper->insert($item); $this->itemMapper->insert($item);
} }
} }
if($createdFeed) { if ($createdFeed) {
return $this->feedMapper->findByUrlHash($urlHash, $userId); return $this->feedMapper->findByUrlHash($urlHash, $userId);
} }
@ -395,7 +408,7 @@ class FeedService extends Service
* @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 feed does not exist * @throws ServiceNotFoundException when feed does not exist
*/ */
public function markDeleted($feedId, $userId) public function markDeleted($feedId, $userId)
{ {
$feed = $this->find($feedId, $userId); $feed = $this->find($feedId, $userId);
$feed->setDeletedAt($this->timeFactory->getTime()); $feed->setDeletedAt($this->timeFactory->getTime());
@ -410,7 +423,7 @@ class FeedService extends Service
* @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 feed does not exist * @throws ServiceNotFoundException when feed does not exist
*/ */
public function unmarkDeleted($feedId, $userId) public function unmarkDeleted($feedId, $userId)
{ {
$feed = $this->find($feedId, $userId); $feed = $this->find($feedId, $userId);
$feed->setDeletedAt(0); $feed->setDeletedAt(0);
@ -426,7 +439,7 @@ class FeedService 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($userId = null, $useInterval = true)
{ {
$deleteOlderThan = null; $deleteOlderThan = null;
@ -449,7 +462,7 @@ class FeedService 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($userId)
{ {
$this->feedMapper->deleteUser($userId); $this->feedMapper->deleteUser($userId);
} }
@ -467,7 +480,7 @@ class FeedService extends Service
* ] * ]
* @throws ServiceNotFoundException if feed does not exist * @throws ServiceNotFoundException if feed does not exist
*/ */
public function patch($feedId, $userId, $diff=[]) public function patch($feedId, $userId, $diff = [])
{ {
$feed = $this->find($feedId, $userId); $feed = $this->find($feedId, $userId);
@ -487,5 +500,4 @@ class FeedService extends Service
return $this->feedMapper->update($feed); return $this->feedMapper->update($feed);
} }
} }

View File

@ -19,7 +19,6 @@ use OCA\News\Db\FolderMapper;
use OCA\News\Config\Config; use OCA\News\Config\Config;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
class FolderService extends Service class FolderService extends Service
{ {
@ -28,7 +27,8 @@ class FolderService extends Service
private $autoPurgeMinimumInterval; private $autoPurgeMinimumInterval;
private $folderMapper; private $folderMapper;
public function __construct(FolderMapper $folderMapper, public function __construct(
FolderMapper $folderMapper,
IL10N $l10n, IL10N $l10n,
Time $timeFactory, Time $timeFactory,
Config $config Config $config
@ -47,7 +47,7 @@ class FolderService extends Service
* @param string $userId the name of the user * @param string $userId the name of the user
* @return array of folders * @return array of folders
*/ */
public function findAll($userId) public function findAll($userId)
{ {
return $this->folderMapper->findAllFromUser($userId); return $this->folderMapper->findAllFromUser($userId);
} }
@ -57,14 +57,13 @@ class FolderService extends Service
{ {
$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')
); );
} }
if(mb_strlen($folderName) === 0) { if (mb_strlen($folderName) === 0) {
throw new ServiceValidationException( throw new ServiceValidationException(
'Folder name can not be empty' 'Folder name can not be empty'
); );
@ -83,7 +82,7 @@ class FolderService extends Service
* @throws ServiceValidationException if the folder has invalid parameters * @throws ServiceValidationException if the folder has invalid parameters
* @return Folder the newly created folder * @return Folder the newly created folder
*/ */
public function create($folderName, $userId, $parentId=0) public function create($folderName, $userId, $parentId = 0)
{ {
$this->validateFolder($folderName, $userId); $this->validateFolder($folderName, $userId);
@ -135,7 +134,7 @@ class FolderService extends Service
* @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($folderId, $userId)
{ {
$folder = $this->find($folderId, $userId); $folder = $this->find($folderId, $userId);
$folder->setDeletedAt($this->timeFactory->getTime()); $folder->setDeletedAt($this->timeFactory->getTime());
@ -150,7 +149,7 @@ class FolderService extends Service
* @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($folderId, $userId)
{ {
$folder = $this->find($folderId, $userId); $folder = $this->find($folderId, $userId);
$folder->setDeletedAt(0); $folder->setDeletedAt(0);
@ -166,7 +165,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($userId = null, $useInterval = true)
{ {
$deleteOlderThan = null; $deleteOlderThan = null;
@ -188,10 +187,8 @@ 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($userId)
{ {
$this->folderMapper->deleteUser($userId); $this->folderMapper->deleteUser($userId);
} }
} }

View File

@ -22,7 +22,6 @@ use OCA\News\Db\FeedType;
use OCA\News\Config\Config; use OCA\News\Config\Config;
use OCA\News\Utility\Time; use OCA\News\Utility\Time;
class ItemService extends Service class ItemService extends Service
{ {
@ -31,7 +30,8 @@ class ItemService extends Service
private $itemMapper; private $itemMapper;
private $systemConfig; private $systemConfig;
public function __construct(ItemMapper $itemMapper, public function __construct(
ItemMapper $itemMapper,
Time $timeFactory, Time $timeFactory,
Config $config, Config $config,
IConfig $systemConfig IConfig $systemConfig
@ -58,19 +58,28 @@ class ItemService extends Service
*/ */
public function findAllNew($id, $type, $updatedSince, $showAll, $userId) public function findAllNew($id, $type, $updatedSince, $showAll, $userId)
{ {
switch($type){ switch ($type) {
case FeedType::FEED: case FeedType::FEED:
return $this->itemMapper->findAllNewFeed( return $this->itemMapper->findAllNewFeed(
$id, $updatedSince, $showAll, $userId $id,
); $updatedSince,
case FeedType::FOLDER: $showAll,
return $this->itemMapper->findAllNewFolder( $userId
$id, $updatedSince, $showAll, $userId );
); case FeedType::FOLDER:
default: return $this->itemMapper->findAllNewFolder(
return $this->itemMapper->findAllNew( $id,
$updatedSince, $type, $showAll, $userId $updatedSince,
); $showAll,
$userId
);
default:
return $this->itemMapper->findAllNew(
$updatedSince,
$type,
$showAll,
$userId
);
} }
} }
@ -90,24 +99,47 @@ class ItemService extends Service
* or body * or body
* @return array of items * @return array of items
*/ */
public function findAll($id, $type, $limit, $offset, $showAll, $oldestFirst, public function findAll(
$userId, $search=[] $id,
$type,
$limit,
$offset,
$showAll,
$oldestFirst,
$userId,
$search = []
) { ) {
switch($type){ switch ($type) {
case FeedType::FEED: case FeedType::FEED:
return $this->itemMapper->findAllFeed( return $this->itemMapper->findAllFeed(
$id, $limit, $offset, $showAll, $oldestFirst, $userId, $id,
$search $limit,
); $offset,
case FeedType::FOLDER: $showAll,
return $this->itemMapper->findAllFolder( $oldestFirst,
$id, $limit, $offset, $showAll, $oldestFirst, $userId, $userId,
$search $search
); );
default: case FeedType::FOLDER:
return $this->itemMapper->findAll( return $this->itemMapper->findAllFolder(
$limit, $offset, $type, $showAll, $oldestFirst, $userId, $search $id,
); $limit,
$offset,
$showAll,
$oldestFirst,
$userId,
$search
);
default:
return $this->itemMapper->findAll(
$limit,
$offset,
$type,
$showAll,
$oldestFirst,
$userId,
$search
);
} }
} }
@ -126,16 +158,18 @@ class ItemService extends Service
{ {
try { try {
/** /**
* @var Item $item * @var Item $item
*/ */
$item = $this->itemMapper->findByGuidHash( $item = $this->itemMapper->findByGuidHash(
$guidHash, $feedId, $userId $guidHash,
$feedId,
$userId
); );
$item->setStarred($isStarred); $item->setStarred($isStarred);
$this->itemMapper->update($item); $this->itemMapper->update($item);
} catch(DoesNotExistException $ex) { } catch (DoesNotExistException $ex) {
throw new ServiceNotFoundException($ex->getMessage()); throw new ServiceNotFoundException($ex->getMessage());
} }
} }
@ -155,7 +189,7 @@ class ItemService extends Service
try { try {
$lastModified = $this->timeFactory->getMicroTime(); $lastModified = $this->timeFactory->getMicroTime();
$this->itemMapper->readItem($itemId, $isRead, $lastModified, $userId); $this->itemMapper->readItem($itemId, $isRead, $lastModified, $userId);
} catch(DoesNotExistException $ex) { } catch (DoesNotExistException $ex) {
throw new ServiceNotFoundException($ex->getMessage()); throw new ServiceNotFoundException($ex->getMessage());
} }
} }
@ -189,7 +223,10 @@ class ItemService extends Service
{ {
$time = $this->timeFactory->getMicroTime(); $time = $this->timeFactory->getMicroTime();
$this->itemMapper->readFolder( $this->itemMapper->readFolder(
$folderId, $highestItemId, $time, $userId $folderId,
$highestItemId,
$time,
$userId
); );
} }
@ -232,11 +269,11 @@ class ItemService extends Service
* @throws ServiceNotFoundException if there is no newest item * @throws ServiceNotFoundException if there is no newest item
* @return int * @return int
*/ */
public function getNewestItemId($userId) public function getNewestItemId($userId)
{ {
try { try {
return $this->itemMapper->getNewestItemId($userId); return $this->itemMapper->getNewestItemId($userId);
} catch(DoesNotExistException $ex) { } catch (DoesNotExistException $ex) {
throw new ServiceNotFoundException($ex->getMessage()); throw new ServiceNotFoundException($ex->getMessage());
} }
} }
@ -258,7 +295,7 @@ class ItemService extends Service
* @param string $userId from which user the items should be taken * @param string $userId from which user the items should be taken
* @return array of items which are starred or unread * @return array of items which are starred or unread
*/ */
public function getUnreadOrStarred($userId) public function getUnreadOrStarred($userId)
{ {
return $this->itemMapper->findAllUnreadOrStarred($userId); return $this->itemMapper->findAllUnreadOrStarred($userId);
} }
@ -269,7 +306,7 @@ class ItemService 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($userId)
{ {
$this->itemMapper->deleteUser($userId); $this->itemMapper->deleteUser($userId);
} }
@ -278,9 +315,8 @@ class ItemService extends Service
/** /**
* Regenerates the search index for all items * Regenerates the search index for all items
*/ */
public function generateSearchIndices() public function generateSearchIndices()
{ {
$this->itemMapper->updateSearchIndices(); $this->itemMapper->updateSearchIndices();
} }
} }

View File

@ -18,7 +18,6 @@ use \OCP\AppFramework\Db\MultipleObjectsReturnedException;
use \OCA\News\Db\NewsMapper; use \OCA\News\Db\NewsMapper;
abstract class Service abstract class Service
{ {
@ -58,11 +57,10 @@ abstract class Service
{ {
try { try {
return $this->mapper->find($id, $userId); return $this->mapper->find($id, $userId);
} catch(DoesNotExistException $ex){ } catch (DoesNotExistException $ex) {
throw new ServiceNotFoundException($ex->getMessage()); throw new ServiceNotFoundException($ex->getMessage());
} catch(MultipleObjectsReturnedException $ex){ } catch (MultipleObjectsReturnedException $ex) {
throw new ServiceNotFoundException($ex->getMessage()); throw new ServiceNotFoundException($ex->getMessage());
} }
} }
} }

View File

@ -13,7 +13,6 @@
namespace OCA\News\Service; namespace OCA\News\Service;
class ServiceConflictException extends ServiceException class ServiceConflictException extends ServiceException
{ {
@ -26,5 +25,4 @@ class ServiceConflictException extends ServiceException
{ {
parent::__construct($msg); parent::__construct($msg);
} }
}
}

View File

@ -13,7 +13,6 @@
namespace OCA\News\Service; namespace OCA\News\Service;
class ServiceException extends \Exception class ServiceException extends \Exception
{ {
@ -26,5 +25,4 @@ class ServiceException extends \Exception
{ {
parent::__construct($msg); parent::__construct($msg);
} }
}
}

View File

@ -13,7 +13,6 @@
namespace OCA\News\Service; namespace OCA\News\Service;
class ServiceNotFoundException extends ServiceException class ServiceNotFoundException extends ServiceException
{ {
@ -26,5 +25,4 @@ class ServiceNotFoundException extends ServiceException
{ {
parent::__construct($msg); parent::__construct($msg);
} }
}
}

View File

@ -13,7 +13,6 @@
namespace OCA\News\Service; namespace OCA\News\Service;
class ServiceValidationException extends ServiceException class ServiceValidationException extends ServiceException
{ {
@ -26,5 +25,4 @@ class ServiceValidationException extends ServiceException
{ {
parent::__construct($msg); parent::__construct($msg);
} }
}
}

View File

@ -20,7 +20,6 @@ use OCP\IDBConnection;
use OCA\News\Config\Config; use OCA\News\Config\Config;
class StatusService class StatusService
{ {
@ -32,8 +31,11 @@ class StatusService
*/ */
private $connection; private $connection;
public function __construct(IConfig $settings, IDBConnection $connection, public function __construct(
Config $config, $AppName IConfig $settings,
IDBConnection $connection,
Config $config,
$AppName
) { ) {
$this->settings = $settings; $this->settings = $settings;
$this->config = $config; $this->config = $config;
@ -41,10 +43,11 @@ class StatusService
$this->connection = $connection; $this->connection = $connection;
} }
public function isProperlyConfigured() public function isProperlyConfigured()
{ {
$cronMode = $this->settings->getAppValue( $cronMode = $this->settings->getAppValue(
'core', 'backgroundjobs_mode' 'core',
'backgroundjobs_mode'
); );
$cronOff = !$this->config->getUseCronUpdates(); $cronOff = !$this->config->getUseCronUpdates();
@ -53,10 +56,11 @@ class StatusService
} }
public function getStatus() public function getStatus()
{ {
$version = $this->settings->getAppValue( $version = $this->settings->getAppValue(
$this->appName, 'installed_version' $this->appName,
'installed_version'
); );
return [ return [
@ -67,5 +71,4 @@ class StatusService
] ]
]; ];
} }
} }

View File

@ -11,12 +11,12 @@ class Admin implements ISettings
{ {
private $config; private $config;
public function __construct(Config $config) public function __construct(Config $config)
{ {
$this->config = $config; $this->config = $config;
} }
public function getForm() public function getForm()
{ {
$data = [ $data = [
'autoPurgeMinimumInterval' => 'autoPurgeMinimumInterval' =>
@ -31,12 +31,12 @@ class Admin implements ISettings
return new TemplateResponse('news', 'admin', $data, ''); return new TemplateResponse('news', 'admin', $data, '');
} }
public function getSection() public function getSection()
{ {
return 'news'; return 'news';
} }
public function getPriority() public function getPriority()
{ {
return 40; return 40;
} }

View File

@ -11,29 +11,29 @@ class Section implements IIconSection
private $l; private $l;
private $url; private $url;
public function __construct(IURLGenerator $url, IL10N $l) public function __construct(IURLGenerator $url, IL10N $l)
{ {
$this->url = $url; $this->url = $url;
$this->l = $l; $this->l = $l;
} }
public function getID() public function getID()
{ {
return 'news'; return 'news';
} }
public function getName() public function getName()
{ {
return $this->l->t('News'); return $this->l->t('News');
} }
public function getPriority() public function getPriority()
{ {
return 10; return 10;
} }
public function getIcon() public function getIcon()
{ {
return $this->url->imagePath('news', 'app-dark.svg'); return $this->url->imagePath('news', 'app-dark.svg');
} }
} }

View File

@ -48,7 +48,7 @@ class OPMLExporter
$body = $document->createElement('body'); $body = $document->createElement('body');
// feeds with folders // feeds with folders
foreach($folders as $folder) { foreach ($folders as $folder) {
$folderOutline = $document->createElement('outline'); $folderOutline = $document->createElement('outline');
$folderOutline->setAttribute('title', $folder->getName()); $folderOutline->setAttribute('title', $folder->getName());
$folderOutline->setAttribute('text', $folder->getName()); $folderOutline->setAttribute('text', $folder->getName());
@ -94,7 +94,4 @@ class OPMLExporter
$feedOutline->setAttribute('htmlUrl', $feed->getLink()); $feedOutline->setAttribute('htmlUrl', $feed->getLink());
return $feedOutline; return $feedOutline;
} }
} }

View File

@ -22,7 +22,7 @@ class PicoFeedClientFactory
private $config; private $config;
public function __construct(Config $config) public function __construct(Config $config)
{ {
$this->config = $config; $this->config = $config;
} }
@ -33,12 +33,10 @@ class PicoFeedClientFactory
* *
* @return \PicoFeed\Client instance * @return \PicoFeed\Client instance
*/ */
public function build() public function build()
{ {
$client = Client::getInstance(); $client = Client::getInstance();
$client->setConfig($this->config); $client->setConfig($this->config);
return $client; return $client;
} }
}
}

View File

@ -22,7 +22,7 @@ class PicoFeedFaviconFactory
private $config; private $config;
public function __construct(Config $config) public function __construct(Config $config)
{ {
$this->config = $config; $this->config = $config;
} }
@ -33,10 +33,8 @@ class PicoFeedFaviconFactory
* *
* @return \PicoFeed\Favicon instance * @return \PicoFeed\Favicon instance
*/ */
public function build() public function build()
{ {
return new Favicon($this->config); return new Favicon($this->config);
} }
}
}

View File

@ -16,13 +16,12 @@ namespace OCA\News\Utility;
use \OCP\IConfig; use \OCP\IConfig;
class ProxyConfigParser class ProxyConfigParser
{ {
private $config; private $config;
public function __construct(IConfig $config) public function __construct(IConfig $config)
{ {
$this->config = $config; $this->config = $config;
} }
@ -33,7 +32,7 @@ class ProxyConfigParser
* *
* @return array * @return array
*/ */
public function parse() public function parse()
{ {
$proxy = $this->config->getSystemValue('proxy'); $proxy = $this->config->getSystemValue('proxy');
$userpasswd = $this->config->getSystemValue('proxyuserpwd'); $userpasswd = $this->config->getSystemValue('proxyuserpwd');
@ -64,6 +63,4 @@ class ProxyConfigParser
return $result; return $result;
} }
}
}

View File

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

View File

@ -18,7 +18,6 @@ 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;
class Updater class Updater
{ {
@ -27,7 +26,8 @@ class Updater
private $feedService; private $feedService;
private $itemService; private $itemService;
public function __construct(FolderService $folderService, public function __construct(
FolderService $folderService,
FeedService $feedService, FeedService $feedService,
ItemService $itemService ItemService $itemService
) { ) {
@ -37,23 +37,21 @@ class Updater
} }
public function beforeUpdate() public function beforeUpdate()
{ {
$this->folderService->purgeDeleted(); $this->folderService->purgeDeleted();
$this->feedService->purgeDeleted(); $this->feedService->purgeDeleted();
} }
public function update() public function update()
{ {
$this->feedService->updateAll(); $this->feedService->updateAll();
} }
public function afterUpdate() public function afterUpdate()
{ {
$this->itemService->autoPurgeOld(); $this->itemService->autoPurgeOld();
} }
}
}