Răsfoiți Sursa

Modernize code to php7.4 (#6043)

* Modernize code to php7.4

* Modernize code to php7.4

* Modernize code to php7.4

* Modernize code to php7.4

* Modernize code to php7.4

* Modernize code to php7.4

* Modernize code to php7.4

* Modernize code to php7.4

* Modernize code to php7.4

* Modernize code to php7.4

* Modernize code to php7.4

* Modernize code to php7.4

* Modernize code to php7.4

* Consistency

---------

Co-authored-by: Luc <sanchezluc+freshrss@gmail.com>
Co-authored-by: Alexandre Alapetite <alexandre@alapetite.fr>
Luc SANCHEZ 1 an în urmă
părinte
comite
f99c8d5f54

+ 1 - 3
app/Controllers/feedController.php

@@ -7,7 +7,7 @@ declare(strict_types=1);
 class FreshRSS_feed_Controller extends FreshRSS_ActionController {
 	/**
 	 * This action is called before every other action in that class. It is
-	 * the common boiler plate for every action. It is triggered by the
+	 * the common boilerplate for every action. It is triggered by the
 	 * underlying framework.
 	 */
 	#[\Override]
@@ -481,8 +481,6 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController {
 			}
 
 			$feedIsNew = $feed->lastUpdate() <= 0;
-			$feedIsEmpty = false;
-			$feedIsUnchanged = false;
 
 			try {
 				if ($simplePiePush !== null) {

+ 3 - 4
app/Controllers/importExportController.php

@@ -243,10 +243,9 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
 		unset($table['article']);
 		for ($i = count($table['items']) - 1; $i >= 0; $i--) {
 			$item = (array)($table['items'][$i]);
-			$item = array_filter($item, static function ($v) {
-					// Filter out empty properties, potentially reported as empty objects
-					return (is_string($v) && trim($v) !== '') || !empty($v);
-				});
+			$item = array_filter($item, static fn($v) =>
+				// Filter out empty properties, potentially reported as empty objects
+				(is_string($v) && trim($v) !== '') || !empty($v));
 			$item['updated'] = isset($item['updated']) ? strtotime($item['updated']) : '';
 			$item['published'] = $item['updated'];
 			$item['content'] = ['content' => $item['content'] ?? ''];

+ 1 - 1
app/Models/Auth.php

@@ -8,7 +8,7 @@ class FreshRSS_Auth {
 	/**
 	 * Determines if user is connected.
 	 */
-	public const DEFAULT_COOKIE_DURATION = 7776000;
+	public const DEFAULT_COOKIE_DURATION = 7_776_000;
 
 	private static bool $login_ok = false;
 

+ 7 - 7
app/Models/Entry.php

@@ -244,12 +244,12 @@ HTML;
 				$content .= '<p class="enclosure-content"><img src="' . $elink . '" alt="" title="' . $etitle . '" /></p>';
 			} elseif ($medium === 'audio' || strpos($mime, 'audio') === 0) {
 				$content .= '<p class="enclosure-content"><audio preload="none" src="' . $elink
-					. ($length == null ? '' : '" data-length="' . intval($length))
+					. ($length == null ? '' : '" data-length="' . (int)$length)
 					. ($mime == '' ? '' : '" data-type="' . htmlspecialchars($mime, ENT_COMPAT, 'UTF-8'))
 					. '" controls="controls" title="' . $etitle . '"></audio> <a download="" href="' . $elink . '">💾</a></p>';
 			} elseif ($medium === 'video' || strpos($mime, 'video') === 0) {
 				$content .= '<p class="enclosure-content"><video preload="none" src="' . $elink
-					. ($length == null ? '' : '" data-length="' . intval($length))
+					. ($length == null ? '' : '" data-length="' . (int)$length)
 					. ($mime == '' ? '' : '" data-type="' . htmlspecialchars($mime, ENT_COMPAT, 'UTF-8'))
 					. '" controls="controls" title="' . $etitle . '"></video> <a download="" href="' . $elink . '">💾</a></p>';
 			} else {	//e.g. application, text, unknown
@@ -401,10 +401,10 @@ HTML;
 			if ($microsecond) {
 				return $this->date_added;
 			} else {
-				return intval(substr($this->date_added, 0, -6));
+				return (int)substr($this->date_added, 0, -6);
 			}
 		} else {
-			$date = intval(substr($this->date_added, 0, -6));
+			$date = (int)substr($this->date_added, 0, -6);
 			return timestamptodate($date);
 		}
 	}
@@ -519,7 +519,7 @@ HTML;
 	}
 	/** @param int|string $value */
 	public function _date($value): void {
-		$value = intval($value);
+		$value = (int)$value;
 		$this->date = $value > 1 ? $value : time();
 	}
 
@@ -552,7 +552,7 @@ HTML;
 	/** @param int|string $id */
 	private function _feedId($id): void {
 		$this->feed = null;
-		$this->feedId = intval($id);
+		$this->feedId = (int)$id;
 	}
 
 	/** @param array<string>|string $value */
@@ -966,7 +966,7 @@ HTML;
 							(self::enclosureIsImage($enclosure) ? 'image' : ''),
 					];
 				if (!empty($enclosure['length'])) {
-					$media['length'] = intval($enclosure['length']);
+					$media['length'] = (int)$enclosure['length'];
 				}
 				$item['enclosure'][] = $media;
 			}

+ 1 - 3
app/Models/EntryDAOSQLite.php

@@ -135,9 +135,7 @@ SQL;
 			Minz_Log::debug('Calling markReadTag(0) is deprecated!');
 		}
 
-		$sql = 'UPDATE `_entry` '
-			 . 'SET is_read = ? '
-			 . 'WHERE is_read <> ? AND id <= ? AND '
+		$sql = 'UPDATE `_entry` SET is_read = ? WHERE is_read <> ? AND id <= ? AND '
 			 . 'id IN (SELECT et.id_entry FROM `_entrytag` et '
 			 . ($id == 0 ? '' : 'WHERE et.id_tag = ?')
 			 . ')';

+ 7 - 7
app/Models/Feed.php

