PHPStan 2.0 (#269)
* Rename to phpstan.dist.neon * PHPStan 2.0 And update to PHP 8.1+ * Update CI * Minor analyseAndScan
This commit is contained in:
parent
fecfe37e1c
commit
15d66caafb
15 changed files with 326 additions and 316 deletions
|
|
@ -19,6 +19,9 @@ indent_style = tab
|
|||
indent_size = 4
|
||||
indent_style = tab
|
||||
|
||||
[*.neon]
|
||||
indent_style = tab
|
||||
|
||||
[*.xml]
|
||||
indent_style = tab
|
||||
|
||||
|
|
|
|||
7
.github/workflows/tests.yml
vendored
7
.github/workflows/tests.yml
vendored
|
|
@ -10,7 +10,7 @@ jobs:
|
|||
|
||||
tests:
|
||||
# https://github.com/actions/virtual-environments
|
||||
runs-on: ubuntu-22.04
|
||||
runs-on: ubuntu-24.04
|
||||
defaults:
|
||||
run:
|
||||
working-directory: ./Extensions
|
||||
|
|
@ -54,16 +54,13 @@ jobs:
|
|||
- name: PHPStan
|
||||
run: composer run-script phpstan
|
||||
|
||||
- name: PHPStan Next Level
|
||||
run: composer run-script phpstan-next
|
||||
|
||||
# NPM tests
|
||||
|
||||
- name: Uses Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
# https://nodejs.org/en/about/releases/
|
||||
node-version: '18'
|
||||
node-version: '22'
|
||||
cache: 'npm'
|
||||
cache-dependency-path: 'Extensions/package-lock.json'
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@
|
|||
"WebSub"
|
||||
],
|
||||
"require": {
|
||||
"php": ">=7.4",
|
||||
"php": ">=8.1",
|
||||
"ext-ctype": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-dom": "*",
|
||||
|
|
@ -45,28 +45,26 @@
|
|||
"ext-pdo_pgsql": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"php": ">=7.4",
|
||||
"php": ">=8.1",
|
||||
"ext-phar": "*",
|
||||
"ext-tokenizer": "*",
|
||||
"ext-xmlwriter": "*",
|
||||
"phpstan/phpstan": "^1.11",
|
||||
"phpstan/phpstan-strict-rules": "^1.6",
|
||||
"squizlabs/php_codesniffer": "^3.9"
|
||||
"phpstan/phpstan": "^2",
|
||||
"phpstan/phpstan-strict-rules": "^2",
|
||||
"squizlabs/php_codesniffer": "^3"
|
||||
},
|
||||
"scripts": {
|
||||
"php-lint": "find . -type d -name 'vendor' -prune -o -name '*.php' -print0 | xargs -0 -n1 -P4 php -l 1>/dev/null",
|
||||
"phtml-lint": "find . -type d -name 'vendor' -prune -o -name '*.phtml' -print0 | xargs -0 -n1 -P4 php -l 1>/dev/null",
|
||||
"phpcs": "phpcs . -s",
|
||||
"phpcbf": "phpcbf . -p -s",
|
||||
"phpstan": "phpstan analyse --memory-limit 512M .",
|
||||
"phpstan-next": "phpstan analyse --memory-limit 512M -c phpstan-next.neon .",
|
||||
"phpstan-third-party": "phpstan analyse --memory-limit 512M -c phpstan-third-party.neon .",
|
||||
"phpstan": "phpstan analyse .",
|
||||
"phpstan-third-party": "phpstan analyse -c phpstan-third-party.neon .",
|
||||
"test": [
|
||||
"@php-lint",
|
||||
"@phtml-lint",
|
||||
"@phpcs",
|
||||
"@phpstan",
|
||||
"@phpstan-next"
|
||||
"@phpstan"
|
||||
],
|
||||
"fix": [
|
||||
"@phpcbf"
|
||||
|
|
|
|||
51
composer.lock
generated
51
composer.lock
generated
|
|
@ -4,25 +4,25 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "52101009acffc9684a721cc20ec9e731",
|
||||
"content-hash": "02054632764558c26a4fbecc0e408c09",
|
||||
"packages": [],
|
||||
"packages-dev": [
|
||||
{
|
||||
"name": "phpstan/phpstan",
|
||||
"version": "1.11.10",
|
||||
"version": "2.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan.git",
|
||||
"reference": "640410b32995914bde3eed26fa89552f9c2c082f"
|
||||
"reference": "cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/640410b32995914bde3eed26fa89552f9c2c082f",
|
||||
"reference": "640410b32995914bde3eed26fa89552f9c2c082f",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7",
|
||||
"reference": "cd6e973e04b4c2b94c86e8612b5a65f0da0e08e7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2|^8.0"
|
||||
"php": "^7.4|^8.0"
|
||||
},
|
||||
"conflict": {
|
||||
"phpstan/phpstan-shim": "*"
|
||||
|
|
@ -63,32 +63,31 @@
|
|||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2024-08-08T09:02:50+00:00"
|
||||
"time": "2025-01-05T16:43:48+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpstan/phpstan-strict-rules",
|
||||
"version": "1.6.0",
|
||||
"version": "2.0.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpstan/phpstan-strict-rules.git",
|
||||
"reference": "363f921dd8441777d4fc137deb99beb486c77df1"
|
||||
"reference": "ed6fea0ad4ad9c7e25f3ad2e7c4d420cf1e67fe3"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/363f921dd8441777d4fc137deb99beb486c77df1",
|
||||
"reference": "363f921dd8441777d4fc137deb99beb486c77df1",
|
||||
"url": "https://api.github.com/repos/phpstan/phpstan-strict-rules/zipball/ed6fea0ad4ad9c7e25f3ad2e7c4d420cf1e67fe3",
|
||||
"reference": "ed6fea0ad4ad9c7e25f3ad2e7c4d420cf1e67fe3",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^7.2 || ^8.0",
|
||||
"phpstan/phpstan": "^1.11"
|
||||
"php": "^7.4 || ^8.0",
|
||||
"phpstan/phpstan": "^2.0.4"
|
||||
},
|
||||
"require-dev": {
|
||||
"nikic/php-parser": "^4.13.0",
|
||||
"php-parallel-lint/php-parallel-lint": "^1.2",
|
||||
"phpstan/phpstan-deprecation-rules": "^1.1",
|
||||
"phpstan/phpstan-phpunit": "^1.0",
|
||||
"phpunit/phpunit": "^9.5"
|
||||
"phpstan/phpstan-deprecation-rules": "^2.0",
|
||||
"phpstan/phpstan-phpunit": "^2.0",
|
||||
"phpunit/phpunit": "^9.6"
|
||||
},
|
||||
"type": "phpstan-extension",
|
||||
"extra": {
|
||||
|
|
@ -110,22 +109,22 @@
|
|||
"description": "Extra strict and opinionated rules for PHPStan",
|
||||
"support": {
|
||||
"issues": "https://github.com/phpstan/phpstan-strict-rules/issues",
|
||||
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/1.6.0"
|
||||
"source": "https://github.com/phpstan/phpstan-strict-rules/tree/2.0.1"
|
||||
},
|
||||
"time": "2024-04-20T06:37:51+00:00"
|
||||
"time": "2024-12-12T20:21:10+00:00"
|
||||
},
|
||||
{
|
||||
"name": "squizlabs/php_codesniffer",
|
||||
"version": "3.10.2",
|
||||
"version": "3.11.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
|
||||
"reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017"
|
||||
"reference": "1368f4a58c3c52114b86b1abe8f4098869cb0079"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/86e5f5dd9a840c46810ebe5ff1885581c42a3017",
|
||||
"reference": "86e5f5dd9a840c46810ebe5ff1885581c42a3017",
|
||||
"url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/1368f4a58c3c52114b86b1abe8f4098869cb0079",
|
||||
"reference": "1368f4a58c3c52114b86b1abe8f4098869cb0079",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
|
@ -192,7 +191,7 @@
|
|||
"type": "open_collective"
|
||||
}
|
||||
],
|
||||
"time": "2024-07-21T23:26:44+00:00"
|
||||
"time": "2024-12-11T16:04:26+00:00"
|
||||
}
|
||||
],
|
||||
"aliases": [],
|
||||
|
|
@ -201,7 +200,7 @@
|
|||
"prefer-stable": false,
|
||||
"prefer-lowest": false,
|
||||
"platform": {
|
||||
"php": ">=7.4",
|
||||
"php": ">=8.1",
|
||||
"ext-ctype": "*",
|
||||
"ext-curl": "*",
|
||||
"ext-dom": "*",
|
||||
|
|
@ -224,7 +223,7 @@
|
|||
"ext-zlib": "*"
|
||||
},
|
||||
"platform-dev": {
|
||||
"php": ">=7.4",
|
||||
"php": ">=8.1",
|
||||
"ext-phar": "*",
|
||||
"ext-tokenizer": "*",
|
||||
"ext-xmlwriter": "*"
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ try {
|
|||
}
|
||||
|
||||
foreach ($repositories as $repository) {
|
||||
if (null === $url = ($repository['url'] ?? null)) {
|
||||
if (!is_array($repository) || !is_string($url = ($repository['url'] ?? null))) {
|
||||
continue;
|
||||
}
|
||||
if (TYPE_GIT === ($repository['type'] ?? null)) {
|
||||
|
|
@ -54,7 +54,7 @@ foreach ($gitRepositories as $key => $gitRepository) {
|
|||
}
|
||||
$directory = basename(dirname($metadataFile));
|
||||
$metadata['url'] = $gitRepository;
|
||||
$metadata['version'] = strval($metadata['version']);
|
||||
$metadata['version'] = is_scalar($metadata['version'] ?? null) ? strval($metadata['version']) : '';
|
||||
$metadata['method'] = TYPE_GIT;
|
||||
$metadata['directory'] = ($directory === sha1($gitRepository)) ? '.' : $directory;
|
||||
$extensions[] = $metadata;
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
includes:
|
||||
- phpstan.neon
|
||||
|
||||
parameters:
|
||||
level: 9
|
||||
excludePaths:
|
||||
analyse:
|
||||
- xExtension-ImageProxy/configure.phtml
|
||||
- xExtension-ImageProxy/extension.php
|
||||
|
|
@ -1,5 +1,8 @@
|
|||
parameters:
|
||||
level: 0
|
||||
phpVersion:
|
||||
min: 80100 # PHP 8.1
|
||||
max: 80499 # PHP 8.4
|
||||
level: 0 # https://phpstan.org/user-guide/rule-levels
|
||||
fileExtensions:
|
||||
- php
|
||||
- phtml
|
||||
|
|
@ -9,13 +12,13 @@ parameters:
|
|||
excludePaths:
|
||||
analyse:
|
||||
- ../FreshRSS
|
||||
- third-party/*/vendor/*
|
||||
- third-party/*/vendor/*?
|
||||
analyseAndScan:
|
||||
- .git/
|
||||
- node_modules/
|
||||
- symbolic/
|
||||
- third-party/*/tests/*
|
||||
- tmp/
|
||||
- .git/*?
|
||||
- node_modules/*?
|
||||
- symbolic/*?
|
||||
- third-party/*/tests/*?
|
||||
- tmp/*?
|
||||
- vendor/
|
||||
- xExtension-*
|
||||
dynamicConstantNames:
|
||||
|
|
|
|||
43
phpstan.dist.neon
Normal file
43
phpstan.dist.neon
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
parameters:
|
||||
phpVersion:
|
||||
min: 80100 # PHP 8.1
|
||||
max: 80499 # PHP 8.4
|
||||
level: 10 # https://phpstan.org/user-guide/rule-levels
|
||||
fileExtensions:
|
||||
- php
|
||||
- phtml
|
||||
paths:
|
||||
- ../FreshRSS
|
||||
- .
|
||||
excludePaths:
|
||||
analyse:
|
||||
- ../FreshRSS
|
||||
- xExtension-ImageProxy/configure.phtml # TODO pass
|
||||
- xExtension-ImageProxy/extension.php # TODO pass
|
||||
analyseAndScan:
|
||||
- .git/*?
|
||||
- node_modules/*?
|
||||
- symbolic/*?
|
||||
- third-party/*?
|
||||
- tmp/*?
|
||||
- vendor/
|
||||
dynamicConstantNames:
|
||||
- TYPE_GIT
|
||||
checkBenevolentUnionTypes: true
|
||||
checkMissingOverrideMethodAttribute: true
|
||||
checkTooWideReturnTypesInProtectedAndPublicMethods: true
|
||||
reportAnyTypeWideningInVarTag: true
|
||||
treatPhpDocTypesAsCertain: false
|
||||
strictRules:
|
||||
disallowedEmpty: false
|
||||
disallowedLooseComparison: false
|
||||
disallowedShortTernary: false
|
||||
exceptions:
|
||||
check:
|
||||
missingCheckedExceptionInThrows: true
|
||||
tooWideThrowType: true
|
||||
implicitThrows: false
|
||||
checkedExceptionClasses:
|
||||
- 'Minz_Exception'
|
||||
includes:
|
||||
- vendor/phpstan/phpstan-strict-rules/rules.neon
|
||||
48
phpstan.neon
48
phpstan.neon
|
|
@ -1,48 +0,0 @@
|
|||
parameters:
|
||||
# TODO: Increase rule-level https://phpstan.org/user-guide/rule-levels
|
||||
level: 1
|
||||
phpVersion: 80399 # TODO: Remove line when moving composer.json to PHP 8+
|
||||
fileExtensions:
|
||||
- php
|
||||
- phtml
|
||||
paths:
|
||||
- ../FreshRSS
|
||||
- .
|
||||
excludePaths:
|
||||
analyse:
|
||||
- ../FreshRSS
|
||||
- vendor/
|
||||
analyseAndScan:
|
||||
- .git/
|
||||
- node_modules/
|
||||
- symbolic/
|
||||
- third-party/
|
||||
- tmp/
|
||||
dynamicConstantNames:
|
||||
- TYPE_GIT
|
||||
checkMissingOverrideMethodAttribute: true
|
||||
reportMaybesInPropertyPhpDocTypes: false
|
||||
treatPhpDocTypesAsCertain: false
|
||||
strictRules:
|
||||
allRules: false
|
||||
booleansInConditions: true
|
||||
closureUsesThis: true
|
||||
disallowedConstructs: false
|
||||
disallowedLooseComparison: false
|
||||
matchingInheritedMethodNames: true
|
||||
noVariableVariables: true
|
||||
numericOperandsInArithmeticOperators: true
|
||||
overwriteVariablesWithLoop: true
|
||||
requireParentConstructorCall: true
|
||||
strictCalls: true
|
||||
switchConditionsMatchingType: true
|
||||
uselessCast: true
|
||||
exceptions:
|
||||
check:
|
||||
missingCheckedExceptionInThrows: false # TODO pass
|
||||
tooWideThrowType: true
|
||||
implicitThrows: false
|
||||
checkedExceptionClasses:
|
||||
- 'Minz_Exception'
|
||||
includes:
|
||||
- vendor/phpstan/phpstan-strict-rules/rules.neon
|
||||
|
|
@ -3,7 +3,10 @@ declare(strict_types=1);
|
|||
|
||||
final class FreshExtension_quickCollapse_Controller extends Minz_ActionController {
|
||||
|
||||
/** @var QuickCollapse\View */
|
||||
/**
|
||||
* @var QuickCollapse\View
|
||||
* @phpstan-ignore property.phpDocType
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
public function __construct() {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@ declare(strict_types=1);
|
|||
final class FreshExtension_shareByEmail_Controller extends Minz_ActionController {
|
||||
public ?Minz_Extension $extension;
|
||||
|
||||
/** @var ShareByEmail\mailers\View */
|
||||
/**
|
||||
* @var ShareByEmail\mailers\View
|
||||
* @phpstan-ignore property.phpDocType
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
public function __construct() {
|
||||
|
|
@ -17,6 +20,12 @@ final class FreshExtension_shareByEmail_Controller extends Minz_ActionController
|
|||
$this->extension = Minz_ExtensionManager::findExtension('Share By Email');
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws FreshRSS_Context_Exception
|
||||
* @throws Minz_ConfigurationException
|
||||
* @throws Minz_ConfigurationNamespaceException
|
||||
* @throws Minz_PDOConnectionException
|
||||
*/
|
||||
public function shareAction(): void {
|
||||
if (!FreshRSS_Auth::hasAccess()) {
|
||||
Minz_Error::error(403);
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ declare(strict_types=1);
|
|||
|
||||
final class ShareByEmailExtension extends Minz_Extension {
|
||||
|
||||
/**
|
||||
* @throws Minz_ConfigurationException
|
||||
*/
|
||||
#[\Override]
|
||||
public function init(): void {
|
||||
$this->registerTranslates();
|
||||
|
|
|
|||
|
|
@ -6,13 +6,19 @@ namespace ShareByEmail\mailers;
|
|||
|
||||
final class Share extends \Minz_Mailer {
|
||||
|
||||
/** @var View */
|
||||
/**
|
||||
* @var View
|
||||
* @phpstan-ignore property.phpDocType
|
||||
*/
|
||||
protected $view;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct(View::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \FreshRSS_Context_Exception
|
||||
*/
|
||||
public function send_article(string $to, string $subject, string $content): bool {
|
||||
$this->view->_path('share_mailer/article.txt.php');
|
||||
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ final class YouTubeExtension extends Minz_Extension
|
|||
/**
|
||||
* Initializes the extension configuration, if the user context is available.
|
||||
* Do not call that in your extensions init() method, it can't be used there.
|
||||
* @throws FreshRSS_Context_Exception
|
||||
*/
|
||||
public function loadConfigValues(): void
|
||||
{
|
||||
|
|
@ -121,6 +122,7 @@ final class YouTubeExtension extends Minz_Extension
|
|||
|
||||
/**
|
||||
* Inserts the YouTube video iframe into the content of an entry, if the entries link points to a YouTube watch URL.
|
||||
* @throws FreshRSS_Context_Exception
|
||||
*/
|
||||
public function embedYouTubeVideo(FreshRSS_Entry $entry): FreshRSS_Entry
|
||||
{
|
||||
|
|
@ -208,21 +210,21 @@ final class YouTubeExtension extends Minz_Extension
|
|||
|
||||
// We hide the title so it doesn't appear in the final article, which would be redundant with the RSS article title,
|
||||
// but we keep it in the content anyway, so RSS clients can extract it if needed.
|
||||
if ($titles->length > 0) {
|
||||
if ($titles->length > 0 && $titles[0] instanceof DOMNode) {
|
||||
$content .= '<p class="enclosure-title" hidden>' . $titles[0]->nodeValue . '</p>';
|
||||
}
|
||||
|
||||
// We hide the thumbnail so it doesn't appear in the final article, which would be redundant with the YouTube player preview,
|
||||
// but we keep it in the content anyway, so RSS clients can extract it to display a preview where it wants (in article listing,
|
||||
// by example, like with Reeder).
|
||||
if ($thumbnails->length > 0) {
|
||||
if ($thumbnails->length > 0 && $thumbnails[0] instanceof DOMNode) {
|
||||
$content .= '<p hidden><img class="enclosure-thumbnail" src="' . $thumbnails[0]->nodeValue . '" alt=""/></p>';
|
||||
}
|
||||
|
||||
$content .= $iframe;
|
||||
|
||||
if ($descriptions->length > 0) {
|
||||
$content .= '<p class="enclosure-description">' . nl2br(htmlentities($descriptions[0]->nodeValue)) . '</p>';
|
||||
if ($descriptions->length > 0 && $descriptions[0] instanceof DOMNode) {
|
||||
$content .= '<p class="enclosure-description">' . nl2br(htmlentities($descriptions[0]->nodeValue ?? '')) . '</p>';
|
||||
}
|
||||
|
||||
$content .= "</div>\n";
|
||||
|
|
@ -242,6 +244,7 @@ final class YouTubeExtension extends Minz_Extension
|
|||
* This function is called by FreshRSS when the configuration page is loaded, and when configuration is saved.
|
||||
* - We save configuration in case of a post.
|
||||
* - We (re)load configuration in all case, so they are in-sync after a save and before a page load.
|
||||
* @throws FreshRSS_Context_Exception
|
||||
*/
|
||||
#[\Override]
|
||||
public function handleConfigureAction(): void
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue