New administrator setting for deleting unread items automatically

Signed-off-by: Benjamin Brahmer <info@b-brahmer.de>
This commit is contained in:
Benjamin Brahmer 2022-10-08 14:08:55 +02:00
parent 64eda2fa61
commit b88e1a546a
8 changed files with 37 additions and 18 deletions

View File

@ -30,6 +30,7 @@
* [Koen Martens](mailto:gmc@sonologic.nl) * [Koen Martens](mailto:gmc@sonologic.nl)
* [Lukas Reschke](mailto:lukas@owncloud.com) * [Lukas Reschke](mailto:lukas@owncloud.com)
* [Tucker McKnight](mailto:tucker.mcknight@gmail.com) * [Tucker McKnight](mailto:tucker.mcknight@gmail.com)
* [Valdnet](mailto:47037905+Valdnet@users.noreply.github.com)
* [Bart Visscher](mailto:bartv@thisnet.nl) * [Bart Visscher](mailto:bartv@thisnet.nl)
* [Christian Elmer](mailto:christian@keinkurt.de) * [Christian Elmer](mailto:christian@keinkurt.de)
* [Nicolas Wendling](mailto:nicolas.wendling1011@gmail.com) * [Nicolas Wendling](mailto:nicolas.wendling1011@gmail.com)
@ -68,7 +69,6 @@
* [Nikita Chernyi](mailto:rakshazi@users.noreply.github.com) * [Nikita Chernyi](mailto:rakshazi@users.noreply.github.com)
* [Peter Hedlund](mailto:peter@peterandlinda.com) * [Peter Hedlund](mailto:peter@peterandlinda.com)
* [Simon Spannagel](mailto:simonspa@kth.se) * [Simon Spannagel](mailto:simonspa@kth.se)
* [Valdnet](mailto:47037905+Valdnet@users.noreply.github.com)
* [bbBowser](mailto:carspi@mail.de) * [bbBowser](mailto:carspi@mail.de)
* [benediktb](mailto:benedikt@blablub.de) * [benediktb](mailto:benedikt@blablub.de)
* [chylex](mailto:contact@chylex.com) * [chylex](mailto:contact@chylex.com)
@ -84,6 +84,7 @@
* [Alexander Grüßung](mailto:alexander@gruessung-online.de) * [Alexander Grüßung](mailto:alexander@gruessung-online.de)
* [Allan Nordhøy](mailto:epost@anotheragency.no) * [Allan Nordhøy](mailto:epost@anotheragency.no)
* [Alwaysin](mailto:adrien@demma.fr) * [Alwaysin](mailto:adrien@demma.fr)
* [Anderson Silva](mailto:UnderEu@users.noreply.github.com)
* [Andrea Boero](mailto:mail@tsumi.it) * [Andrea Boero](mailto:mail@tsumi.it)
* [Andreas Demmelbauer](mailto:git@notice.at) * [Andreas Demmelbauer](mailto:git@notice.at)
* [Artem Lavrukhin](mailto:lavryha4590@gmail.com) * [Artem Lavrukhin](mailto:lavryha4590@gmail.com)
@ -94,6 +95,7 @@
* [Bernhard Posselt](mailto:bernhard@desktop.localdomain) * [Bernhard Posselt](mailto:bernhard@desktop.localdomain)
* [Björn Bidar](mailto:bjorn.bidar@thaodan.de) * [Björn Bidar](mailto:bjorn.bidar@thaodan.de)
* [Candid Dauth](mailto:cdauth@cdauth.eu) * [Candid Dauth](mailto:cdauth@cdauth.eu)
* [Carl Schwan](mailto:carl@carlschwan.eu)
* [Carlos Silva](mailto:r3pek@r3pek.org) * [Carlos Silva](mailto:r3pek@r3pek.org)
* [Cesar Enrique Garcia Dabo](mailto:enrique@engarda.org) * [Cesar Enrique Garcia Dabo](mailto:enrique@engarda.org)
* [Chris Aumann](mailto:me@chr4.org) * [Chris Aumann](mailto:me@chr4.org)
@ -131,6 +133,7 @@
* [Martin Ferretti](mailto:ferrettimartin@protonmail.com) * [Martin Ferretti](mailto:ferrettimartin@protonmail.com)
* [Matthias](mailto:matthias.baier@mabaart.de) * [Matthias](mailto:matthias.baier@mabaart.de)
* [Matthias Blümel](mailto:user@inanna.local) * [Matthias Blümel](mailto:user@inanna.local)
* [Michael Chang](mailto:github@micbase.com)
* [Michael Grosser](mailto:github@stp-ip.net) * [Michael Grosser](mailto:github@stp-ip.net)
* [Michael Hamann](mailto:michael@content-space.de) * [Michael Hamann](mailto:michael@content-space.de)
* [Michael Holley](mailto:michaelwholley@gmail.com) * [Michael Holley](mailto:michaelwholley@gmail.com)