@@ -47,7 +47,7 @@ class FreshRSS_Feed extends Minz_Model {
 	private string $url = '';
 	private int $kind = 0;
 	private int $categoryId = 0;
-	private ?FreshRSS_Category $category;
+	private ?FreshRSS_Category $category = null;
 	private int $nbEntries = -1;
 	private int $nbNotRead = -1;
 	private string $name = '';
@@ -291,7 +291,7 @@ class FreshRSS_Feed extends Minz_Model {
 	/** @param int|string $id */
 	public function _categoryId($id): void {
 		$this->category = null;
-		$this->categoryId = intval($id);
+		$this->categoryId = (int)$id;
 	}
 
 	public function _name(string $value): void {
@@ -330,7 +330,7 @@ class FreshRSS_Feed extends Minz_Model {
 		$this->mute = $value;
 	}
 	public function _ttl(int $value): void {
-		$value = min($value, 100000000);
+		$value = min($value, 100_000_000);
 		$this->ttl = abs($value);
 		$this->mute = $value < self::TTL_DEFAULT;
 	}
@@ -492,7 +492,7 @@ class FreshRSS_Feed extends Minz_Model {
 
 			//Tag processing (tag == category)
 			$categories = $item->get_categories();
-			$tags = array();
+			$tags = [];
 			if (is_array($categories)) {
 				foreach ($categories as $category) {
 					$text = html_only_entity_decode($category->get_label());
@@ -550,13 +550,13 @@ class FreshRSS_Feed extends Minz_Model {
 							$attributeEnclosure['medium'] = $medium;
 						}
 						if ($length != '') {
-							$attributeEnclosure['length'] = intval($length);
+							$attributeEnclosure['length'] = (int)$length;
 						}
 						if ($height != '') {
-							$attributeEnclosure['height'] = intval($height);
+							$attributeEnclosure['height'] = (int)$height;
 						}
 						if ($width != '') {
-							$attributeEnclosure['width'] = intval($width);
+							$attributeEnclosure['width'] = (int)$width;
 						}
 
 						if (!empty($enclosure->get_thumbnails())) {

+ 3 - 3
app/Models/FilterActionsTrait.php

@@ -32,9 +32,9 @@ trait FreshRSS_FilterActionsTrait {
 	private function _filterActions(?array $filterActions): void {
 		$this->filterActions = $filterActions;
 		if ($this->filterActions !== null && !empty($this->filterActions)) {
-			$this->_attribute('filters', array_map(static function (?FreshRSS_FilterAction $af) {
-					return $af == null ? null : $af->toJSON();
-				}, $this->filterActions));
+			$this->_attribute('filters', array_map(
+				static fn(?FreshRSS_FilterAction $af) => $af == null ? null : $af->toJSON(),
+				$this->filterActions));
 		} else {
 			$this->_attribute('filters', null);
 		}

+ 1 - 3
app/Models/Search.php

@@ -235,9 +235,7 @@ class FreshRSS_Search {
 	 * @return array<string>
 	 */
 	private static function removeEmptyValues(?array $anArray): array {
-		return empty($anArray) ? [] : array_filter($anArray, static function(string $value) {
-			return $value !== '';
-		});
+		return empty($anArray) ? [] : array_filter($anArray, static fn(string $value) => $value !== '');
 	}
 
 	/**

+ 1 - 3
app/Models/Share.php

@@ -50,9 +50,7 @@ class FreshRSS_Share {
 			self::register($share_options);
 		}
 
-		uasort(self::$list_sharing, static function (FreshRSS_Share $a, FreshRSS_Share $b) {
-			return strcasecmp($a->name() ?? '', $b->name() ?? '');
-		});
+		uasort(self::$list_sharing, static fn(FreshRSS_Share $a, FreshRSS_Share $b) => strcasecmp($a->name() ?? '', $b->name() ?? ''));
 	}
 
 	/**

+ 3 - 7
app/Models/StatsDAO.php

@@ -222,7 +222,7 @@ SQL;
 			$interval_in_days = $period;
 		}
 
-		return intval($res[0]['count']) / ($interval_in_days / $period);
+		return (int)$res[0]['count'] / ($interval_in_days / $period);
 	}
 
 	/**
@@ -230,9 +230,7 @@ SQL;
 	 * @return array<int,int>
 	 */
 	protected function initStatsArray(int $min, int $max): array {
-		return array_map(function () {
-			return 0;
-		}, array_flip(range($min, $max)));
+		return array_map(fn() => 0, array_flip(range($min, $max)));
 	}
 
 	/**
@@ -369,9 +367,7 @@ SQL;
 	 * @return array<string>
 	 */
 	private function convertToTranslatedJson(array $data = []): array {
-		$translated = array_map(static function (string $a) {
-			return _t('gen.date.' . $a);
-		}, $data);
+		$translated = array_map(static fn(string $a) => _t('gen.date.' . $a), $data);
 
 		return $translated;
 	}

+ 1 - 1
app/Models/TagDAO.php

@@ -230,7 +230,7 @@ SQL;
 		if ($id_tag === null) {
 			$sql .= ' GROUP BY t.id';
 		} else {
-			$sql .= ' WHERE t.id=' . intval($id_tag);
+			$sql .= ' WHERE t.id=' . $id_tag;
 		}
 		$res = $this->fetchAssoc($sql);
 		if ($res == null) {

+ 2 - 2
cli/CliOptionsParser.php

@@ -92,11 +92,11 @@ abstract class CliOptionsParser {
 						break;
 					case 'int':
 						$validValues = array_filter($values, static fn($value) => ctype_digit($value));
-						$typedValues = array_map(static fn($value) => (int) $value, $validValues);
+						$typedValues = array_map(static fn($value) => (int)$value, $validValues);
 						break;
 					case 'bool':
 						$validValues = array_filter($values, static fn($value) => filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE) !== null);
-						$typedValues = array_map(static fn($value) => (bool) filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE), $validValues);
+						$typedValues = array_map(static fn($value) => (bool)filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE), $validValues);
 						break;
 				}
 

+ 1 - 1
cli/export-opml-for-user.php

@@ -23,7 +23,7 @@ $username = cliInitUser($cliOptions->user);
 fwrite(STDERR, 'FreshRSS exporting OPML for user “' . $username . "”…\n");
 
 $export_service = new FreshRSS_Export_Service($username);
-list($filename, $content) = $export_service->generateOpml();
+[$filename, $content] = $export_service->generateOpml();
 echo $content;
 
 invalidateHttpCache($username);

+ 3 - 6
cli/i18n/I18nData.php

@@ -93,9 +93,8 @@ class I18nData {
 	 * @return array<string>
 	 */
 	private function getNonReferenceLanguages(): array {
-		return array_filter(array_keys($this->data), static function (string $value) {
-			return static::REFERENCE_LANGUAGE !== $value;
-		});
+		return array_filter(array_keys($this->data),
+			static fn(string $value) => static::REFERENCE_LANGUAGE !== $value);
 	}
 
 	/**
@@ -145,9 +144,7 @@ class I18nData {
 		$keys = array_keys($this->data[static::REFERENCE_LANGUAGE][$this->getFilenamePrefix($key)]);
 		$parent = $this->getParentKey($key);
 
-		return array_values(array_filter($keys, static function (string $element) use ($parent) {
-			return false !== strpos($element, $parent);
-		}));
+		return array_values(array_filter($keys, static fn(string $element) => false !== strpos($element, $parent)));
 	}
 
 	/**

+ 7 - 7
cli/i18n/I18nFile.php

@@ -8,7 +8,7 @@ class I18nFile {
 	 * @return array<string,array<string,array<string,I18nValue>>>
 	 */
 	public function load(): array {
-		$i18n = array();
+		$i18n = [];
 		$dirs = new DirectoryIterator(I18N_PATH);
 		foreach ($dirs as $dir) {
 			if ($dir->isDot()) {
@@ -86,7 +86,7 @@ class I18nFile {
 	 * @return array<string,I18nValue>
 	 */
 	private function flatten(array $translation, string $prefix = ''): array {
-		$a = array();
+		$a = [];
 
 		if ('' !== $prefix) {
 			$prefix .= '.';
@@ -113,7 +113,7 @@ class I18nFile {
 	 * @return array<string,array<string,I18nValue>>
 	 */
 	private function unflatten(array $translation): array {
-		$a = array();
+		$a = [];
 
 		ksort($translation, SORT_NATURAL);
 		foreach ($translation as $compoundKey => $value) {
@@ -136,7 +136,7 @@ class I18nFile {
 	 */
 	private function format(array $translation): string {
 		$translation = var_export($this->unflatten($translation), true);
-		$patterns = array(
+		$patterns = [
 			'/ -> todo\',/',
 			'/ -> dirty\',/',
 			'/ -> ignore\',/',
@@ -144,8 +144,8 @@ class I18nFile {
 			'/=>\s*array/',
 			'/(\w) {2}/',
 			'/ {2}/',
-		);
-		$replacements = array(
+		];
+		$replacements = [
 			"',\t// TODO", // Double quoting is mandatory to have a tab instead of the \t string
 			"',\t// DIRTY", // Double quoting is mandatory to have a tab instead of the \t string
 			"',\t// IGNORE", // Double quoting is mandatory to have a tab instead of the \t string
@@ -153,7 +153,7 @@ class I18nFile {
 			'=> array',
 			'$1 ',
 			"\t", // Double quoting is mandatory to have a tab instead of the \t string
-		);
+		];
 		$translation = preg_replace($patterns, $replacements, $translation);
 
 		return <<<OUTPUT

+ 15 - 14
cli/prepare.php

@@ -3,7 +3,7 @@
 declare(strict_types=1);
 require(__DIR__ . '/_cli.php');
 
-$dirs = array(
+$dirs = [
 	'/',
 	'/cache',
 	'/extensions-data',
@@ -15,7 +15,7 @@ $dirs = array(
 	'/tokens',
 	'/users',
 	'/users/_',
-);
+];
 
 $ok = true;
 
@@ -24,18 +24,19 @@ foreach ($dirs as $dir) {
 	$ok &= touch(DATA_PATH . $dir . '/index.html');
 }
 
-file_put_contents(DATA_PATH . '/.htaccess',
-"# Apache 2.2\n" .
-"<IfModule !mod_authz_core.c>\n" .
-"	Order	Allow,Deny\n" .
-"	Deny	from all\n" .
-"	Satisfy	all\n" .
-"</IfModule>\n" .
-"\n" .
-"# Apache 2.4\n" .
-"<IfModule mod_authz_core.c>\n" .
-"	Require all denied\n" .
-"</IfModule>\n"
+file_put_contents(DATA_PATH . '/.htaccess', <<<'EOF'
+	# Apache 2.2
+	<IfModule !mod_authz_core.c>
+		Order	Allow,Deny
+		Deny	from all
+		Satisfy	all
+	</IfModule>
+
+	# Apache 2.4
+	<IfModule mod_authz_core.c>
+		Require all denied
+	</IfModule>
+	EOF
 );
 
 accessRights();

+ 36 - 36
p/api/fever.php

@@ -31,13 +31,13 @@ Minz_Session::init('FreshRSS', true);
 // ================================================================================================
 
 // <Debug>
-$ORIGINAL_INPUT = file_get_contents('php://input', false, null, 0, 1048576) ?: '';;
+$ORIGINAL_INPUT = file_get_contents('php://input', false, null, 0, 1_048_576) ?: '';;
 
 function debugInfo(): string {
 	if (function_exists('getallheaders')) {
 		$ALL_HEADERS = getallheaders();
 	} else {	//nginx	http://php.net/getallheaders#84262
-		$ALL_HEADERS = array();
+		$ALL_HEADERS = [];
 		foreach ($_SERVER as $name => $value) {
 			if (substr($name, 0, 5) === 'HTTP_') {
 				$ALL_HEADERS[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
@@ -82,7 +82,7 @@ final class FeverDAO extends Minz_ModelPdo
 	 * @return FreshRSS_Entry[]
 	 */
 	public function findEntries(array $feed_ids, array $entry_ids, string $max_id, string $since_id): array {
-		$values = array();
+		$values = [];
 		$order = '';
 		$entryDAO = FreshRSS_Factory::createEntryDao();
 
@@ -118,7 +118,7 @@ final class FeverDAO extends Minz_ModelPdo
 		if ($stm !== false && $stm->execute($values)) {
 			$result = $stm->fetchAll(PDO::FETCH_ASSOC);
 
-			$entries = array();
+			$entries = [];
 			foreach ($result as $dao) {
 				$entries[] = FreshRSS_Entry::fromArray($dao);
 			}
@@ -134,9 +134,9 @@ final class FeverDAO extends Minz_ModelPdo
  */
 final class FeverAPI
 {
-	const API_LEVEL = 3;
-	const STATUS_OK = 1;
-	const STATUS_ERR = 0;
+	public const API_LEVEL = 3;
+	public const STATUS_OK = 1;
+	public const STATUS_ERR = 0;
 
 	private FreshRSS_EntryDAO $entryDAO;
 
@@ -186,7 +186,7 @@ final class FeverAPI
 	 * @throws Exception
 	 */
 	public function process(): array {
-		$response_arr = array();
+		$response_arr = [];
 
 		if (!$this->isAuthenticatedApiUser()) {
 			throw new Exception('No user given or user is not allowed to access API');
@@ -280,8 +280,8 @@ final class FeverAPI
 	 * Returns the complete JSON, with 'api_version' and status as 'auth'.
 	 * @param array<string,mixed> $reply
 	 */
-	public function wrap(int $status, array $reply = array()): string {
-		$arr = array('api_version' => self::API_LEVEL, 'auth' => $status);
+	public function wrap(int $status, array $reply = []): string {
+		$arr = ['api_version' => self::API_LEVEL, 'auth' => $status];
 
 		if ($status === self::STATUS_OK) {
 			$arr['last_refreshed_on_time'] = $this->lastRefreshedOnTime();
@@ -309,20 +309,21 @@ final class FeverAPI
 
 	/** @return array<array<string,string|int>> */
 	private function getFeeds(): array {
-		$feeds = array();
+		$feeds = [];
 		$myFeeds = $this->feedDAO->listFeeds();
 
 		/** @var FreshRSS_Feed $feed */
 		foreach ($myFeeds as $feed) {
-			$feeds[] = array(
+			$feeds[] = [
 				'id' => $feed->id(),
 				'favicon_id' => $feed->id(),
 				'title' => escapeToUnicodeAlternative($feed->name(), true),
 				'url' => htmlspecialchars_decode($feed->url(), ENT_QUOTES),
 				'site_url' => htmlspecialchars_decode($feed->website(), ENT_QUOTES),
-				'is_spark' => 0, // unsupported
+				'is_spark' => 0,
+				// unsupported
 				'last_updated_on_time' => $feed->lastUpdate(),
-			);
+			];
 		}
 
 		return $feeds;
@@ -330,16 +331,16 @@ final class FeverAPI
 
 	/** @return array<array<string,int|string>> */
 	private function getGroups(): array {
-		$groups = array();
+		$groups = [];
 
 		$categoryDAO = FreshRSS_Factory::createCategoryDao();
 		$categories = $categoryDAO->listCategories(false, false) ?: [];
 
 		foreach ($categories as $category) {
-			$groups[] = array(
+			$groups[] = [
 				'id' => $category->id(),
-				'title' => escapeToUnicodeAlternative($category->name(), true),
-			);
+				'title' => escapeToUnicodeAlternative($category->name(), true)
+			];
 		}
 
 		return $groups;
@@ -350,7 +351,7 @@ final class FeverAPI
 		if (!FreshRSS_Context::hasSystemConf()) {
 			return [];
 		}
-		$favicons = array();
+		$favicons = [];
 		$salt = FreshRSS_Context::systemConf()->salt;
 		$myFeeds = $this->feedDAO->listFeeds();
 
@@ -362,10 +363,10 @@ final class FeverAPI
 				continue;
 			}
 
-			$favicons[] = array(
+			$favicons[] = [
 				'id' => $feed->id(),
 				'data' => image_type_to_mime_type(exif_imagetype($filename) ?: 0) . ';base64,' . base64_encode(file_get_contents($filename) ?: '')
-			);
+			];
 		}
 
 		return $favicons;
@@ -379,8 +380,8 @@ final class FeverAPI
 	 * @return array<array<string,int|string>>
 	 */
 	private function getFeedsGroup(): array {
-		$groups = array();
-		$ids = array();
+		$groups = [];
+		$ids = [];
 		$myFeeds = $this->feedDAO->listFeeds();
 
 		foreach ($myFeeds as $feed) {
@@ -388,10 +389,10 @@ final class FeverAPI
 		}
 
 		foreach ($ids as $category => $feedIds) {
-			$groups[] = array(
+			$groups[] = [
 				'group_id' => $category,
 				'feed_ids' => implode(',', $feedIds)
-			);
+			];
 		}
 
 		return $groups;
@@ -402,13 +403,13 @@ final class FeverAPI
 	 * @return array<string>
 	 */
 	private function getLinks(): array {
-		return array();
+		return [];
 	}
 
 	/**
 	 * @param array<string> $ids
 	 */
-	private function entriesToIdList(array $ids = array()): string {
+	private function entriesToIdList(array $ids = []): string {
 		return implode(',', array_values($ids));
 	}
 
@@ -452,8 +453,8 @@ final class FeverAPI
 
 	/** @return array<array<string,string|int>> */
 	private function getItems(): array {
-		$feed_ids = array();
-		$entry_ids = array();
+		$feed_ids = [];
+		$entry_ids = [];
 		$max_id = '';
 		$since_id = '';
 
@@ -495,7 +496,7 @@ final class FeverAPI
 			}
 		}
 
-		$items = array();
+		$items = [];
 
 		$feverDAO = new FeverDAO();
 		$entries = $feverDAO->findEntries($feed_ids, $entry_ids, $max_id, $since_id);
@@ -509,17 +510,16 @@ final class FeverAPI
 			if ($entry == null) {
 				continue;
 			}
-			$items[] = array(
-				'id' => '' . $entry->id(),
+			$items[] = [
+				'id' => $entry->id(),
 				'feed_id' => $entry->feedId(),
 				'title' => escapeToUnicodeAlternative($entry->title(), false),
 				'author' => escapeToUnicodeAlternative(trim($entry->authors(true), '; '), false),
-				'html' => $entry->content(),
-				'url' => htmlspecialchars_decode($entry->link(), ENT_QUOTES),
+				'html' => $entry->content(), 'url' => htmlspecialchars_decode($entry->link(), ENT_QUOTES),
 				'is_saved' => $entry->isFavorite() ? 1 : 0,
 				'is_read' => $entry->isRead() ? 1 : 0,
 				'created_on_time' => $entry->date(true),
-			);
+			];
 		}
 
 		return $items;
@@ -570,7 +570,7 @@ $handler = new FeverAPI();
 header('Content-Type: application/json; charset=UTF-8');
 
 if (!$handler->isAuthenticatedApiUser()) {
-	echo $handler->wrap(FeverAPI::STATUS_ERR, array());
+	echo $handler->wrap(FeverAPI::STATUS_ERR, []);
 } else {
 	echo $handler->wrap(FeverAPI::STATUS_OK, $handler->process());
 }

+ 4 - 4
p/api/index.php

@@ -14,10 +14,10 @@
 require(__DIR__ . '/../../constants.php');
 require(LIB_PATH . '/lib_rss.php');	//Includes class autoloader
 FreshRSS_Context::initSystem();
-echo json_encode(array(
-		'greader' => Minz_Url::display('/api/greader.php', 'php', true),
-		'fever' => Minz_Url::display('/api/fever.php', 'php', true),
-	));
+echo json_encode([
+	'greader' => Minz_Url::display('/api/greader.php', 'php', true),
+	'fever' => Minz_Url::display('/api/fever.php', 'php', true),
+]);
 ?>
 </script>
 </head>

+ 6 - 6
p/api/pshb.php

@@ -3,7 +3,7 @@ declare(strict_types=1);
 require(__DIR__ . '/../../constants.php');
 require(LIB_PATH . '/lib_rss.php');	//Includes class autoloader
 
-const MAX_PAYLOAD = 3145728;
+const MAX_PAYLOAD = 3_145_728;
 
 header('Content-Type: text/plain; charset=UTF-8');
 header('X-Content-Type-Options: nosniff');
@@ -30,7 +30,7 @@ if ($canonical === false) {
 	if (!empty($_REQUEST['hub_mode']) && $_REQUEST['hub_mode'] === 'unsubscribe') {
 		Minz_Log::warning('Warning: Accept unknown unsubscribe', PSHB_LOG);
 		header('Connection: close');
-		exit(isset($_REQUEST['hub_challenge']) ? $_REQUEST['hub_challenge'] : '');
+		exit($_REQUEST['hub_challenge'] ?? '');
 	}
 	// https://github.com/w3c/websub/issues/106 , https://w3c.github.io/websub/#content-distribution
 	header('HTTP/1.1 410 Gone');
@@ -67,7 +67,7 @@ if (empty($users)) {
 }
 
 if (!empty($_REQUEST['hub_mode']) && $_REQUEST['hub_mode'] === 'subscribe') {
-	$leaseSeconds = empty($_REQUEST['hub_lease_seconds']) ? 0 : intval($_REQUEST['hub_lease_seconds']);
+	$leaseSeconds = empty($_REQUEST['hub_lease_seconds']) ? 0 : (int) $_REQUEST['hub_lease_seconds'];
 	if ($leaseSeconds > 60) {
 		$hubJson['lease_end'] = time() + $leaseSeconds;
 	} else {
@@ -79,13 +79,13 @@ if (!empty($_REQUEST['hub_mode']) && $_REQUEST['hub_mode'] === 'subscribe') {
 	}
 	file_put_contents('./!hub.json', json_encode($hubJson));
 	header('Connection: close');
-	exit(isset($_REQUEST['hub_challenge']) ? $_REQUEST['hub_challenge'] : '');
+	exit($_REQUEST['hub_challenge'] ?? '');
 }
 
 if (!empty($_REQUEST['hub_mode']) && $_REQUEST['hub_mode'] === 'unsubscribe') {
 	if (empty($hubJson['lease_end']) || $hubJson['lease_end'] < time()) {
 		header('Connection: close');
-		exit(isset($_REQUEST['hub_challenge']) ? $_REQUEST['hub_challenge'] : '');
+		exit($_REQUEST['hub_challenge'] ?? '');
 	} else {
 		header('HTTP/1.1 422 Unprocessable Entity');
 		die('We did not ask to unsubscribe!');
@@ -103,7 +103,7 @@ $simplePie->init();
 unset($ORIGINAL_INPUT);
 
 $links = $simplePie->get_links('self');
-$self = isset($links[0]) ? $links[0] : null;
+$self = $links[0] ?? null;
 
 if ($self !== $canonical) {
 	//header('HTTP/1.1 422 Unprocessable Entity');

+ 1 - 1
p/ext.php

@@ -60,7 +60,7 @@ function is_valid_path_extension(string $path, string $extensionPath, bool $isSt
 
 	// Static files to serve must be under a `ext_dir/static/` directory.
 	$path_relative_to_ext = substr($path, strlen($real_ext_path) + 1);
-	list(, $static, $file) = sscanf($path_relative_to_ext, '%[^/]/%[^/]/%s') ?? [null, null, null];
+	[, $static, $file] = sscanf($path_relative_to_ext, '%[^/]/%[^/]/%s') ?? [null, null, null];
 	if (null === $file || 'static' !== $static) {
 		return false;
 	}

+ 1 - 1
p/f.php

@@ -14,7 +14,7 @@ function show_default_favicon(int $cacheSeconds = 3600): void {
 	}
 }
 
-$id = isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '0';
+$id = $_SERVER['QUERY_STRING'] ?? '0';
 if (!ctype_xdigit($id)) {
 	$id = '0';
 }

+ 8 - 8
tests/app/Models/CategoryTest.php

@@ -19,14 +19,14 @@ class CategoryTest extends PHPUnit\Framework\TestCase {
 
 	/** @return array<array{string,string}> */
 	public function provideValidNames(): array {
-		return array(
-			array('', ''),
-			array('this string does not need trimming', 'this string does not need trimming'),
-			array('  this string needs trimming on left', 'this string needs trimming on left'),
-			array('this string needs trimming on right  ', 'this string needs trimming on right'),
-			array('  this string needs trimming on both ends  ', 'this string needs trimming on both ends'),
-			array(str_repeat('X', 512), str_repeat('X', FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE)),	// max length
-		);
+		return [
+			['', ''],
+			['this string does not need trimming', 'this string does not need trimming'],
+			['  this string needs trimming on left', 'this string needs trimming on left'],
+			['this string needs trimming on right  ', 'this string needs trimming on right'],
+			['  this string needs trimming on both ends  ', 'this string needs trimming on both ends'],
+			[str_repeat('X', 512), str_repeat('X', FreshRSS_DatabaseDAO::LENGTH_INDEX_UNICODE)],    // max length
+		];
 	}
 
 	public function test_feedOrdering(): void {

+ 58 - 58
tests/app/Models/SearchTest.php

@@ -47,26 +47,26 @@ class SearchTest extends PHPUnit\Framework\TestCase {
 	 * @return array<array<mixed>>
 	 */
 	public function provideIntitleSearch(): array {
-		return array(
-			array('intitle:word1', array('word1'), null),
-			array('intitle:word1-word2', array('word1-word2'), null),
-			array('intitle:word1 word2', array('word1'), array('word2')),
-			array('intitle:"word1 word2"', array('word1 word2'), null),
-			array("intitle:'word1 word2'", array('word1 word2'), null),
-			array('word1 intitle:word2', array('word2'), array('word1')),
-			array('word1 intitle:word2 word3', array('word2'), array('word1', 'word3')),
-			array('word1 intitle:"word2 word3"', array('word2 word3'), array('word1')),
-			array("word1 intitle:'word2 word3'", array('word2 word3'), array('word1')),
-			array('intitle:word1 intitle:word2', array('word1', 'word2'), null),
-			array('intitle: word1 word2', null, array('word1', 'word2')),
-			array('intitle:123', array('123'), null),
-			array('intitle:"word1 word2" word3"', array('word1 word2'), array('word3"')),
-			array("intitle:'word1 word2' word3'", array('word1 word2'), array("word3'")),
-			array('intitle:"word1 word2\' word3"', array("word1 word2' word3"), null),
-			array("intitle:'word1 word2\" word3'", array('word1 word2" word3'), null),
-			array("intitle:word1 'word2 word3' word4", array('word1'), array('word2 word3', 'word4')),
+		return [
+			['intitle:word1', ['word1'], null],
+			['intitle:word1-word2', ['word1-word2'], null],
+			['intitle:word1 word2', ['word1'], ['word2']],
+			['intitle:"word1 word2"', ['word1 word2'], null],
+			["intitle:'word1 word2'", ['word1 word2'], null],
+			['word1 intitle:word2', ['word2'], ['word1']],
+			['word1 intitle:word2 word3', ['word2'], ['word1', 'word3']],
+			['word1 intitle:"word2 word3"', ['word2 word3'], ['word1']],
+			["word1 intitle:'word2 word3'", ['word2 word3'], ['word1']],
+			['intitle:word1 intitle:word2', ['word1', 'word2'], null],
+			['intitle: word1 word2', null, ['word1', 'word2']],
+			['intitle:123', ['123'], null],
+			['intitle:"word1 word2" word3"', ['word1 word2'], ['word3"']],
+			["intitle:'word1 word2' word3'", ['word1 word2'], ["word3'"]],
+			['intitle:"word1 word2\' word3"', ["word1 word2' word3"], null],
+			["intitle:'word1 word2\" word3'", ['word1 word2" word3'], null],
+			["intitle:word1 'word2 word3' word4", ['word1'], ['word2 word3', 'word4']],
 			['intitle:word1+word2', ['word1+word2'], null],
-		);
+		];
 	}
 
 	/**
@@ -84,26 +84,26 @@ class SearchTest extends PHPUnit\Framework\TestCase {
 	 * @return array<array<mixed>>
 	 */
 	public function provideAuthorSearch(): array {
-		return array(
-			array('author:word1', array('word1'), null),
-			array('author:word1-word2', array('word1-word2'), null),
-			array('author:word1 word2', array('word1'), array('word2')),
-			array('author:"word1 word2"', array('word1 word2'), null),
-			array("author:'word1 word2'", array('word1 word2'), null),
-			array('word1 author:word2', array('word2'), array('word1')),
-			array('word1 author:word2 word3', array('word2'), array('word1', 'word3')),
-			array('word1 author:"word2 word3"', array('word2 word3'), array('word1')),
-			array("word1 author:'word2 word3'", array('word2 word3'), array('word1')),
-			array('author:word1 author:word2', array('word1', 'word2'), null),
-			array('author: word1 word2', null, array('word1', 'word2')),
-			array('author:123', array('123'), null),
-			array('author:"word1 word2" word3"', array('word1 word2'), array('word3"')),
-			array("author:'word1 word2' word3'", array('word1 word2'), array("word3'")),
-			array('author:"word1 word2\' word3"', array("word1 word2' word3"), null),
-			array("author:'word1 word2\" word3'", array('word1 word2" word3'), null),
-			array("author:word1 'word2 word3' word4", array('word1'), array('word2 word3', 'word4')),
+		return [
+			['author:word1', ['word1'], null],
+			['author:word1-word2', ['word1-word2'], null],
+			['author:word1 word2', ['word1'], ['word2']],
+			['author:"word1 word2"', ['word1 word2'], null],
+			["author:'word1 word2'", ['word1 word2'], null],
+			['word1 author:word2', ['word2'], ['word1']],
+			['word1 author:word2 word3', ['word2'], ['word1', 'word3']],
+			['word1 author:"word2 word3"', ['word2 word3'], ['word1']],
+			["word1 author:'word2 word3'", ['word2 word3'], ['word1']],
+			['author:word1 author:word2', ['word1', 'word2'], null],
+			['author: word1 word2', null, ['word1', 'word2']],
+			['author:123', ['123'], null],
+			['author:"word1 word2" word3"', ['word1 word2'], ['word3"']],
+			["author:'word1 word2' word3'", ['word1 word2'], ["word3'"]],
+			['author:"word1 word2\' word3"', ["word1 word2' word3"], null],
+			["author:'word1 word2\" word3'", ['word1 word2" word3'], null],
+			["author:word1 'word2 word3' word4", ['word1'], ['word2 word3', 'word4']],
 			['author:word1+word2', ['word1+word2'], null],
-		);
+		];
 	}
 
 	/**
@@ -121,16 +121,16 @@ class SearchTest extends PHPUnit\Framework\TestCase {
 	 * @return array<array<mixed>>
 	 */
 	public function provideInurlSearch(): array {
-		return array(
-			array('inurl:word1', array('word1'), null),
-			array('inurl: word1', array(), array('word1')),
-			array('inurl:123', array('123'), null),
-			array('inurl:word1 word2', array('word1'), array('word2')),
-			array('inurl:"word1 word2"', array('"word1'), array('word2"')),
-			array('inurl:word1 word2 inurl:word3', array('word1', 'word3'), array('word2')),
-			array("inurl:word1 'word2 word3' word4", array('word1'), array('word2 word3', 'word4')),
+		return [
+			['inurl:word1', ['word1'], null],
+			['inurl: word1', [], ['word1']],
+			['inurl:123', ['123'], null],
+			['inurl:word1 word2', ['word1'], ['word2']],
+			['inurl:"word1 word2"', ['"word1'], ['word2"']],
+			['inurl:word1 word2 inurl:word3', ['word1', 'word3'], ['word2']],
+			["inurl:word1 'word2 word3' word4", ['word1'], ['word2 word3', 'word4']],
 			['inurl:word1+word2', ['word1+word2'], null],
-		);
+		];
 	}
 
 	/**
@@ -194,16 +194,16 @@ class SearchTest extends PHPUnit\Framework\TestCase {
 	 * @return array<array<string|array<string>|null>>
 	 */
 	public function provideTagsSearch(): array {
-		return array(
-			array('#word1', array('word1'), null),
-			array('# word1', null, array('#', 'word1')),
-			array('#123', array('123'), null),
-			array('#word1 word2', array('word1'), array('word2')),
-			array('#"word1 word2"', array('"word1'), array('word2"')),
-			array('#word1 #word2', array('word1', 'word2'), null),
-			array("#word1 'word2 word3' word4", array('word1'), array('word2 word3', 'word4')),
-			['#word1+word2', ['word1 word2'], null],
-		);
+		return [
+			['#word1', ['word1'], null],
+			['# word1', null, ['#', 'word1']],
+			['#123', ['123'], null],
+			['#word1 word2', ['word1'], ['word2']],
+			['#"word1 word2"', ['"word1'], ['word2"'],],
+			['#word1 #word2', ['word1', 'word2'], null],
+			["#word1 'word2 word3' word4", ['word1'], ['word2 word3', 'word4']],
+			['#word1+word2', ['word1 word2'], null]
+		];
 	}
 
 	/**
@@ -289,7 +289,7 @@ class SearchTest extends PHPUnit\Framework\TestCase {
 	 * @param array<string> $values
 	 */
 	public function test__construct_parentheses(string $input, string $sql, array $values): void {
-		list($filterValues, $filterSearch) = FreshRSS_EntryDAOPGSQL::sqlBooleanSearch('e.', new FreshRSS_BooleanSearch($input));
+		[$filterValues, $filterSearch] = FreshRSS_EntryDAOPGSQL::sqlBooleanSearch('e.', new FreshRSS_BooleanSearch($input));
 		self::assertEquals($sql, $filterSearch);
 		self::assertEquals($values, $filterValues);
 	}

+ 4 - 12
tests/cli/i18n/I18nDataTest.php

@@ -466,9 +466,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase {
 	}
 
 	public function testAddKey(): void {
-		$getTargetedValue = static function (I18nData $data, string $language) {
-			return $data->getData()[$language]['file2.php']['file2.l1.l2.k3'];
-		};
+		$getTargetedValue = static fn(I18nData $data, string $language) => $data->getData()[$language]['file2.php']['file2.l1.l2.k3'];
 
 		$rawData = array_merge($this->referenceData, [
 			'fr' => [],
@@ -502,9 +500,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase {
 	}
 
 	public function testAddValueWhenLanguageIsReferenceAndValueInOtherLanguageHasNotChange(): void {
-		$getTargetedValue = static function (I18nData $data, string $language) {
-			return $data->getData()[$language]['file2.php']['file2.l1.l2.k2'];
-		};
+		$getTargetedValue = static fn(I18nData $data, string $language) => $data->getData()[$language]['file2.php']['file2.l1.l2.k2'];
 
 		$this->value->expects(self::atLeast(2))
 			->method('equal')
@@ -530,9 +526,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase {
 	}
 
 	public function testAddValueWhenLanguageIsReferenceAndValueInOtherLanguageHasChange(): void {
-		$getTargetedValue = static function (I18nData $data, string $language) {
-			return $data->getData()[$language]['file2.php']['file2.l1.l2.k2'];
-		};
+		$getTargetedValue = static fn(I18nData $data, string $language) => $data->getData()[$language]['file2.php']['file2.l1.l2.k2'];
 
 		$this->value->expects(self::any())
 			->method('equal')
@@ -565,9 +559,7 @@ class I18nDataTest extends PHPUnit\Framework\TestCase {
 	}
 
 	public function testAddValueWhenLanguageIsNotReference(): void {
-		$getTargetedValue = static function (I18nData $data, string $language) {
-			return $data->getData()[$language]['file2.php']['file2.l1.l2.k2'];
-		};
+		$getTargetedValue = static fn(I18nData $data, string $language) => $data->getData()[$language]['file2.php']['file2.l1.l2.k2'];
 
 		$rawData = array_merge($this->referenceData, [
 			'fr' => [],

+ 17 - 51
tests/lib/Minz/MigratorTest.php

@@ -7,9 +7,7 @@ class MigratorTest extends TestCase
 	public function testAddMigration(): void {
 		$migrator = new Minz_Migrator();
 
-		$migrator->addMigration('foo', function () {
-			return true;
-		});
+		$migrator->addMigration('foo', fn() => true);
 
 		$migrations = $migrator->migrations();
 		self::assertArrayHasKey('foo', $migrations);
@@ -19,15 +17,9 @@ class MigratorTest extends TestCase
 
 	public function testMigrationsIsSorted(): void {
 		$migrator = new Minz_Migrator();
-		$migrator->addMigration('2_foo', function () {
-			return true;
-		});
-		$migrator->addMigration('10_foo', function () {
-			return true;
-		});
-		$migrator->addMigration('1_foo', function () {
-			return true;
-		});
+		$migrator->addMigration('2_foo', fn() => true);
+		$migrator->addMigration('10_foo', fn() => true);
+		$migrator->addMigration('1_foo', fn() => true);
 		$expected_versions = ['1_foo', '2_foo', '10_foo'];
 
 		$migrations = $migrator->migrations();
@@ -37,9 +29,7 @@ class MigratorTest extends TestCase
 
 	public function testSetAppliedVersions(): void {
 		$migrator = new Minz_Migrator();
-		$migrator->addMigration('foo', function () {
-			return true;
-		});
+		$migrator->addMigration('foo', fn() => true);
 
 		$migrator->setAppliedVersions(['foo']);
 
@@ -48,9 +38,7 @@ class MigratorTest extends TestCase
 
 	public function testSetAppliedVersionsTrimArgument(): void {
 		$migrator = new Minz_Migrator();
-		$migrator->addMigration('foo', function () {
-			return true;
-		});
+		$migrator->addMigration('foo', fn() => true);
 
 		$migrator->setAppliedVersions(["foo\n"]);
 
@@ -68,12 +56,8 @@ class MigratorTest extends TestCase
 
 	public function testVersions(): void {
 		$migrator = new Minz_Migrator();
-		$migrator->addMigration('foo', function () {
-			return true;
-		});
-		$migrator->addMigration('bar', function () {
-			return true;
-		});
+		$migrator->addMigration('foo', fn() => true);
+		$migrator->addMigration('bar', fn() => true);
 
 		$versions = $migrator->versions();
 
@@ -135,15 +119,9 @@ class MigratorTest extends TestCase
 
 	public function testMigrateCallNonAppliedBetweenTwoApplied(): void {
 		$migrator = new Minz_Migrator();
-		$migrator->addMigration('1_foo', function () {
-			return true;
-		});
-		$migrator->addMigration('2_foo', function () {
-			return true;
-		});
-		$migrator->addMigration('3_foo', function () {
-			return true;
-		});
+		$migrator->addMigration('1_foo', fn() => true);
+		$migrator->addMigration('2_foo', fn() => true);
+		$migrator->addMigration('3_foo', fn() => true);
 		$migrator->setAppliedVersions(['1_foo', '3_foo']);
 
 		$result = $migrator->migrate();
@@ -156,12 +134,8 @@ class MigratorTest extends TestCase
 
 	public function testMigrateWithMigrationReturningFalseDoesNotApplyVersion(): void {
 		$migrator = new Minz_Migrator();
-		$migrator->addMigration('1_foo', function () {
-			return true;
-		});
-		$migrator->addMigration('2_foo', function () {
-			return false;
-		});
+		$migrator->addMigration('1_foo', fn() => true);
+		$migrator->addMigration('2_foo', fn() => false);
 
 		$result = $migrator->migrate();
 
@@ -174,9 +148,7 @@ class MigratorTest extends TestCase
 
 	public function testMigrateWithMigrationReturningFalseDoesNotExecuteNextMigrations(): void {
 		$migrator = new Minz_Migrator();
-		$migrator->addMigration('1_foo', function () {
-			return false;
-		});
+		$migrator->addMigration('1_foo', fn() => false);
 		$spy = false;
 		$migrator->addMigration('2_foo', function () use (&$spy) {
 			$spy = true;
@@ -208,9 +180,7 @@ class MigratorTest extends TestCase
 
 	public function testUpToDate(): void {
 		$migrator = new Minz_Migrator();
-		$migrator->addMigration('foo', function () {
-			return true;
-		});
+		$migrator->addMigration('foo', fn() => true);
 		$migrator->setAppliedVersions(['foo']);
 
 		$upToDate = $migrator->upToDate();
@@ -220,12 +190,8 @@ class MigratorTest extends TestCase
 
 	public function testUpToDateIfRemainingMigration(): void {
 		$migrator = new Minz_Migrator();
-		$migrator->addMigration('1_foo', function () {
-			return true;
-		});
-		$migrator->addMigration('2_foo', function () {
-			return true;
-		});
+		$migrator->addMigration('1_foo', fn() => true);
+		$migrator->addMigration('2_foo', fn() => true);
 		$migrator->setAppliedVersions(['2_foo']);
 
 		$upToDate = $migrator->upToDate();

+ 3 - 1
tests/lib/PHPMailer/PHPMailerTest.php

@@ -1,9 +1,11 @@
 <?php
 declare(strict_types=1);
 
+use PHPMailer\PHPMailer\PHPMailer;
+
 class PHPMailerTest extends PHPUnit\Framework\TestCase
 {
 	public function testPHPMailerClassExists(): void {
-		self::assertTrue(class_exists('PHPMailer\\PHPMailer\\PHPMailer'));
+		self::assertTrue(class_exists(PHPMailer::class));
 	}
 }