Use native PHP #[Deprecated] (#8325)

https://php.watch/versions/8.4/Deprecated
And enfore it with PHPUnit + PHPStan.
Especially useful for extensions.
This commit is contained in:
Alexandre Alapetite
2025-12-17 10:11:18 +01:00
committed by GitHub
parent 4bd5035914
commit 00cd5df294
15 changed files with 140 additions and 72 deletions

View File

@@ -227,8 +227,8 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController {
/**
* This action displays the RSS feed of FreshRSS.
* @deprecated See user query RSS sharing instead
*/
#[Deprecated('See user query RSS sharing instead')]
public function rssAction(): void {
$allow_anonymous = FreshRSS_Context::systemConf()->allow_anonymous;
@@ -262,9 +262,7 @@ class FreshRSS_index_Controller extends FreshRSS_ActionController {
header('Content-Type: application/rss+xml; charset=utf-8');
}
/**
* @deprecated See user query OPML sharing instead
*/
#[Deprecated('See user query OPML sharing instead')]
public function opmlAction(): void {
$allow_anonymous = FreshRSS_Context::systemConf()->allow_anonymous;

View File

@@ -57,11 +57,13 @@ final class FreshRSS_Context {
/**
* @access private
* @deprecated Will be made `private`; use `FreshRSS_Context::systemConf()` instead.
* @internal
*/
public static ?FreshRSS_SystemConfiguration $system_conf = null;
/**
* @access private
* @deprecated Will be made `private`; use `FreshRSS_Context::userConf()` instead.
* @internal
*/
public static ?FreshRSS_UserConfiguration $user_conf = null;
@@ -186,6 +188,13 @@ final class FreshRSS_Context {
FreshRSS_Context::$user_conf = null;
}
/**
* @internal
*/
public static function setUserConf(?FreshRSS_UserConfiguration $user_conf): void {
FreshRSS_Context::$user_conf = $user_conf;
}
/** @return array<int,FreshRSS_Category> where the key is the category ID */
public static function categories(): array {
if (empty(self::$categories)) {

View File

@@ -160,7 +160,8 @@ class FreshRSS_Entry extends Minz_Model {
}
return $title;
}
/** @deprecated */
#[Deprecated('Use authors() instead')]
public function author(): string {
return $this->authors(true);
}
@@ -540,7 +541,8 @@ HTML;
$this->hash = '';
$this->title = trim($value);
}
/** @deprecated */
#[Deprecated('Use _authors() instead')]
public function _author(string $value): void {
$this->_authors($value);
}

View File

@@ -40,7 +40,7 @@ class FreshRSS_Feed extends Minz_Model {
public const PRIORITY_CATEGORY = 0;
public const PRIORITY_FEED = -5;
public const PRIORITY_HIDDEN = -10;
/** @deprecated use PRIORITY_HIDDEN instead */
#[Deprecated('Use PRIORITY_HIDDEN instead')]
public const PRIORITY_ARCHIVED = -10;
public const TTL_DEFAULT = 0;

View File

@@ -13,8 +13,8 @@ final class FreshRSS_SimplePieCustom extends \SimplePie\SimplePie
$limits = FreshRSS_Context::systemConf()->limits;
$this->get_registry()->register(\SimplePie\File::class, FreshRSS_SimplePieFetch::class);
$this->set_useragent(FRESHRSS_USERAGENT);
$this->set_cache_name_function('sha1');
$this->set_cache_location(CACHE_PATH);
$this->set_cache_name_function('sha1'); // @phpstan-ignore method.deprecated
$this->set_cache_location(CACHE_PATH); // @phpstan-ignore method.deprecated
$this->set_cache_duration($limits['cache_duration'], $limits['cache_duration_min'], $limits['cache_duration_max']);
$this->enable_order_by_date(false);

View File

@@ -58,6 +58,7 @@
"ext-tokenizer": "*",
"ext-xmlwriter": "*",
"phpstan/phpstan": "^2.1",
"phpstan/phpstan-deprecation-rules": "^2.0",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^10",
@@ -70,7 +71,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 --display-notices --display-phpunit-deprecations ./tests",
"phpunit": "phpunit --bootstrap ./tests/bootstrap.php --display-notices --display-deprecations --display-phpunit-deprecations ./tests",
"translations": "cli/manipulate.translation.php --action format && cli/check.translation.php --generate-readme",
"test": [
"@php-lint",

109
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "3a4fbd6ff5c1cb410b629030fe0571e7",
"content-hash": "a9fa7dc52d7ae1c05b7c889cb59881db",
"packages": [],
"packages-dev": [
{
@@ -69,16 +69,16 @@
},
{
"name": "nikic/php-parser",
"version": "v5.6.2",
"version": "v5.7.0",
"source": {
"type": "git",
"url": "https://github.com/nikic/PHP-Parser.git",
"reference": "3a454ca033b9e06b63282ce19562e892747449bb"
"reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/3a454ca033b9e06b63282ce19562e892747449bb",
"reference": "3a454ca033b9e06b63282ce19562e892747449bb",
"url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82",
"reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82",
"shasum": ""
},
"require": {
@@ -121,9 +121,9 @@
],
"support": {
"issues": "https://github.com/nikic/PHP-Parser/issues",
"source": "https://github.com/nikic/PHP-Parser/tree/v5.6.2"
"source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0"
},
"time": "2025-10-21T19:32:17+00:00"
"time": "2025-12-06T11:56:16+00:00"
},
{
"name": "phar-io/manifest",
@@ -245,11 +245,11 @@
},
{
"name": "phpstan/phpstan",
"version": "2.1.32",
"version": "2.1.33",
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/e126cad1e30a99b137b8ed75a85a676450ebb227",
"reference": "e126cad1e30a99b137b8ed75a85a676450ebb227",
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/9e800e6bee7d5bd02784d4c6069b48032d16224f",
"reference": "9e800e6bee7d5bd02784d4c6069b48032d16224f",
"shasum": ""
},
"require": {
@@ -294,20 +294,67 @@
"type": "github"
}
],
"time": "2025-11-11T15:18:17+00:00"
"time": "2025-12-05T10:24:31+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
"version": "2.0.8",
"name": "phpstan/phpstan-deprecation-rules",
"version": "2.0.3",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git",
"reference": "2fe9fbeceaf76dd1ebaa7bbbb25e2fb5e59db2fe"
"url": "https://github.com/phpstan/phpstan-deprecation-rules.git",
"reference": "468e02c9176891cc901143da118f09dc9505fc2f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/2fe9fbeceaf76dd1ebaa7bbbb25e2fb5e59db2fe",
"reference": "2fe9fbeceaf76dd1ebaa7bbbb25e2fb5e59db2fe",
"url": "https://api.github.com/repos/phpstan/phpstan-deprecation-rules/zipball/468e02c9176891cc901143da118f09dc9505fc2f",
"reference": "468e02c9176891cc901143da118f09dc9505fc2f",
"shasum": ""
},
"require": {
"php": "^7.4 || ^8.0",
"phpstan/phpstan": "^2.1.15"
},
"require-dev": {
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/phpstan-phpunit": "^2.0",
"phpunit/phpunit": "^9.6"
},
"type": "phpstan-extension",
"extra": {
"phpstan": {
"includes": [
"rules.neon"
]
}
},
"autoload": {
"psr-4": {
"PHPStan\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"description": "PHPStan rules for detecting usage of deprecated classes, methods, properties, constants and traits.",
"support": {
"issues": "https://github.com/phpstan/phpstan-deprecation-rules/issues",
"source": "https://github.com/phpstan/phpstan-deprecation-rules/tree/2.0.3"
},
"time": "2025-05-14T10:56:57+00:00"
},
{
"name": "phpstan/phpstan-phpunit",
"version": "2.0.10",
"source": {
"type": "git",
"url": "https://github.com/phpstan/phpstan-phpunit.git",
"reference": "8d61a5854e7497d95bc85188e13537e99bd7aae7"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/phpstan/phpstan-phpunit/zipball/8d61a5854e7497d95bc85188e13537e99bd7aae7",
"reference": "8d61a5854e7497d95bc85188e13537e99bd7aae7",
"shasum": ""
},
"require": {
@@ -345,9 +392,9 @@
"description": "PHPUnit extensions and rules for PHPStan",
"support": {
"issues": "https://github.com/phpstan/phpstan-phpunit/issues",
"source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.8"
"source": "https://github.com/phpstan/phpstan-phpunit/tree/2.0.10"
},
"time": "2025-11-11T07:55:22+00:00"
"time": "2025-12-06T11:15:39+00:00"
},
{
"name": "phpstan/phpstan-strict-rules",
@@ -720,16 +767,16 @@
},
{
"name": "phpunit/phpunit",
"version": "10.5.58",
"version": "10.5.60",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "e24fb46da450d8e6a5788670513c1af1424f16ca"
"reference": "f2e26f52f80ef77832e359205f216eeac00e320c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/e24fb46da450d8e6a5788670513c1af1424f16ca",
"reference": "e24fb46da450d8e6a5788670513c1af1424f16ca",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f2e26f52f80ef77832e359205f216eeac00e320c",
"reference": "f2e26f52f80ef77832e359205f216eeac00e320c",
"shasum": ""
},
"require": {
@@ -801,7 +848,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.58"
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.60"
},
"funding": [
{
@@ -825,7 +872,7 @@
"type": "tidelift"
}
],
"time": "2025-09-28T12:04:46+00:00"
"time": "2025-12-06T07:50:42+00:00"
},
{
"name": "sebastian/cli-parser",
@@ -1861,16 +1908,16 @@
},
{
"name": "theseer/tokenizer",
"version": "1.2.3",
"version": "1.3.1",
"source": {
"type": "git",
"url": "https://github.com/theseer/tokenizer.git",
"reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2"
"reference": "b7489ce515e168639d17feec34b8847c326b0b3c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
"reference": "737eda637ed5e28c3413cb1ebe8bb52cbf1ca7a2",
"url": "https://api.github.com/repos/theseer/tokenizer/zipball/b7489ce515e168639d17feec34b8847c326b0b3c",
"reference": "b7489ce515e168639d17feec34b8847c326b0b3c",
"shasum": ""
},
"require": {
@@ -1899,7 +1946,7 @@
"description": "A small library for converting tokenized PHP source code into XML and potentially other formats",
"support": {
"issues": "https://github.com/theseer/tokenizer/issues",
"source": "https://github.com/theseer/tokenizer/tree/1.2.3"
"source": "https://github.com/theseer/tokenizer/tree/1.3.1"
},
"funding": [
{
@@ -1907,7 +1954,7 @@
"type": "github"
}
],
"time": "2024-03-03T12:36:25+00:00"
"time": "2025-11-17T20:03:58+00:00"
}
],
"aliases": [],

View File

@@ -27,6 +27,8 @@ abstract class Minz_ActionController {
* Gives the possibility to override the default view model type.
* @var class-string
* @deprecated Use constructor with view type instead
* @access private
* @internal
*/
public static string $defaultViewType = Minz_View::class;
@@ -43,8 +45,8 @@ abstract class Minz_ActionController {
$view = null;
}
}
if ($view === null && class_exists(self::$defaultViewType)) {
$view = new self::$defaultViewType();
if ($view === null && class_exists(self::$defaultViewType)) { /// @phpstan-ignore staticProperty.deprecated
$view = new self::$defaultViewType(); // @phpstan-ignore staticProperty.deprecated
if (!($view instanceof Minz_View)) {
$view = null;
}

View File

@@ -26,7 +26,7 @@ class Minz_Configuration {
* @param string $namespace the name of the current configuration
* @param string $config_filename the filename of the configuration
* @param string $default_filename a filename containing default values for the configuration
* @param Minz_ConfigurationSetterInterface $configuration_setter an optional helper to set values in configuration
* @param Minz_ConfigurationSetterInterface $configuration_setter an optional helper to set values in configuration @deprecated
* @throws Minz_FileNotExistException
*/
public static function register(string $namespace, string $config_filename, ?string $default_filename = null,
@@ -102,7 +102,7 @@ class Minz_Configuration {
* @param string $namespace the name of the current configuration.
* @param string $config_filename the file containing configuration values.
* @param string $default_filename the file containing default values, null by default.
* @param Minz_ConfigurationSetterInterface $configuration_setter an optional helper to set values in configuration
* @param Minz_ConfigurationSetterInterface $configuration_setter an optional helper to set values in configuration @deprecated
* @throws Minz_FileNotExistException
*/
final private function __construct(string $namespace, string $config_filename, ?string $default_filename = null,
@@ -138,6 +138,7 @@ class Minz_Configuration {
}
}
#[Deprecated]
public function configurationSetter(): ?Minz_ConfigurationSetterInterface {
return $this->configuration_setter;
}
@@ -155,13 +156,12 @@ class Minz_Configuration {
* @param string $key the name of the param.
* @param mixed $default default value to return if key does not exist.
* @return array|mixed value corresponding to the key.
* @access private
* @deprecated Use `attribute*()` methods instead.
*/
#[Deprecated('Use `attribute*()` methods instead.')]
public function param(string $key, mixed $default = null): mixed {
if (isset($this->data[$key])) {
return $this->data[$key];
} elseif (!is_null($default)) {
} elseif ($default !== null) {
return $default;
} else {
Minz_Log::warning($key . ' does not exist in configuration');
@@ -170,13 +170,14 @@ class Minz_Configuration {
}
/**
* A wrapper for param().
* @return array|mixed
* @access private
* @deprecated
*/
public function __get(string $key): mixed {
return $this->param($key);
if (isset($this->data[$key])) {
return $this->data[$key];
}
Minz_Log::warning($key . ' does not exist in configuration');
return null;
}
/**
@@ -184,13 +185,12 @@ 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.
* @access private
* @deprecated Use `_attribute()` instead.
*/
#[Deprecated('Use `_attribute()` instead.')]
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)) {
} elseif (isset($this->data[$key]) && $value === null) {
unset($this->data[$key]);
} elseif ($value !== null) {
$this->data[$key] = $value;
@@ -198,12 +198,16 @@ class Minz_Configuration {
}
/**
* A wrapper for _param().
* @access private
* @deprecated
* {@see Minz_Configuration::_attribute()} instead.
* @param string $key the param name to set.
* @param mixed $value the value to set. If null, the key is removed.
*/
public function __set(string $key, mixed $value): void {
$this->_param($key, $value);
if ($value === null) {
unset($this->data[$key]);
} else {
$this->data[$key] = $value;
}
}
/**
@@ -266,6 +270,10 @@ class Minz_Configuration {
* @param array<string,mixed>|mixed|null $value Value, not HTML-encoded
*/
public function _attribute(string $key, $value = null): void {
self::_param($key, $value);
if (isset($this->data[$key]) && $value === null) {
unset($this->data[$key]);
} elseif ($value !== null) {
$this->data[$key] = $value;
}
}
}

View File

@@ -42,8 +42,8 @@ class Minz_Request {
* @param mixed $default default value, if no parameter is given
* @param bool $specialchars `true` to return special characters, `false` (default) to XML-encode them
* @return mixed value of the parameter
* @deprecated use typed versions instead
*/
#[Deprecated('Use typed versions instead')]
public static function param(string $key, mixed $default = false, bool $specialchars = false): mixed {
if (isset(self::$params[$key])) {
$p = self::$params[$key];

View File

@@ -61,8 +61,8 @@ class Minz_Session {
* @param string $p the parameter to retrieve
* @param mixed|false $default the default value if the parameter doesnt exist
* @return mixed|false the value of the session variable, false if doesnt exist
* @deprecated Use typed versions instead
*/
#[Deprecated('Use typed versions instead')]
public static function param(string $p, $default = false): mixed {
return $_SESSION[$p] ?? $default;
}

View File

@@ -39,8 +39,9 @@ class Minz_View {
}
/**
* @deprecated Change the view file based on controller and action.
* Change the view file based on controller and action.
*/
#[Deprecated('Use Minz_View::_path() instead.')]
public function change_view(string $controller_name, string $action_name): void {
Minz_Log::warning('Minz_View::change_view is deprecated, it will be removed in a future version. Please use Minz_View::_path instead.');
$this->_path($controller_name . '/' . $action_name . '.phtml');
@@ -170,9 +171,9 @@ class Minz_View {
/**
* Choose if we want to use the layout or not.
* @deprecated Please use the `_layout` function instead.
* @param bool $use true if we want to use the layout, false else
*/
#[Deprecated('Use Minz_View::_layout() instead.')]
public function _useLayout(bool $use): void {
Minz_Log::warning('Minz_View::_useLayout is deprecated, it will be removed in a future version. Please use Minz_View::_layout instead.');
if ($use) {

View File

@@ -307,16 +307,12 @@ function invalidateHttpCache(string $username = ''): bool {
return FreshRSS_UserDAO::ctouch($username);
}
/**
* @deprecated Use {@see Minz_Request::connectionRemoteAddress()} instead.
*/
#[Deprecated('Use Minz_Request::connectionRemoteAddress() instead.')]
function connectionRemoteAddress(): string {
return Minz_Request::connectionRemoteAddress();
}
/**
* @deprecated Use {@see FreshRSS_http_Util::checkTrustedIP()} instead.
*/
#[Deprecated('Use FreshRSS_http_Util::checkTrustedIP() instead.')]
function checkTrustedIP(): bool {
return FreshRSS_http_Util::checkTrustedIP();
}

View File

@@ -57,7 +57,11 @@ parameters:
- 'Minz_Exception'
ignoreErrors:
- '#Only booleans are allowed in (a negated boolean|a ternary operator condition|an elseif condition|an if condition|&&|\|\|), (bool|false|int(<[0-9, max]+>)?|true|null|\|)+ given.*#'
-
message: '#Access to deprecated#'
path: app/Models/Context.php
includes:
- vendor/phpstan/phpstan-deprecation-rules/rules.neon
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
- vendor/phpstan/phpstan-strict-rules/rules.neon

View File

@@ -251,7 +251,7 @@ final class SearchTest extends \PHPUnit\Framework\TestCase {
$previousUserConf = FreshRSS_Context::hasUserConf() ? FreshRSS_Context::userConf() : null;
$newUserConf = $previousUserConf instanceof FreshRSS_UserConfiguration ? clone $previousUserConf : clone FreshRSS_UserConfiguration::default();
$newUserConf->queries = $queries;
FreshRSS_Context::$user_conf = $newUserConf;
FreshRSS_Context::setUserConf($newUserConf);
try {
$search = new FreshRSS_BooleanSearch($input);
@@ -259,7 +259,7 @@ final class SearchTest extends \PHPUnit\Framework\TestCase {
self::assertSame($expectedResult[0], trim($actualSql));
self::assertSame($expectedResult[1], $actualValues);
} finally {
FreshRSS_Context::$user_conf = $previousUserConf;
FreshRSS_Context::setUserConf($previousUserConf);
}
}