aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Docker/Dockerfile-Oldest14
-rw-r--r--README.fr.md2
-rw-r--r--README.md2
-rw-r--r--app/Controllers/apiController.php3
-rw-r--r--app/Controllers/configureController.php2
-rw-r--r--app/Controllers/feedController.php2
-rw-r--r--app/Controllers/importExportController.php17
-rw-r--r--app/Controllers/updateController.php2
-rw-r--r--app/Models/CategoryDAO.php18
-rw-r--r--app/Models/Context.php2
-rw-r--r--app/Models/Entry.php19
-rw-r--r--app/Models/EntryDAO.php30
-rw-r--r--app/Models/EntryDAOSQLite.php7
-rw-r--r--app/Models/Feed.php23
-rw-r--r--app/Models/FeedDAO.php39
-rw-r--r--app/Models/FormAuth.php6
-rw-r--r--app/Models/Search.php6
-rw-r--r--app/Models/Share.php2
-rw-r--r--app/Models/StatsDAO.php2
-rw-r--r--app/Models/Tag.php15
-rw-r--r--app/Models/TagDAO.php32
-rw-r--r--app/Models/Themes.php4
-rw-r--r--app/Services/ExportService.php17
-rw-r--r--app/Services/ImportService.php12
-rw-r--r--app/Utils/dotNotationUtil.php16
-rw-r--r--app/Utils/feverUtil.php2
-rwxr-xr-xcli/_cli.php6
-rwxr-xr-xcli/check.translation.php3
-rw-r--r--cli/i18n/I18nFile.php1
-rw-r--r--cli/i18n/I18nValue.php2
-rw-r--r--composer.json10
-rw-r--r--composer.lock603
-rw-r--r--config.default.php4
-rw-r--r--constants.php2
-rw-r--r--docs/en/admins/02_Prerequisites.md2
-rw-r--r--docs/en/admins/10_ServerConfig.md2
-rw-r--r--docs/fr/users/01_Installation.md4
-rw-r--r--lib/Minz/Configuration.php12
-rw-r--r--lib/Minz/ConfigurationSetterInterface.php2
-rw-r--r--lib/Minz/Extension.php16
-rw-r--r--lib/Minz/ExtensionManager.php2
-rw-r--r--lib/Minz/FrontController.php3
-rw-r--r--lib/Minz/Helper.php5
-rw-r--r--lib/Minz/Log.php1
-rw-r--r--lib/Minz/Mailer.php4
-rw-r--r--lib/Minz/Migrator.php5
-rw-r--r--lib/Minz/ModelPdo.php2
-rw-r--r--lib/Minz/Paginator.php4
-rw-r--r--lib/Minz/Pdo.php22
-rw-r--r--lib/Minz/PdoMysql.php5
-rw-r--r--lib/Minz/PdoSqlite.php5
-rw-r--r--lib/Minz/Request.php4
-rw-r--r--lib/Minz/Session.php2
-rw-r--r--lib/Minz/Translate.php4
-rw-r--r--lib/Minz/Url.php11
-rw-r--r--lib/Minz/View.php7
-rw-r--r--lib/lib_date.php2
-rw-r--r--lib/lib_rss.php43
-rw-r--r--p/api/fever.php22
-rw-r--r--p/api/greader.php80
-rw-r--r--p/ext.php6
-rw-r--r--phpstan.neon1
-rw-r--r--tests/README.md17
-rw-r--r--tests/app/Models/CategoryTest.php12
-rw-r--r--tests/app/Models/FeedDAOTest.php2
-rw-r--r--tests/app/Models/SearchTest.php77
-rw-r--r--tests/app/Models/UserQueryTest.php36
-rw-r--r--tests/app/Utils/dotNotationUtilTest.php8
-rw-r--r--tests/cli/CliOptionsParserTest.php129
-rw-r--r--tests/cli/i18n/I18nCompletionValidatorTest.php2
-rw-r--r--tests/cli/i18n/I18nUsageValidatorTest.php2
-rw-r--r--tests/cli/i18n/I18nValueTest.php18
-rw-r--r--tests/lib/CssXPath/CssXPathTest.php2
-rw-r--r--tests/lib/Minz/MigratorTest.php42
-rw-r--r--tests/lib/PHPMailer/PHPMailerTest.php2
75 files changed, 596 insertions, 958 deletions
diff --git a/Docker/Dockerfile-Oldest b/Docker/Dockerfile-Oldest
index ee478c2cd..9227e53f4 100644
--- a/Docker/Dockerfile-Oldest
+++ b/Docker/Dockerfile-Oldest
@@ -1,14 +1,14 @@
-FROM alpine:3.13
+FROM alpine:3.16
ENV TZ UTC
SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
RUN apk add --no-cache \
tzdata \
- apache2 php7-apache2 \
- php7 php7-curl php7-gmp php7-intl php7-mbstring php7-xml php7-zip \
- php7-ctype php7-dom php7-fileinfo php7-iconv php7-json php7-opcache php7-openssl php7-phar php7-session php7-simplexml php7-xmlreader php7-xmlwriter php7-xml php7-tokenizer php7-zlib \
- php7-pdo_sqlite php7-pdo_mysql php7-pdo_pgsql
+ apache2 php81-apache2 \
+ php81 php81-curl php81-gmp php81-intl php81-mbstring php81-xml php81-zip \
+ php81-ctype php81-dom php81-fileinfo php81-iconv php81-json php81-opcache php81-openssl php81-phar php81-session php81-simplexml php81-xmlreader php81-xmlwriter php81-xml php81-tokenizer php81-zlib \
+ php81-pdo_sqlite php81-pdo_mysql php81-pdo_pgsql
RUN mkdir -p /var/www/FreshRSS /run/apache2/
WORKDIR /var/www/FreshRSS
@@ -39,8 +39,8 @@ RUN rm -f /etc/apache2/conf.d/languages.conf /etc/apache2/conf.d/info.conf \
/etc/apache2/httpd.conf && \
sed -r -i "/^\s*(CustomLog|ErrorLog|Listen) /s/^/#/" \
/etc/apache2/httpd.conf && \
- if [ ! -f /usr/bin/php ]; then ln -s /usr/bin/php7 /usr/bin/php; else true; fi && \
- echo 'memory_limit = 256M' > /etc/php7/conf.d/10_memory.ini && \
+ if [ ! -f /usr/bin/php ]; then ln -s /usr/bin/php81 /usr/bin/php; else true; fi && \
+ echo 'memory_limit = 256M' > /etc/php81/conf.d/10_memory.ini && \
# Disable built-in updates when using Docker, as the full image is supposed to be updated instead.
sed -r -i "\\#disable_update#s#^.*#\t'disable_update' => true,#" ./config.default.php && \
touch /var/www/FreshRSS/Docker/env.txt && \
diff --git a/README.fr.md b/README.fr.md
index ca9b6bc06..ad592227e 100644
--- a/README.fr.md
+++ b/README.fr.md
@@ -62,7 +62,7 @@ FreshRSS n’est fourni avec aucune garantie.
* Serveur modeste, par exemple sous Linux ou Windows
* Fonctionne même sur un Raspberry Pi 1 avec des temps de réponse < 1s (testé sur 150 flux, 22k articles)
* Serveur Web Apache2.4+ (recommandé), ou nginx, lighttpd (non testé sur les autres)
-* PHP 7.4+
+* PHP 8.1+
* Extensions requises : [cURL](https://www.php.net/curl), [DOM](https://www.php.net/dom), [JSON](https://www.php.net/json), [XML](https://www.php.net/xml), [session](https://www.php.net/session), [ctype](https://www.php.net/ctype)
* Extensions recommandées : [PDO_SQLite](https://www.php.net/pdo-sqlite) (pour l’export/import), [GMP](https://www.php.net/gmp) (pour accès API sur plateformes < 64 bits), [IDN](https://www.php.net/intl.idn) (pour les noms de domaines internationalisés), [mbstring](https://www.php.net/mbstring) (pour le texte Unicode), [iconv](https://www.php.net/iconv) (pour conversion d’encodages), [ZIP](https://www.php.net/zip) (pour import/export), [zlib](https://www.php.net/zlib) (pour les flux compressés)
* Extension pour base de données : [PDO_PGSQL](https://www.php.net/pdo-pgsql) ou [PDO_SQLite](https://www.php.net/pdo-sqlite) ou [PDO_MySQL](https://www.php.net/pdo-mysql)
diff --git a/README.md b/README.md
index 093b94e40..38db3cfc3 100644
--- a/README.md
+++ b/README.md
@@ -62,7 +62,7 @@ FreshRSS comes with absolutely no warranty.
* Light server running Linux or Windows
* It even works on Raspberry Pi 1 with response time under a second (tested with 150 feeds, 22k articles)
* A web server: Apache2.4+ (recommended), nginx, lighttpd (not tested on others)
-* PHP 7.4+
+* PHP 8.1+
* Required extensions: [cURL](https://www.php.net/curl), [DOM](https://www.php.net/dom), [JSON](https://www.php.net/json), [XML](https://www.php.net/xml), [session](https://www.php.net/session), [ctype](https://www.php.net/ctype)
* Recommended extensions: [PDO_SQLite](https://www.php.net/pdo-sqlite) (for export/import), [GMP](https://www.php.net/gmp) (for API access on 32-bit platforms), [IDN](https://www.php.net/intl.idn) (for Internationalized Domain Names), [mbstring](https://www.php.net/mbstring) (for Unicode strings), [iconv](https://www.php.net/iconv) (for charset conversion), [ZIP](https://www.php.net/zip) (for import/export), [zlib](https://www.php.net/zlib) (for compressed feeds)
* Extension for database: [PDO_PGSQL](https://www.php.net/pdo-pgsql) or [PDO_SQLite](https://www.php.net/pdo-sqlite) or [PDO_MySQL](https://www.php.net/pdo-mysql)
diff --git a/app/Controllers/apiController.php b/app/Controllers/apiController.php
index 7c20b630b..585a7a9bb 100644
--- a/app/Controllers/apiController.php
+++ b/app/Controllers/apiController.php
@@ -9,9 +9,8 @@ class FreshRSS_api_Controller extends FreshRSS_ActionController {
/**
* Update the user API password.
* Return an error message, or `false` if no error.
- * @return false|string
*/
- public static function updatePassword(string $apiPasswordPlain) {
+ public static function updatePassword(string $apiPasswordPlain): string|false {
$username = Minz_User::name();
if ($username == null) {
return _t('feedback.api.password.failed');
diff --git a/app/Controllers/configureController.php b/app/Controllers/configureController.php
index 385bd1e2e..a9304376f 100644
--- a/app/Controllers/configureController.php
+++ b/app/Controllers/configureController.php
@@ -479,8 +479,6 @@ class FreshRSS_configure_Controller extends FreshRSS_ActionController {
* - user category limit (default: 16384)
* - user feed limit (default: 16384)
* - user login duration for form auth (default: FreshRSS_Auth::DEFAULT_COOKIE_DURATION)
- *
- * The `force-email-validation` is ignored with PHP < 5.5
*/
public function systemAction(): void {
if (!FreshRSS_Auth::hasAccess('admin')) {
diff --git a/app/Controllers/feedController.php b/app/Controllers/feedController.php
index dbdf858a7..42639f5e1 100644
--- a/app/Controllers/feedController.php
+++ b/app/Controllers/feedController.php
@@ -755,7 +755,7 @@ class FreshRSS_feed_Controller extends FreshRSS_ActionController {
* @param int $nbNewEntries The number of top recent entries to process.
* @return int|false The number of new labels added, or false in case of error.
*/
- private static function applyLabelActions(int $nbNewEntries) {
+ private static function applyLabelActions(int $nbNewEntries): int|false {
$tagDAO = FreshRSS_Factory::createTagDao();
$labels = FreshRSS_Context::labels();
$labels = array_filter($labels, static function (FreshRSS_Tag $label) {
diff --git a/app/Controllers/importExportController.php b/app/Controllers/importExportController.php
index 2dc25fa2f..c4f64337b 100644
--- a/app/Controllers/importExportController.php
+++ b/app/Controllers/importExportController.php
@@ -33,10 +33,7 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
FreshRSS_View::prependTitle(_t('sub.import_export.title') . ' · ');
}
- /**
- * @return float|int|string
- */
- private static function megabytes(string $size_str) {
+ private static function megabytes(string $size_str): float|int|string {
switch (substr($size_str, -1)) {
case 'M':
case 'm':
@@ -51,10 +48,7 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
return $size_str;
}
- /**
- * @param string|int $mb
- */
- private static function minimumMemory($mb): void {
+ private static function minimumMemory(int|string $mb): void {
$mb = (int)$mb;
$ini = self::megabytes(ini_get('memory_limit') ?: '0');
if ($ini < $mb) {
@@ -240,11 +234,8 @@ class FreshRSS_importExport_Controller extends FreshRSS_ActionController {
return 'unknown';
}
- /**
- * @return false|string
- */
- private function ttrssXmlToJson(string $xml) {
- $table = (array)simplexml_load_string($xml, null, LIBXML_NOBLANKS | LIBXML_NOCDATA);
+ private function ttrssXmlToJson(string $xml): string|false {
+ $table = (array)simplexml_load_string($xml, options: LIBXML_NOBLANKS | LIBXML_NOCDATA);
$table['items'] = $table['article'] ?? [];
unset($table['article']);
for ($i = count($table['items']) - 1; $i >= 0; $i--) {
diff --git a/app/Controllers/updateController.php b/app/Controllers/updateController.php
index f07ed338b..e5bf276cd 100644
--- a/app/Controllers/updateController.php
+++ b/app/Controllers/updateController.php
@@ -93,7 +93,7 @@ class FreshRSS_update_Controller extends FreshRSS_ActionController {
}
/** @return string|true */
- public static function gitPull() {
+ public static function gitPull(): string|bool {
Minz_Log::notice(_t('admin.update.viaGit'));
$cwd = getcwd();
if ($cwd === false) {
diff --git a/app/Models/CategoryDAO.php b/app/Models/CategoryDAO.php
index da770ade7..b101f0b3f 100644
--- a/app/Models/CategoryDAO.php
+++ b/app/Models/CategoryDAO.php
@@ -100,9 +100,8 @@ class FreshRSS_CategoryDAO extends Minz_ModelPdo {
/**
* @param array{'name':string,'id'?:int,'kind'?:int,'lastUpdate'?:int,'error'?:int|bool,'attributes'?:string|array<string,mixed>} $valuesTmp
- * @return int|false
*/
- public function addCategory(array $valuesTmp) {
+ public function addCategory(array $valuesTmp): int|false {
// TRIM() to provide a type hint as text
// No tag of the same name
$sql = <<<'SQL'
@@ -136,8 +135,7 @@ SQL;
}
}
- /** @return int|false */
- public function addCategoryObject(FreshRSS_Category $category) {
+ public function addCategoryObject(FreshRSS_Category $category): int|false {
$cat = $this->searchByName($category->name());
if (!$cat) {
$values = [
@@ -153,9 +151,8 @@ SQL;
/**
* @param array{'name':string,'kind':int,'attributes'?:array<string,mixed>|mixed|null} $valuesTmp
- * @return int|false
*/
- public function updateCategory(int $id, array $valuesTmp) {
+ public function updateCategory(int $id, array $valuesTmp): int|false {
// No tag of the same name
$sql = <<<'SQL'
UPDATE `_category` SET name=?, kind=?, attributes=? WHERE id=?
@@ -187,8 +184,7 @@ SQL;
}
}
- /** @return int|false */
- public function updateLastUpdate(int $id, bool $inError = false, int $mtime = 0) {
+ public function updateLastUpdate(int $id, bool $inError = false, int $mtime = 0): int|false {
$sql = 'UPDATE `_category` SET `lastUpdate`=?, error=? WHERE id=?';
$values = [
$mtime <= 0 ? time() : $mtime,
@@ -206,8 +202,7 @@ SQL;
}
}
- /** @return int|false */
- public function deleteCategory(int $id) {
+ public function deleteCategory(int $id): int|false {
if ($id <= self::DEFAULTCATEGORYID) {
return false;
}
@@ -345,8 +340,7 @@ SQL;
}
}
- /** @return int|bool */
- public function checkDefault() {
+ public function checkDefault(): int|bool {
$def_cat = $this->searchById(self::DEFAULTCATEGORYID);
if ($def_cat == null) {
diff --git a/app/Models/Context.php b/app/Models/Context.php
index 988eedc71..8634b5e71 100644
--- a/app/Models/Context.php
+++ b/app/Models/Context.php
@@ -274,7 +274,7 @@ final class FreshRSS_Context {
* @phpstan-return ($asArray is true ? array{'a'|'c'|'f'|'i'|'s'|'t'|'T',bool|int} : string)
* @return string|array{string,bool|int}
*/
- public static function currentGet(bool $asArray = false) {
+ public static function currentGet(bool $asArray = false): string|array {
if (self::$current_get['all']) {
return $asArray ? ['a', true] : 'a';
} elseif (self::$current_get['important']) {
diff --git a/app/Models/Entry.php b/app/Models/Entry.php
index f2701fb68..4b331419b 100644
--- a/app/Models/Entry.php
+++ b/app/Models/Entry.php
@@ -32,13 +32,10 @@ class FreshRSS_Entry extends Minz_Model {
private array $tags = [];
/**
- * @param int|string $pubdate
- * @param bool|int|null $is_read
- * @param bool|int|null $is_favorite
* @param string|array<string> $tags
*/
public function __construct(int $feedId = 0, string $guid = '', string $title = '', string $authors = '', string $content = '',
- string $link = '', $pubdate = 0, $is_read = false, $is_favorite = false, $tags = '') {
+ string $link = '', int|string $pubdate = 0, bool|int|null $is_read = false, bool|int|null $is_favorite = false, $tags = '') {
$this->_title($title);
$this->_authors($authors);
$this->_content($content);
@@ -149,7 +146,7 @@ class FreshRSS_Entry extends Minz_Model {
* @phpstan-return ($asString is true ? string : array<string>)
* @return string|array<string>
*/
- public function authors(bool $asString = false) {
+ public function authors(bool $asString = false): string|array {
if ($asString) {
return $this->authors == null ? '' : ';' . implode('; ', $this->authors);
} else {
@@ -384,9 +381,8 @@ HTML;
}
/**
* @phpstan-return ($raw is false ? string : int)
- * @return string|int
*/
- public function date(bool $raw = false) {
+ public function date(bool $raw = false): int|string {
if ($raw) {
return $this->date;
}
@@ -402,9 +398,8 @@ HTML;
/**
* @phpstan-return ($raw is false ? string : ($microsecond is true ? string : int))
- * @return int|string
*/
- public function dateAdded(bool $raw = false, bool $microsecond = false) {
+ public function dateAdded(bool $raw = false, bool $microsecond = false): int|string {
if ($raw) {
if ($microsecond) {
return $this->date_added;
@@ -451,7 +446,7 @@ HTML;
* @phpstan-return ($asString is true ? string : array<string>)
* @return string|array<string>
*/
- public function tags(bool $asString = false) {
+ public function tags(bool $asString = false): array|string {
if ($asString) {
return $this->tags == null ? '' : '#' . implode(' #', $this->tags);
} else {
@@ -719,9 +714,7 @@ HTML;
}
}
FreshRSS_Context::userConf()->applyFilterActions($this);
- if ($feed->category() !== null) {
- $feed->category()->applyFilterActions($this);
- }
+ $feed->category()?->applyFilterActions($this);
$feed->applyFilterActions($this);
}
diff --git a/app/Models/EntryDAO.php b/app/Models/EntryDAO.php
index a90b98a60..175df15c3 100644
--- a/app/Models/EntryDAO.php
+++ b/app/Models/EntryDAO.php
@@ -291,9 +291,8 @@ SQL;
* there is an other way to do that.
*
* @param numeric-string|array<numeric-string> $ids
- * @return int|false
*/
- public function markFavorite($ids, bool $is_favorite = true) {
+ public function markFavorite($ids, bool $is_favorite = true): int|false {
if (!is_array($ids)) {
$ids = [$ids];
}
@@ -369,10 +368,9 @@ SQL;
* Then the cache is updated.
*
* @param numeric-string|array<numeric-string> $ids
- * @param bool $is_read
* @return int|false affected rows
*/
- public function markRead($ids, bool $is_read = true) {
+ public function markRead(array|string $ids, bool $is_read = true): int|false {
if (is_array($ids)) { //Many IDs at once
if (count($ids) < 6) { //Speed heuristics
$affected = 0;
@@ -438,7 +436,7 @@ SQL;
* @param numeric-string $idMax fail safe article ID
* @return int|false affected rows
*/
- public function markReadEntries(string $idMax = '0', bool $onlyFavorites = false, ?int $priorityMin = null, ?int $prioritMax = null,
+ public function markReadEntries(string $idMax = '0', bool $onlyFavorites = false, ?int $priorityMin = null, ?int $priorityMax = null,
?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) {
FreshRSS_UserDAO::touch();
if ($idMax == '0') {
@@ -451,15 +449,15 @@ SQL;
if ($onlyFavorites) {
$sql .= ' AND is_favorite=1';
}
- if ($priorityMin !== null || $prioritMax !== null) {
+ if ($priorityMin !== null || $priorityMax !== null) {
$sql .= ' AND id_feed IN (SELECT f.id FROM `_feed` f WHERE 1=1';
if ($priorityMin !== null) {
$sql .= ' AND f.priority >= ?';
$values[] = $priorityMin;
}
- if ($prioritMax !== null) {
+ if ($priorityMax !== null) {
$sql .= ' AND f.priority < ?';
- $values[] = $prioritMax;
+ $values[] = $priorityMax;
}
$sql .= ')';
}
@@ -490,7 +488,7 @@ SQL;
* @param numeric-string $idMax fail safe article ID
* @return int|false affected rows
*/
- public function markReadCat(int $id, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) {
+ public function markReadCat(int $id, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true): int|false {
FreshRSS_UserDAO::touch();
if ($idMax == '0') {
$idMax = time() . '000000';
@@ -531,7 +529,7 @@ SQL;
* @param numeric-string $idMax fail safe article ID
* @return int|false affected rows
*/
- public function markReadFeed(int $id_feed, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) {
+ public function markReadFeed(int $id_feed, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true): int|false {
FreshRSS_UserDAO::touch();
if ($idMax == '0') {
$idMax = time() . '000000';
@@ -623,9 +621,8 @@ SQL;
/**
* Remember to call updateCachedValues($id_feed) or updateCachedValues() just after.
* @param array<string,bool|int|string> $options
- * @return int|false
*/
- public function cleanOldEntries(int $id_feed, array $options = []) {
+ public function cleanOldEntries(int $id_feed, array $options = []): int|false {
$sql = 'DELETE FROM `_entry` WHERE id_feed = :id_feed1'; //No alias for MySQL / MariaDB
$params = [];
$params[':id_feed1'] = $id_feed;
@@ -1121,12 +1118,11 @@ SQL;
* @phpstan-param 'a'|'A'|'s'|'S'|'i'|'c'|'f'|'t'|'T'|'ST' $type
* @param 'ASC'|'DESC' $order
* @param int $id category/feed/tag ID
- * @return PDOStatement|false
* @throws FreshRSS_EntriesGetter_Exception
*/
private function listWhereRaw(string $type = 'a', int $id = 0, int $state = FreshRSS_Entry::STATE_ALL,
string $order = 'DESC', int $limit = 1, int $offset = 0, string $firstId = '', ?FreshRSS_BooleanSearch $filters = null,
- int $date_min = 0) {
+ int $date_min = 0): PDOStatement|false {
[$values, $sql] = $this->sqlListWhere($type, $id, $state, $order, $limit, $offset, $firstId, $filters, $date_min);
if ($order !== 'DESC' && $order !== 'ASC') {
@@ -1244,7 +1240,7 @@ SQL;
* @param array<string> $guids
* @return array<string>|false
*/
- public function listHashForFeedGuids(int $id_feed, array $guids) {
+ public function listHashForFeedGuids(int $id_feed, array $guids): array|false {
$result = [];
if (count($guids) < 1) {
return $result;
@@ -1283,7 +1279,7 @@ SQL;
* @param array<string> $guids
* @return int|false The number of affected entries, or false if error
*/
- public function updateLastSeen(int $id_feed, array $guids, int $mtime = 0) {
+ public function updateLastSeen(int $id_feed, array $guids, int $mtime = 0): int|false {
if (count($guids) < 1) {
return 0;
} elseif (count($guids) > FreshRSS_DatabaseDAO::MAX_VARIABLE_NUMBER) {
@@ -1321,7 +1317,7 @@ SQL;
* To be performed just before {@see FreshRSS_FeedDAO::updateLastUpdate()}
* @return int|false The number of affected entries, or false in case of error
*/
- public function updateLastSeenUnchanged(int $id_feed, int $mtime = 0) {
+ public function updateLastSeenUnchanged(int $id_feed, int $mtime = 0): int|false {
$sql = <<<'SQL'
UPDATE `_entry` SET `lastSeen` = :mtime
WHERE id_feed = :id_feed1 AND `lastSeen` = (
diff --git a/app/Models/EntryDAOSQLite.php b/app/Models/EntryDAOSQLite.php
index d6364fec9..9c2b37623 100644
--- a/app/Models/EntryDAOSQLite.php
+++ b/app/Models/EntryDAOSQLite.php
@@ -77,12 +77,11 @@ SQL;
* Toggle the read marker on one or more article.
* Then the cache is updated.
*
- * @param string|array<string> $ids
- * @param bool $is_read
+ * @param numeric-string|array<numeric-string> $ids
* @return int|false affected rows
*/
#[\Override]
- public function markRead($ids, bool $is_read = true) {
+ public function markRead(array|string $ids, bool $is_read = true): int|false {
if (is_array($ids)) { //Many IDs at once (used by API)
//if (true) { //Speed heuristics //TODO: Not implemented yet for SQLite (so always call IDs one by one)
$affected = 0;
@@ -128,7 +127,7 @@ SQL;
* @return int|false affected rows
*/
#[\Override]
- public function markReadTag($id = 0, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true) {
+ public function markReadTag($id = 0, string $idMax = '0', ?FreshRSS_BooleanSearch $filters = null, int $state = 0, bool $is_read = true): int|false {
FreshRSS_UserDAO::touch();
if ($idMax == 0) {
$idMax = time() . '000000';
diff --git a/app/Models/Feed.php b/app/Models/Feed.php
index 36cc58cfd..6e468e33f 100644
--- a/app/Models/Feed.php
+++ b/app/Models/Feed.php
@@ -116,10 +116,7 @@ class FreshRSS_Feed extends Minz_Model {
}
public function categoryId(): int {
- if ($this->category !== null) {
- return $this->category->id() ?: $this->categoryId;
- }
- return $this->categoryId;
+ return $this->category?->id() ?: $this->categoryId;
}
/**
@@ -155,7 +152,7 @@ class FreshRSS_Feed extends Minz_Model {
* @phpstan-return ($raw is true ? string : array{'username':string,'password':string})
* @return array{'username':string,'password':string}|string
*/
- public function httpAuth(bool $raw = true) {
+ public function httpAuth(bool $raw = true): array|string {
if ($raw) {
return $this->httpAuth;
} else {
@@ -816,7 +813,7 @@ class FreshRSS_Feed extends Minz_Model {
/**
* @return int|null The max number of unread articles to keep, or null if disabled.
*/
- public function keepMaxUnread() {
+ public function keepMaxUnread(): ?int {
$keepMaxUnread = $this->attributeInt('keep_max_n_unread');
if ($keepMaxUnread === null) {
$keepMaxUnread = FreshRSS_Context::userConf()->mark_when['max_n_unread'];
@@ -827,7 +824,7 @@ class FreshRSS_Feed extends Minz_Model {
/**
* @return int|false The number of articles marked as read, of false if error
*/
- public function markAsReadMaxUnread() {
+ public function markAsReadMaxUnread(): int|false {
$keepMaxUnread = $this->keepMaxUnread();
if ($keepMaxUnread === null) {
return false;
@@ -842,7 +839,7 @@ class FreshRSS_Feed extends Minz_Model {
* Remember to call `updateCachedValues($id_feed)` or `updateCachedValues()` just after.
* @return int|false the number of lines affected, or false if not applicable
*/
- public function markAsReadUponGone(bool $upstreamIsEmpty, int $minLastSeen = 0) {
+ public function markAsReadUponGone(bool $upstreamIsEmpty, int $minLastSeen = 0): int|false {
$readUponGone = $this->attributeBoolean('read_upon_gone');
if ($readUponGone === null) {
$readUponGone = FreshRSS_Context::userConf()->mark_when['gone'];
@@ -868,9 +865,8 @@ class FreshRSS_Feed extends Minz_Model {
/**
* Remember to call `updateCachedValues($id_feed)` or `updateCachedValues()` just after
- * @return int|false
*/
- public function cleanOldEntries() {
+ public function cleanOldEntries(): int|false {
/** @var array<string,bool|int|string>|null $archiving */
$archiving = $this->attributeArray('archiving');
if ($archiving === null) {
@@ -926,7 +922,7 @@ class FreshRSS_Feed extends Minz_Model {
}
/** @return int|false */
- public function cacheModifiedTime() {
+ public function cacheModifiedTime(): int|false {
$filename = $this->cacheFilename();
clearstatcache(true, $filename);
return @filemtime($filename);
@@ -977,10 +973,7 @@ class FreshRSS_Feed extends Minz_Model {
return false;
}
- /**
- * @return string|false
- */
- public function pubSubHubbubPrepare() {
+ public function pubSubHubbubPrepare(): string|false {
$key = '';
if (Minz_Request::serverIsPublic(FreshRSS_Context::systemConf()->base_url) &&
$this->hubUrl && $this->selfUrl && @is_dir(PSHB_PATH)) {
diff --git a/app/Models/FeedDAO.php b/app/Models/FeedDAO.php
index 11eef4e90..96a8fc3c5 100644
--- a/app/Models/FeedDAO.php
+++ b/app/Models/FeedDAO.php
@@ -36,9 +36,8 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo {
/**
* @param array{'url':string,'kind':int,'category':int,'name':string,'website':string,'description':string,'lastUpdate':int,'priority'?:int,
* 'pathEntries'?:string,'httpAuth':string,'error':int|bool,'ttl'?:int,'attributes'?:string|array<string|mixed>} $valuesTmp
- * @return int|false
*/
- public function addFeed(array $valuesTmp) {
+ public function addFeed(array $valuesTmp): int|false {
$sql = 'INSERT INTO `_feed` (url, kind, category, name, website, description, `lastUpdate`, priority, `pathEntries`, `httpAuth`, error, ttl, attributes)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)';
$stm = $this->pdo->prepare($sql);
@@ -81,8 +80,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo {
}
}
- /** @return int|false */
- public function addFeedObject(FreshRSS_Feed $feed) {
+ public function addFeedObject(FreshRSS_Feed $feed): int|false {
// Add feed only if we don’t find it in DB
$feed_search = $this->searchByUrl($feed->url());
if (!$feed_search) {
@@ -141,9 +139,8 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo {
/**
* @param array{'url'?:string,'kind'?:int,'category'?:int,'name'?:string,'website'?:string,'description'?:string,'lastUpdate'?:int,'priority'?:int,
* 'pathEntries'?:string,'httpAuth'?:string,'error'?:int,'ttl'?:int,'attributes'?:string|array<string,mixed>} $valuesTmp $valuesTmp
- * @return int|false
*/
- public function updateFeed(int $id, array $valuesTmp) {
+ public function updateFeed(int $id, array $valuesTmp): int|false {
$values = [];
$originalValues = $valuesTmp;
if (isset($valuesTmp['name'])) {
@@ -191,9 +188,8 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo {
/**
* @param non-empty-string $key
* @param string|array<mixed>|bool|int|null $value
- * @return int|false
*/
- public function updateFeedAttribute(FreshRSS_Feed $feed, string $key, $value) {
+ public function updateFeedAttribute(FreshRSS_Feed $feed, string $key, $value): int|false {
$feed->_attribute($key, $value);
return $this->updateFeed(
$feed->id(),
@@ -202,10 +198,9 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo {
}
/**
- * @return int|false
* @see updateCachedValues()
*/
- public function updateLastUpdate(int $id, bool $inError = false, int $mtime = 0) {
+ public function updateLastUpdate(int $id, bool $inError = false, int $mtime = 0): int|false {
$sql = 'UPDATE `_feed` SET `lastUpdate`=?, error=? WHERE id=?';
$values = [
$mtime <= 0 ? time() : $mtime,
@@ -223,14 +218,12 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo {
}
}
- /** @return int|false */
- public function mute(int $id, bool $value = true) {
+ public function mute(int $id, bool $value = true): int|false {
$sql = 'UPDATE `_feed` SET ttl=' . ($value ? '-' : '') . 'ABS(ttl) WHERE id=' . intval($id);
return $this->pdo->exec($sql);
}
- /** @return int|false */
- public function changeCategory(int $idOldCat, int $idNewCat) {
+ public function changeCategory(int $idOldCat, int $idNewCat): int|false {
$catDAO = FreshRSS_Factory::createCategoryDao();
$newCat = $catDAO->searchById($idNewCat);
if ($newCat === null) {
@@ -257,8 +250,7 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo {
}
}
- /** @return int|false */
- public function deleteFeed(int $id) {
+ public function deleteFeed(int $id): int|false {
$sql = 'DELETE FROM `_feed` WHERE id=?';
$stm = $this->pdo->prepare($sql);
@@ -275,9 +267,8 @@ class FreshRSS_FeedDAO extends Minz_ModelPdo {
/**
* @param bool|null $muted to include only muted feeds
- * @return int|false
*/
- public function deleteFeedByCategory(int $id, ?bool $muted = null) {
+ public function deleteFeedByCategory(int $id, ?bool $muted = null): int|false {
$sql = 'DELETE FROM `_feed` WHERE category=?';
if ($muted) {
$sql .= ' AND ttl < 0';
@@ -454,9 +445,8 @@ SQL;
/**
* Update cached values for selected feeds, or all feeds if no feed ID is provided.
- * @return int|false
*/
- public function updateCachedValues(int ...$feedIds) {
+ public function updateCachedValues(int ...$feedIds): int|false {
//2 sub-requests with FOREIGN KEY(e.id_feed), INDEX(e.is_read) faster than 1 request with GROUP BY or CASE
$sql = <<<SQL
UPDATE `_feed`
@@ -480,7 +470,7 @@ SQL;
* Remember to call updateCachedValues() after calling this function
* @return int|false number of lines affected or false in case of error
*/
- public function markAsReadMaxUnread(int $id, int $n) {
+ public function markAsReadMaxUnread(int $id, int $n): int|false {
//Double SELECT for MySQL workaround ERROR 1093 (HY000)
$sql = <<<'SQL'
UPDATE `_entry` SET is_read=1
@@ -509,7 +499,7 @@ SQL;
* Remember to call updateCachedValues() after calling this function
* @return int|false number of lines affected or false in case of error
*/
- public function markAsReadNotSeen(int $id, int $minLastSeen) {
+ public function markAsReadNotSeen(int $id, int $minLastSeen): int|false {
$sql = <<<'SQL'
UPDATE `_entry` SET is_read=1
WHERE id_feed=:id_feed AND is_read=0 AND (`lastSeen` + 10 < :min_last_seen)
@@ -527,10 +517,7 @@ SQL;
}
}
- /**
- * @return int|false
- */
- public function truncate(int $id) {
+ public function truncate(int $id): int|false {
$sql = 'DELETE FROM `_entry` WHERE id_feed=:id';
$stm = $this->pdo->prepare($sql);
$this->pdo->beginTransaction();
diff --git a/app/Models/FormAuth.php b/app/Models/FormAuth.php
index a8b4dab8a..5bd6d97bc 100644
--- a/app/Models/FormAuth.php
+++ b/app/Models/FormAuth.php
@@ -38,8 +38,7 @@ class FreshRSS_FormAuth {
return [];
}
- /** @return string|false */
- private static function renewCookie(string $token) {
+ private static function renewCookie(string $token): string|false {
$token_file = DATA_PATH . '/tokens/' . $token . '.txt';
if (touch($token_file)) {
$limits = FreshRSS_Context::systemConf()->limits;
@@ -51,8 +50,7 @@ class FreshRSS_FormAuth {
return false;
}
- /** @return string|false */
- public static function makeCookie(string $username, string $password_hash) {
+ public static function makeCookie(string $username, string $password_hash): string|false {
do {
$token = sha1(FreshRSS_Context::systemConf()->salt . $username . uniqid('' . mt_rand(), true));
$token_file = DATA_PATH . '/tokens/' . $token . '.txt';
diff --git a/app/Models/Search.php b/app/Models/Search.php
index 31b3d8d5a..7eaf741c3 100644
--- a/app/Models/Search.php
+++ b/app/Models/Search.php
@@ -135,11 +135,11 @@ class FreshRSS_Search {
}
/** @return array<int>|'*'|null */
- public function getLabelIds() {
+ public function getLabelIds(): array|string|null {
return $this->label_ids;
}
/** @return array<int>|'*'|null */
- public function getNotLabelIds() {
+ public function getNotLabelIds(): array|string|null {
return $this->not_label_ids;
}
/** @return array<string>|null */
@@ -242,7 +242,7 @@ class FreshRSS_Search {
* @param array<string>|string $value
* @return ($value is array ? array<string> : string)
*/
- private static function decodeSpaces($value) {
+ private static function decodeSpaces($value): array|string {
if (is_array($value)) {
for ($i = count($value) - 1; $i >= 0; $i--) {
$value[$i] = self::decodeSpaces($value[$i]);
diff --git a/app/Models/Share.php b/app/Models/Share.php
index 9c8f2084e..2df9dd4d9 100644
--- a/app/Models/Share.php
+++ b/app/Models/Share.php
@@ -106,9 +106,7 @@ class FreshRSS_Share {
* decentralized ones.
* @param string $help_url is an optional url to give help on this option.
* @param 'GET'|'POST' $method defines the sharing method (GET or POST)
- * @param string|null $field
* @param 'button'|null $HTMLtag
- * @param bool $isDeprecated
*/
private function __construct(string $type, string $url_transform, array $transforms, string $form_type,
string $help_url, string $method, ?string $field, ?string $HTMLtag, bool $isDeprecated = false) {
diff --git a/app/Models/StatsDAO.php b/app/Models/StatsDAO.php
index 6331e24f2..c9753cf2c 100644
--- a/app/Models/StatsDAO.php
+++ b/app/Models/StatsDAO.php
@@ -31,7 +31,7 @@ class FreshRSS_StatsDAO extends Minz_ModelPdo {
*
* @return array{'total':int,'count_unreads':int,'count_reads':int,'count_favorites':int}|false
*/
- public function calculateEntryRepartitionPerFeed(?int $feed = null, bool $only_main = false) {
+ public function calculateEntryRepartitionPerFeed(?int $feed = null, bool $only_main = false): array|false {
$filter = '';
if ($only_main) {
$filter .= 'AND f.priority = 10';
diff --git a/app/Models/Tag.php b/app/Models/Tag.php
index 0ed7c462c..9a3baffcd 100644
--- a/app/Models/Tag.php
+++ b/app/Models/Tag.php
@@ -17,10 +17,7 @@ class FreshRSS_Tag extends Minz_Model {
return $this->id;
}
- /**
- * @param int|string $value
- */
- public function _id($value): void {
+ public function _id(int|string $value): void {
$this->id = (int)$value;
}
@@ -40,10 +37,7 @@ class FreshRSS_Tag extends Minz_Model {
return $this->nbEntries;
}
- /**
- * @param string|int $value
- */
- public function _nbEntries($value): void {
+ public function _nbEntries(int|string $value): void {
$this->nbEntries = (int)$value;
}
@@ -55,10 +49,7 @@ class FreshRSS_Tag extends Minz_Model {
return $this->nbUnread;
}
- /**
- * @param string|int $value
- */
- public function _nbUnread($value): void {
+ public function _nbUnread(int|string $value): void {
$this->nbUnread = (int)$value;
}
}
diff --git a/app/Models/TagDAO.php b/app/Models/TagDAO.php
index 1feba263e..920a09c2c 100644
--- a/app/Models/TagDAO.php
+++ b/app/Models/TagDAO.php
@@ -9,9 +9,8 @@ class FreshRSS_TagDAO extends Minz_ModelPdo {
/**
* @param array{'id'?:int,'name':string,'attributes'?:array<string,mixed>} $valuesTmp
- * @return int|false
*/
- public function addTag(array $valuesTmp) {
+ public function addTag(array $valuesTmp): int|false {
// TRIM() gives a text type hint to PostgreSQL
// No category of the same name
$sql = <<<'SQL'
@@ -41,8 +40,7 @@ SQL;
}
}
- /** @return int|false */
- public function addTagObject(FreshRSS_Tag $tag) {
+ public function addTagObject(FreshRSS_Tag $tag): int|false {
$tag0 = $this->searchByName($tag->name());
if (!$tag0) {
$values = [
@@ -54,8 +52,7 @@ SQL;
return $tag->id();
}
- /** @return int|false */
- public function updateTagName(int $id, string $name) {
+ public function updateTagName(int $id, string $name): int|false {
// No category of the same name
$sql = <<<'SQL'
UPDATE `_tag` SET name = :name1 WHERE id = :id
@@ -79,9 +76,8 @@ SQL;
/**
* @param array<string,mixed> $attributes
- * @return int|false
*/
- public function updateTagAttributes(int $id, array $attributes) {
+ public function updateTagAttributes(int $id, array $attributes): int|false {
$sql = 'UPDATE `_tag` SET attributes=:attributes WHERE id=:id';
$stm = $this->pdo->prepare($sql);
if ($stm !== false &&
@@ -97,18 +93,13 @@ SQL;
/**
* @param non-empty-string $key
- * @param mixed $value
- * @return int|false
*/
- public function updateTagAttribute(FreshRSS_Tag $tag, string $key, $value) {
+ public function updateTagAttribute(FreshRSS_Tag $tag, string $key, mixed $value): int|false {
$tag->_attribute($key, $value);
return $this->updateTagAttributes($tag->id(), $tag->attributes());
}
- /**
- * @return int|false
- */
- public function deleteTag(int $id) {
+ public function deleteTag(int $id): int|false {
if ($id <= 0) {
return false;
}
@@ -155,8 +146,7 @@ SQL;
}
}
- /** @return int|false */
- public function updateEntryTag(int $oldTagId, int $newTagId) {
+ public function updateEntryTag(int $oldTagId, int $newTagId): int|false {
$sql = <<<'SQL'
DELETE FROM `_entrytag` WHERE EXISTS (
SELECT 1 FROM `_entrytag` AS e
@@ -194,7 +184,7 @@ SQL;
}
/** @return array<int,FreshRSS_Tag>|false */
- public function listTags(bool $precounts = false) {
+ public function listTags(bool $precounts = false): array|false {
if ($precounts) {
$sql = <<<'SQL'
SELECT t.id, t.name, count(e.id) AS unreads
@@ -304,7 +294,7 @@ SQL;
* @param array<array{id_tag:int,id_entry:string}> $addLabels Labels to insert as batch
* @return int|false Number of new entries or false in case of error
*/
- public function tagEntries(array $addLabels) {
+ public function tagEntries(array $addLabels): int|false {
$hasValues = false;
$sql = 'INSERT ' . $this->sqlIgnore() . ' INTO `_entrytag`(id_tag, id_entry) VALUES ';
foreach ($addLabels as $addLabel) {
@@ -332,7 +322,7 @@ SQL;
/**
* @return array<int,array{'id':int,'name':string,'id_entry':string,'checked':bool}>|false
*/
- public function getTagsForEntry(string $id_entry) {
+ public function getTagsForEntry(string $id_entry): array|false {
$sql = <<<'SQL'
SELECT t.id, t.name, et.id_entry IS NOT NULL as checked
FROM `_tag` t
@@ -360,7 +350,7 @@ SQL;
* @param array<FreshRSS_Entry|numeric-string|array<string,string>> $entries
* @return array<array{'id_entry':string,'id_tag':int,'name':string}>|false
*/
- public function getTagsForEntries(array $entries) {
+ public function getTagsForEntries(array $entries): array|false {
$sql = <<<'SQL'
SELECT et.id_entry, et.id_tag, t.name
FROM `_tag` t
diff --git a/app/Models/Themes.php b/app/Models/Themes.php
index 04ce0a36d..055db42e5 100644
--- a/app/Models/Themes.php
+++ b/app/Models/Themes.php
@@ -31,7 +31,7 @@ class FreshRSS_Themes extends Minz_Model {
/**
* @return false|array{'id':string,'name':string,'author':string,'description':string,'version':float|string,'files':array<string>,'theme-color'?:string|array{'dark'?:string,'light'?:string,'default'?:string}}
*/
- public static function get_infos(string $theme_id) {
+ public static function get_infos(string $theme_id): array|false {
$theme_dir = PUBLIC_PATH . self::$themesUrl . $theme_id;
if (is_dir($theme_dir)) {
$json_filename = $theme_dir . '/metadata.json';
@@ -58,7 +58,7 @@ class FreshRSS_Themes extends Minz_Model {
/**
* @return false|array{'id':string,'name':string,'author':string,'description':string,'version':float|string,'files':array<string>,'theme-color'?:string|array{'dark'?:string,'light'?:string,'default'?:string}}
*/
- public static function load(string $theme_id) {
+ public static function load(string $theme_id): array|false {
$infos = self::get_infos($theme_id);
if (!$infos) {
if ($theme_id !== self::$defaultTheme) { //Fall-back to default theme
diff --git a/app/Services/ExportService.php b/app/Services/ExportService.php
index 91c8c91e3..ba4042d21 100644
--- a/app/Services/ExportService.php
+++ b/app/Services/ExportService.php
@@ -16,13 +16,13 @@ class FreshRSS_Export_Service {
private FreshRSS_TagDAO $tag_dao;
- public const FRSS_NAMESPACE = 'https://freshrss.org/opml';
- public const TYPE_HTML_XPATH = 'HTML+XPath';
- public const TYPE_XML_XPATH = 'XML+XPath';
- public const TYPE_RSS_ATOM = 'rss';
- public const TYPE_JSON_DOTPATH = 'JSON+DotPath'; // Legacy 1.24.0-dev
- public const TYPE_JSON_DOTNOTATION = 'JSON+DotNotation';
- public const TYPE_JSONFEED = 'JSONFeed';
+ final public const FRSS_NAMESPACE = 'https://freshrss.org/opml';
+ final public const TYPE_HTML_XPATH = 'HTML+XPath';
+ final public const TYPE_XML_XPATH = 'XML+XPath';
+ final public const TYPE_RSS_ATOM = 'rss';
+ final public const TYPE_JSON_DOTPATH = 'JSON+DotPath'; // Legacy 1.24.0-dev
+ final public const TYPE_JSON_DOTNOTATION = 'JSON+DotNotation';
+ final public const TYPE_JSONFEED = 'JSONFeed';
/**
* Initialize the service for the given user.
@@ -87,8 +87,6 @@ class FreshRSS_Export_Service {
/**
* Generate the entries file content for the given feed.
- * @param int $feed_id
- * @param int $max_number_entries
* @return array{0:string,1:string}|null First item is the filename, second item is the content.
* It also can return null if the feed doesn’t exist.
*/
@@ -124,7 +122,6 @@ class FreshRSS_Export_Service {
/**
* Generate the entries file content for all the feeds.
- * @param int $max_number_entries
* @return array<string,string> Keys are filenames and values are contents.
*/
public function generateAllFeedEntries(int $max_number_entries): array {
diff --git a/app/Services/ImportService.php b/app/Services/ImportService.php
index 11da49217..8060e4d51 100644
--- a/app/Services/ImportService.php
+++ b/app/Services/ImportService.php
@@ -362,10 +362,8 @@ class FreshRSS_Import_Service {
* This method is applied to a list of outlines. It merges the different
* list of feeds from several outlines into one array.
*
- * @param array<array<mixed>> $outlines
- * The outlines from which to extract the outlines.
- * @param string $parent_category_name
- * The name of the parent category of the current outlines.
+ * @param array<array<mixed>> $outlines The outlines from which to extract the outlines.
+ * @param string $parent_category_name The name of the parent category of the current outlines.
* @return array{0:array<string,array<string,string>>,1:array<string,array<array<string,string>>>}
*/
private function loadFromOutlines(array $outlines, string $parent_category_name): array {
@@ -405,10 +403,8 @@ class FreshRSS_Import_Service {
* exists), it will add the outline to an array accessible by its category
* name.
*
- * @param array<mixed> $outline
- * The outline from which to extract the categories and feeds outlines.
- * @param string $parent_category_name
- * The name of the parent category of the current outline.
+ * @param array<mixed> $outline The outline from which to extract the categories and feeds outlines.
+ * @param string $parent_category_name The name of the parent category of the current outline.
*
* @return array{0:array<string,array<string,string>>,1:array<array<string,array<string,string>>>}
*/
diff --git a/app/Utils/dotNotationUtil.php b/app/Utils/dotNotationUtil.php
index 9c44e5312..73addbe74 100644
--- a/app/Utils/dotNotationUtil.php
+++ b/app/Utils/dotNotationUtil.php
@@ -12,11 +12,8 @@ final class FreshRSS_dotNotation_Util
* https://github.com/laravel/framework/blob/10.x/src/Illuminate/Collections/Arr.php#L302-L337
*
* @param \ArrayAccess<string,mixed>|array<string,mixed>|mixed $array
- * @param string|null $key
- * @param mixed $default
- * @return mixed
*/
- public static function get($array, ?string $key, mixed $default = null) {
+ public static function get($array, ?string $key, mixed $default = null): mixed {
if (!static::accessible($array)) {
return static::value($default);
}
@@ -51,7 +48,6 @@ final class FreshRSS_dotNotation_Util
* Get a string from an array using "dot" notation.
*
* @param \ArrayAccess<string,mixed>|array<string,mixed>|mixed $array
- * @param string|null $key
*/
public static function getString($array, ?string $key): ?string {
$result = self::get($array, $key, null);
@@ -60,11 +56,8 @@ final class FreshRSS_dotNotation_Util
/**
* Determine whether the given value is array accessible.
- *
- * @param mixed $value
- * @return bool
*/
- private static function accessible($value): bool {
+ private static function accessible(mixed $value): bool {
return is_array($value) || $value instanceof \ArrayAccess;
}
@@ -72,8 +65,6 @@ final class FreshRSS_dotNotation_Util
* Determine if the given key exists in the provided array.
*
* @param \ArrayAccess<string,mixed>|array<string,mixed>|mixed $array
- * @param string $key
- * @return bool
*/
private static function exists($array, string $key): bool {
if ($array instanceof \ArrayAccess) {
@@ -85,8 +76,7 @@ final class FreshRSS_dotNotation_Util
return false;
}
- /** @param mixed $value */
- private static function value($value): mixed {
+ private static function value(mixed $value): mixed {
return $value instanceof Closure ? $value() : $value;
}
diff --git a/app/Utils/feverUtil.php b/app/Utils/feverUtil.php
index 571c2bc00..8b06568dd 100644
--- a/app/Utils/feverUtil.php
+++ b/app/Utils/feverUtil.php
@@ -38,7 +38,7 @@ class FreshRSS_fever_Util {
* @return string|false the Fever key, or false if the update failed
* @throws FreshRSS_Context_Exception
*/
- public static function updateKey(string $username, string $passwordPlain) {
+ public static function updateKey(string $username, string $passwordPlain): string|false {
if (!self::checkFeverPath()) {
return false;
}
diff --git a/cli/_cli.php b/cli/_cli.php
index 9d9d9c32d..9486405aa 100755
--- a/cli/_cli.php
+++ b/cli/_cli.php
@@ -20,8 +20,7 @@ Minz_Translate::init('en');
FreshRSS_Context::$isCli = true;
-/** @return never */
-function fail(string $message, int $exitCode = 1) {
+function fail(string $message, int $exitCode = 1): never {
fwrite(STDERR, $message . "\n");
die($exitCode);
}
@@ -51,8 +50,7 @@ function accessRights(): void {
"\t", 'sudo cli/access-permissions.sh', "\n";
}
-/** @return never */
-function done(bool $ok = true) {
+function done(bool $ok = true): never {
if (!$ok) {
fwrite(STDERR, (empty($_SERVER['argv'][0]) ? 'Process' : basename($_SERVER['argv'][0])) . ' failed!' . "\n");
}
diff --git a/cli/check.translation.php b/cli/check.translation.php
index 0da415d85..b452054ed 100755
--- a/cli/check.translation.php
+++ b/cli/check.translation.php
@@ -102,9 +102,8 @@ function findUsedTranslations(): array {
/**
* Output help message.
- * @return never
*/
-function checkHelp() {
+function checkHelp(): never {
$file = str_replace(__DIR__ . '/', '', __FILE__);
echo <<<HELP
diff --git a/cli/i18n/I18nFile.php b/cli/i18n/I18nFile.php
index 8085164c5..5d310d6bf 100644
--- a/cli/i18n/I18nFile.php
+++ b/cli/i18n/I18nFile.php
@@ -82,7 +82,6 @@ class I18nFile {
* Flatten an array of translation
*
* @param array<string,I18nValue|array<string,I18nValue>> $translation
- * @param string $prefix
* @return array<string,I18nValue>
*/
private function flatten(array $translation, string $prefix = ''): array {
diff --git a/cli/i18n/I18nValue.php b/cli/i18n/I18nValue.php
index 03e7676ae..aa2a670e1 100644
--- a/cli/i18n/I18nValue.php
+++ b/cli/i18n/I18nValue.php
@@ -32,7 +32,7 @@ class I18nValue {
}
}
- public function __clone() {
+ public function __clone(): void {
$this->markAsTodo();
}
diff --git a/composer.json b/composer.json
index c654e4db5..f2d27bb1a 100644
--- a/composer.json
+++ b/composer.json
@@ -17,7 +17,7 @@
"WebSub"
],
"require": {
- "php": ">=7.4",
+ "php": ">=8.1",
"ext-ctype": "*",
"ext-curl": "*",
"ext-dom": "*",
@@ -49,18 +49,18 @@
"phpstan/extension-installer": false
},
"platform": {
- "php": "7.4"
+ "php": "8.1"
}
},
"require-dev": {
- "php": ">=7.4",
+ "php": ">=8.1",
"ext-phar": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"phpstan/phpstan": "^1.11",
"phpstan/phpstan-phpunit": "^1.4",
"phpstan/phpstan-strict-rules": "^1.6",
- "phpunit/phpunit": "^9",
+ "phpunit/phpunit": "^10",
"squizlabs/php_codesniffer": "^3.9"
},
"scripts": {
@@ -70,7 +70,7 @@
"phpcbf": "phpcbf . -p -s",
"phpstan": "phpstan analyse --memory-limit 512M .",
"phpstan-next": "phpstan analyse --memory-limit 512M -c phpstan-next.neon .",
- "phpunit": "phpunit --bootstrap ./tests/bootstrap.php --verbose ./tests",
+ "phpunit": "phpunit --bootstrap ./tests/bootstrap.php --display-notices ./tests",
"translations": "cli/manipulate.translation.php -a format",
"test": [
"@php-lint",
diff --git a/composer.lock b/composer.lock
index 67502ba9b..6d5f7e045 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,80 +4,10 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "2dcd52d3495f0c8bbca900f58e469323",
+ "content-hash": "2857227089a97e428fe66e5f6c207e8d",
"packages": [],
"packages-dev": [
{
- "name": "doctrine/instantiator",
- "version": "1.5.0",
- "source": {
- "type": "git",
- "url": "https://github.com/doctrine/instantiator.git",
- "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b",
- "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b",
- "shasum": ""
- },
- "require": {
- "php": "^7.1 || ^8.0"
- },
- "require-dev": {
- "doctrine/coding-standard": "^9 || ^11",
- "ext-pdo": "*",
- "ext-phar": "*",
- "phpbench/phpbench": "^0.16 || ^1",
- "phpstan/phpstan": "^1.4",
- "phpstan/phpstan-phpunit": "^1",
- "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5",
- "vimeo/psalm": "^4.30 || ^5.4"
- },
- "type": "library",
- "autoload": {
- "psr-4": {
- "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/"
- }
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "MIT"
- ],
- "authors": [
- {
- "name": "Marco Pivetta",
- "email": "ocramius@gmail.com",
- "homepage": "https://ocramius.github.io/"
- }
- ],
- "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors",
- "homepage": "https://www.doctrine-project.org/projects/instantiator.html",
- "keywords": [
- "constructor",
- "instantiate"
- ],
- "support": {
- "issues": "https://github.com/doctrine/instantiator/issues",
- "source": "https://github.com/doctrine/instantiator/tree/1.5.0"
- },
- "funding": [
- {
- "url": "https://www.doctrine-project.org/sponsorship.html",
- "type": "custom"
- },
- {
- "url": "https://www.patreon.com/phpdoctrine",
- "type": "patreon"
- },
- {
- "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator",
- "type": "tidelift"
- }
- ],
- "time": "2022-12-30T00:15:36+00:00"
- },
- {
"name": "myclabs/deep-copy",
"version": "1.12.0",
"source": {
@@ -315,16 +245,16 @@
},
{
"name": "phpstan/phpstan",
- "version": "1.12.0",
+ "version": "1.12.1",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan.git",
- "reference": "384af967d35b2162f69526c7276acadce534d0e1"
+ "reference": "d8ed7fffa66de1db0d2972267d8ed1d8fa0fe5a2"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/384af967d35b2162f69526c7276acadce534d0e1",
- "reference": "384af967d35b2162f69526c7276acadce534d0e1",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/d8ed7fffa66de1db0d2972267d8ed1d8fa0fe5a2",
+ "reference": "d8ed7fffa66de1db0d2972267d8ed1d8fa0fe5a2",
"shasum": ""
},
"require": {
@@ -369,7 +299,7 @@
"type": "github"
}
],
- "time": "2024-08-27T09:18:05+00:00"
+ "time": "2024-09-03T19:55:22+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
@@ -474,16 +404,16 @@
},
{
"name": "phpunit/php-code-coverage",
- "version": "9.2.32",
+ "version": "10.1.16",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git",
- "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5"
+ "reference": "7e308268858ed6baedc8704a304727d20bc07c77"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5",
- "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77",
+ "reference": "7e308268858ed6baedc8704a304727d20bc07c77",
"shasum": ""
},
"require": {
@@ -491,18 +421,18 @@
"ext-libxml": "*",
"ext-xmlwriter": "*",
"nikic/php-parser": "^4.19.1 || ^5.1.0",
- "php": ">=7.3",
- "phpunit/php-file-iterator": "^3.0.6",
- "phpunit/php-text-template": "^2.0.4",
- "sebastian/code-unit-reverse-lookup": "^2.0.3",
- "sebastian/complexity": "^2.0.3",
- "sebastian/environment": "^5.1.5",
- "sebastian/lines-of-code": "^1.0.4",
- "sebastian/version": "^3.0.2",
+ "php": ">=8.1",
+ "phpunit/php-file-iterator": "^4.1.0",
+ "phpunit/php-text-template": "^3.0.1",
+ "sebastian/code-unit-reverse-lookup": "^3.0.0",
+ "sebastian/complexity": "^3.2.0",
+ "sebastian/environment": "^6.1.0",
+ "sebastian/lines-of-code": "^2.0.2",
+ "sebastian/version": "^4.0.1",
"theseer/tokenizer": "^1.2.3"
},
"require-dev": {
- "phpunit/phpunit": "^9.6"
+ "phpunit/phpunit": "^10.1"
},
"suggest": {
"ext-pcov": "PHP extension that provides line coverage",
@@ -511,7 +441,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-main": "9.2.x-dev"
+ "dev-main": "10.1.x-dev"
}
},
"autoload": {
@@ -540,7 +470,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
- "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32"
+ "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16"
},
"funding": [
{
@@ -548,32 +478,32 @@
"type": "github"
}
],
- "time": "2024-08-22T04:23:01+00:00"
+ "time": "2024-08-22T04:31:57+00:00"
},
{
"name": "phpunit/php-file-iterator",
- "version": "3.0.6",
+ "version": "4.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-file-iterator.git",
- "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf"
+ "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
- "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c",
+ "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-main": "4.0-dev"
}
},
"autoload": {
@@ -600,7 +530,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-file-iterator/issues",
- "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6"
+ "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0"
},
"funding": [
{
@@ -608,28 +539,28 @@
"type": "github"
}
],
- "time": "2021-12-02T12:48:52+00:00"
+ "time": "2023-08-31T06:24:48+00:00"
},
{
"name": "phpunit/php-invoker",
- "version": "3.1.1",
+ "version": "4.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-invoker.git",
- "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67"
+ "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
- "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7",
+ "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
"ext-pcntl": "*",
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"suggest": {
"ext-pcntl": "*"
@@ -637,7 +568,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.1-dev"
+ "dev-main": "4.0-dev"
}
},
"autoload": {
@@ -663,7 +594,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-invoker/issues",
- "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1"
+ "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0"
},
"funding": [
{
@@ -671,32 +602,32 @@
"type": "github"
}
],
- "time": "2020-09-28T05:58:55+00:00"
+ "time": "2023-02-03T06:56:09+00:00"
},
{
"name": "phpunit/php-text-template",
- "version": "2.0.4",
+ "version": "3.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-text-template.git",
- "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28"
+ "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
- "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748",
+ "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-main": "3.0-dev"
}
},
"autoload": {
@@ -722,7 +653,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-text-template/issues",
- "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4"
+ "security": "https://github.com/sebastianbergmann/php-text-template/security/policy",
+ "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1"
},
"funding": [
{
@@ -730,32 +662,32 @@
"type": "github"
}
],
- "time": "2020-10-26T05:33:50+00:00"
+ "time": "2023-08-31T14:07:24+00:00"
},
{
"name": "phpunit/php-timer",
- "version": "5.0.3",
+ "version": "6.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/php-timer.git",
- "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2"
+ "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
- "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2",
+ "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d",
+ "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.0-dev"
+ "dev-main": "6.0-dev"
}
},
"autoload": {
@@ -781,7 +713,7 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/php-timer/issues",
- "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3"
+ "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0"
},
"funding": [
{
@@ -789,24 +721,23 @@
"type": "github"
}
],
- "time": "2020-10-26T13:16:10+00:00"
+ "time": "2023-02-03T06:57:52+00:00"
},
{
"name": "phpunit/phpunit",
- "version": "9.6.20",
+ "version": "10.5.32",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "49d7820565836236411f5dc002d16dd689cde42f"
+ "reference": "f069f46840445d37a4e6f0de8c5879598f9c4327"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/49d7820565836236411f5dc002d16dd689cde42f",
- "reference": "49d7820565836236411f5dc002d16dd689cde42f",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f069f46840445d37a4e6f0de8c5879598f9c4327",
+ "reference": "f069f46840445d37a4e6f0de8c5879598f9c4327",
"shasum": ""
},
"require": {
- "doctrine/instantiator": "^1.5.0 || ^2",
"ext-dom": "*",
"ext-json": "*",
"ext-libxml": "*",
@@ -816,27 +747,26 @@
"myclabs/deep-copy": "^1.12.0",
"phar-io/manifest": "^2.0.4",
"phar-io/version": "^3.2.1",
- "php": ">=7.3",
- "phpunit/php-code-coverage": "^9.2.31",
- "phpunit/php-file-iterator": "^3.0.6",
- "phpunit/php-invoker": "^3.1.1",
- "phpunit/php-text-template": "^2.0.4",
- "phpunit/php-timer": "^5.0.3",
- "sebastian/cli-parser": "^1.0.2",
- "sebastian/code-unit": "^1.0.8",
- "sebastian/comparator": "^4.0.8",
- "sebastian/diff": "^4.0.6",
- "sebastian/environment": "^5.1.5",
- "sebastian/exporter": "^4.0.6",
- "sebastian/global-state": "^5.0.7",
- "sebastian/object-enumerator": "^4.0.4",
- "sebastian/resource-operations": "^3.0.4",
- "sebastian/type": "^3.2.1",
- "sebastian/version": "^3.0.2"
+ "php": ">=8.1",
+ "phpunit/php-code-coverage": "^10.1.16",
+ "phpunit/php-file-iterator": "^4.1.0",
+ "phpunit/php-invoker": "^4.0.0",
+ "phpunit/php-text-template": "^3.0.1",
+ "phpunit/php-timer": "^6.0.0",
+ "sebastian/cli-parser": "^2.0.1",
+ "sebastian/code-unit": "^2.0.0",
+ "sebastian/comparator": "^5.0.2",
+ "sebastian/diff": "^5.1.1",
+ "sebastian/environment": "^6.1.0",
+ "sebastian/exporter": "^5.1.2",
+ "sebastian/global-state": "^6.0.2",
+ "sebastian/object-enumerator": "^5.0.0",
+ "sebastian/recursion-context": "^5.0.0",
+ "sebastian/type": "^4.0.0",
+ "sebastian/version": "^4.0.1"
},
"suggest": {
- "ext-soap": "To be able to generate mocks based on WSDL files",
- "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage"
+ "ext-soap": "To be able to generate mocks based on WSDL files"
},
"bin": [
"phpunit"
@@ -844,7 +774,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "9.6-dev"
+ "dev-main": "10.5-dev"
}
},
"autoload": {
@@ -876,7 +806,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.20"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.32"
},
"funding": [
{
@@ -892,32 +822,32 @@
"type": "tidelift"
}
],
- "time": "2024-07-10T11:45:39+00:00"
+ "time": "2024-09-04T13:33:39+00:00"
},
{
"name": "sebastian/cli-parser",
- "version": "1.0.2",
+ "version": "2.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/cli-parser.git",
- "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b"
+ "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b",
- "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b",
+ "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084",
+ "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0-dev"
+ "dev-main": "2.0-dev"
}
},
"autoload": {
@@ -940,7 +870,8 @@
"homepage": "https://github.com/sebastianbergmann/cli-parser",
"support": {
"issues": "https://github.com/sebastianbergmann/cli-parser/issues",
- "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2"
+ "security": "https://github.com/sebastianbergmann/cli-parser/security/policy",
+ "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1"
},
"funding": [
{
@@ -948,32 +879,32 @@
"type": "github"
}
],
- "time": "2024-03-02T06:27:43+00:00"
+ "time": "2024-03-02T07:12:49+00:00"
},
{
"name": "sebastian/code-unit",
- "version": "1.0.8",
+ "version": "2.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit.git",
- "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120"
+ "reference": "a81fee9eef0b7a76af11d121767abc44c104e503"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120",
- "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503",
+ "reference": "a81fee9eef0b7a76af11d121767abc44c104e503",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0-dev"
+ "dev-main": "2.0-dev"
}
},
"autoload": {
@@ -996,7 +927,7 @@
"homepage": "https://github.com/sebastianbergmann/code-unit",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit/issues",
- "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8"
+ "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0"
},
"funding": [
{
@@ -1004,32 +935,32 @@
"type": "github"
}
],
- "time": "2020-10-26T13:08:54+00:00"
+ "time": "2023-02-03T06:58:43+00:00"
},
{
"name": "sebastian/code-unit-reverse-lookup",
- "version": "2.0.3",
+ "version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git",
- "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5"
+ "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
- "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5",
+ "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d",
+ "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-main": "3.0-dev"
}
},
"autoload": {
@@ -1051,7 +982,7 @@
"homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/",
"support": {
"issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues",
- "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3"
+ "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0"
},
"funding": [
{
@@ -1059,34 +990,36 @@
"type": "github"
}
],
- "time": "2020-09-28T05:30:19+00:00"
+ "time": "2023-02-03T06:59:15+00:00"
},
{
"name": "sebastian/comparator",
- "version": "4.0.8",
+ "version": "5.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/comparator.git",
- "reference": "fa0f136dd2334583309d32b62544682ee972b51a"
+ "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/fa0f136dd2334583309d32b62544682ee972b51a",
- "reference": "fa0f136dd2334583309d32b62544682ee972b51a",
+ "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53",
+ "reference": "2d3e04c3b4c1e84a5e7382221ad8883c8fbc4f53",
"shasum": ""
},
"require": {
- "php": ">=7.3",
- "sebastian/diff": "^4.0",
- "sebastian/exporter": "^4.0"
+ "ext-dom": "*",
+ "ext-mbstring": "*",
+ "php": ">=8.1",
+ "sebastian/diff": "^5.0",
+ "sebastian/exporter": "^5.0"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.4"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-main": "5.0-dev"
}
},
"autoload": {
@@ -1125,7 +1058,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/comparator/issues",
- "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.8"
+ "security": "https://github.com/sebastianbergmann/comparator/security/policy",
+ "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.2"
},
"funding": [
{
@@ -1133,33 +1067,33 @@
"type": "github"
}
],
- "time": "2022-09-14T12:41:17+00:00"
+ "time": "2024-08-12T06:03:08+00:00"
},
{
"name": "sebastian/complexity",
- "version": "2.0.3",
+ "version": "3.2.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/complexity.git",
- "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a"
+ "reference": "68ff824baeae169ec9f2137158ee529584553799"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a",
- "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a",
+ "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799",
+ "reference": "68ff824baeae169ec9f2137158ee529584553799",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.18 || ^5.0",
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-main": "3.2-dev"
}
},
"autoload": {
@@ -1182,7 +1116,8 @@
"homepage": "https://github.com/sebastianbergmann/complexity",
"support": {
"issues": "https://github.com/sebastianbergmann/complexity/issues",
- "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3"
+ "security": "https://github.com/sebastianbergmann/complexity/security/policy",
+ "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0"
},
"funding": [
{
@@ -1190,33 +1125,33 @@
"type": "github"
}
],
- "time": "2023-12-22T06:19:30+00:00"
+ "time": "2023-12-21T08:37:17+00:00"
},
{
"name": "sebastian/diff",
- "version": "4.0.6",
+ "version": "5.1.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/diff.git",
- "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc"
+ "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc",
- "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc",
+ "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e",
+ "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3",
- "symfony/process": "^4.2 || ^5"
+ "phpunit/phpunit": "^10.0",
+ "symfony/process": "^6.4"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-main": "5.1-dev"
}
},
"autoload": {
@@ -1248,7 +1183,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/diff/issues",
- "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6"
+ "security": "https://github.com/sebastianbergmann/diff/security/policy",
+ "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1"
},
"funding": [
{
@@ -1256,27 +1192,27 @@
"type": "github"
}
],
- "time": "2024-03-02T06:30:58+00:00"
+ "time": "2024-03-02T07:15:17+00:00"
},
{
"name": "sebastian/environment",
- "version": "5.1.5",
+ "version": "6.1.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/environment.git",
- "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed"
+ "reference": "8074dbcd93529b357029f5cc5058fd3e43666984"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed",
- "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed",
+ "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984",
+ "reference": "8074dbcd93529b357029f5cc5058fd3e43666984",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"suggest": {
"ext-posix": "*"
@@ -1284,7 +1220,7 @@
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.1-dev"
+ "dev-main": "6.1-dev"
}
},
"autoload": {
@@ -1303,7 +1239,7 @@
}
],
"description": "Provides functionality to handle HHVM/PHP environments",
- "homepage": "http://www.github.com/sebastianbergmann/environment",
+ "homepage": "https://github.com/sebastianbergmann/environment",
"keywords": [
"Xdebug",
"environment",
@@ -1311,7 +1247,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/environment/issues",
- "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5"
+ "security": "https://github.com/sebastianbergmann/environment/security/policy",
+ "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0"
},
"funding": [
{
@@ -1319,34 +1256,34 @@
"type": "github"
}
],
- "time": "2023-02-03T06:03:51+00:00"
+ "time": "2024-03-23T08:47:14+00:00"
},
{
"name": "sebastian/exporter",
- "version": "4.0.6",
+ "version": "5.1.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/exporter.git",
- "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72"
+ "reference": "955288482d97c19a372d3f31006ab3f37da47adf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/78c00df8f170e02473b682df15bfcdacc3d32d72",
- "reference": "78c00df8f170e02473b682df15bfcdacc3d32d72",
+ "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/955288482d97c19a372d3f31006ab3f37da47adf",
+ "reference": "955288482d97c19a372d3f31006ab3f37da47adf",
"shasum": ""
},
"require": {
- "php": ">=7.3",
- "sebastian/recursion-context": "^4.0"
+ "ext-mbstring": "*",
+ "php": ">=8.1",
+ "sebastian/recursion-context": "^5.0"
},
"require-dev": {
- "ext-mbstring": "*",
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-main": "5.1-dev"
}
},
"autoload": {
@@ -1388,7 +1325,8 @@
],
"support": {
"issues": "https://github.com/sebastianbergmann/exporter/issues",
- "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.6"
+ "security": "https://github.com/sebastianbergmann/exporter/security/policy",
+ "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.2"
},
"funding": [
{
@@ -1396,38 +1334,35 @@
"type": "github"
}
],
- "time": "2024-03-02T06:33:00+00:00"
+ "time": "2024-03-02T07:17:12+00:00"
},
{
"name": "sebastian/global-state",
- "version": "5.0.7",
+ "version": "6.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/global-state.git",
- "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9"
+ "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9",
- "reference": "bca7df1f32ee6fe93b4d4a9abbf69e13a4ada2c9",
+ "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9",
+ "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9",
"shasum": ""
},
"require": {
- "php": ">=7.3",
- "sebastian/object-reflector": "^2.0",
- "sebastian/recursion-context": "^4.0"
+ "php": ">=8.1",
+ "sebastian/object-reflector": "^3.0",
+ "sebastian/recursion-context": "^5.0"
},
"require-dev": {
"ext-dom": "*",
- "phpunit/phpunit": "^9.3"
- },
- "suggest": {
- "ext-uopz": "*"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "5.0-dev"
+ "dev-main": "6.0-dev"
}
},
"autoload": {
@@ -1446,13 +1381,14 @@
}
],
"description": "Snapshotting of global state",
- "homepage": "http://www.github.com/sebastianbergmann/global-state",
+ "homepage": "https://www.github.com/sebastianbergmann/global-state",
"keywords": [
"global state"
],
"support": {
"issues": "https://github.com/sebastianbergmann/global-state/issues",
- "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.7"
+ "security": "https://github.com/sebastianbergmann/global-state/security/policy",
+ "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2"
},
"funding": [
{
@@ -1460,33 +1396,33 @@
"type": "github"
}
],
- "time": "2024-03-02T06:35:11+00:00"
+ "time": "2024-03-02T07:19:19+00:00"
},
{
"name": "sebastian/lines-of-code",
- "version": "1.0.4",
+ "version": "2.0.2",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/lines-of-code.git",
- "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5"
+ "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5",
- "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5",
+ "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0",
+ "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0",
"shasum": ""
},
"require": {
"nikic/php-parser": "^4.18 || ^5.0",
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "1.0-dev"
+ "dev-main": "2.0-dev"
}
},
"autoload": {
@@ -1509,7 +1445,8 @@
"homepage": "https://github.com/sebastianbergmann/lines-of-code",
"support": {
"issues": "https://github.com/sebastianbergmann/lines-of-code/issues",
- "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4"
+ "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy",
+ "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2"
},
"funding": [
{
@@ -1517,34 +1454,34 @@
"type": "github"
}
],
- "time": "2023-12-22T06:20:34+00:00"
+ "time": "2023-12-21T08:38:20+00:00"
},
{
"name": "sebastian/object-enumerator",
- "version": "4.0.4",
+ "version": "5.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-enumerator.git",
- "reference": "5c9eeac41b290a3712d88851518825ad78f45c71"
+ "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71",
- "reference": "5c9eeac41b290a3712d88851518825ad78f45c71",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906",
+ "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906",
"shasum": ""
},
"require": {
- "php": ">=7.3",
- "sebastian/object-reflector": "^2.0",
- "sebastian/recursion-context": "^4.0"
+ "php": ">=8.1",
+ "sebastian/object-reflector": "^3.0",
+ "sebastian/recursion-context": "^5.0"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-main": "5.0-dev"
}
},
"autoload": {
@@ -1566,7 +1503,7 @@
"homepage": "https://github.com/sebastianbergmann/object-enumerator/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-enumerator/issues",
- "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4"
+ "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0"
},
"funding": [
{
@@ -1574,32 +1511,32 @@
"type": "github"
}
],
- "time": "2020-10-26T13:12:34+00:00"
+ "time": "2023-02-03T07:08:32+00:00"
},
{
"name": "sebastian/object-reflector",
- "version": "2.0.4",
+ "version": "3.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/object-reflector.git",
- "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7"
+ "reference": "24ed13d98130f0e7122df55d06c5c4942a577957"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
- "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7",
+ "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957",
+ "reference": "24ed13d98130f0e7122df55d06c5c4942a577957",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "2.0-dev"
+ "dev-main": "3.0-dev"
}
},
"autoload": {
@@ -1621,7 +1558,7 @@
"homepage": "https://github.com/sebastianbergmann/object-reflector/",
"support": {
"issues": "https://github.com/sebastianbergmann/object-reflector/issues",
- "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4"
+ "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0"
},
"funding": [
{
@@ -1629,32 +1566,32 @@
"type": "github"
}
],
- "time": "2020-10-26T13:14:26+00:00"
+ "time": "2023-02-03T07:06:18+00:00"
},
{
"name": "sebastian/recursion-context",
- "version": "4.0.5",
+ "version": "5.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/recursion-context.git",
- "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1"
+ "reference": "05909fb5bc7df4c52992396d0116aed689f93712"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1",
- "reference": "e75bd0f07204fec2a0af9b0f3cfe97d05f92efc1",
+ "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/05909fb5bc7df4c52992396d0116aed689f93712",
+ "reference": "05909fb5bc7df4c52992396d0116aed689f93712",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.3"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "4.0-dev"
+ "dev-main": "5.0-dev"
}
},
"autoload": {
@@ -1684,7 +1621,7 @@
"homepage": "https://github.com/sebastianbergmann/recursion-context",
"support": {
"issues": "https://github.com/sebastianbergmann/recursion-context/issues",
- "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.5"
+ "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.0"
},
"funding": [
{
@@ -1692,86 +1629,32 @@
"type": "github"
}
],
- "time": "2023-02-03T06:07:39+00:00"
- },
- {
- "name": "sebastian/resource-operations",
- "version": "3.0.4",
- "source": {
- "type": "git",
- "url": "https://github.com/sebastianbergmann/resource-operations.git",
- "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e"
- },
- "dist": {
- "type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e",
- "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e",
- "shasum": ""
- },
- "require": {
- "php": ">=7.3"
- },
- "require-dev": {
- "phpunit/phpunit": "^9.0"
- },
- "type": "library",
- "extra": {
- "branch-alias": {
- "dev-main": "3.0-dev"
- }
- },
- "autoload": {
- "classmap": [
- "src/"
- ]
- },
- "notification-url": "https://packagist.org/downloads/",
- "license": [
- "BSD-3-Clause"
- ],
- "authors": [
- {
- "name": "Sebastian Bergmann",
- "email": "sebastian@phpunit.de"
- }
- ],
- "description": "Provides a list of PHP built-in functions that operate on resources",
- "homepage": "https://www.github.com/sebastianbergmann/resource-operations",
- "support": {
- "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4"
- },
- "funding": [
- {
- "url": "https://github.com/sebastianbergmann",
- "type": "github"
- }
- ],
- "time": "2024-03-14T16:00:52+00:00"
+ "time": "2023-02-03T07:05:40+00:00"
},
{
"name": "sebastian/type",
- "version": "3.2.1",
+ "version": "4.0.0",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/type.git",
- "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7"
+ "reference": "462699a16464c3944eefc02ebdd77882bd3925bf"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7",
- "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7",
+ "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf",
+ "reference": "462699a16464c3944eefc02ebdd77882bd3925bf",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"require-dev": {
- "phpunit/phpunit": "^9.5"
+ "phpunit/phpunit": "^10.0"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.2-dev"
+ "dev-main": "4.0-dev"
}
},
"autoload": {
@@ -1794,7 +1677,7 @@
"homepage": "https://github.com/sebastianbergmann/type",
"support": {
"issues": "https://github.com/sebastianbergmann/type/issues",
- "source": "https://github.com/sebastianbergmann/type/tree/3.2.1"
+ "source": "https://github.com/sebastianbergmann/type/tree/4.0.0"
},
"funding": [
{
@@ -1802,29 +1685,29 @@
"type": "github"
}
],
- "time": "2023-02-03T06:13:03+00:00"
+ "time": "2023-02-03T07:10:45+00:00"
},
{
"name": "sebastian/version",
- "version": "3.0.2",
+ "version": "4.0.1",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/version.git",
- "reference": "c6c1022351a901512170118436c764e473f6de8c"
+ "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c",
- "reference": "c6c1022351a901512170118436c764e473f6de8c",
+ "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17",
+ "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17",
"shasum": ""
},
"require": {
- "php": ">=7.3"
+ "php": ">=8.1"
},
"type": "library",
"extra": {
"branch-alias": {
- "dev-master": "3.0-dev"
+ "dev-main": "4.0-dev"
}
},
"autoload": {
@@ -1847,7 +1730,7 @@
"homepage": "https://github.com/sebastianbergmann/version",
"support": {
"issues": "https://github.com/sebastianbergmann/version/issues",
- "source": "https://github.com/sebastianbergmann/version/tree/3.0.2"
+ "source": "https://github.com/sebastianbergmann/version/tree/4.0.1"
},
"funding": [
{
@@ -1855,7 +1738,7 @@
"type": "github"
}
],
- "time": "2020-09-28T06:39:44+00:00"
+ "time": "2023-02-07T11:34:05+00:00"
},
{
"name": "squizlabs/php_codesniffer",
@@ -1994,7 +1877,7 @@
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
- "php": ">=7.4",
+ "php": ">=8.1",
"ext-ctype": "*",
"ext-curl": "*",
"ext-dom": "*",
@@ -2017,13 +1900,13 @@
"ext-zlib": "*"
},
"platform-dev": {
- "php": ">=7.4",
+ "php": ">=8.1",
"ext-phar": "*",
"ext-tokenizer": "*",
"ext-xmlwriter": "*"
},
"platform-overrides": {
- "php": "7.4"
+ "php": "8.1"
},
"plugin-api-version": "2.6.0"
}
diff --git a/config.default.php b/config.default.php
index 80c2f257c..af9f45511 100644
--- a/config.default.php
+++ b/config.default.php
@@ -42,8 +42,6 @@ return array(
# Force users to validate their email address. If `true`, an email with a
# validation URL is sent during registration, and users cannot access their
# feed if they didn’t access this URL.
- # Note: it is recommended to not enable it with PHP < 5.5 (emails cannot be
- # sent).
'force_email_validation' => false,
# Allow or not visitors without login to see the articles
@@ -173,7 +171,7 @@ return array(
],
- # Configuration to send emails. Be aware that PHP < 5.5 are not supported.
+ # Configuration to send emails.
# These options are basically a mapping of the PHPMailer class attributes
# from the PHPMailer library.
#
diff --git a/constants.php b/constants.php
index bf52b8daf..c7765cb12 100644
--- a/constants.php
+++ b/constants.php
@@ -3,7 +3,7 @@ declare(strict_types=1);
//NB: Do not edit; use ./constants.local.php instead.
//<Not customisable>
-const FRESHRSS_MIN_PHP_VERSION = '7.4.0';
+const FRESHRSS_MIN_PHP_VERSION = '8.1.0';
const FRESHRSS_VERSION = '1.25.0-dev';
const FRESHRSS_WEBSITE = 'https://freshrss.org';
const FRESHRSS_WIKI = 'https://freshrss.github.io/FreshRSS/';
diff --git a/docs/en/admins/02_Prerequisites.md b/docs/en/admins/02_Prerequisites.md
index f048d8534..c54a7fd56 100644
--- a/docs/en/admins/02_Prerequisites.md
+++ b/docs/en/admins/02_Prerequisites.md
@@ -7,7 +7,7 @@ You need to verify that your server can run FreshRSS before installing it. If yo
| Software | Recommended | Also Works With |
| ------------- | ----------------------- | ----------------------- |
| Web server | **Apache 2.4** | nginx, lighttpd<br />minimal compatibility with Apache 2.2 |
-| PHP | **PHP 7.4+** | FreshRSS 1.21/1.22: PHP 7.2+; FreshRSS 1.23/1.24: PHP 7.4+ |
+| PHP | **PHP 8.1+** | FreshRSS 1.21/1.22: PHP 7.2+; FreshRSS 1.23/1.24: PHP 7.4+ |
| PHP modules | Required: libxml, cURL, JSON, PDO_MySQL, PCRE and ctype.<br />Required (32-bit only): GMP <br />Recommended: Zlib, mbstring, iconv, ZipArchive<br />*For the whole modules list see [Dockerfile](https://github.com/FreshRSS/FreshRSS/blob/edge/Docker/Dockerfile-Alpine#L7-L9)* | |
| Database | **PostgreSQL 10+** | SQLite, MySQL 5.5.3+, MariaDB 5.5+ |
| Browser | **Firefox** | Chrome, Opera, Safari, or Edge |
diff --git a/docs/en/admins/10_ServerConfig.md b/docs/en/admins/10_ServerConfig.md
index 2db12883e..b7f57e61a 100644
--- a/docs/en/admins/10_ServerConfig.md
+++ b/docs/en/admins/10_ServerConfig.md
@@ -95,7 +95,7 @@ server {
# php files handling
# this regex is mandatory because of the API
location ~ ^.+?\.php(/.*)?$ {
- fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
+ fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
# By default, the variable PATH_INFO is not set under PHP-FPM
# But FreshRSS API greader.php need it. If you have a “Bad Request” error, double check this var!
diff --git a/docs/fr/users/01_Installation.md b/docs/fr/users/01_Installation.md
index 7e331776c..390052ec5 100644
--- a/docs/fr/users/01_Installation.md
+++ b/docs/fr/users/01_Installation.md
@@ -7,7 +7,7 @@ Il est toutefois de votre responsabilité de vérifier que votre hébergement pe
| Logiciel | Recommandé | Fonctionne aussi avec |
| -------- | ----------- | --------------------- |
| Serveur web | **Apache 2.4+** | nginx, lighttpd |
-| PHP | **PHP 7.4+** | |
+| PHP | **PHP 8.1+** | |
| Modules PHP | Requis : libxml, cURL, JSON, PDO_MySQL, PCRE et ctype<br />Requis (32 bits seulement) : GMP<br />Recommandé : Zlib, mbstring et iconv, ZipArchive<br />*Pour une liste complète des modules nécessaires voir le [Dockerfile](https://github.com/FreshRSS/FreshRSS/blob/edge/Docker/Dockerfile-Alpine#L7-L9)* | |
| Base de données | **PostgreSQL 10+** | SQLite, MySQL 5.5.3+, MariaDB 5.5+ |
| Navigateur | **Firefox** | Chrome, Opera, Safari, or Edge |
@@ -115,7 +115,7 @@ server {
# gestion des fichiers php
# il est nécessaire d’utiliser cette expression régulière pour le bon fonctionnement de l’API
location ~ ^.+?\.php(/.*)?$ {
- fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
+ fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;
fastcgi_split_path_info ^(.+\.php)(/.*)$;
# Par défaut la variable PATH_INFO n’est pas définie sous PHP-FPM
# or l’API FreshRSS greader.php en a besoin. Si vous avez un “Bad Request”, vérifiez bien cette dernière !
diff --git a/lib/Minz/Configuration.php b/lib/Minz/Configuration.php
index 7205f3009..89aea4fae 100644
--- a/lib/Minz/Configuration.php
+++ b/lib/Minz/Configuration.php
@@ -56,10 +56,9 @@ class Minz_Configuration {
* Return the configuration related to a given namespace.
*
* @param string $namespace the name of the configuration to get.
- * @return static object
* @throws Minz_ConfigurationNamespaceException if the namespace does not exist.
*/
- public static function get(string $namespace) {
+ public static function get(string $namespace): static {
if (!isset(self::$config_list[$namespace])) {
throw new Minz_ConfigurationNamespaceException(
$namespace . ' namespace does not exist'
@@ -156,7 +155,7 @@ class Minz_Configuration {
* @param mixed $default default value to return if key does not exist.
* @return array|mixed value corresponding to the key.
*/
- public function param(string $key, $default = null) {
+ public function param(string $key, mixed $default = null): mixed {
if (isset($this->data[$key])) {
return $this->data[$key];
} elseif (!is_null($default)) {
@@ -171,7 +170,7 @@ class Minz_Configuration {
* A wrapper for param().
* @return array|mixed
*/
- public function __get(string $key) {
+ public function __get(string $key): mixed {
return $this->param($key);
}
@@ -181,7 +180,7 @@ class Minz_Configuration {
* @param string $key the param name to set.
* @param mixed $value the value to set. If null, the key is removed from the configuration.
*/
- public function _param(string $key, $value = null): void {
+ public function _param(string $key, mixed $value = null): void {
if ($this->configuration_setter !== null && $this->configuration_setter->support($key)) {
$this->configuration_setter->handle($this->data, $key, $value);
} elseif (isset($this->data[$key]) && is_null($value)) {
@@ -193,9 +192,8 @@ class Minz_Configuration {
/**
* A wrapper for _param().
- * @param mixed $value
*/
- public function __set(string $key, $value): void {
+ public function __set(string $key, mixed $value): void {
$this->_param($key, $value);
}
diff --git a/lib/Minz/ConfigurationSetterInterface.php b/lib/Minz/ConfigurationSetterInterface.php
index f141a1a6f..451d4cb0e 100644
--- a/lib/Minz/ConfigurationSetterInterface.php
+++ b/lib/Minz/ConfigurationSetterInterface.php
@@ -16,5 +16,5 @@ interface Minz_ConfigurationSetterInterface {
* @param string $key the key to update.
* @param mixed $value the value to set.
*/
- public function handle(&$data, string $key, $value): void;
+ public function handle(array &$data, string $key, mixed $value): void;
}
diff --git a/lib/Minz/Extension.php b/lib/Minz/Extension.php
index 95d28af8a..69b9c569c 100644
--- a/lib/Minz/Extension.php
+++ b/lib/Minz/Extension.php
@@ -105,7 +105,7 @@ abstract class Minz_Extension {
*
* @return string|false html content from ext_dir/configure.phtml, false if it does not exist.
*/
- final public function getConfigureView() {
+ final public function getConfigureView(): string|false {
$filename = $this->path . '/configure.phtml';
if (!file_exists($filename)) {
return false;
@@ -146,7 +146,7 @@ abstract class Minz_Extension {
return $this->version;
}
/** @return 'system'|'user' */
- final public function getType() {
+ final public function getType(): string {
return $this->type;
}
@@ -296,11 +296,7 @@ abstract class Minz_Extension {
return [];
}
- /**
- * @param mixed $default
- * @return mixed
- */
- final public function getSystemConfigurationValue(string $key, $default = null) {
+ final public function getSystemConfigurationValue(string $key, mixed $default = null): mixed {
if (!is_array($this->system_configuration)) {
$this->system_configuration = $this->getSystemConfiguration();
}
@@ -311,11 +307,7 @@ abstract class Minz_Extension {
return $default;
}
- /**
- * @param mixed $default
- * @return mixed
- */
- final public function getUserConfigurationValue(string $key, $default = null) {
+ final public function getUserConfigurationValue(string $key, mixed $default = null): mixed {
if (!is_array($this->user_configuration)) {
$this->user_configuration = $this->getUserConfiguration();
}
diff --git a/lib/Minz/ExtensionManager.php b/lib/Minz/ExtensionManager.php
index d9e38955b..2d7c92d6b 100644
--- a/lib/Minz/ExtensionManager.php
+++ b/lib/Minz/ExtensionManager.php
@@ -369,7 +369,7 @@ final class Minz_ExtensionManager {
* @return mixed|null final chained result of the hooks. If nothing is changed,
* the initial argument is returned.
*/
- private static function callOneToOne(string $hook_name, $arg) {
+ private static function callOneToOne(string $hook_name, mixed $arg): mixed {
$result = $arg;
foreach (self::$hook_list[$hook_name]['list'] as $function) {
$result = call_user_func($function, $arg);
diff --git a/lib/Minz/FrontController.php b/lib/Minz/FrontController.php
index e57fb69c6..3a86d2d6d 100644
--- a/lib/Minz/FrontController.php
+++ b/lib/Minz/FrontController.php
@@ -79,9 +79,8 @@ class Minz_FrontController {
/**
* Kills the programme
- * @return never
*/
- public static function killApp(string $txt = '') {
+ public static function killApp(string $txt = ''): never {
header('HTTP/1.1 500 Internal Server Error', true, 500);
if (function_exists('errorMessageInfo')) {
//If the application has defined a custom error message function
diff --git a/lib/Minz/Helper.php b/lib/Minz/Helper.php
index 50243ded0..91c1bdc00 100644
--- a/lib/Minz/Helper.php
+++ b/lib/Minz/Helper.php
@@ -18,11 +18,8 @@ final class Minz_Helper {
* @phpstan-template T of mixed
* @phpstan-param T $var
* @phpstan-return T
- *
- * @param mixed $var
- * @return mixed
*/
- public static function htmlspecialchars_utf8($var) {
+ public static function htmlspecialchars_utf8(mixed $var): mixed {
if (is_array($var)) {
// @phpstan-ignore argument.type, return.type
return array_map([self::class, 'htmlspecialchars_utf8'], $var);
diff --git a/lib/Minz/Log.php b/lib/Minz/Log.php
index 648c2c663..8bf193ffe 100644
--- a/lib/Minz/Log.php
+++ b/lib/Minz/Log.php
@@ -76,7 +76,6 @@ class Minz_Log {
* This method can be called multiple times for one script execution, but its result will not change unless
* you call clearstatcache() in between. We won’t do do that for performance reasons.
*
- * @param string $file_name
* @throws Minz_PermissionDeniedException
*/
protected static function ensureMaxLogSize(string $file_name): void {
diff --git a/lib/Minz/Mailer.php b/lib/Minz/Mailer.php
index 8e1211807..c657bd486 100644
--- a/lib/Minz/Mailer.php
+++ b/lib/Minz/Mailer.php
@@ -18,10 +18,6 @@ use PHPMailer\PHPMailer\Exception;
* $this->view->_path('user_mailer/email_need_validation.txt.php')
* ```
*
- * Minz_Mailer uses the PHPMailer library under the hood. The latter requires
- * PHP >= 5.5 to work. If you instantiate a Minz_Mailer with PHP < 5.5, a
- * warning will be logged.
- *
* The email is sent by calling the `mail` method.
*/
class Minz_Mailer {
diff --git a/lib/Minz/Migrator.php b/lib/Minz/Migrator.php
index c1978dc69..39c834765 100644
--- a/lib/Minz/Migrator.php
+++ b/lib/Minz/Migrator.php
@@ -19,9 +19,6 @@ class Minz_Migrator
/**
* Execute a list of migrations, skipping versions indicated in a file
*
- * @param string $migrations_path
- * @param string $applied_migrations_path
- *
* @return true|string Returns true if execute succeeds to apply
* migrations, or a string if it fails.
* @throws DomainException if there is no migrations corresponding to the
@@ -31,7 +28,7 @@ class Minz_Migrator
*
* @throws BadFunctionCallException if a callback isn’t callable.
*/
- public static function execute(string $migrations_path, string $applied_migrations_path) {
+ public static function execute(string $migrations_path, string $applied_migrations_path): string|bool {
$applied_migrations = @file_get_contents($applied_migrations_path);
if ($applied_migrations === false) {
return "Cannot open the {$applied_migrations_path} file";
diff --git a/lib/Minz/ModelPdo.php b/lib/Minz/ModelPdo.php
index b39ae2f81..f27ae5dc7 100644
--- a/lib/Minz/ModelPdo.php
+++ b/lib/Minz/ModelPdo.php
@@ -86,8 +86,6 @@ class Minz_ModelPdo {
/**
* Create the connection to the database using the variables
* HOST, BASE, USER and PASS variables defined in the configuration file
- * @param string|null $currentUser
- * @param Minz_Pdo|null $currentPdo
* @throws Minz_ConfigurationException
* @throws Minz_PDOConnectionException
*/
diff --git a/lib/Minz/Paginator.php b/lib/Minz/Paginator.php
index 3b3c0961e..727fe42d3 100644
--- a/lib/Minz/Paginator.php
+++ b/lib/Minz/Paginator.php
@@ -64,7 +64,7 @@ class Minz_Paginator {
* @param Minz_Model $item l'élément à retrouver
* @return int|false la page à laquelle se trouve l’élément, false si non trouvé
*/
- public function pageByItem($item) {
+ public function pageByItem($item): int|false {
$i = 0;
do {
@@ -82,7 +82,7 @@ class Minz_Paginator {
* @param Minz_Model $item the element to search
* @return int|false the position of the element, or false if not found
*/
- public function positionByItem($item) {
+ public function positionByItem($item): int|false {
$i = 0;
do {
diff --git a/lib/Minz/Pdo.php b/lib/Minz/Pdo.php
index 33d84eb45..705c2d58c 100644
--- a/lib/Minz/Pdo.php
+++ b/lib/Minz/Pdo.php
@@ -37,58 +37,44 @@ abstract class Minz_Pdo extends PDO {
return $this->autoPrefix($statement);
}
- // PHP8+: PDO::lastInsertId(?string $name = null): string|false
/**
- * @param string|null $name
- * @return string|false
* @throws PDOException if the attribute `PDO::ATTR_ERRMODE` is set to `PDO::ERRMODE_EXCEPTION`
*/
#[\Override]
- #[\ReturnTypeWillChange]
- public function lastInsertId($name = null) {
+ public function lastInsertId(?string $name = null): string|false {
if ($name != null) {
$name = $this->preSql($name);
}
return parent::lastInsertId($name);
}
- // PHP8+: PDO::prepare(string $query, array $options = []): PDOStatement|false
/**
- * @param string $query
* @param array<int,string> $options
- * @return PDOStatement|false
* @throws PDOException if the attribute `PDO::ATTR_ERRMODE` is set to `PDO::ERRMODE_EXCEPTION`
* @phpstan-ignore method.childParameterType, throws.unusedType
*/
#[\Override]
- #[\ReturnTypeWillChange]
- public function prepare($query, $options = []) {
+ public function prepare(string $query, array $options = []): PDOStatement|false {
$query = $this->preSql($query);
return parent::prepare($query, $options);
}
- // PHP8+: PDO::exec(string $statement): int|false
/**
- * @param string $statement
- * @return int|false
* @throws PDOException if the attribute `PDO::ATTR_ERRMODE` is set to `PDO::ERRMODE_EXCEPTION`
* @phpstan-ignore throws.unusedType
*/
#[\Override]
- #[\ReturnTypeWillChange]
- public function exec($statement) {
+ public function exec(string $statement): int|false {
$statement = $this->preSql($statement);
return parent::exec($statement);
}
/**
- * @return PDOStatement|false
* @throws PDOException if the attribute `PDO::ATTR_ERRMODE` is set to `PDO::ERRMODE_EXCEPTION`
* @phpstan-ignore throws.unusedType
*/
#[\Override]
- #[\ReturnTypeWillChange]
- public function query(string $query, ?int $fetch_mode = null, ...$fetch_mode_args) {
+ public function query(string $query, ?int $fetch_mode = null, ...$fetch_mode_args): PDOStatement|false {
$query = $this->preSql($query);
return $fetch_mode === null ? parent::query($query) : parent::query($query, $fetch_mode, ...$fetch_mode_args);
}
diff --git a/lib/Minz/PdoMysql.php b/lib/Minz/PdoMysql.php
index 3f7a804a3..d7fca0168 100644
--- a/lib/Minz/PdoMysql.php
+++ b/lib/Minz/PdoMysql.php
@@ -22,13 +22,10 @@ class Minz_PdoMysql extends Minz_Pdo {
}
/**
- * @param string|null $name
- * @return string|false
* @throws PDOException if the attribute `PDO::ATTR_ERRMODE` is set to `PDO::ERRMODE_EXCEPTION`
*/
#[\Override]
- #[\ReturnTypeWillChange]
- public function lastInsertId($name = null) {
+ public function lastInsertId(?string $name = null): string|false {
return parent::lastInsertId(); //We discard the name, only used by PostgreSQL
}
}
diff --git a/lib/Minz/PdoSqlite.php b/lib/Minz/PdoSqlite.php
index 537b6cdc6..6aa83690c 100644
--- a/lib/Minz/PdoSqlite.php
+++ b/lib/Minz/PdoSqlite.php
@@ -22,13 +22,10 @@ class Minz_PdoSqlite extends Minz_Pdo {
}
/**
- * @param string|null $name
- * @return string|false
* @throws PDOException if the attribute `PDO::ATTR_ERRMODE` is set to `PDO::ERRMODE_EXCEPTION`
*/
#[\Override]
- #[\ReturnTypeWillChange]
- public function lastInsertId($name = null) {
+ public function lastInsertId(?string $name = null): string|false {
return parent::lastInsertId(); //We discard the name, only used by PostgreSQL
}
}
diff --git a/lib/Minz/Request.php b/lib/Minz/Request.php
index 1f15730fb..fcece464b 100644
--- a/lib/Minz/Request.php
+++ b/lib/Minz/Request.php
@@ -44,7 +44,7 @@ class Minz_Request {
* @return mixed value of the parameter
* @deprecated use typed versions instead
*/
- public static function param(string $key, $default = false, bool $specialchars = false) {
+ public static function param(string $key, mixed $default = false, bool $specialchars = false): mixed {
if (isset(self::$params[$key])) {
$p = self::$params[$key];
if (is_string($p) || is_array($p)) {
@@ -156,7 +156,7 @@ class Minz_Request {
}
/** @return array{c?:string,a?:string,params?:array<string,mixed>} */
- public static function originalRequest() {
+ public static function originalRequest(): array {
return self::$originalRequest;
}
diff --git a/lib/Minz/Session.php b/lib/Minz/Session.php
index 99b7fef45..c08ad688b 100644
--- a/lib/Minz/Session.php
+++ b/lib/Minz/Session.php
@@ -63,7 +63,7 @@ class Minz_Session {
* @return mixed|false the value of the session variable, false if doesn’t exist
* @deprecated Use typed versions instead
*/
- public static function param(string $p, $default = false) {
+ public static function param(string $p, $default = false): mixed {
return $_SESSION[$p] ?? $default;
}
diff --git a/lib/Minz/Translate.php b/lib/Minz/Translate.php
index 183fa48ca..a8dc889ee 100644
--- a/lib/Minz/Translate.php
+++ b/lib/Minz/Translate.php
@@ -255,9 +255,7 @@ class Minz_Translate {
/**
* Alias for Minz_Translate::t()
- * @param string $key
- * @param bool|float|int|string ...$args
*/
-function _t(string $key, ...$args): string {
+function _t(string $key, bool|float|int|string ...$args): string {
return Minz_Translate::t($key, ...$args);
}
diff --git a/lib/Minz/Url.php b/lib/Minz/Url.php
index 310067382..3948414d8 100644
--- a/lib/Minz/Url.php
+++ b/lib/Minz/Url.php
@@ -13,11 +13,10 @@ class Minz_Url {
* $url['params'] = array of additional parameters
* or as a string
* @param string $encoding how to encode & (& ou &amp; pour html)
- * @param bool|string $absolute
* @return string Formatted URL
* @throws Minz_ConfigurationException
*/
- public static function display($url = [], string $encoding = 'html', $absolute = false): string {
+ public static function display($url = [], string $encoding = 'html', bool|string $absolute = false): string {
$isArray = is_array($url);
if ($isArray) {
@@ -160,13 +159,7 @@ class Minz_Url {
}
}
-/**
- * @param string $controller
- * @param string $action
- * @param string|int ...$args
- * @return string|false
- */
-function _url(string $controller, string $action, ...$args) {
+function _url(string $controller, string $action, int|string ...$args): string|false {
$nb_args = count($args);
if ($nb_args % 2 !== 0) {
diff --git a/lib/Minz/View.php b/lib/Minz/View.php
index 44b7378b6..f7dceef0a 100644
--- a/lib/Minz/View.php
+++ b/lib/Minz/View.php
@@ -232,8 +232,6 @@ class Minz_View {
/**
* Append a `<link>` element referencing stylesheet.
- * @param string $url
- * @param string $media
* @param bool $cond Conditional comment for IE, now deprecated and ignored @deprecated
*/
public static function appendStyle(string $url, string $media = 'all', bool $cond = false): void {
@@ -298,7 +296,6 @@ class Minz_View {
}
/**
* Prepend a `<script>` element.
- * @param string $url
* @param bool $cond Conditional comment for IE, now deprecated and ignored @deprecated
* @param bool $defer Use `defer` flag
* @param bool $async Use `async` flag
@@ -318,7 +315,6 @@ class Minz_View {
/**
* Append a `<script>` element.
- * @param string $url
* @param bool $cond Conditional comment for IE, now deprecated and ignored @deprecated
* @param bool $defer Use `defer` flag
* @param bool $async Use `async` flag
@@ -338,9 +334,8 @@ class Minz_View {
/**
* Management of parameters added to the view
- * @param mixed $value
*/
- public static function _param(string $key, $value): void {
+ public static function _param(string $key, mixed $value): void {
self::$params[$key] = $value;
}
diff --git a/lib/lib_date.php b/lib/lib_date.php
index ee8bf92f6..201d548ad 100644
--- a/lib/lib_date.php
+++ b/lib/lib_date.php
@@ -36,7 +36,7 @@ example('PT6M/');
example('PT7S/');
example('P1DT1H/');
-function example(string $dateInterval) {
+function example(string $dateInterval): void {
$dateIntervalArray = parseDateInterval($dateInterval);
echo $dateInterval, "\t=>\t",
$dateIntervalArray[0] == null ? 'null' : @date('c', $dateIntervalArray[0]), '/',
diff --git a/lib/lib_rss.php b/lib/lib_rss.php
index d066bd254..61055153c 100644
--- a/lib/lib_rss.php
+++ b/lib/lib_rss.php
@@ -5,37 +5,12 @@ if (version_compare(PHP_VERSION, FRESHRSS_MIN_PHP_VERSION, '<')) {
die(sprintf('FreshRSS error: FreshRSS requires PHP %s+!', FRESHRSS_MIN_PHP_VERSION));
}
-if (!function_exists('array_is_list')) {
- /**
- * Polyfill for PHP <8.1
- * https://php.net/array-is-list#127044
- * @param array<mixed> $array
- */
- function array_is_list(array $array): bool {
- $i = -1;
- foreach ($array as $k => $v) {
- ++$i;
- if ($k !== $i) {
- return false;
- }
- }
- return true;
- }
-}
-
if (!function_exists('mb_strcut')) {
function mb_strcut(string $str, int $start, ?int $length = null, string $encoding = 'UTF-8'): string {
return substr($str, $start, $length) ?: '';
}
}
-if (!function_exists('str_starts_with')) {
- /** Polyfill for PHP <8.0 */
- function str_starts_with(string $haystack, string $needle): bool {
- return strncmp($haystack, $needle, strlen($needle)) === 0;
- }
-}
-
if (!function_exists('syslog')) {
if (COPY_SYSLOG_TO_STDERR && !defined('STDERR')) {
define('STDERR', fopen('php://stderr', 'w'));
@@ -149,14 +124,7 @@ function idn_to_puny(string $url): string {
if (function_exists('idn_to_ascii')) {
$idn = parse_url($url, PHP_URL_HOST);
if (is_string($idn) && $idn != '') {
- // https://wiki.php.net/rfc/deprecate-and-remove-intl_idna_variant_2003
- if (defined('INTL_IDNA_VARIANT_UTS46')) {
- $puny = idn_to_ascii($idn, IDNA_DEFAULT, INTL_IDNA_VARIANT_UTS46);
- } elseif (defined('INTL_IDNA_VARIANT_2003')) {
- $puny = idn_to_ascii($idn, IDNA_DEFAULT, INTL_IDNA_VARIANT_2003);
- } else {
- $puny = idn_to_ascii($idn);
- }
+ $puny = idn_to_ascii($idn);
$pos = strpos($url, $idn);
if ($puny != false && $pos !== false) {
$url = substr_replace($url, $puny, $pos, strlen($idn));
@@ -166,10 +134,7 @@ function idn_to_puny(string $url): string {
return $url;
}
-/**
- * @return string|false
- */
-function checkUrl(string $url, bool $fixScheme = true) {
+function checkUrl(string $url, bool $fixScheme = true): string|false {
$url = trim($url);
if ($url == '') {
return '';
@@ -178,7 +143,7 @@ function checkUrl(string $url, bool $fixScheme = true) {
$url = 'https://' . ltrim($url, '/');
}
- $url = idn_to_puny($url); //PHP bug #53474 IDN
+ $url = idn_to_puny($url); // https://bugs.php.net/bug.php?id=53474
$urlRelaxed = str_replace('_', 'z', $url); //PHP discussion #64948 Underscore
if (is_string(filter_var($urlRelaxed, FILTER_VALIDATE_URL))) {
@@ -279,7 +244,7 @@ function html_only_entity_decode(?string $text): string {
* @param array<string,mixed>|string $log
* @return array<string,mixed>|string
*/
-function sensitive_log($log) {
+function sensitive_log($log): array|string {
if (is_array($log)) {
foreach ($log as $k => $v) {
if (in_array($k, ['api_key', 'Passwd', 'T'], true)) {
diff --git a/p/api/fever.php b/p/api/fever.php
index 77d778305..5ddfba269 100644
--- a/p/api/fever.php
+++ b/p/api/fever.php
@@ -426,33 +426,29 @@ final class FeverAPI
/**
* @param numeric-string $id
- * @return int|false
*/
- private function setItemAsRead(string $id) {
+ private function setItemAsRead(string $id): int|false {
return $this->entryDAO->markRead($id, true);
}
/**
* @param numeric-string $id
- * @return int|false
*/
- private function setItemAsUnread(string $id) {
+ private function setItemAsUnread(string $id): int|false {
return $this->entryDAO->markRead($id, false);
}
/**
* @param numeric-string $id
- * @return int|false
*/
- private function setItemAsSaved(string $id) {
+ private function setItemAsSaved(string $id): int|false {
return $this->entryDAO->markFavorite($id, true);
}
/**
* @param numeric-string $id
- * @return int|false
*/
- private function setItemAsUnsaved(string $id) {
+ private function setItemAsUnsaved(string $id): int|false {
return $this->entryDAO->markFavorite($id, false);
}
@@ -538,18 +534,12 @@ final class FeverAPI
return $beforeTimestamp == 0 ? '0' : $beforeTimestamp . '000000';
}
- /**
- * @return int|false
- */
- private function setFeedAsRead(int $id, int $before) {
+ private function setFeedAsRead(int $id, int $before): int|false {
$before = $this->convertBeforeToId($before);
return $this->entryDAO->markReadFeed($id, $before);
}
- /**
- * @return int|false
- */
- private function setGroupAsRead(int $id, int $before) {
+ private function setGroupAsRead(int $id, int $before): int|false {
$before = $this->convertBeforeToId($before);
// special case to mark all items as read
diff --git a/p/api/greader.php b/p/api/greader.php
index 8a492a213..1fd821307 100644
--- a/p/api/greader.php
+++ b/p/api/greader.php
@@ -112,14 +112,12 @@ function debugInfo(): string {
final class GReaderAPI {
- /** @return never */
- private static function noContent() {
+ private static function noContent(): never {
header('HTTP/1.1 204 No Content');
exit();
}
- /** @return never */
- private static function badRequest() {
+ private static function badRequest(): never {
Minz_Log::warning(__METHOD__, API_LOG);
Minz_Log::debug(__METHOD__ . ' ' . debugInfo(), API_LOG);
header('HTTP/1.1 400 Bad Request');
@@ -127,8 +125,7 @@ final class GReaderAPI {
die('Bad Request!');
}
- /** @return never */
- private static function unauthorized() {
+ private static function unauthorized(): never {
Minz_Log::warning(__METHOD__, API_LOG);
Minz_Log::debug(__METHOD__ . ' ' . debugInfo(), API_LOG);
header('HTTP/1.1 401 Unauthorized');
@@ -137,8 +134,7 @@ final class GReaderAPI {
die('Unauthorized!');
}
- /** @return never */
- private static function internalServerError() {
+ private static function internalServerError(): never {
Minz_Log::warning(__METHOD__, API_LOG);
Minz_Log::debug(__METHOD__ . ' ' . debugInfo(), API_LOG);
header('HTTP/1.1 500 Internal Server Error');
@@ -146,8 +142,7 @@ final class GReaderAPI {
die('Internal Server Error!');
}
- /** @return never */
- private static function notImplemented() {
+ private static function notImplemented(): never {
Minz_Log::warning(__METHOD__, API_LOG);
Minz_Log::debug(__METHOD__ . ' ' . debugInfo(), API_LOG);
header('HTTP/1.1 501 Not Implemented');
@@ -155,8 +150,7 @@ final class GReaderAPI {
die('Not Implemented!');
}
- /** @return never */
- private static function serviceUnavailable() {
+ private static function serviceUnavailable(): never {
Minz_Log::warning(__METHOD__, API_LOG);
Minz_Log::debug(__METHOD__ . ' ' . debugInfo(), API_LOG);
header('HTTP/1.1 503 Service Unavailable');
@@ -164,8 +158,7 @@ final class GReaderAPI {
die('Service Unavailable!');
}
- /** @return never */
- private static function checkCompatibility() {
+ private static function checkCompatibility(): never {
Minz_Log::warning(__METHOD__, API_LOG);
Minz_Log::debug(__METHOD__ . ' ' . debugInfo(), API_LOG);
header('Content-Type: text/plain; charset=UTF-8');
@@ -211,8 +204,7 @@ final class GReaderAPI {
return '';
}
- /** @return never */
- private static function clientLogin(string $email, string $pass) {
+ private static function clientLogin(string $email, string $pass): never {
//https://web.archive.org/web/20130604091042/http://undoc.in/clientLogin.html
if (FreshRSS_user_Controller::checkUsername($email)) {
FreshRSS_Context::initUser($email);
@@ -237,10 +229,7 @@ final class GReaderAPI {
}
}
- /**
- * @return never
- */
- private static function token(?FreshRSS_UserConfiguration $conf) {
+ private static function token(?FreshRSS_UserConfiguration $conf): never {
//http://blog.martindoms.com/2009/08/15/using-the-google-reader-api-part-1/
//https://github.com/ericmann/gReader-Library/blob/master/greader.class.php
$user = Minz_User::name();
@@ -271,8 +260,7 @@ final class GReaderAPI {
self::unauthorized();
}
- /** @return never */
- private static function userInfo() {
+ private static function userInfo(): never {
//https://github.com/theoldreader/api#user-info
if (!FreshRSS_Context::hasUserConf()) {
self::unauthorized();
@@ -286,8 +274,7 @@ final class GReaderAPI {
), JSON_OPTIONS));
}
- /** @return never */
- private static function tagList() {
+ private static function tagList(): never {
header('Content-Type: application/json; charset=UTF-8');
$tags = array(
@@ -320,8 +307,7 @@ final class GReaderAPI {
exit();
}
- /** @return never */
- private static function subscriptionExport() {
+ private static function subscriptionExport(): never {
$user = Minz_User::name() ?? Minz_User::INTERNAL_USER;
$export_service = new FreshRSS_Export_Service($user);
[$filename, $content] = $export_service->generateOpml();
@@ -331,8 +317,7 @@ final class GReaderAPI {
exit();
}
- /** @return never */
- private static function subscriptionImport(string $opml) {
+ private static function subscriptionImport(string $opml): never {
$user = Minz_User::name() ?? Minz_User::INTERNAL_USER;
$importService = new FreshRSS_Import_Service($user);
$importService->importOpml($opml);
@@ -345,8 +330,7 @@ final class GReaderAPI {
}
}
- /** @return never */
- private static function subscriptionList() {
+ private static function subscriptionList(): never {
if (!FreshRSS_Context::hasSystemConf()) {
self::internalServerError();
}
@@ -384,9 +368,8 @@ final class GReaderAPI {
/**
* @param array<string> $streamNames
* @param array<string> $titles
- * @return never
*/
- private static function subscriptionEdit(array $streamNames, array $titles, string $action, string $add = '', string $remove = '') {
+ private static function subscriptionEdit(array $streamNames, array $titles, string $action, string $add = '', string $remove = ''): never {
//https://github.com/mihaip/google-reader-api/blob/master/wiki/ApiSubscriptionEdit.wiki
switch ($action) {
case 'subscribe':
@@ -474,8 +457,7 @@ final class GReaderAPI {
exit('OK');
}
- /** @return never */
- private static function quickadd(string $url) {
+ private static function quickadd(string $url): never {
try {
$url = htmlspecialchars($url, ENT_COMPAT, 'UTF-8');
if (str_starts_with($url, 'feed/')) {
@@ -497,8 +479,7 @@ final class GReaderAPI {
}
}
- /** @return never */
- private static function unreadCount() {
+ private static function unreadCount(): never {
//http://blog.martindoms.com/2009/10/16/using-the-google-reader-api-part-2/#unread-count
header('Content-Type: application/json; charset=UTF-8');
@@ -592,10 +573,9 @@ final class GReaderAPI {
/**
* @param 'A'|'c'|'f'|'s' $type
- * @param string|int $streamId
* @phpstan-return array{'A'|'c'|'f'|'s'|'t',int,int,FreshRSS_BooleanSearch}
*/
- private static function streamContentsFilters(string $type, $streamId,
+ private static function streamContentsFilters(string $type, int|string $streamId,
string $filter_target, string $exclude_target, int $start_time, int $stop_time): array {
switch ($type) {
case 'f': //feed
@@ -670,9 +650,8 @@ final class GReaderAPI {
return array($type, $streamId, $state, $searches);
}
- /** @return never */
private static function streamContents(string $path, string $include_target, int $start_time, int $stop_time, int $count,
- string $order, string $filter_target, string $exclude_target, string $continuation) {
+ string $order, string $filter_target, string $exclude_target, string $continuation): never {
//http://code.google.com/p/pyrfeed/wiki/GoogleReaderAPI
//http://blog.martindoms.com/2009/10/16/using-the-google-reader-api-part-2/#feed
header('Content-Type: application/json; charset=UTF-8');
@@ -728,9 +707,8 @@ final class GReaderAPI {
exit();
}
- /** @return never */
private static function streamContentsItemsIds(string $streamId, int $start_time, int $stop_time, int $count,
- string $order, string $filter_target, string $exclude_target, string $continuation) {
+ string $order, string $filter_target, string $exclude_target, string $continuation): never {
//http://code.google.com/p/google-reader-api/wiki/ApiStreamItemsIds
//http://code.google.com/p/pyrfeed/wiki/GoogleReaderAPI
//http://blog.martindoms.com/2009/10/16/using-the-google-reader-api-part-2/#feed
@@ -790,9 +768,8 @@ final class GReaderAPI {
/**
* @param array<string> $e_ids
- * @return never
*/
- private static function streamContentsItems(array $e_ids, string $order) {
+ private static function streamContentsItems(array $e_ids, string $order): never {
header('Content-Type: application/json; charset=UTF-8');
foreach ($e_ids as $i => $e_id) {
@@ -822,9 +799,8 @@ final class GReaderAPI {
/**
* @param array<string> $e_ids
- * @return never
*/
- private static function editTag(array $e_ids, string $a, string $r): void {
+ private static function editTag(array $e_ids, string $a, string $r): never {
foreach ($e_ids as $i => $e_id) {
if (!ctype_digit($e_id) || $e_id[0] === '0') {
$e_ids[$i] = hex2dec(basename($e_id)); //Strip prefix 'tag:google.com,2005:reader/item/'
@@ -898,8 +874,7 @@ final class GReaderAPI {
exit('OK');
}
- /** @return never */
- private static function renameTag(string $s, string $dest) {
+ private static function renameTag(string $s, string $dest): never {
if ($s != '' && strpos($s, 'user/-/label/') === 0 &&
$dest != '' && strpos($dest, 'user/-/label/') === 0) {
$s = substr($s, 13);
@@ -926,8 +901,7 @@ final class GReaderAPI {
self::badRequest();
}
- /** @return never */
- private static function disableTag(string $s) {
+ private static function disableTag(string $s): never {
if ($s != '' && strpos($s, 'user/-/label/') === 0) {
$s = substr($s, 13);
$s = htmlspecialchars($s, ENT_COMPAT, 'UTF-8');
@@ -954,9 +928,8 @@ final class GReaderAPI {
/**
* @param numeric-string $olderThanId
- * @return never
*/
- private static function markAllAsRead(string $streamId, string $olderThanId) {
+ private static function markAllAsRead(string $streamId, string $olderThanId): never {
$entryDAO = FreshRSS_Factory::createEntryDao();
if (strpos($streamId, 'feed/') === 0) {
$f_id = basename($streamId);
@@ -989,8 +962,7 @@ final class GReaderAPI {
exit('OK');
}
- /** @return never */
- public static function parse() {
+ public static function parse(): never {
global $ORIGINAL_INPUT;
header('Access-Control-Allow-Headers: Authorization');
diff --git a/p/ext.php b/p/ext.php
index a9dee3756..5d95107da 100644
--- a/p/ext.php
+++ b/p/ext.php
@@ -83,14 +83,12 @@ function is_valid_path(string $path): bool {
|| is_valid_path_extension($path, USERS_PATH, false);
}
-/** @return never */
-function sendBadRequestResponse(string $message = null) {
+function sendBadRequestResponse(string $message = null): never {
header('HTTP/1.1 400 Bad Request');
die($message);
}
-/** @return never */
-function sendNotFoundResponse() {
+function sendNotFoundResponse(): never {
header('HTTP/1.1 404 Not Found');
die();
}
diff --git a/phpstan.neon b/phpstan.neon
index 640e4d9f9..1b75235b4 100644
--- a/phpstan.neon
+++ b/phpstan.neon
@@ -1,6 +1,5 @@
parameters:
level: 9 # https://phpstan.org/user-guide/rule-levels
- phpVersion: 80399 # TODO: Remove line when moving composer.json to PHP 8+
fileExtensions:
- php
- phtml
diff --git a/tests/README.md b/tests/README.md
index 311461d0c..59035a775 100644
--- a/tests/README.md
+++ b/tests/README.md
@@ -1,8 +1,23 @@
# FreshRSS tests
+See our [documentation about running tests](https://freshrss.github.io/FreshRSS/en/developers/03_Running_tests.html).
+
+```sh
+make test-all
+```
+
+See [`test.yml`](../.github/workflows/tests.yml) for the GitHub Actions automated tests.
+
+See [`composer.json`](../composer.json) for the different tests and versions, to be run locally.
+
+## Details about this *tests* folder
+
+Unit tests are based on [PHPUnit](https://phpunit.de/).
+Here is an example of manual install:
+
```sh
cd ./tests/
-wget -O phpunit.phar https://phar.phpunit.de/phpunit-9.phar
+wget -O phpunit.phar https://phar.phpunit.de/phpunit-10.phar
php phpunit.phar --bootstrap bootstrap.php
```
diff --git a/tests/app/Models/CategoryTest.php b/tests/app/Models/CategoryTest.php
index c9e88a32d..f9aa1a280 100644
--- a/tests/app/Models/CategoryTest.php
+++ b/tests/app/Models/CategoryTest.php
@@ -1,24 +1,24 @@
<?php
declare(strict_types=1);
+use PHPUnit\Framework\Attributes\DataProvider;
+
class CategoryTest extends PHPUnit\Framework\TestCase {
- public function test__construct_whenNoParameters_createsObjectWithDefaultValues(): void {
+ public static function test__construct_whenNoParameters_createsObjectWithDefaultValues(): void {
$category = new FreshRSS_Category();
self::assertEquals(0, $category->id());
self::assertEquals('', $category->name());
}
- /**
- * @dataProvider provideValidNames
- */
- public function test_name_whenValidValue_storesModifiedValue(string $input, string $expected): void {
+ #[DataProvider('provideValidNames')]
+ public static function test_name_whenValidValue_storesModifiedValue(string $input, string $expected): void {
$category = new FreshRSS_Category($input);
self::assertEquals($expected, $category->name());
}
/** @return array<array{string,string}> */
- public function provideValidNames(): array {
+ public static function provideValidNames(): array {
return [
['', ''],
['this string does not need trimming', 'this string does not need trimming'],
diff --git a/tests/app/Models/FeedDAOTest.php b/tests/app/Models/FeedDAOTest.php
index cd197bf9e..31cfc57f9 100644
--- a/tests/app/Models/FeedDAOTest.php
+++ b/tests/app/Models/FeedDAOTest.php
@@ -2,7 +2,7 @@
declare(strict_types=1);
class FeedDAOTest extends PHPUnit\Framework\TestCase {
- public function test_ttl_min(): void {
+ public static function test_ttl_min(): void {
$feed = new FreshRSS_Feed('https://example.net/', false);
$feed->_ttl(-5);
self::assertEquals(-5, $feed->ttl(true));
diff --git a/tests/app/Models/SearchTest.php b/tests/app/Models/SearchTest.php
index e01830314..27943cdb2 100644
--- a/tests/app/Models/SearchTest.php
+++ b/tests/app/Models/SearchTest.php
@@ -1,13 +1,14 @@
<?php
declare(strict_types=1);
+
+use PHPUnit\Framework\Attributes\DataProvider;
+
require_once(LIB_PATH . '/lib_date.php');
class SearchTest extends PHPUnit\Framework\TestCase {
- /**
- * @dataProvider provideEmptyInput
- */
- public function test__construct_whenInputIsEmpty_getsOnlyNullValues(string $input): void {
+ #[DataProvider('provideEmptyInput')]
+ public static function test__construct_whenInputIsEmpty_getsOnlyNullValues(string $input): void {
$search = new FreshRSS_Search($input);
self::assertEquals('', $search->getRawInput());
self::assertNull($search->getIntitle());
@@ -25,7 +26,7 @@ class SearchTest extends PHPUnit\Framework\TestCase {
* Here is the description of the values
* @return array{array{''},array{' '}}
*/
- public function provideEmptyInput(): array {
+ public static function provideEmptyInput(): array {
return [
[''],
[' '],
@@ -33,11 +34,11 @@ class SearchTest extends PHPUnit\Framework\TestCase {
}
/**
- * @dataProvider provideIntitleSearch
* @param array<string>|null $intitle_value
* @param array<string>|null $search_value
*/
- public function test__construct_whenInputContainsIntitle_setsIntitleProperty(string $input, ?array $intitle_value, ?array $search_value): void {
+ #[DataProvider('provideIntitleSearch')]
+ public static function test__construct_whenInputContainsIntitle_setsIntitleProperty(string $input, ?array $intitle_value, ?array $search_value): void {
$search = new FreshRSS_Search($input);
self::assertEquals($intitle_value, $search->getIntitle());
self::assertEquals($search_value, $search->getSearch());
@@ -46,7 +47,7 @@ class SearchTest extends PHPUnit\Framework\TestCase {
/**
* @return array<array<mixed>>
*/
- public function provideIntitleSearch(): array {
+ public static function provideIntitleSearch(): array {
return [
['intitle:word1', ['word1'], null],
['intitle:word1-word2', ['word1-word2'], null],
@@ -70,11 +71,11 @@ class SearchTest extends PHPUnit\Framework\TestCase {
}
/**
- * @dataProvider provideAuthorSearch
* @param array<string>|null $author_value
* @param array<string>|null $search_value
*/
- public function test__construct_whenInputContainsAuthor_setsAuthorValue(string $input, ?array $author_value, ?array $search_value): void {
+ #[DataProvider('provideAuthorSearch')]
+ public static function test__construct_whenInputContainsAuthor_setsAuthorValue(string $input, ?array $author_value, ?array $search_value): void {
$search = new FreshRSS_Search($input);
self::assertEquals($author_value, $search->getAuthor());
self::assertEquals($search_value, $search->getSearch());
@@ -83,7 +84,7 @@ class SearchTest extends PHPUnit\Framework\TestCase {
/**
* @return array<array<mixed>>
*/
- public function provideAuthorSearch(): array {
+ public static function provideAuthorSearch(): array {
return [
['author:word1', ['word1'], null],
['author:word1-word2', ['word1-word2'], null],
@@ -107,11 +108,11 @@ class SearchTest extends PHPUnit\Framework\TestCase {
}
/**
- * @dataProvider provideInurlSearch
* @param array<string>|null $inurl_value
* @param array<string>|null $search_value
*/
- public function test__construct_whenInputContainsInurl_setsInurlValue(string $input, ?array $inurl_value, ?array $search_value): void {
+ #[DataProvider('provideInurlSearch')]
+ public static function test__construct_whenInputContainsInurl_setsInurlValue(string $input, ?array $inurl_value, ?array $search_value): void {
$search = new FreshRSS_Search($input);
self::assertEquals($inurl_value, $search->getInurl());
self::assertEquals($search_value, $search->getSearch());
@@ -120,7 +121,7 @@ class SearchTest extends PHPUnit\Framework\TestCase {
/**
* @return array<array<mixed>>
*/
- public function provideInurlSearch(): array {
+ public static function provideInurlSearch(): array {
return [
['inurl:word1', ['word1'], null],
['inurl: word1', [], ['word1']],
@@ -133,10 +134,8 @@ class SearchTest extends PHPUnit\Framework\TestCase {
];
}
- /**
- * @dataProvider provideDateSearch
- */
- public function test__construct_whenInputContainsDate_setsDateValues(string $input, ?int $min_date_value, ?int $max_date_value): void {
+ #[DataProvider('provideDateSearch')]
+ public static function test__construct_whenInputContainsDate_setsDateValues(string $input, ?int $min_date_value, ?int $max_date_value): void {
$search = new FreshRSS_Search($input);
self::assertEquals($min_date_value, $search->getMinDate());
self::assertEquals($max_date_value, $search->getMaxDate());
@@ -145,7 +144,7 @@ class SearchTest extends PHPUnit\Framework\TestCase {
/**
* @return array<array<mixed>>
*/
- public function provideDateSearch(): array {
+ public static function provideDateSearch(): array {
return array(
array('date:2007-03-01T13:00:00Z/2008-05-11T15:30:00Z', 1172754000, 1210519800),
array('date:2007-03-01T13:00:00Z/P1Y2M10DT2H30M', 1172754000, 1210519799),
@@ -156,10 +155,8 @@ class SearchTest extends PHPUnit\Framework\TestCase {
);
}
- /**
- * @dataProvider providePubdateSearch
- */
- public function test__construct_whenInputContainsPubdate_setsPubdateValues(string $input, ?int $min_pubdate_value, ?int $max_pubdate_value): void {
+ #[DataProvider('providePubdateSearch')]
+ public static function test__construct_whenInputContainsPubdate_setsPubdateValues(string $input, ?int $min_pubdate_value, ?int $max_pubdate_value): void {
$search = new FreshRSS_Search($input);
self::assertEquals($min_pubdate_value, $search->getMinPubdate());
self::assertEquals($max_pubdate_value, $search->getMaxPubdate());
@@ -168,7 +165,7 @@ class SearchTest extends PHPUnit\Framework\TestCase {
/**
* @return array<array<mixed>>
*/
- public function providePubdateSearch(): array {
+ public static function providePubdateSearch(): array {
return array(
array('pubdate:2007-03-01T13:00:00Z/2008-05-11T15:30:00Z', 1172754000, 1210519800),
array('pubdate:2007-03-01T13:00:00Z/P1Y2M10DT2H30M', 1172754000, 1210519799),
@@ -180,11 +177,11 @@ class SearchTest extends PHPUnit\Framework\TestCase {
}
/**
- * @dataProvider provideTagsSearch
* @param array<string>|null $tags_value
* @param array<string>|null $search_value
*/
- public function test__construct_whenInputContainsTags_setsTagsValue(string $input, ?array $tags_value, ?array $search_value): void {
+ #[DataProvider('provideTagsSearch')]
+ public static function test__construct_whenInputContainsTags_setsTagsValue(string $input, ?array $tags_value, ?array $search_value): void {
$search = new FreshRSS_Search($input);
self::assertEquals($tags_value, $search->getTags());
self::assertEquals($search_value, $search->getSearch());
@@ -193,7 +190,7 @@ class SearchTest extends PHPUnit\Framework\TestCase {
/**
* @return array<array<string|array<string>|null>>
*/
- public function provideTagsSearch(): array {
+ public static function provideTagsSearch(): array {
return [
['#word1', ['word1'], null],
['# word1', null, ['#', 'word1']],
@@ -207,14 +204,14 @@ class SearchTest extends PHPUnit\Framework\TestCase {
}
/**
- * @dataProvider provideMultipleSearch
* @param array<string>|null $author_value
* @param array<string> $intitle_value
* @param array<string>|null $inurl_value
* @param array<string>|null $tags_value
* @param array<string>|null $search_value
*/
- public function test__construct_whenInputContainsMultipleKeywords_setsValues(string $input, ?array $author_value, ?int $min_date_value,
+ #[DataProvider('provideMultipleSearch')]
+ public static function test__construct_whenInputContainsMultipleKeywords_setsValues(string $input, ?array $author_value, ?int $min_date_value,
?int $max_date_value, ?array $intitle_value, ?array $inurl_value, ?int $min_pubdate_value,
?int $max_pubdate_value, ?array $tags_value, ?array $search_value): void {
$search = new FreshRSS_Search($input);
@@ -231,7 +228,7 @@ class SearchTest extends PHPUnit\Framework\TestCase {
}
/** @return array<array<mixed>> */
- public function provideMultipleSearch(): array {
+ public static function provideMultipleSearch(): array {
return array(
array(
'author:word1 date:2007-03-01/2008-05-11 intitle:word2 inurl:word3 pubdate:2007-03-01/2008-05-11 #word4 #word5',
@@ -284,15 +281,13 @@ class SearchTest extends PHPUnit\Framework\TestCase {
);
}
- /**
- * @dataProvider provideAddOrParentheses
- */
- public function test__addOrParentheses(string $input, string $output): void {
+ #[DataProvider('provideAddOrParentheses')]
+ public static function test__addOrParentheses(string $input, string $output): void {
self::assertEquals($output, FreshRSS_BooleanSearch::addOrParentheses($input));
}
/** @return array<array{string,string}> */
- public function provideAddOrParentheses(): array {
+ public static function provideAddOrParentheses(): array {
return [
['ab', 'ab'],
['ab cd', 'ab cd'],
@@ -304,15 +299,13 @@ class SearchTest extends PHPUnit\Framework\TestCase {
];
}
- /**
- * @dataProvider provideconsistentOrParentheses
- */
- public function test__consistentOrParentheses(string $input, string $output): void {
+ #[DataProvider('provideconsistentOrParentheses')]
+ public static function test__consistentOrParentheses(string $input, string $output): void {
self::assertEquals($output, FreshRSS_BooleanSearch::consistentOrParentheses($input));
}
/** @return array<array{string,string}> */
- public function provideconsistentOrParentheses(): array {
+ public static function provideconsistentOrParentheses(): array {
return [
['ab cd ef', 'ab cd ef'],
['(ab cd ef)', '(ab cd ef)'],
@@ -332,9 +325,9 @@ class SearchTest extends PHPUnit\Framework\TestCase {
}
/**
- * @dataProvider provideParentheses
* @param array<string> $values
*/
+ #[DataProvider('provideParentheses')]
public function test__parentheses(string $input, string $sql, array $values): void {
[$filterValues, $filterSearch] = FreshRSS_EntryDAOPGSQL::sqlBooleanSearch('e.', new FreshRSS_BooleanSearch($input));
self::assertEquals(trim($sql), trim($filterSearch));
@@ -342,7 +335,7 @@ class SearchTest extends PHPUnit\Framework\TestCase {
}
/** @return array<array<mixed>> */
- public function provideParentheses(): array {
+ public static function provideParentheses(): array {
return [
[
'f:1 (f:2 OR f:3 OR f:4) (f:5 OR (f:6 OR f:7))',
diff --git a/tests/app/Models/UserQueryTest.php b/tests/app/Models/UserQueryTest.php
index 828bd4276..f9577e49b 100644
--- a/tests/app/Models/UserQueryTest.php
+++ b/tests/app/Models/UserQueryTest.php
@@ -6,13 +6,13 @@ declare(strict_types=1);
*/
class UserQueryTest extends PHPUnit\Framework\TestCase {
- public function test__construct_whenAllQuery_storesAllParameters(): void {
+ public static function test__construct_whenAllQuery_storesAllParameters(): void {
$query = array('get' => 'a');
$user_query = new FreshRSS_UserQuery($query, [], []);
self::assertEquals('all', $user_query->getGetType());
}
- public function test__construct_whenFavoriteQuery_storesFavoriteParameters(): void {
+ public static function test__construct_whenFavoriteQuery_storesFavoriteParameters(): void {
$query = array('get' => 's');
$user_query = new FreshRSS_UserQuery($query, [], []);
self::assertEquals('favorite', $user_query->getGetType());
@@ -56,47 +56,47 @@ class UserQueryTest extends PHPUnit\Framework\TestCase {
self::assertEquals('feed', $user_query->getGetType());
}
- public function test__construct_whenUnknownQuery_doesStoreParameters(): void {
+ public static function test__construct_whenUnknownQuery_doesStoreParameters(): void {
$query = array('get' => 'q');
$user_query = new FreshRSS_UserQuery($query, [], []);
self::assertEmpty($user_query->getGetName());
self::assertEmpty($user_query->getGetType());
}
- public function test__construct_whenName_storesName(): void {
+ public static function test__construct_whenName_storesName(): void {
$name = 'some name';
$query = array('name' => $name);
$user_query = new FreshRSS_UserQuery($query, [], []);
self::assertEquals($name, $user_query->getName());
}
- public function test__construct_whenOrder_storesOrder(): void {
+ public static function test__construct_whenOrder_storesOrder(): void {
$order = 'some order';
$query = array('order' => $order);
$user_query = new FreshRSS_UserQuery($query, [], []);
self::assertEquals($order, $user_query->getOrder());
}
- public function test__construct_whenState_storesState(): void {
+ public static function test__construct_whenState_storesState(): void {
$state = FreshRSS_Entry::STATE_NOT_READ | FreshRSS_Entry::STATE_FAVORITE;
$query = array('state' => $state);
$user_query = new FreshRSS_UserQuery($query, [], []);
self::assertEquals($state, $user_query->getState());
}
- public function test__construct_whenUrl_storesUrl(): void {
+ public static function test__construct_whenUrl_storesUrl(): void {
$url = 'some url';
$query = array('url' => $url);
$user_query = new FreshRSS_UserQuery($query, [], []);
self::assertEquals($url, $user_query->getUrl());
}
- public function testToArray_whenNoData_returnsEmptyArray(): void {
+ public static function testToArray_whenNoData_returnsEmptyArray(): void {
$user_query = new FreshRSS_UserQuery([], [], []);
self::assertCount(0, $user_query->toArray());
}
- public function testToArray_whenData_returnsArray(): void {
+ public static function testToArray_whenData_returnsArray(): void {
$query = array(
'get' => 's',
'name' => 'some name',
@@ -110,7 +110,7 @@ class UserQueryTest extends PHPUnit\Framework\TestCase {
self::assertEquals($query, $user_query->toArray());
}
- public function testHasSearch_whenSearch_returnsTrue(): void {
+ public static function testHasSearch_whenSearch_returnsTrue(): void {
$query = array(
'search' => 'some search',
);
@@ -118,24 +118,24 @@ class UserQueryTest extends PHPUnit\Framework\TestCase {
self::assertTrue($user_query->hasSearch());
}
- public function testHasSearch_whenNoSearch_returnsFalse(): void {
+ public static function testHasSearch_whenNoSearch_returnsFalse(): void {
$user_query = new FreshRSS_UserQuery([], [], []);
self::assertFalse($user_query->hasSearch());
}
- public function testHasParameters_whenAllQuery_returnsFalse(): void {
+ public static function testHasParameters_whenAllQuery_returnsFalse(): void {
$query = array('get' => 'a');
$user_query = new FreshRSS_UserQuery($query, [], []);
self::assertFalse($user_query->hasParameters());
}
- public function testHasParameters_whenNoParameter_returnsFalse(): void {
+ public static function testHasParameters_whenNoParameter_returnsFalse(): void {
$query = array();
$user_query = new FreshRSS_UserQuery($query, [], []);
self::assertFalse($user_query->hasParameters());
}
- public function testHasParameters_whenParameter_returnTrue(): void {
+ public static function testHasParameters_whenParameter_returnTrue(): void {
$query = array('get' => 's');
$user_query = new FreshRSS_UserQuery($query, [], []);
self::assertTrue($user_query->hasParameters());
@@ -153,7 +153,7 @@ class UserQueryTest extends PHPUnit\Framework\TestCase {
self::assertFalse($user_query->isDeprecated());
}
- public function testIsDeprecated_whenCategoryDoesNotExist_returnTrue(): void {
+ public static function testIsDeprecated_whenCategoryDoesNotExist_returnTrue(): void {
$query = array('get' => 'c_1');
$user_query = new FreshRSS_UserQuery($query, [], []);
self::assertTrue($user_query->isDeprecated());
@@ -193,19 +193,19 @@ class UserQueryTest extends PHPUnit\Framework\TestCase {
self::assertTrue($user_query->isDeprecated());
}
- public function testIsDeprecated_whenAllQuery_returnFalse(): void {
+ public static function testIsDeprecated_whenAllQuery_returnFalse(): void {
$query = array('get' => 'a');
$user_query = new FreshRSS_UserQuery($query, [], []);
self::assertFalse($user_query->isDeprecated());
}
- public function testIsDeprecated_whenFavoriteQuery_returnFalse(): void {
+ public static function testIsDeprecated_whenFavoriteQuery_returnFalse(): void {
$query = array('get' => 's');
$user_query = new FreshRSS_UserQuery($query, [], []);
self::assertFalse($user_query->isDeprecated());
}
- public function testIsDeprecated_whenUnknownQuery_returnFalse(): void {
+ public static function testIsDeprecated_whenUnknownQuery_returnFalse(): void {
$query = array('get' => 'q');
$user_query = new FreshRSS_UserQuery($query, [], []);
self::assertFalse($user_query->isDeprecated());
diff --git a/tests/app/Utils/dotNotationUtilTest.php b/tests/app/Utils/dotNotationUtilTest.php
index a04ddba4f..e49220d30 100644
--- a/tests/app/Utils/dotNotationUtilTest.php
+++ b/tests/app/Utils/dotNotationUtilTest.php
@@ -1,12 +1,14 @@
<?php
declare(strict_types=1);
+use PHPUnit\Framework\Attributes\DataProvider;
+
class dotNotationUtilTest extends PHPUnit\Framework\TestCase {
/**
* @return Traversable<array{array<string,mixed>,string,string}>
*/
- public function provideJsonDots(): Traversable {
+ public static function provideJsonDots(): Traversable {
$json = <<<json
{
"hello": "world",
@@ -34,10 +36,10 @@ class dotNotationUtilTest extends PHPUnit\Framework\TestCase {
}
/**
- * @dataProvider provideJsonDots
* @param array<string,mixed> $array
*/
- public function testJsonDots(array $array, string $key, string $expected): void {
+ #[DataProvider('provideJsonDots')]
+ public static function testJsonDots(array $array, string $key, string $expected): void {
$value = FreshRSS_dotNotation_Util::get($array, $key);
self::assertEquals($expected, $value);
}
diff --git a/tests/cli/CliOptionsParserTest.php b/tests/cli/CliOptionsParserTest.php
index facb5dbc5..046617721 100644
--- a/tests/cli/CliOptionsParserTest.php
+++ b/tests/cli/CliOptionsParserTest.php
@@ -52,163 +52,138 @@ final class CliOptionsOptionalAndRequiredTest extends CliOptionsParser {
class CliOptionsParserTest extends TestCase {
- public function testInvalidOptionSetWithValueReturnsError(): void {
- $result = $this->runOptionalOptions('--invalid=invalid');
-
+ public static function testInvalidOptionSetWithValueReturnsError(): void {
+ $result = self::runOptionalOptions('--invalid=invalid');
self::assertEquals(['invalid' => 'unknown option: invalid'], $result->errors);
}
- public function testInvalidOptionSetWithoutValueReturnsError(): void {
- $result = $this->runOptionalOptions('--invalid');
-
+ public static function testInvalidOptionSetWithoutValueReturnsError(): void {
+ $result = self::runOptionalOptions('--invalid');
self::assertEquals(['invalid' => 'unknown option: invalid'], $result->errors);
}
- public function testValidOptionSetWithValidValueAndInvalidOptionSetWithValueReturnsValueForValidOptionAndErrorForInvalidOption(): void {
- $result = $this->runOptionalOptions('--string=string --invalid=invalid');
-
+ public static function testValidOptionSetWithValidValueAndInvalidOptionSetWithValueReturnsValueForValidOptionAndErrorForInvalidOption(): void {
+ $result = self::runOptionalOptions('--string=string --invalid=invalid');
self::assertEquals('string', $result->string);
self::assertEquals(['invalid' => 'unknown option: invalid'], $result->errors);
}
- public function testOptionWithValueTypeOfStringSetOnceWithValidValueReturnsValueAsString(): void {
- $result = $this->runOptionalOptions('--string=string');
-
+ public static function testOptionWithValueTypeOfStringSetOnceWithValidValueReturnsValueAsString(): void {
+ $result = self::runOptionalOptions('--string=string');
self::assertEquals('string', $result->string);
}
- public function testOptionWithRequiredValueTypeOfIntSetOnceWithValidValueReturnsValueAsInt(): void {
- $result = $this->runOptionalOptions('--int=111');
-
+ public static function testOptionWithRequiredValueTypeOfIntSetOnceWithValidValueReturnsValueAsInt(): void {
+ $result = self::runOptionalOptions('--int=111');
self::assertEquals(111, $result->int);
}
- public function testOptionWithRequiredValueTypeOfBoolSetOnceWithValidValueReturnsValueAsBool(): void {
- $result = $this->runOptionalOptions('--bool=on');
-
+ public static function testOptionWithRequiredValueTypeOfBoolSetOnceWithValidValueReturnsValueAsBool(): void {
+ $result = self::runOptionalOptions('--bool=on');
self::assertEquals(true, $result->bool);
}
- public function testOptionWithValueTypeOfArrayOfStringSetOnceWithValidValueReturnsValueAsArrayOfString(): void {
- $result = $this->runOptionalOptions('--array-of-string=string');
-
+ public static function testOptionWithValueTypeOfArrayOfStringSetOnceWithValidValueReturnsValueAsArrayOfString(): void {
+ $result = self::runOptionalOptions('--array-of-string=string');
self::assertEquals(['string'], $result->arrayOfString);
}
- public function testOptionWithValueTypeOfStringSetMultipleTimesWithValidValueReturnsLastValueSetAsString(): void {
- $result = $this->runOptionalOptions('--string=first --string=second');
-
+ public static function testOptionWithValueTypeOfStringSetMultipleTimesWithValidValueReturnsLastValueSetAsString(): void {
+ $result = self::runOptionalOptions('--string=first --string=second');
self::assertEquals('second', $result->string);
}
- public function testOptionWithValueTypeOfIntSetMultipleTimesWithValidValueReturnsLastValueSetAsInt(): void {
- $result = $this->runOptionalOptions('--int=111 --int=222');
-
+ public static function testOptionWithValueTypeOfIntSetMultipleTimesWithValidValueReturnsLastValueSetAsInt(): void {
+ $result = self::runOptionalOptions('--int=111 --int=222');
self::assertEquals(222, $result->int);
}
- public function testOptionWithValueTypeOfBoolSetMultipleTimesWithValidValueReturnsLastValueSetAsBool(): void {
- $result = $this->runOptionalOptions('--bool=on --bool=off');
-
+ public static function testOptionWithValueTypeOfBoolSetMultipleTimesWithValidValueReturnsLastValueSetAsBool(): void {
+ $result = self::runOptionalOptions('--bool=on --bool=off');
self::assertEquals(false, $result->bool);
}
- public function testOptionWithValueTypeOfArrayOfStringSetMultipleTimesWithValidValueReturnsAllSetValuesAsArrayOfString(): void {
- $result = $this->runOptionalOptions('--array-of-string=first --array-of-string=second');
-
+ public static function testOptionWithValueTypeOfArrayOfStringSetMultipleTimesWithValidValueReturnsAllSetValuesAsArrayOfString(): void {
+ $result = self::runOptionalOptions('--array-of-string=first --array-of-string=second');
self::assertEquals(['first', 'second'], $result->arrayOfString);
}
- public function testOptionWithValueTypeOfIntSetWithInvalidValueReturnsAnError(): void {
- $result = $this->runOptionalOptions('--int=one');
-
+ public static function testOptionWithValueTypeOfIntSetWithInvalidValueReturnsAnError(): void {
+ $result = self::runOptionalOptions('--int=one');
self::assertEquals(['int' => 'invalid input: int must be an integer'], $result->errors);
}
- public function testOptionWithValueTypeOfBoolSetWithInvalidValuesReturnsAnError(): void {
- $result = $this->runOptionalOptions('--bool=bad');
-
+ public static function testOptionWithValueTypeOfBoolSetWithInvalidValuesReturnsAnError(): void {
+ $result = self::runOptionalOptions('--bool=bad');
self::assertEquals(['bool' => 'invalid input: bool must be a boolean'], $result->errors);
}
- public function testOptionWithValueTypeOfIntSetMultipleTimesWithValidAndInvalidValuesReturnsLastValidValueSetAsIntAndError(): void {
- $result = $this->runOptionalOptions('--int=111 --int=one --int=222 --int=two');
-
+ public static function testOptionWithValueTypeOfIntSetMultipleTimesWithValidAndInvalidValuesReturnsLastValidValueSetAsIntAndError(): void {
+ $result = self::runOptionalOptions('--int=111 --int=one --int=222 --int=two');
self::assertEquals(222, $result->int);
self::assertEquals(['int' => 'invalid input: int must be an integer'], $result->errors);
}
- public function testOptionWithValueTypeOfBoolSetMultipleTimesWithWithValidAndInvalidValuesReturnsLastValidValueSetAsBoolAndError(): void {
- $result = $this->runOptionalOptions('--bool=on --bool=good --bool=off --bool=bad');
-
+ public static function testOptionWithValueTypeOfBoolSetMultipleTimesWithWithValidAndInvalidValuesReturnsLastValidValueSetAsBoolAndError(): void {
+ $result = self::runOptionalOptions('--bool=on --bool=good --bool=off --bool=bad');
self::assertEquals(false, $result->bool);
self::assertEquals(['bool' => 'invalid input: bool must be a boolean'], $result->errors);
}
- public function testNotSetOptionWithDefaultInputReturnsDefaultInput(): void {
- $result = $this->runOptionalOptions('');
-
+ public static function testNotSetOptionWithDefaultInputReturnsDefaultInput(): void {
+ $result = self::runOptionalOptions('');
self::assertEquals('default', $result->defaultInput);
}
- public function testOptionWithDefaultInputSetWithValidValueReturnsCorrectlyTypedValue(): void {
- $result = $this->runOptionalOptions('--default-input=input');
-
+ public static function testOptionWithDefaultInputSetWithValidValueReturnsCorrectlyTypedValue(): void {
+ $result = self::runOptionalOptions('--default-input=input');
self::assertEquals('input', $result->defaultInput);
}
- public function testOptionWithOptionalValueSetWithoutValueReturnsEmptyString(): void {
- $result = $this->runOptionalOptions('--optional-value');
-
+ public static function testOptionWithOptionalValueSetWithoutValueReturnsEmptyString(): void {
+ $result = self::runOptionalOptions('--optional-value');
self::assertEquals('', $result->optionalValue);
}
- public function testOptionWithOptionalValueDefaultSetWithoutValueReturnsOptionalValueDefault(): void {
- $result = $this->runOptionalOptions('--optional-value-with-default');
-
+ public static function testOptionWithOptionalValueDefaultSetWithoutValueReturnsOptionalValueDefault(): void {
+ $result = self::runOptionalOptions('--optional-value-with-default');
self::assertEquals(true, $result->optionalValueWithDefault);
}
- public function testNotSetOptionWithOptionalValueDefaultAndDefaultInputReturnsDefaultInput(): void {
- $result = $this->runOptionalOptions('');
-
+ public static function testNotSetOptionWithOptionalValueDefaultAndDefaultInputReturnsDefaultInput(): void {
+ $result = self::runOptionalOptions('');
self::assertEquals('default', $result->defaultInputAndOptionalValueWithDefault);
}
- public function testOptionWithOptionalValueDefaultAndDefaultInputSetWithoutValueReturnsOptionalValueDefault(): void {
- $result = $this->runOptionalOptions('--default-input-and-optional-value-with-default');
-
+ public static function testOptionWithOptionalValueDefaultAndDefaultInputSetWithoutValueReturnsOptionalValueDefault(): void {
+ $result = self::runOptionalOptions('--default-input-and-optional-value-with-default');
self::assertEquals('optional', $result->defaultInputAndOptionalValueWithDefault);
}
- public function testRequiredOptionNotSetReturnsError(): void {
- $result = $this->runOptionalAndRequiredOptions('');
-
+ public static function testRequiredOptionNotSetReturnsError(): void {
+ $result = self::runOptionalAndRequiredOptions('');
self::assertEquals(['required' => 'invalid input: required cannot be empty'], $result->errors);
}
- public function testOptionSetWithDeprecatedAliasGeneratesDeprecationWarningAndReturnsValue(): void {
- $result = $this->runCommandReadingStandardError('--deprecated-string=string');
-
+ public static function testOptionSetWithDeprecatedAliasGeneratesDeprecationWarningAndReturnsValue(): void {
+ $result = self::runCommandReadingStandardError('--deprecated-string=string');
self::assertEquals('FreshRSS deprecation warning: the CLI option(s): deprecated-string are deprecated ' .
'and will be removed in a future release. Use: string instead',
$result
);
- $result = $this->runOptionalOptions('--deprecated-string=string');
-
+ $result = self::runOptionalOptions('--deprecated-string=string');
self::assertEquals('string', $result->string);
}
- public function testAlwaysReturnUsageMessageWithUsageInfoForAllOptions(): void {
- $result = $this->runOptionalAndRequiredOptions('');
-
+ public static function testAlwaysReturnUsageMessageWithUsageInfoForAllOptions(): void {
+ $result = self::runOptionalAndRequiredOptions('');
self::assertEquals('Usage: cli-parser-test.php --required=<required> [-s --string=<string>] [-i --int=<int>] [-b --bool=<bool>] [-f --flag]',
$result->usage,
);
}
- private function runOptionalOptions(string $cliOptions = ''): CliOptionsOptionalTest {
+ private static function runOptionalOptions(string $cliOptions = ''): CliOptionsOptionalTest {
$command = __DIR__ . '/cli-parser-test.php';
$className = CliOptionsOptionalTest::class;
@@ -219,7 +194,7 @@ class CliOptionsParserTest extends TestCase {
return $result;
}
- private function runOptionalAndRequiredOptions(string $cliOptions = ''): CliOptionsOptionalAndRequiredTest {
+ private static function runOptionalAndRequiredOptions(string $cliOptions = ''): CliOptionsOptionalAndRequiredTest {
$command = __DIR__ . '/cli-parser-test.php';
$className = CliOptionsOptionalAndRequiredTest::class;
@@ -230,7 +205,7 @@ class CliOptionsParserTest extends TestCase {
return $result;
}
- private function runCommandReadingStandardError(string $cliOptions = ''): string {
+ private static function runCommandReadingStandardError(string $cliOptions = ''): string {
$command = __DIR__ . '/cli-parser-test.php';
$className = CliOptionsOptionalTest::class;
diff --git a/tests/cli/i18n/I18nCompletionValidatorTest.php b/tests/cli/i18n/I18nCompletionValidatorTest.php
index bc992edbe..f16285005 100644
--- a/tests/cli/i18n/I18nCompletionValidatorTest.php
+++ b/tests/cli/i18n/I18nCompletionValidatorTest.php
@@ -42,7 +42,7 @@ class I18nCompletionValidatorTest extends PHPUnit\Framework\TestCase {
$validator->displayReport();
}
- public function testValidateWhenNoData(): void {
+ public static function testValidateWhenNoData(): void {
$validator = new I18nCompletionValidator([], []);
self::assertTrue($validator->validate());
self::assertEquals('', $validator->displayResult());
diff --git a/tests/cli/i18n/I18nUsageValidatorTest.php b/tests/cli/i18n/I18nUsageValidatorTest.php
index 3135cef22..1c604390f 100644
--- a/tests/cli/i18n/I18nUsageValidatorTest.php
+++ b/tests/cli/i18n/I18nUsageValidatorTest.php
@@ -42,7 +42,7 @@ class I18nUsageValidatorTest extends PHPUnit\Framework\TestCase {
$validator->displayReport();
}
- public function testValidateWhenNoData(): void {
+ public static function testValidateWhenNoData(): void {
$validator = new I18nUsageValidator([], []);
self::assertTrue($validator->validate());
self::assertEquals('', $validator->displayResult());
diff --git a/tests/cli/i18n/I18nValueTest.php b/tests/cli/i18n/I18nValueTest.php
index 06d57eb08..44984d7b2 100644
--- a/tests/cli/i18n/I18nValueTest.php
+++ b/tests/cli/i18n/I18nValueTest.php
@@ -3,35 +3,35 @@ declare(strict_types=1);
require_once __DIR__ . '/../../../cli/i18n/I18nValue.php';
class I18nValueTest extends PHPUnit\Framework\TestCase {
- public function testConstructorWithoutState(): void {
+ public static function testConstructorWithoutState(): void {
$value = new I18nValue('some value');
self::assertEquals('some value', $value->getValue());
self::assertFalse($value->isIgnore());
self::assertFalse($value->isTodo());
}
- public function testConstructorWithUnknownState(): void {
+ public static function testConstructorWithUnknownState(): void {
$value = new I18nValue('some value -> unknown');
self::assertEquals('some value', $value->getValue());
self::assertFalse($value->isIgnore());
self::assertFalse($value->isTodo());
}
- public function testConstructorWithTodoState(): void {
+ public static function testConstructorWithTodoState(): void {
$value = new I18nValue('some value -> todo');
self::assertEquals('some value', $value->getValue());
self::assertFalse($value->isIgnore());
self::assertTrue($value->isTodo());
}
- public function testConstructorWithIgnoreState(): void {
+ public static function testConstructorWithIgnoreState(): void {
$value = new I18nValue('some value -> ignore');
self::assertEquals('some value', $value->getValue());
self::assertTrue($value->isIgnore());
self::assertFalse($value->isTodo());
}
- public function testClone(): void {
+ public static function testClone(): void {
$value = new I18nValue('some value');
$clonedValue = clone $value;
self::assertEquals('some value', $value->getValue());
@@ -42,21 +42,21 @@ class I18nValueTest extends PHPUnit\Framework\TestCase {
self::assertTrue($clonedValue->isTodo());
}
- public function testEqualWhenValueIsIdentical(): void {
+ public static function testEqualWhenValueIsIdentical(): void {
$value = new I18nValue('some value');
$clonedValue = clone $value;
self::assertTrue($value->equal($clonedValue));
self::assertTrue($clonedValue->equal($value));
}
- public function testEqualWhenValueIsDifferent(): void {
+ public static function testEqualWhenValueIsDifferent(): void {
$value = new I18nValue('some value');
$otherValue = new I18nValue('some other value');
self::assertFalse($value->equal($otherValue));
self::assertFalse($otherValue->equal($value));
}
- public function testStates(): void {
+ public static function testStates(): void {
$reflectionProperty = new ReflectionProperty(I18nValue::class, 'state');
$reflectionProperty->setAccessible(true);
@@ -74,7 +74,7 @@ class I18nValueTest extends PHPUnit\Framework\TestCase {
self::assertEquals('todo', $reflectionProperty->getValue($value));
}
- public function testToString(): void {
+ public static function testToString(): void {
$value = new I18nValue('some value');
self::assertEquals('some value', $value->__toString());
$value->markAsTodo();
diff --git a/tests/lib/CssXPath/CssXPathTest.php b/tests/lib/CssXPath/CssXPathTest.php
index ed92ece16..8197f5b87 100644
--- a/tests/lib/CssXPath/CssXPathTest.php
+++ b/tests/lib/CssXPath/CssXPathTest.php
@@ -3,7 +3,7 @@ declare(strict_types=1);
class CssXPathTest extends PHPUnit\Framework\TestCase
{
- public function testCssXPathTranslatorClassExists(): void {
+ public static function testCssXPathTranslatorClassExists(): void {
self::assertTrue(class_exists('Gt\\CssXPath\\Translator'));
}
}
diff --git a/tests/lib/Minz/MigratorTest.php b/tests/lib/Minz/MigratorTest.php
index 6560715da..75c6eee23 100644
--- a/tests/lib/Minz/MigratorTest.php
+++ b/tests/lib/Minz/MigratorTest.php
@@ -4,7 +4,7 @@ use PHPUnit\Framework\TestCase;
class MigratorTest extends TestCase
{
- public function testAddMigration(): void {
+ public static function testAddMigration(): void {
$migrator = new Minz_Migrator();
$migrator->addMigration('foo', fn() => true);
@@ -15,7 +15,7 @@ class MigratorTest extends TestCase
self::assertTrue($result);
}
- public function testMigrationsIsSorted(): void {
+ public static function testMigrationsIsSorted(): void {
$migrator = new Minz_Migrator();
$migrator->addMigration('2_foo', fn() => true);
$migrator->addMigration('10_foo', fn() => true);
@@ -27,7 +27,7 @@ class MigratorTest extends TestCase
self::assertSame($expected_versions, array_keys($migrations));
}
- public function testSetAppliedVersions(): void {
+ public static function testSetAppliedVersions(): void {
$migrator = new Minz_Migrator();
$migrator->addMigration('foo', fn() => true);
@@ -36,7 +36,7 @@ class MigratorTest extends TestCase
self::assertSame(['foo'], $migrator->appliedVersions());
}
- public function testSetAppliedVersionsTrimArgument(): void {
+ public static function testSetAppliedVersionsTrimArgument(): void {
$migrator = new Minz_Migrator();
$migrator->addMigration('foo', fn() => true);
@@ -54,7 +54,7 @@ class MigratorTest extends TestCase
$migrator->setAppliedVersions(['foo']);
}
- public function testVersions(): void {
+ public static function testVersions(): void {
$migrator = new Minz_Migrator();
$migrator->addMigration('foo', fn() => true);
$migrator->addMigration('bar', fn() => true);
@@ -64,7 +64,7 @@ class MigratorTest extends TestCase
self::assertSame(['bar', 'foo'], $versions);
}
- public function testMigrate(): void {
+ public static function testMigrate(): void {
$migrator = new Minz_Migrator();
$spy = false;
$migrator->addMigration('foo', function () use (&$spy) {
@@ -82,7 +82,7 @@ class MigratorTest extends TestCase
], $result);
}
- public function testMigrateCallsMigrationsInSortedOrder(): void {
+ public static function testMigrateCallsMigrationsInSortedOrder(): void {
$migrator = new Minz_Migrator();
$spy_foo_1_is_called = false;
$migrator->addMigration('2_foo', function () use (&$spy_foo_1_is_called) {
@@ -102,7 +102,7 @@ class MigratorTest extends TestCase
], $result);
}
- public function testMigrateDoesNotCallAppliedMigrations(): void {
+ public static function testMigrateDoesNotCallAppliedMigrations(): void {
$migrator = new Minz_Migrator();
$spy = false;
$migrator->addMigration('1_foo', function () use (&$spy) {
@@ -117,7 +117,7 @@ class MigratorTest extends TestCase
self::assertSame([], $result);
}
- public function testMigrateCallNonAppliedBetweenTwoApplied(): void {
+ public static function testMigrateCallNonAppliedBetweenTwoApplied(): void {
$migrator = new Minz_Migrator();
$migrator->addMigration('1_foo', fn() => true);
$migrator->addMigration('2_foo', fn() => true);
@@ -132,7 +132,7 @@ class MigratorTest extends TestCase
], $result);
}
- public function testMigrateWithMigrationReturningFalseDoesNotApplyVersion(): void {
+ public static function testMigrateWithMigrationReturningFalseDoesNotApplyVersion(): void {
$migrator = new Minz_Migrator();
$migrator->addMigration('1_foo', fn() => true);
$migrator->addMigration('2_foo', fn() => false);
@@ -146,7 +146,7 @@ class MigratorTest extends TestCase
], $result);
}
- public function testMigrateWithMigrationReturningFalseDoesNotExecuteNextMigrations(): void {
+ public static function testMigrateWithMigrationReturningFalseDoesNotExecuteNextMigrations(): void {
$migrator = new Minz_Migrator();
$migrator->addMigration('1_foo', fn() => false);
$spy = false;
@@ -164,7 +164,7 @@ class MigratorTest extends TestCase
], $result);
}
- public function testMigrateWithFailingMigration(): void {
+ public static function testMigrateWithFailingMigration(): void {
$migrator = new Minz_Migrator();
$migrator->addMigration('foo', function () {
throw new \Exception('Oops, it failed.');
@@ -178,7 +178,7 @@ class MigratorTest extends TestCase
], $result);
}
- public function testUpToDate(): void {
+ public static function testUpToDate(): void {
$migrator = new Minz_Migrator();
$migrator->addMigration('foo', fn() => true);
$migrator->setAppliedVersions(['foo']);
@@ -188,7 +188,7 @@ class MigratorTest extends TestCase
self::assertTrue($upToDate);
}
- public function testUpToDateIfRemainingMigration(): void {
+ public static function testUpToDateIfRemainingMigration(): void {
$migrator = new Minz_Migrator();
$migrator->addMigration('1_foo', fn() => true);
$migrator->addMigration('2_foo', fn() => true);
@@ -199,7 +199,7 @@ class MigratorTest extends TestCase
self::assertFalse($upToDate);
}
- public function testUpToDateIfNoMigrations(): void {
+ public static function testUpToDateIfNoMigrations(): void {
$migrator = new Minz_Migrator();
$upToDate = $migrator->upToDate();
@@ -207,7 +207,7 @@ class MigratorTest extends TestCase
self::assertTrue($upToDate);
}
- public function testConstructorLoadsDirectory(): void {
+ public static function testConstructorLoadsDirectory(): void {
$migrations_path = TESTS_PATH . '/fixtures/migrations/';
$migrator = new Minz_Migrator($migrations_path);
$expected_versions = ['2019_12_22_FooBar', '2019_12_23_Baz'];
@@ -217,7 +217,7 @@ class MigratorTest extends TestCase
self::assertSame($expected_versions, array_keys($migrations));
}
- public function testExecute(): void {
+ public static function testExecute(): void {
$migrations_path = TESTS_PATH . '/fixtures/migrations/';
$applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt');
self::assertIsString($applied_migrations_path);
@@ -229,7 +229,7 @@ class MigratorTest extends TestCase
@unlink($applied_migrations_path);
}
- public function testExecuteWithAlreadyAppliedMigration(): void {
+ public static function testExecuteWithAlreadyAppliedMigration(): void {
$migrations_path = TESTS_PATH . '/fixtures/migrations/';
$applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt');
self::assertIsString($applied_migrations_path);
@@ -243,7 +243,7 @@ class MigratorTest extends TestCase
@unlink($applied_migrations_path);
}
- public function testExecuteWithAppliedMigrationInDifferentOrder(): void {
+ public static function testExecuteWithAppliedMigrationInDifferentOrder(): void {
$migrations_path = TESTS_PATH . '/fixtures/migrations/';
$applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt');
self::assertIsString($applied_migrations_path);
@@ -258,7 +258,7 @@ class MigratorTest extends TestCase
@unlink($applied_migrations_path);
}
- public function testExecuteFailsIfVersionPathDoesNotExist(): void {
+ public static function testExecuteFailsIfVersionPathDoesNotExist(): void {
$migrations_path = TESTS_PATH . '/fixtures/migrations/';
$applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt');
$expected_result = "Cannot open the {$applied_migrations_path} file";
@@ -270,7 +270,7 @@ class MigratorTest extends TestCase
@unlink($applied_migrations_path);
}
- public function testExecuteFailsIfAMigrationIsFailing(): void {
+ public static function testExecuteFailsIfAMigrationIsFailing(): void {
$migrations_path = TESTS_PATH . '/fixtures/migrations_with_failing/';
$applied_migrations_path = tempnam('/tmp', 'applied_migrations.txt');
$expected_result = 'A migration failed to be applied, please see previous logs.';
diff --git a/tests/lib/PHPMailer/PHPMailerTest.php b/tests/lib/PHPMailer/PHPMailerTest.php
index bb08deaa8..8bc8378b6 100644
--- a/tests/lib/PHPMailer/PHPMailerTest.php
+++ b/tests/lib/PHPMailer/PHPMailerTest.php
@@ -5,7 +5,7 @@ use PHPMailer\PHPMailer\PHPMailer;
class PHPMailerTest extends PHPUnit\Framework\TestCase
{
- public function testPHPMailerClassExists(): void {
+ public static function testPHPMailerClassExists(): void {
self::assertTrue(class_exists(PHPMailer::class));
}
}