Jelajahi Sumber

New extension hook entry_auto_read (#5505)

* New extension hook entry_auto_read
For extensions to be notified of articles being automatically marked as read for various reasons

* Documentation + entry_auto_unread
Alexandre Alapetite 2 tahun lalu
induk
melakukan
1db606bc1b

+ 9 - 1
app/Controllers/feedController.php

@@ -479,8 +479,16 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController {
 							//This entry already exists but has been updated
 							//Minz_Log::debug('Entry with GUID `' . $entry->guid() . '` updated in feed ' . $feed->url(false) .
 								//', old hash ' . $existingHash . ', new hash ' . $entry->hash());
-							$entry->_isRead($mark_updated_article_unread ? false : null);	//Change is_read according to policy.
 							$entry->_isFavorite(null);	// Do not change favourite state
+							$entry->_isRead($mark_updated_article_unread ? false : null);	//Change is_read according to policy.
+							if ($mark_updated_article_unread) {
+								Minz_ExtensionManager::callHook('entry_auto_unread', $entry, 'updated_article');
+							}
+
+							$entry->applyFilterActions($titlesAsRead);
+							if ($readWhenSameTitleInFeed > 0) {
+								$titlesAsRead[$entry->title()] = true;
+							}
 
 							$entry = Minz_ExtensionManager::callHook('entry_before_insert', $entry);
 							if (!($entry instanceof FreshRSS_Entry)) {

+ 15 - 8
app/Models/Entry.php

@@ -643,20 +643,27 @@ HTML;
 	/** @param array<string,bool> $titlesAsRead */
 	public function applyFilterActions(array $titlesAsRead = []): void {
 		if ($this->feed != null) {
-			if ($this->feed->attributes('read_upon_reception') ||
-				($this->feed->attributes('read_upon_reception') === null && FreshRSS_Context::$user_conf->mark_when['reception'])) {
-				$this->_isRead(true);
-			}
-			if (!empty($titlesAsRead[$this->title()])) {
-				Minz_Log::debug('Mark title as read: ' . $this->title());
-				$this->_isRead(true);
+			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');
+				}
 			}
 			foreach ($this->feed->filterActions() as $filterAction) {
 				if ($this->matches($filterAction->booleanSearch())) {
 					foreach ($filterAction->actions() as $action) {
 						switch ($action) {
 							case 'read':
-								$this->_isRead(true);
+								if (!$this->isRead()) {
+									$this->_isRead(true);
+									Minz_ExtensionManager::callHook('entry_auto_read', $this, 'filter');
+								}
 								break;
 							case 'star':
 								$this->_isFavorite(true);

+ 6 - 4
docs/en/developers/03_Backend/05_Extensions.md

@@ -131,13 +131,13 @@ The `Minz_Extension` abstract class defines another set of methods that should n
 
 You can register at the FreshRSS event system in an extensions `init()` method, to manipulate data when some of the core functions are executed.
 
-```html
+```php
 class HelloWorldExtension extends Minz_Extension
 {
-	public function init() {
-		$this->registerHook('entry_before_display', array($this, 'renderEntry'));
+	public function init(): void {
+		$this->registerHook('entry_before_display', [$this, 'renderEntry']);
 	}
-	public function renderEntry($entry) {
+	public function renderEntry(FreshRSS_Entry $entry): FreshRSS_Entry {
 		$entry->_content('<h1>Hello World</h1>' . $entry->content());
 		return $entry;
 	}
@@ -147,6 +147,8 @@ class HelloWorldExtension extends Minz_Extension
 The following events are available:
 
 * `check_url_before_add` (`function($url) -> Url | null`): will be executed every time a URL is added. The URL itself will be passed as parameter. This way a website known to have feeds which doesn’t advertise it in the header can still be automatically supported.
+* `entry_auto_read` (`function(FreshRSS_Entry $entry, string $why): void`): Triggered when an entry is automatically marked as read. The *why* parameter supports the rules {`filter`, `upon_reception`, `same_title_in_feed`}.
+* `entry_auto_unread` (`function(FreshRSS_Entry $entry, string $why): void`): Triggered when an entry is automatically marked as unread. The *why* parameter supports the rules {`updated_article`}.
 * `entry_before_display` (`function($entry) -> Entry | null`): will be executed every time an entry is rendered. The entry itself (instance of FreshRSS\_Entry) will be passed as parameter.
 * `entry_before_insert` (`function($entry) -> Entry | null`): will be executed when a feed is refreshed and new entries will be imported into the database. The new entry (instance of FreshRSS\_Entry) will be passed as parameter.
 * `feed_before_actualize` (`function($feed) -> Feed | null`): will be executed when a feed is updated. The feed (instance of FreshRSS\_Feed) will be passed as parameter.

+ 8 - 4
docs/fr/developers/03_Backend/05_Extensions.md

@@ -187,13 +187,13 @@ Your class will benefit from four methods to redefine:
 You can register at the FreshRSS event system in an extensions `init()`
 method, to manipulate data when some of the core functions are executed.
 
-```html
+```php
 class HelloWorldExtension extends Minz_Extension
 {
-	public function init() {
-		$this->registerHook('entry_before_display', array($this, 'renderEntry'));
+	public function init(): void {
+		$this->registerHook('entry_before_display', [$this, 'renderEntry']);
 	}
-	public function renderEntry($entry) {
+	public function renderEntry(FreshRSS_Entry $entry): FreshRSS_Entry {
 		$entry->_content('<h1>Hello World</h1>' . $entry->content());
 		return $entry;
 	}
@@ -206,6 +206,10 @@ The following events are available:
 	every time a URL is added. The URL itself will be passed as
 	parameter. This way a website known to have feeds which doesn’t advertise
 	it in the header can still be automatically supported.
+* `entry_auto_read` (`function(FreshRSS_Entry $entry, string $why): void`):
+	Appelé lorsqu’une entrée est automatiquement marquée comme lue. Le paramètre *why* supporte les règles {`filter`, `upon_reception`, `same_title_in_feed`}.
+* `entry_auto_unread` (`function(FreshRSS_Entry $entry, string $why): void`):
+	Appelé lorsqu’une entrée est automatiquement marquée comme non-lue. Le paramètre *why* supporte les règles {`updated_article`}.
 * `entry_before_display` (`function($entry) -> Entry | null`): will be
 	executed every time an entry is rendered. The entry itself (instance of
 	FreshRSS\_Entry) will be passed as parameter.

+ 8 - 0
lib/Minz/ExtensionManager.php

@@ -26,6 +26,14 @@ final class Minz_ExtensionManager {
 			'list' => array(),
 			'signature' => 'OneToOne',
 		),
+		'entry_auto_read' => array(	// function(FreshRSS_Entry $entry, string $why): void
+			'list' => array(),
+			'signature' => 'PassArguments',
+		),
+		'entry_auto_unread' => array(	// function(FreshRSS_Entry $entry, string $why): void
+			'list' => array(),
+			'signature' => 'PassArguments',
+		),
 		'entry_before_display' => array(	// function($entry) -> Entry | null
 			'list' => array(),
 			'signature' => 'OneToOne',