Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add filter actions (auto mark read) at category and global levels #5942

Merged
merged 5 commits into from
Dec 15, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
79 changes: 57 additions & 22 deletions app/Controllers/categoryController.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,45 +80,80 @@ public function createAction() :void {

/**
* This action updates the given category.
* @todo Check whether this function is used at all
* @see FreshRSS_subscription_Controller::categoryAction() (consider merging)
Comment on lines -83 to -84
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merged with FreshRSS_subscription_Controller::categoryAction() (to avoid partially duplicated and dead code)

*
* Request parameters are:
* - id
* - name
*/
public function updateAction(): void {
$catDAO = FreshRSS_Factory::createCategoryDao();
$url_redirect = ['c' => 'subscription', 'a' => 'index'];
if (Minz_Request::paramBoolean('ajax')) {
$this->view->_layout(null);
}

$categoryDAO = FreshRSS_Factory::createCategoryDao();

$id = Minz_Request::paramInt('id');
$category = $categoryDAO->searchById($id);
if ($id === 0 || null === $category) {
Minz_Error::error(404);
return;
}
$this->view->category = $category;

FreshRSS_View::prependTitle($category->name() . ' · ' . _t('sub.title') . ' · ');

if (Minz_Request::isPost()) {
invalidateHttpCache();
$category->_filtersAction('read', Minz_Request::paramTextToArray('filteractions_read'));

$id = Minz_Request::paramInt('id');
$name = Minz_Request::paramString('name');
if (strlen($name) <= 0) {
Minz_Request::bad(_t('feedback.sub.category.no_name'), $url_redirect);
if (Minz_Request::paramBoolean('use_default_purge_options')) {
$category->_attributes('archiving', null);
} else {
if (!Minz_Request::paramBoolean('enable_keep_max')) {
$keepMax = false;
} elseif (($keepMax = Minz_Request::paramInt('keep_max')) !== 0) {
$keepMax = FreshRSS_Feed::ARCHIVING_RETENTION_COUNT_LIMIT;
}
if (Minz_Request::paramBoolean('enable_keep_period')) {
$keepPeriod = FreshRSS_Feed::ARCHIVING_RETENTION_PERIOD;
if (is_numeric(Minz_Request::paramString('keep_period_count')) && preg_match('/^PT?1[YMWDH]$/', Minz_Request::paramString('keep_period_unit'))) {
$keepPeriod = str_replace('1', Minz_Request::paramString('keep_period_count'), Minz_Request::paramString('keep_period_unit'));
}
} else {
$keepPeriod = false;
}
$category->_attributes('archiving', [
'keep_period' => $keepPeriod,
'keep_max' => $keepMax,
'keep_min' => Minz_Request::paramInt('keep_min'),
'keep_favourites' => Minz_Request::paramBoolean('keep_favourites'),
'keep_labels' => Minz_Request::paramBoolean('keep_labels'),
'keep_unreads' => Minz_Request::paramBoolean('keep_unreads'),
]);
}

$cat = $catDAO->searchById($id);
if ($cat === null) {
Minz_Request::bad(_t('feedback.sub.category.not_exist'), $url_redirect);
$position = Minz_Request::paramInt('position') ?: null;
$category->_attributes('position', $position);

$opml_url = checkUrl(Minz_Request::paramString('opml_url'));
if ($opml_url != '') {
$category->_kind(FreshRSS_Category::KIND_DYNAMIC_OPML);
$category->_attributes('opml_url', $opml_url);
} else {
$category->_kind(FreshRSS_Category::KIND_NORMAL);
$category->_attributes('opml_url', null);
}

$values = [
'name' => $cat->name(),
'kind' => $cat->kind(),
'attributes' => $cat->attributes(),
'kind' => $category->kind(),
'name' => Minz_Request::paramString('name'),
'attributes' => $category->attributes(),
];

if ($catDAO->updateCategory($id, $values)) {
invalidateHttpCache();

$url_redirect = ['c' => 'subscription', 'params' => ['id' => $id, 'type' => 'category']];
if (false !== $categoryDAO->updateCategory($id, $values)) {
Minz_Request::good(_t('feedback.sub.category.updated'), $url_redirect);
} else {
Minz_Request::bad(_t('feedback.sub.category.error'), $url_redirect);
}
}

Minz_Request::forward($url_redirect, true);
}

/**
Expand Down
13 changes: 13 additions & 0 deletions app/Controllers/feedController.php
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,19 @@ public static function actualizeFeeds(?int $feed_id = null, ?string $feed_url =
}
} else {
$feeds = $feedDAO->listFeedsOrderUpdate(-1);

// Hydrate category for each feed to avoid that each feed has to make an SQL request
$categories = [];
$catDAO = FreshRSS_Factory::createCategoryDao();
foreach ($catDAO->listCategories(false, false) as $category) {
$categories[$category->id()] = $category;
}
foreach ($feeds as $feed) {
$category = $categories[$feed->categoryId()] ?? null;
if ($category !== null) {
$feed->_category($category);
}
}
}

// WebSub (PubSubHubbub) support
Expand Down
75 changes: 1 addition & 74 deletions app/Controllers/subscriptionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ public function feedAction(): void {
]);
}

$feed->_filtersAction('read', preg_split('/[\n\r]+/', Minz_Request::paramString('filteractions_read')) ?: []);
$feed->_filtersAction('read', Minz_Request::paramTextToArray('filteractions_read'));

$feed->_kind(Minz_Request::paramInt('feed_kind') ?: FreshRSS_Feed::KIND_RSS);
if ($feed->kind() === FreshRSS_Feed::KIND_HTML_XPATH || $feed->kind() === FreshRSS_Feed::KIND_XML_XPATH) {
Expand Down Expand Up @@ -280,79 +280,6 @@ public function feedAction(): void {
}
}

public function categoryAction(): void {
if (Minz_Request::paramBoolean('ajax')) {
$this->view->_layout(null);
}

$categoryDAO = FreshRSS_Factory::createCategoryDao();

$id = Minz_Request::paramInt('id');
$category = $categoryDAO->searchById($id);
if ($id === 0 || null === $category) {
Minz_Error::error(404);
return;
}
$this->view->category = $category;

FreshRSS_View::prependTitle($category->name() . ' · ' . _t('sub.title') . ' · ');

if (Minz_Request::isPost()) {
if (Minz_Request::paramBoolean('use_default_purge_options')) {
$category->_attributes('archiving', null);
} else {
if (!Minz_Request::paramBoolean('enable_keep_max')) {
$keepMax = false;
} elseif (($keepMax = Minz_Request::paramInt('keep_max')) !== 0) {
$keepMax = FreshRSS_Feed::ARCHIVING_RETENTION_COUNT_LIMIT;
}
if (Minz_Request::paramBoolean('enable_keep_period')) {
$keepPeriod = FreshRSS_Feed::ARCHIVING_RETENTION_PERIOD;
if (is_numeric(Minz_Request::paramString('keep_period_count')) && preg_match('/^PT?1[YMWDH]$/', Minz_Request::paramString('keep_period_unit'))) {
$keepPeriod = str_replace('1', Minz_Request::paramString('keep_period_count'), Minz_Request::paramString('keep_period_unit'));
}
} else {
$keepPeriod = false;
}
$category->_attributes('archiving', [
'keep_period' => $keepPeriod,
'keep_max' => $keepMax,
'keep_min' => Minz_Request::paramInt('keep_min'),
'keep_favourites' => Minz_Request::paramBoolean('keep_favourites'),
'keep_labels' => Minz_Request::paramBoolean('keep_labels'),
'keep_unreads' => Minz_Request::paramBoolean('keep_unreads'),
]);
}

$position = Minz_Request::paramInt('position') ?: null;
$category->_attributes('position', $position);

$opml_url = checkUrl(Minz_Request::paramString('opml_url'));
if ($opml_url != '') {
$category->_kind(FreshRSS_Category::KIND_DYNAMIC_OPML);
$category->_attributes('opml_url', $opml_url);
} else {
$category->_kind(FreshRSS_Category::KIND_NORMAL);
$category->_attributes('opml_url', null);
}

$values = [
'kind' => $category->kind(),
'name' => Minz_Request::paramString('name'),
'attributes' => $category->attributes(),
];

invalidateHttpCache();

$url_redirect = ['c' => 'subscription', 'params' => ['id' => $id, 'type' => 'category']];
if (false !== $categoryDAO->updateCategory($id, $values)) {
Minz_Request::good(_t('feedback.sub.category.updated'), $url_redirect);
} else {
Minz_Request::bad(_t('feedback.sub.category.error'), $url_redirect);
}
}
}

/**
* This action displays the bookmarklet page.
*/
Expand Down
2 changes: 2 additions & 0 deletions app/Models/Category.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
declare(strict_types=1);

class FreshRSS_Category extends Minz_Model {
use FreshRSS_FilterActionsTrait;

/**
* Normal
Expand Down Expand Up @@ -37,6 +38,7 @@ public function __construct(string $name = '', ?array $feeds = null) {
$this->nbFeeds = 0;
$this->nbNotRead = 0;
foreach ($feeds as $feed) {
$feed->_category($this);
$this->nbFeeds++;
$this->nbNotRead += $feed->nbNotRead();
$this->hasFeedsWithError |= $feed->inError();
Expand Down
47 changes: 16 additions & 31 deletions app/Models/Entry.php
Original file line number Diff line number Diff line change
Expand Up @@ -660,40 +660,25 @@ public function matches(FreshRSS_BooleanSearch $booleanSearch): bool {

/** @param array<string,bool> $titlesAsRead */
public function applyFilterActions(array $titlesAsRead = []): void {
if ($this->feed != null) {
if (!$this->isRead()) {
if ($this->feed->attributes('read_upon_reception') ||
($this->feed->attributes('read_upon_reception') === null && FreshRSS_Context::$user_conf->mark_when['reception'])) {
$this->_isRead(true);
Minz_ExtensionManager::callHook('entry_auto_read', $this, 'upon_reception');
}
if (!empty($titlesAsRead[$this->title()])) {
Minz_Log::debug('Mark title as read: ' . $this->title());
$this->_isRead(true);
Minz_ExtensionManager::callHook('entry_auto_read', $this, 'same_title_in_feed');
}
if ($this->feed === null) {
return;
}
if (!$this->isRead()) {
if ($this->feed->attributes('read_upon_reception') ||
($this->feed->attributes('read_upon_reception') === null && FreshRSS_Context::$user_conf->mark_when['reception'])) {
$this->_isRead(true);
Minz_ExtensionManager::callHook('entry_auto_read', $this, 'upon_reception');
}
foreach ($this->feed->filterActions() as $filterAction) {
if ($this->matches($filterAction->booleanSearch())) {
foreach ($filterAction->actions() as $action) {
switch ($action) {
case 'read':
if (!$this->isRead()) {
$this->_isRead(true);
Minz_ExtensionManager::callHook('entry_auto_read', $this, 'filter');
}
break;
case 'star':
$this->_isFavorite(true);
break;
case 'label':
//TODO: Implement more actions
break;
}
}
}
if (!empty($titlesAsRead[$this->title()])) {
Minz_Log::debug('Mark title as read: ' . $this->title());
$this->_isRead(true);
Minz_ExtensionManager::callHook('entry_auto_read', $this, 'same_title_in_feed');
}
}
$this->feed->applyFilterActions($this);
if ($this->feed->category() !== null) {
$this->feed->category()->applyFilterActions($this);
}
}

public function isDay(int $day, int $today): bool {
Expand Down