Selaa lähdekoodia

Report new articles count per feed in actualize_script output (#8948)

* feat: report new articles count per feed in actualize_script output

Closes #8291

## Changes proposed in this pull request

`app/actualize_script.php` now reports, for each feed that received new articles, how many new articles were fetched — in addition to the existing per-user summary. This makes batch refreshes (cron / systemd timers) much more informative.

Example output:

```
FreshRSS actualize admin…
	10 new article(s) from feed: FreshRSS releases
	3 new article(s) from feed: Some other blog
```

The feature is implemented **entirely within the CLI script**, reusing the existing extension-hook mechanism that the script already uses for the actualization mutex — no change to `feedController` or to any other behaviour:

- `FeedBeforeActualize` records each feed's name.
- `EntryBeforeAdd` counts new entries per feed. This hook fires only in the "genuinely new GUID" branch of the actualization loop (updated articles go through `EntryBeforeUpdate`), so the count matches the controller's own `$nbNewArticles` counter. Because the counting hook is registered after `$app->init()`, it runs last in the chain and is skipped for entries dropped by another extension — i.e. it counts only articles that are actually added.

Counts are printed through the script's existing `notice()` helper, so they reach STDOUT regardless of the `environment` setting (unlike `Minz_Log::notice`, which is suppressed in `production`).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Minor

* Remove tab
The tab character is escaped in some logs, e.g.

```
 [notice] --- \x091 new article(s) from feed: L’Express
```

* Sort per-feed output and also report updated articles

Addresses review feedback on #8948:
- Sort the per-feed report by descending article count, then feed name.
- Also count updated articles (via EntryBeforeUpdate) and report them
  alongside new ones, e.g. '10 new, 2 updated article(s) from feed: X'.
  EntryBeforeAdd fires only for new articles (new-GUID branch), so
  updated articles need the separate EntryBeforeUpdate hook.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Reduced code

* Do not report feeds with no new or updated articles

FeedBeforeActualize initializes every actualized feed in $feedStatistics
and fires before the TTL/mute skips, so skipped or unchanged feeds would
otherwise print an empty count ('  article(s) from feed: X'). Skip them.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* Minor code logic preference

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
Jam Balaya 2 päivää sitten
vanhempi
commit
c90e48fd62
1 muutettua tiedostoa jossa 40 lisäystä ja 1 poistoa
  1. 40 1
      app/actualize_script.php

+ 40 - 1
app/actualize_script.php

@@ -96,15 +96,54 @@ foreach ($users as $user) {
 	// NB: Extensions and hooks are reinitialised there
 	$app->init();
 
-	Minz_ExtensionManager::addHook(Minz_HookType::FeedBeforeActualize, static function (FreshRSS_Feed $feed) use ($mutexFile) {
+	/**
+	 * Count new and updated articles per feed, to report them on the output
+	 * @var array<int,array{name:string,new:int,updated:int}> $feedStatistics
+	 */
+	$feedStatistics = [];
+
+	Minz_ExtensionManager::addHook(Minz_HookType::FeedBeforeActualize, static function (FreshRSS_Feed $feed) use ($mutexFile, &$feedStatistics) {
 		touch($mutexFile);
+		$feedStatistics[$feed->id()] = [
+			'name' => $feed->name() ?: $feed->url(false),
+			'new' => 0,
+			'updated' => 0,
+		];
 		return $feed;
 	});
+	Minz_ExtensionManager::addHook(Minz_HookType::EntryBeforeAdd, static function (FreshRSS_Entry $entry) use (&$feedStatistics) {
+		if (isset($feedStatistics[$entry->feedId()])) {
+			$feedStatistics[$entry->feedId()]['new'] = $feedStatistics[$entry->feedId()]['new'] + 1;
+		}
+		return $entry;
+	});
+	Minz_ExtensionManager::addHook(Minz_HookType::EntryBeforeUpdate, static function (FreshRSS_Entry $entry) use (&$feedStatistics) {
+		if (isset($feedStatistics[$entry->feedId()])) {
+			$feedStatistics[$entry->feedId()]['updated'] = $feedStatistics[$entry->feedId()]['updated'] + 1;
+		}
+		return $entry;
+	});
 
 	notice('FreshRSS actualize ' . $user . '…');
 	echo $user, ' ';	//Buffered
 	$app->run();
 
+	// Sort by descending total number of articles, then alphabetically by feed name
+	usort($feedStatistics, static fn(array $a, array $b): int =>
+		(($b['new'] + $b['updated']) <=> ($a['new'] + $a['updated'])) ?: strcasecmp($a['name'], $b['name']));
+	foreach ($feedStatistics as $row) {
+		$parts = [];
+		if ($row['new'] > 0) {
+			$parts[] = $row['new'] . ' new';
+		}
+		if ($row['updated'] > 0) {
+			$parts[] = $row['updated'] . ' updated';
+		}
+		if (!empty($parts)) {
+			notice(implode(', ', $parts) . ' article(s) from feed: ' . $row['name']);
+		}
+	}
+
 	if (!invalidateHttpCache()) {
 		Minz_Log::warning('FreshRSS write access problem in ' . join_path(USERS_PATH, $user, LOG_FILENAME), ADMIN_LOG);
 		if (defined('STDERR')) {