View File

@ -5,7 +5,7 @@ The format is mostly based on [Keep a Changelog](https://keepachangelog.com/en/1
# Unreleased # Unreleased
## [18.x.x] ## [18.x.x]
### Changed ### Changed
- New administrator setting for deleting unread items automatically (#1931)
### Fixed ### Fixed
# Releases # Releases

View File

@ -55,6 +55,7 @@ class Application extends App implements IBootstrap
public const DEFAULT_SETTINGS = [ public const DEFAULT_SETTINGS = [
'autoPurgeMinimumInterval' => 60, 'autoPurgeMinimumInterval' => 60,
'autoPurgeCount' => 200, 'autoPurgeCount' => 200,
'purgeUnread' => false,
'maxRedirects' => 10, 'maxRedirects' => 10,
'feedFetcherTimeout' => 60, 'feedFetcherTimeout' => 60,
'useCronUpdates' => true, 'useCronUpdates' => true,

View File

@ -185,13 +185,13 @@ class ItemMapperV2 extends NewsMapperV2
* Delete items from feed that are over the max item threshold * Delete items from feed that are over the max item threshold
* *
* @param int $threshold Deletion threshold * @param int $threshold Deletion threshold
* @param bool $removeUnread If unread articles should be removed * @param bool $purgeUnread If unread articles should be removed
* *
* @return int|null Removed items * @return int|null Removed items
* *
* @throws \Doctrine\DBAL\Exception * @throws \Doctrine\DBAL\Exception
*/ */
public function deleteOverThreshold(int $threshold, bool $removeUnread = false): ?int public function deleteOverThreshold(int $threshold, bool $purgeUnread): ?int
{ {
$feedQb = $this->db->getQueryBuilder(); $feedQb = $this->db->getQueryBuilder();
$feedQb->select('feed_id', $feedQb->func()->count('*', 'itemCount')) $feedQb->select('feed_id', $feedQb->func()->count('*', 'itemCount'))
@ -214,7 +214,7 @@ class ItemMapperV2 extends NewsMapperV2
->andWhere('starred = false') ->andWhere('starred = false')
->addOrderBy('id', 'DESC'); ->addOrderBy('id', 'DESC');
if ($removeUnread === false) { if ($purgeUnread === false) {
$rangeQuery->andWhere('unread = false'); $rangeQuery->andWhere('unread = false');
} }

View File

@ -145,12 +145,12 @@ class ItemServiceV2 extends Service
} }
/** /**
* @param int|null $threshold * @param int|null $threshold
* @param bool $removeUnread * @param bool|null $purgeUnread
* *
* @return int|null Amount of deleted items or null if not applicable * @return int|null Amount of deleted items or null if not applicable
*/ */
public function purgeOverThreshold(int $threshold = null, bool $removeUnread = false): ?int public function purgeOverThreshold(int $threshold = null, bool $purgeUnread = null): ?int
{ {
$threshold = (int) ($threshold ?? $this->config->getAppValue( $threshold = (int) ($threshold ?? $this->config->getAppValue(
Application::NAME, Application::NAME,
@ -158,11 +158,17 @@ class ItemServiceV2 extends Service
Application::DEFAULT_SETTINGS['autoPurgeCount'] Application::DEFAULT_SETTINGS['autoPurgeCount']
)); ));
$purgeUnread = (bool) ($purgeUnread ?? $this->config->getAppValue(
Application::NAME,
'purgeUnread',
Application::DEFAULT_SETTINGS['purgeUnread']
));
if ($threshold <= 0) { if ($threshold <= 0) {
return null; return null;
} }
return $this->mapper->deleteOverThreshold($threshold, $removeUnread); return $this->mapper->deleteOverThreshold($threshold, $purgeUnread);
} }
/** /**
* Mark an item as starred * Mark an item as starred

View File

@ -58,6 +58,6 @@ class UpdaterService
public function afterUpdate(): void public function afterUpdate(): void
{ {
$this->itemService->purgeOverThreshold(null); $this->itemService->purgeOverThreshold();
} }
} }

View File

@ -26,6 +26,13 @@ SPDX-Licence-Identifier: AGPL-3.0-or-later
@update:value="update('autoPurgeCount', autoPurgeCount)" /> @update:value="update('autoPurgeCount', autoPurgeCount)" />
<p><em>{{ t('news', 'Defines the maximum amount of articles that can be read per feed which will not be deleted by the cleanup job; if old articles reappear after being read, increase this value; negative values such as -1 will turn this feature off.') }}</em></p> <p><em>{{ t('news', 'Defines the maximum amount of articles that can be read per feed which will not be deleted by the cleanup job; if old articles reappear after being read, increase this value; negative values such as -1 will turn this feature off.') }}</em></p>
<NcCheckboxRadioSwitch type="switch"
:checked.sync="purgeUnread"
@update:checked="update('purgeUnread', purgeUnread)">
{{ t('news', 'Delete unread items automatically') }}
</NcCheckboxRadioSwitch>
<p><em>{{ t('news', 'Enable this if you also want to delete unread items. Consider increasing the value above.') }}</em></p>
<NcTextField :value.sync="maxRedirects" <NcTextField :value.sync="maxRedirects"
:label="t('news', 'Maximum redirects')" :label="t('news', 'Maximum redirects')"
:label-visible="true" :label-visible="true"
@ -90,6 +97,7 @@ export default {
useCronUpdates: loadState('news', 'useCronUpdates') === '1', useCronUpdates: loadState('news', 'useCronUpdates') === '1',
autoPurgeMinimumInterval: loadState('news', 'autoPurgeMinimumInterval'), autoPurgeMinimumInterval: loadState('news', 'autoPurgeMinimumInterval'),
autoPurgeCount: loadState('news', 'autoPurgeCount'), autoPurgeCount: loadState('news', 'autoPurgeCount'),
purgeUnread: loadState('news', 'purgeUnread') === '1',
maxRedirects: loadState('news', 'maxRedirects'), maxRedirects: loadState('news', 'maxRedirects'),
feedFetcherTimeout: loadState('news', 'feedFetcherTimeout'), feedFetcherTimeout: loadState('news', 'feedFetcherTimeout'),
exploreUrl: loadState('news', 'exploreUrl'), exploreUrl: loadState('news', 'exploreUrl'),
@ -103,7 +111,7 @@ export default {
appId: 'news', appId: 'news',
key, key,
}) })
if (key === 'useCronUpdates') { if (key === 'useCronUpdates' || key === 'purgeUnread') {
value = value ? '1' : '0' value = value ? '1' : '0'
} }
try { try {

View File

@ -605,23 +605,24 @@ class ItemServiceTest extends TestCase
public function testPurgeOverThresholdNull() public function testPurgeOverThresholdNull()
{ {
$this->config->expects($this->once()) $this->config->expects($this->exactly(2))
->method('getAppValue') ->method('getAppValue')
->with('news', 'autoPurgeCount', 200) ->withConsecutive(['news', 'autoPurgeCount', 200], ['news', 'purgeUnread', false])
->will($this->returnValue(200)); ->willReturnOnConsecutiveCalls(200, false);
$this->mapper->expects($this->once()) $this->mapper->expects($this->once())
->method('deleteOverThreshold') ->method('deleteOverThreshold')
->with(200); ->with(200, false);
$this->class->purgeOverThreshold(); $this->class->purgeOverThreshold();
} }
public function testPurgeOverThresholdSet() public function testPurgeOverThresholdSet()
{ {
$this->config->expects($this->never()) $this->config->expects($this->once())
->method('getAppValue') ->method('getAppValue')
->with('news', 'autoPurgeCount', 200); ->with('news', 'purgeUnread', false)
->will($this->returnValue(false));
$this->mapper->expects($this->once()) $this->mapper->expects($this->once())
->method('deleteOverThreshold') ->method('deleteOverThreshold')