From bc01761221384c0bbac0297d38e85bcaa6286a9a Mon Sep 17 00:00:00 2001 From: Sean Molenaar Date: Mon, 28 Sep 2020 21:07:24 +0200 Subject: Fix repair step and test it Signed-off-by: Sean Molenaar --- lib/AppInfo/Application.php | 146 +++++++++++----------------- lib/Config/DependencyException.php | 29 ------ lib/Config/FetcherConfig.php | 104 +++++--------------- lib/Config/LegacyConfig.php | 5 +- lib/Controller/FeedApiController.php | 2 +- lib/Controller/FeedController.php | 2 +- lib/Controller/FolderApiController.php | 2 +- lib/Controller/FolderController.php | 2 +- lib/Controller/ItemApiController.php | 2 +- lib/Controller/ItemController.php | 2 +- lib/Controller/JSONHttpError.php | 29 ------ lib/Controller/JSONHttpErrorTrait.php | 27 +++++ lib/Controller/PageController.php | 2 +- lib/Explore/RecommendedSites.php | 11 ++- lib/Fetcher/Client/LegacyGuzzleClient.php | 66 ------------- lib/Fetcher/Client/LegacyGuzzleResponse.php | 86 ---------------- lib/Fetcher/FeedFetcher.php | 22 +++-- lib/Fetcher/Fetcher.php | 24 ++--- lib/Fetcher/IFeedFetcher.php | 10 +- lib/Fetcher/YoutubeFetcher.php | 19 +++- lib/Hooks/User.php | 36 ------- lib/Hooks/UserDeleteHook.php | 44 +++++++++ lib/Migration/MigrateConfig.php | 7 ++ 23 files changed, 229 insertions(+), 450 deletions(-) delete mode 100644 lib/Config/DependencyException.php delete mode 100644 lib/Controller/JSONHttpError.php create mode 100644 lib/Controller/JSONHttpErrorTrait.php delete mode 100644 lib/Fetcher/Client/LegacyGuzzleClient.php delete mode 100644 lib/Fetcher/Client/LegacyGuzzleResponse.php delete mode 100644 lib/Hooks/User.php create mode 100644 lib/Hooks/UserDeleteHook.php (limited to 'lib') diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 005a264a4..f6a5dcdd2 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -18,19 +18,13 @@ use HTMLPurifier; use HTMLPurifier_Config; use Favicon\Favicon; -use OC\Encryption\Update; use OCA\News\Config\LegacyConfig; use OCA\News\Config\FetcherConfig; -use OCA\News\Db\FolderMapper; -use OCA\News\Service\FeedService; -use OCA\News\Service\FolderService; -use OCA\News\Service\ItemService; -use OCA\News\Utility\PsrLogger; - -use OCA\News\Utility\Updater; -use OCP\IContainer; -use OCP\IConfig; -use OCP\ILogger; +use OCA\News\Hooks\UserDeleteHook; + +use OCP\AppFramework\Bootstrap\IBootContext; +use OCP\AppFramework\Bootstrap\IBootstrap; +use OCP\AppFramework\Bootstrap\IRegistrationContext; use OCP\ITempManager; use OCP\AppFramework\App; use OCP\Files\IRootFolder; @@ -42,7 +36,8 @@ use OCA\News\Db\ItemMapper; use OCA\News\Fetcher\FeedFetcher; use OCA\News\Fetcher\Fetcher; use OCA\News\Fetcher\YoutubeFetcher; -use OCA\News\Scraper\Scraper; +use OCP\User\Events\BeforeUserDeletedEvent; +use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; /** @@ -50,7 +45,7 @@ use Psr\Log\LoggerInterface; * * @package OCA\News\AppInfo */ -class Application extends App +class Application extends App implements IBootstrap { /** @@ -71,64 +66,38 @@ class Application extends App 'updateInterval' => 3600, ]; - /** - * Application constructor. - * - * @param array $urlParams Parameters - */ public function __construct(array $urlParams = []) { parent::__construct(self::NAME, $urlParams); + } - $container = $this->getContainer(); - - // files - $container->registerService('checksums', function () { - return file_get_contents(__DIR__ . '/checksum.json'); - }); - $container->registerService('info', function () { - return file_get_contents(__DIR__ . '/../../appinfo/info.xml'); - }); + public function register(IRegistrationContext $context): void + { + @include_once __DIR__ . '/../../vendor/autoload.php'; - // parameters - $container->registerParameter('exploreDir', __DIR__ . '/../Explore/feeds'); - $container->registerParameter('configFile', 'config.ini'); + $context->registerService(Fetcher::class, function (ContainerInterface $container): Fetcher { + $fetcher = new Fetcher(); - // factories - $container->registerService(ItemMapper::class, function (IContainer $c): ItemMapper { - return $c->query(MapperFactory::class)->build(); + // register fetchers in order, the most generic fetcher should be + // the last one + $fetcher->registerFetcher($container->get(YoutubeFetcher::class)); + $fetcher->registerFetcher($container->get(FeedFetcher::class)); + return $fetcher; }); - /** - * Core - */ - $container->registerService('LoggerParameters', function (IContainer $c): array { - return ['app' => $c->query('AppName')]; - }); + $context->registerEventListener(BeforeUserDeletedEvent::class, UserDeleteHook::class); - $container->registerService('ConfigView', function (IContainer $c): ?Node { - /** @var IRootFolder $fs */ - $fs = $c->query(IRootFolder::class); - $path = 'news/config'; - if ($fs->nodeExists($path)) { - return $fs->get($path); - } else { - return null; - } - }); + // parameters + $context->registerParameter('exploreDir', __DIR__ . '/../Explore/feeds'); + $context->registerParameter('configFile', 'config.ini'); - $container->registerService(LegacyConfig::class, function (IContainer $c): LegacyConfig { - $config = new LegacyConfig( - $c->query('ConfigView'), - $c->query(LoggerInterface::class), - $c->query('LoggerParameters') - ); - $config->read($c->query('configFile'), false); - return $config; + // factories + $context->registerService(ItemMapper::class, function (ContainerInterface $c): ItemMapper { + return $c->get(MapperFactory::class)->build(); }); - $container->registerService(HTMLPurifier::class, function (IContainer $c): HTMLPurifier { - $directory = $c->query(IConfig::class)->getSystemValue('datadirectory') . '/news/cache/purifier'; + $context->registerService(HTMLPurifier::class, function (ContainerInterface $c): HTMLPurifier { + $directory = $c->get(ITempManager::class)->getTempBaseDir() . '/news/cache/purifier'; if (!is_dir($directory)) { mkdir($directory, 0770, true); @@ -164,47 +133,42 @@ class Application extends App return new HTMLPurifier($config); }); - /** - * Fetchers - */ - $container->registerService(FetcherConfig::class, function (IContainer $c): FetcherConfig { - $fConfig = new FetcherConfig(); - $fConfig->setConfig($c->query(IConfig::class)) - ->setProxy($c->query(IConfig::class)); - - return $fConfig; - }); - - $container->registerService(FeedIo::class, function (IContainer $c): FeedIo { - $config = $c->query(FetcherConfig::class); - return new FeedIo($config->getClient(), $c->query(LoggerInterface::class)); + $context->registerService(FeedIo::class, function (ContainerInterface $c): FeedIo { + $config = $c->get(FetcherConfig::class); + return new FeedIo($config->getClient(), $c->get(LoggerInterface::class)); }); - $container->registerService(Favicon::class, function (IContainer $c): Favicon { + $context->registerService(Favicon::class, function (ContainerInterface $c): Favicon { $favicon = new Favicon(); - $tempManager = $c->query(ITempManager::class); - $settings = ['dir' => $tempManager->getTempBaseDir()]; - $favicon->cache($settings); + $favicon->cache(['dir' => $c->get(ITempManager::class)->getTempBaseDir()]); return $favicon; }); - $container->registerService(Fetcher::class, function (IContainer $c): Fetcher { - $fetcher = new Fetcher(); - - // register fetchers in order, the most generic fetcher should be - // the last one - $fetcher->registerFetcher($c->query(YoutubeFetcher::class)); - $fetcher->registerFetcher($c->query(FeedFetcher::class)); - return $fetcher; + //TODO: Remove code after 15.1 + $context->registerService('ConfigView', function (ContainerInterface $c): ?Node { + /** @var IRootFolder $fs */ + $fs = $c->get(IRootFolder::class); + $path = 'news/config'; + if ($fs->nodeExists($path)) { + return $fs->get($path); + } else { + return null; + } }); - /** - * Scrapers - */ - $container->registerService(Scraper::class, function (IContainer $c): Scraper { - return new Scraper( - $c->query(LoggerInterface::class) + //TODO: Remove code after 15.1 + $context->registerService(LegacyConfig::class, function (ContainerInterface $c): LegacyConfig { + $config = new LegacyConfig( + $c->get('ConfigView'), + $c->get(LoggerInterface::class) ); + $config->read($c->get('configFile'), false); + return $config; }); } + + public function boot(IBootContext $context): void + { + //NO-OP + } } diff --git a/lib/Config/DependencyException.php b/lib/Config/DependencyException.php deleted file mode 100644 index 6f9d21be6..000000000 --- a/lib/Config/DependencyException.php +++ /dev/null @@ -1,29 +0,0 @@ - - * @author Bernhard Posselt - * @copyright 2012 Alessandro Cosentino - * @copyright 2012-2014 Bernhard Posselt - */ - -namespace OCA\News\Config; - -class DependencyException extends \Exception -{ - - - /** - * Constructor - * - * @param string $msg the error message - */ - public function __construct($msg) - { - parent::__construct($msg); - } -} diff --git a/lib/Config/FetcherConfig.php b/lib/Config/FetcherConfig.php index 1e9b7941e..4966f5b40 100644 --- a/lib/Config/FetcherConfig.php +++ b/lib/Config/FetcherConfig.php @@ -60,71 +60,11 @@ class FetcherConfig 'text/xml;q=0.4, */*;q=0.2'; /** - * Configure a guzzle client - * - * @return ClientInterface Legacy client to guzzle. - */ - public function getClient() - { - if (!class_exists('GuzzleHttp\Collection')) { - return new FeedIoClient($this->getConfig()); - } - - return new LegacyGuzzleClient($this->getOldConfig()); - } - /** - * Get configuration for modern guzzle. - * @return Client Guzzle client. - */ - private function getConfig() - { - $config = [ - 'timeout' => $this->client_timeout, - 'headers' => ['User-Agent' => static::DEFAULT_USER_AGENT, 'Accept' => static::DEFAULT_ACCEPT], - ]; - - if (!empty($this->proxy)) { - $config['proxy'] = $this->proxy; - } - if (!empty($this->redirects)) { - $config['redirect.max'] = $this->redirects; - } - - return new Client($config); - } - - /** - * Get configuration for old guzzle. - * @return Client Guzzle client. - */ - private function getOldConfig() - { - $config = [ - 'request.options' => [ - 'timeout' => $this->client_timeout, - 'headers' => ['User-Agent' => static::DEFAULT_USER_AGENT], - ], - ]; - - if (!empty($this->proxy)) { - $config['request.options']['proxy'] = $this->proxy; - } - - if (!empty($this->redirects)) { - $config['request.options']['redirect.max'] = $this->redirects; - } - - return new Client($config); - } - - /** - * Set settings for config. - * - * @param IConfig $config The shared configuration + * FetcherConfig constructor. * - * @return self + * @param IConfig $config */ - public function setConfig(IConfig $config) + public function __construct(IConfig $config) { $this->client_timeout = $config->getAppValue( Application::NAME, @@ -137,27 +77,14 @@ class FetcherConfig Application::DEFAULT_SETTINGS['maxRedirects'] ); - return $this; - } - - /** - * Set the proxy - * - * @param IConfig $config Nextcloud config. - * - * @return self - */ - public function setProxy(IConfig $config) - { $proxy = $config->getSystemValue('proxy', null); - $creds = $config->getSystemValue('proxyuserpwd', null); - if (is_null($proxy)) { return $this; } $url = new \Net_URL2($proxy); + $creds = $config->getSystemValue('proxyuserpwd', null); if ($creds) { $auth = explode(':', $creds, 2); $url->setUserinfo($auth[0], $auth[1]); @@ -167,4 +94,27 @@ class FetcherConfig return $this; } + + /** + * Configure a guzzle client + * + * @return ClientInterface Legacy client to guzzle. + */ + public function getClient() + { + $config = [ + 'timeout' => $this->client_timeout, + 'headers' => ['User-Agent' => static::DEFAULT_USER_AGENT, 'Accept' => static::DEFAULT_ACCEPT], + ]; + + if (!empty($this->proxy)) { + $config['proxy'] = $this->proxy; + } + if (!empty($this->redirects)) { + $config['redirect.max'] = $this->redirects; + } + + $client = new Client($config); + return new FeedIoClient($client); + } } diff --git a/lib/Config/LegacyConfig.php b/lib/Config/LegacyConfig.php index 71e19acfa..370638843 100644 --- a/lib/Config/LegacyConfig.php +++ b/lib/Config/LegacyConfig.php @@ -39,8 +39,7 @@ class LegacyConfig public function __construct( ?Folder $fileSystem, - LoggerInterface $logger, - $LoggerParameters + LoggerInterface $logger ) { $this->fileSystem = $fileSystem; $this->autoPurgeMinimumInterval = 60; @@ -51,7 +50,7 @@ class LegacyConfig $this->useCronUpdates = true; $this->logger = $logger; $this->exploreUrl = ''; - $this->loggerParams = $LoggerParameters; + $this->loggerParams = ['app' => Application::NAME]; $this->updateInterval = 3600; } diff --git a/lib/Controller/FeedApiController.php b/lib/Controller/FeedApiController.php index f2b77c72b..c0b4f1a56 100644 --- a/lib/Controller/FeedApiController.php +++ b/lib/Controller/FeedApiController.php @@ -29,7 +29,7 @@ use Psr\Log\LoggerInterface; class FeedApiController extends ApiController { - use JSONHttpError; + use JSONHttpErrorTrait; /** * @var ItemService diff --git a/lib/Controller/FeedController.php b/lib/Controller/FeedController.php index 40aef909a..d0c25d55b 100644 --- a/lib/Controller/FeedController.php +++ b/lib/Controller/FeedController.php @@ -27,7 +27,7 @@ use OCA\News\Db\FeedType; class FeedController extends Controller { - use JSONHttpError; + use JSONHttpErrorTrait; private $feedService; private $folderService; diff --git a/lib/Controller/FolderApiController.php b/lib/Controller/FolderApiController.php index 3bafd81a0..ff61f3300 100644 --- a/lib/Controller/FolderApiController.php +++ b/lib/Controller/FolderApiController.php @@ -27,7 +27,7 @@ use \OCA\News\Service\Exceptions\ServiceValidationException; class FolderApiController extends ApiController { - use JSONHttpError; + use JSONHttpErrorTrait; private $folderService; private $itemService; diff --git a/lib/Controller/FolderController.php b/lib/Controller/FolderController.php index 22baf8db6..38c580ff0 100644 --- a/lib/Controller/FolderController.php +++ b/lib/Controller/FolderController.php @@ -26,7 +26,7 @@ use \OCA\News\Service\Exceptions\ServiceValidationException; class FolderController extends Controller { - use JSONHttpError; + use JSONHttpErrorTrait; private $folderService; private $feedService; diff --git a/lib/Controller/ItemApiController.php b/lib/Controller/ItemApiController.php index d5b1de680..dac2b0a5f 100644 --- a/lib/Controller/ItemApiController.php +++ b/lib/Controller/ItemApiController.php @@ -24,7 +24,7 @@ use \OCA\News\Service\Exceptions\ServiceNotFoundException; class ItemApiController extends ApiController { - use JSONHttpError; + use JSONHttpErrorTrait; private $itemService; private $serializer; diff --git a/lib/Controller/ItemController.php b/lib/Controller/ItemController.php index 658e92883..95a13ee21 100644 --- a/lib/Controller/ItemController.php +++ b/lib/Controller/ItemController.php @@ -25,7 +25,7 @@ use \OCA\News\Service\FeedService; class ItemController extends Controller { - use JSONHttpError; + use JSONHttpErrorTrait; private $itemService; private $feedService; diff --git a/lib/Controller/JSONHttpError.php b/lib/Controller/JSONHttpError.php deleted file mode 100644 index 6a66f9c29..000000000 --- a/lib/Controller/JSONHttpError.php +++ /dev/null @@ -1,29 +0,0 @@ - - * @copyright Bernhard Posselt 2014 - */ - -namespace OCA\News\Controller; - -use \OCP\AppFramework\Http\JSONResponse; - -trait JSONHttpError -{ - - - /** - * @param \Exception $exception The exception to report - * @param int $code The http error code - * @return JSONResponse - */ - public function error(\Exception $exception, $code) - { - return new JSONResponse(['message' => $exception->getMessage()], $code); - } -} diff --git a/lib/Controller/JSONHttpErrorTrait.php b/lib/Controller/JSONHttpErrorTrait.php new file mode 100644 index 000000000..785f3f02a --- /dev/null +++ b/lib/Controller/JSONHttpErrorTrait.php @@ -0,0 +1,27 @@ + + * @copyright Bernhard Posselt 2014 + */ + +namespace OCA\News\Controller; + +use \OCP\AppFramework\Http\JSONResponse; + +trait JSONHttpErrorTrait +{ + /** + * @param \Exception $exception The exception to report + * @param int $code The http error code + * @return JSONResponse + */ + public function error(\Exception $exception, $code) + { + return new JSONResponse(['message' => $exception->getMessage()], $code); + } +} diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index d88f8181d..ffcf2e62d 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -31,7 +31,7 @@ use OCA\News\Db\FeedType; class PageController extends Controller { - use JSONHttpError; + use JSONHttpErrorTrait; /** * @var IConfig diff --git a/lib/Explore/RecommendedSites.php b/lib/Explore/RecommendedSites.php index 504d63497..38fa510da 100644 --- a/lib/Explore/RecommendedSites.php +++ b/lib/Explore/RecommendedSites.php @@ -22,13 +22,20 @@ class RecommendedSites * @param string $exploreDir the absolute path to where the recommendation * config files lie without a trailing slash */ - public function __construct($exploreDir) + public function __construct(string $exploreDir) { $this->directory = $exploreDir; } - public function forLanguage($languageCode) + /** + * @param string $languageCode + * + * @return array + * + * @throws RecommendedSiteNotFoundException + */ + public function forLanguage(string $languageCode) { $file = $this->directory . '/feeds.' . $languageCode . '.json'; diff --git a/lib/Fetcher/Client/LegacyGuzzleClient.php b/lib/Fetcher/Client/LegacyGuzzleClient.php deleted file mode 100644 index 59bbc9dc4..000000000 --- a/lib/Fetcher/Client/LegacyGuzzleClient.php +++ /dev/null @@ -1,66 +0,0 @@ - - * @copyright 2018 Sean Molenaar - */ - -namespace OCA\News\Fetcher\Client; - -use FeedIo\Adapter\ClientInterface as FeedIoClientInterface; -use FeedIo\Adapter\ResponseInterface; -use FeedIo\Adapter\NotFoundException; -use FeedIo\Adapter\ServerErrorException; -use Guzzle\Service\ClientInterface; -use GuzzleHttp\Exception\BadResponseException; - -/** - * Guzzle dependent HTTP client - */ -class LegacyGuzzleClient implements FeedIoClientInterface -{ - /** - * @var ClientInterface - */ - protected $guzzleClient; - - /** - * @param ClientInterface $guzzleClient - */ - public function __construct(ClientInterface $guzzleClient) - { - $this->guzzleClient = $guzzleClient; - } - - /** - * @param string $url - * @param \DateTime $modifiedSince - * @throws \FeedIo\Adapter\NotFoundException - * @throws \FeedIo\Adapter\ServerErrorException - * @return \FeedIo\Adapter\ResponseInterface - */ - public function getResponse(string $url, \DateTime $modifiedSince) : ResponseInterface - { - $modifiedSince->setTimezone(new \DateTimeZone('GMT')); - try { - $options = [ - 'headers' => [ - 'If-Modified-Since' => $modifiedSince->format('D, d M Y H:i:s e') - ] - ]; - - return new LegacyGuzzleResponse($this->guzzleClient->get($url, $options)); - } catch (BadResponseException $e) { - switch ((int) $e->getResponse()->getStatusCode()) { - case 404: - throw new NotFoundException($e->getMessage()); - default: - throw new ServerErrorException($e->getMessage()); - } - } - } -} diff --git a/lib/Fetcher/Client/LegacyGuzzleResponse.php b/lib/Fetcher/Client/LegacyGuzzleResponse.php deleted file mode 100644 index f8d6d7601..000000000 --- a/lib/Fetcher/Client/LegacyGuzzleResponse.php +++ /dev/null @@ -1,86 +0,0 @@ - - * @copyright 2018 Sean Molenaar - */ - -namespace OCA\News\Fetcher\Client; - -use FeedIo\Adapter\ResponseInterface; -use GuzzleHttp\Message\ResponseInterface as GuzzleResponseInterface; - -/** - * Guzzle dependent HTTP Response - */ -class LegacyGuzzleResponse implements ResponseInterface -{ - const HTTP_LAST_MODIFIED = 'Last-Modified'; - - /** - * @var \GuzzleHttp\Message\ResponseInterface - */ - protected $response; - - /** - * @param \GuzzleHttp\Message\ResponseInterface - */ - public function __construct(GuzzleResponseInterface $psrResponse) - { - $this->response = $psrResponse; - } - - /** - * @return boolean - */ - public function isModified() : bool - { - return $this->response->getStatusCode() !== 304 && $this->response->getBody()->getSize() > 0; - } - - /** - * @return \Psr\Http\Message\StreamInterface - */ - public function getBody() : ? string - { - return $this->response->getBody(); - } - - /** - * @return \DateTime|null - */ - public function getLastModified() : ?\DateTime - { - if ($this->response->hasHeader(static::HTTP_LAST_MODIFIED)) { - $lastModified = \DateTime::createFromFormat( - 'D, d M Y H:i:s e', - $this->getHeader(static::HTTP_LAST_MODIFIED) - ); - - return false === $lastModified ? null : $lastModified; - } - - return null; - } - - /** - * @return array - */ - public function getHeaders() : iterable - { - return $this->response->getHeaders(); - } - - /** - * @param string $name - * @return string[] - */ - public function getHeader(string $name) : iterable - { - return current($this->response->getHeader($name)); - } -} diff --git a/lib/Fetcher/FeedFetcher.php b/lib/Fetcher/FeedFetcher.php index 4e93424ba..5a84e2170 100755 --- a/lib/Fetcher/FeedFetcher.php +++ b/lib/Fetcher/FeedFetcher.php @@ -75,8 +75,14 @@ class FeedFetcher implements IFeedFetcher * * @inheritdoc */ - public function fetch(string $url, bool $favicon, $lastModified, bool $fullTextEnabled, $user, $password): array - { + public function fetch( + string $url, + bool $favicon, + ?string $lastModified, + bool $fullTextEnabled, + ?string $user, + ?string $password + ): array { $url2 = new Net_URL2($url); if (!empty($user) && !empty(trim($user))) { $url2->setUserinfo(urlencode($user), urlencode($password)); @@ -148,7 +154,7 @@ class FeedFetcher implements IFeedFetcher * * @return string */ - private function decodeTwice($string): string + private function decodeTwice(string $string): string { return html_entity_decode( html_entity_decode( @@ -195,12 +201,12 @@ class FeedFetcher implements IFeedFetcher * Build an item based on a feed. * * @param ItemInterface $parsedItem The item to use - * @param string $body Text of the item, if not provided use description from $parsedItem + * @param string|null $body Text of the item, if not provided use description from $parsedItem * @param bool $RTL True if the feed is RTL (Right-to-left) * * @return Item */ - protected function buildItem(ItemInterface $parsedItem, string $body = null, bool $RTL = false): Item + protected function buildItem(ItemInterface $parsedItem, ?string $body = null, bool $RTL = false): Item { $item = new Item(); $item->setUnread(true); @@ -208,18 +214,18 @@ class FeedFetcher implements IFeedFetcher $item->setGuid($parsedItem->getPublicId()); $item->setGuidHash(md5($item->getGuid())); - $lastmodified = $parsedItem->getLastModified() ?? new DateTime(); + $lastModified = $parsedItem->getLastModified() ?? new DateTime(); if ($parsedItem->getValue('pubDate') !== null) { $pubDT = new DateTime($parsedItem->getValue('pubDate')); } elseif ($parsedItem->getValue('published') !== null) { $pubDT = new DateTime($parsedItem->getValue('published')); } else { - $pubDT = $lastmodified; + $pubDT = $lastModified; } $item->setPubDate($pubDT->getTimestamp()); - $item->setLastModified($lastmodified->getTimestamp()); + $item->setLastModified($lastModified->getTimestamp()); $item->setRtl($RTL); // unescape content because angularjs helps against XSS diff --git a/lib/Fetcher/Fetcher.php b/lib/Fetcher/Fetcher.php index f52141dda..955875084 100644 --- a/lib/Fetcher/Fetcher.php +++ b/lib/Fetcher/Fetcher.php @@ -43,25 +43,25 @@ class Fetcher /** * Fetch a feed from remote * - * @param string $url remote url of the feed - * @param boolean $getFavicon if the favicon should also be fetched, defaults to true - * @param string $lastModified a last modified value from an http header defaults to false. + * @param string $url remote url of the feed + * @param boolean $getFavicon if the favicon should also be fetched, defaults to true + * @param string|null $lastModified a last modified value from an http header defaults to false. * If lastModified matches the http header from the feed no results are fetched - * @param bool $fullTextEnabled If true use a scraper to download the full article - * @param string $user if given, basic auth is set for this feed - * @param string $password if given, basic auth is set for this feed. Ignored if user is empty + * @param bool $fullTextEnabled If true use a scraper to download the full article + * @param string|null $user if given, basic auth is set for this feed + * @param string|null $password if given, basic auth is set for this feed. Ignored if user is empty * * @throws ReadErrorException if FeedIO fails * @return array an array containing the new feed and its items, first * element being the Feed and second element being an array of Items */ public function fetch( - $url, - $getFavicon = true, - $lastModified = null, - $fullTextEnabled = false, - $user = null, - $password = null + string $url, + bool $getFavicon = true, + ?string $lastModified = null, + bool $fullTextEnabled = false, + ?string $user = null, + ?string $password = null ) { foreach ($this->fetchers as $fetcher) { if (!$fetcher->canHandle($url)) { diff --git a/lib/Fetcher/IFeedFetcher.php b/lib/Fetcher/IFeedFetcher.php index ce44ec104..aaba9de67 100644 --- a/lib/Fetcher/IFeedFetcher.php +++ b/lib/Fetcher/IFeedFetcher.php @@ -31,9 +31,17 @@ interface IFeedFetcher * * @return array an array containing the new feed and its items, first * element being the Feed and second element being an array of Items + * * @throws ReadErrorException if the Feed-IO fetcher encounters a problem */ - public function fetch(string $url, bool $favicon, $lastModified, bool $fullTextEnabled, $user, $password): array; + public function fetch( + string $url, + bool $favicon, + ?string $lastModified, + bool $fullTextEnabled, + ?string $user, + ?string $password + ): array; /** * Can a fetcher handle a feed. diff --git a/lib/Fetcher/YoutubeFetcher.php b/lib/Fetcher/YoutubeFetcher.php index 85aad5d59..67a4d5afa 100644 --- a/lib/Fetcher/YoutubeFetcher.php +++ b/lib/Fetcher/YoutubeFetcher.php @@ -22,7 +22,14 @@ class YoutubeFetcher implements IFeedFetcher } - private function buildUrl($url) + /** + * Build YouTube URL + * + * @param string $url + * + * @return string + */ + private function buildUrl(string $url) { $baseRegex = '%(?:https?://|//)?(?:www.)?youtube.com'; $playRegex = $baseRegex . '.*?list=([^&]*)%'; @@ -54,8 +61,14 @@ class YoutubeFetcher implements IFeedFetcher * * @inheritdoc */ - public function fetch(string $url, bool $favicon, $lastModified, bool $fullTextEnabled, $user, $password): array - { + public function fetch( + string $url, + bool $favicon, + ?string $lastModified, + bool $fullTextEnabled, + ?string $user, + ?string $password + ): array { $transformedUrl = $this->buildUrl($url); $result = $this->feedFetcher->fetch( diff --git a/lib/Hooks/User.php b/lib/Hooks/User.php deleted file mode 100644 index 1a494c5f2..000000000 --- a/lib/Hooks/User.php +++ /dev/null @@ -1,36 +0,0 @@ - - * @author Bernhard Posselt - * @copyright 2012 Alessandro Cosentino - * @copyright 2012-2014 Bernhard Posselt - */ - -namespace OCA\News\Hooks; - -use OCA\News\AppInfo\Application; -use OCA\News\Service\ItemService; -use OCA\News\Service\FeedService; -use OCA\News\Service\FolderService; - -class User -{ - - public static function deleteUser($params) - { - $userId = $params['uid']; - - $app = new Application(); - $container = $app->getContainer(); - - // order is important! - $container->query(ItemService::class)->deleteUser($userId); - $container->query(FeedService::class)->deleteUser($userId); - $container->query(FolderService::class)->deleteUser($userId); - } -} diff --git a/lib/Hooks/UserDeleteHook.php b/lib/Hooks/UserDeleteHook.php new file mode 100644 index 000000000..491f84fcb --- /dev/null +++ b/lib/Hooks/UserDeleteHook.php @@ -0,0 +1,44 @@ + + * @author Bernhard Posselt + * @copyright 2012 Alessandro Cosentino + * @copyright 2012-2014 Bernhard Posselt + */ + +namespace OCA\News\Hooks; + +use OCA\News\AppInfo\Application; +use OCA\News\Service\ItemService; +use OCA\News\Service\FeedService; +use OCA\News\Service\FolderService; +use OCP\EventDispatcher\Event; +use OCP\EventDispatcher\IEventListener; +use OCP\User\Events\BeforeUserDeletedEvent; + +class UserDeleteHook implements IEventListener +{ + + /** + * Handle user deletion + * + * @param BeforeUserDeletedEvent $event + */ + public function handle(Event $event): void + { + $userId = $event->getUser()->getUID(); + + $app = new Application(); + $container = $app->getContainer(); + + // order is important! + $container->get(ItemService::class)->deleteUser($userId); + $container->get(FeedService::class)->deleteUser($userId); + $container->get(FolderService::class)->deleteUser($userId); + } +} diff --git a/lib/Migration/MigrateConfig.php b/lib/Migration/MigrateConfig.php index b25fb8e75..e07760d64 100644 --- a/lib/Migration/MigrateConfig.php +++ b/lib/Migration/MigrateConfig.php @@ -52,7 +52,14 @@ class MigrateConfig implements IRepairStep return; } + $app_keys = $this->iConfig->getAppKeys(Application::NAME); foreach ($this->config as $key => $value) { + if (!isset(Application::DEFAULT_SETTINGS[$key])) { + continue; + } + if (in_array($key, $app_keys)) { + continue; + } $this->iConfig->setAppValue(Application::NAME, $key, $value); } } -- cgit v1.2.3