diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9e0aedb824..955896a797 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -79,4 +79,4 @@ jobs: run: | rm -r public_html # remove once https://github.com/phpstan/phpstan/issues/10321 is fixed mkdir node_modules # remove once https://github.com/phpstan/phpstan/issues/11436 is fixed - vendor/bin/phpstan analyse + vendor/bin/phpstan analyse -v diff --git a/composer.json b/composer.json index 94a70f134a..fdd7dc213a 100644 --- a/composer.json +++ b/composer.json @@ -24,6 +24,7 @@ "phpstan/extension-installer": "^1.1", "phpstan/phpstan": "^1.2", "phpstan/phpstan-deprecation-rules": "^1.2", + "phpstan/phpstan-strict-rules": "^1.3", "phpunit/phpunit": "^9.6.20 || ^10.0 || ^11.0", "roundcube/acl": "*", "roundcube/additional_message_headers": "*", diff --git a/phpstan.neon.dist b/phpstan.neon.dist index fee816962a..0e6ee8f236 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -11,6 +11,26 @@ parameters: - vendor ignoreErrors: + # relax strict rules + - '~^Only booleans are allowed in .+, .+ given( on the (left|right) side)?\.~' + - '~^Variable (static )?(property access|method call) on .+\.~' + - '~^Variable variables are not allowed.~' + - '~^Variable .* might not be defined\.~' + - '~Call to function array_filter\(\) requires parameter #2 to be passed to avoid loose comparison semantics.~' + # TODO + - '~^Dynamic call to static method .+\.~' # TODO in https://github.com/roundcube/roundcubemail/pull/9314 + - '~^Construct empty\(\) is not allowed\. Use more strict comparison\.~' + - '~^Loose comparison via "[=!]=" is not allowed\.~' + - '~^Casting to .+ something that''s already .+\.~' + - '~^Short ternary operator is not allowed\. Use null coalesce operator if applicable or consider using long ternary\.~' + - '~^Call to function (array_search|in_array)\(\) requires parameter #3 to be set\.~' + - '~^Call to function base64_decode\(\) requires parameter #2 to be (set|true).~' + + - + message: '~^Parameter #1 \$browser \(Roundcube\\Tests\\Browser\\Browser\) of method Roundcube\\Tests\\Browser\\Components\\\w+::assert\(\) should be contravariant with parameter \$browser \(Laravel\\Dusk\\Browser\) of method Laravel\\Dusk\\Component::assert\(\)$~' + count: 7 + path: tests/Browser/Components/*.php + # https://github.com/php/pecl-authentication-krb5 - path: 'program/lib/Roundcube/rcube_imap_generic.php' diff --git a/plugins/managesieve/managesieve.php b/plugins/managesieve/managesieve.php index 1e160b60f8..910e285cb6 100644 --- a/plugins/managesieve/managesieve.php +++ b/plugins/managesieve/managesieve.php @@ -60,8 +60,8 @@ public function init() $this->register_action('plugin.managesieve-save', [$this, 'managesieve_save']); $this->register_action('plugin.managesieve-saveraw', [$this, 'managesieve_saveraw']); - $task = $this->rc->task ?? null; - $action = $this->rc->action ?? null; + $task = $this->rc->task ?? null; // @phpstan-ignore-line + $action = $this->rc->action ?? null; // @phpstan-ignore-line if ($task == 'settings') { $this->add_hook('settings_actions', [$this, 'settings_actions']); diff --git a/program/actions/contacts/delete.php b/program/actions/contacts/delete.php index 3933e17555..5657bfad82 100644 --- a/program/actions/contacts/delete.php +++ b/program/actions/contacts/delete.php @@ -41,6 +41,7 @@ public function run($args = []) foreach ($cids as $source => $cid) { $CONTACTS = self::contact_source($source); + // @phpstan-ignore-next-line if ($CONTACTS->readonly && empty($CONTACTS->deletable)) { // more sources? do nothing, probably we have search results from // more than one source, some of these sources can be readonly diff --git a/program/actions/contacts/move.php b/program/actions/contacts/move.php index 0649d94b40..399520456c 100644 --- a/program/actions/contacts/move.php +++ b/program/actions/contacts/move.php @@ -63,6 +63,7 @@ public function run($args = []) break; } + // @phpstan-ignore-next-line if (!$CONTACTS || !$CONTACTS->ready || ($CONTACTS->readonly && empty($CONTACTS->deletable))) { continue; } diff --git a/program/actions/contacts/save.php b/program/actions/contacts/save.php index cf4bd23778..0cf5100e1a 100644 --- a/program/actions/contacts/save.php +++ b/program/actions/contacts/save.php @@ -245,6 +245,7 @@ public static function process_input() foreach ($subtypes as $i => $subtype) { $suffix = $subtype ? ":{$subtype}" : ''; + // @phpstan-ignore-next-line if (!empty($values[$i])) { $record[$col . $suffix][] = $values[$i]; } diff --git a/program/actions/mail/compose.php b/program/actions/mail/compose.php index 900fc8161d..9961d895cd 100644 --- a/program/actions/mail/compose.php +++ b/program/actions/mail/compose.php @@ -1639,7 +1639,7 @@ public static function save_attachment($message, $pid, $compose_id, $params = [] $filename = !empty($params['filename']) ? $params['filename'] : self::attachment_name($part); } elseif ($message instanceof rcube_message) { // the whole message requested - $size = $message->size ?? null; + $size = $message->size ?? null; // @phpstan-ignore-line $mimetype = 'message/rfc822'; $filename = !empty($params['filename']) ? $params['filename'] : 'message_rfc822.eml'; } elseif (is_string($message)) { diff --git a/program/include/rcmail.php b/program/include/rcmail.php index 53884058cc..dbaafa7c22 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -56,7 +56,7 @@ class rcmail extends rcube public $oauth; /** @var rcmail_output_cli|rcmail_output_html|rcmail_output_json|null Output handler */ - public $output; + public $output; // @phpstan-ignore-line private $address_books = []; private $action_args = []; diff --git a/program/include/rcmail_sendmail.php b/program/include/rcmail_sendmail.php index aa0f0f8653..bdd522e920 100644 --- a/program/include/rcmail_sendmail.php +++ b/program/include/rcmail_sendmail.php @@ -457,6 +457,7 @@ public function deliver_message($message, $disconnect = true) return false; } + // @phpstan-ignore-next-line if ($mailbody_file) { $this->temp_files[$message->headers()['Message-ID']] = $mailbody_file; } diff --git a/program/lib/Roundcube/rcube.php b/program/lib/Roundcube/rcube.php index c0b409a136..ebcbeef755 100644 --- a/program/lib/Roundcube/rcube.php +++ b/program/lib/Roundcube/rcube.php @@ -659,9 +659,9 @@ public function text_exists($name, $domain = null, &$ref_domain = null) // any of loaded domains (plugins) if ($domain == '*') { - foreach ($this->plugins->loaded_plugins() as $domain) { - if (isset($this->texts[$domain . '.' . $name])) { - $ref_domain = $domain; + foreach ($this->plugins->loaded_plugins() as $domain2) { + if (isset($this->texts[$domain2 . '.' . $name])) { + $ref_domain = $domain2; return true; } } diff --git a/program/lib/Roundcube/rcube_imap.php b/program/lib/Roundcube/rcube_imap.php index cc41965a39..7d27c3b5c3 100644 --- a/program/lib/Roundcube/rcube_imap.php +++ b/program/lib/Roundcube/rcube_imap.php @@ -4368,7 +4368,6 @@ public function sort_folder_list($a_folders, $skip_special = false) } // Force the type of folder name variable (#1485527) - /** @var array $folders */ $folders = array_map('strval', $folders); $count = count($folders); diff --git a/program/lib/Roundcube/rcube_washtml.php b/program/lib/Roundcube/rcube_washtml.php index 5560e890ef..53362bf116 100644 --- a/program/lib/Roundcube/rcube_washtml.php +++ b/program/lib/Roundcube/rcube_washtml.php @@ -593,7 +593,7 @@ private function dumpHtml($node, $level = 20) } foreach ($ns_nodes as $ns) { - if (isset($ns->nodeName) && isset($ns->nodeValue) + if (isset($ns->nodeName) && isset($ns->nodeValue) // @phpstan-ignore property.notFound && $ns->nodeName != 'xmlns:xml' && preg_match('/^[a-zA-Z:-]+$/', $ns->nodeName) && strpos($ns->nodeValue, '://') diff --git a/tests/Actions/Contacts/QrcodeTest.php b/tests/Actions/Contacts/QrcodeTest.php index 5a52c2a6cb..8e6aefb26b 100644 --- a/tests/Actions/Contacts/QrcodeTest.php +++ b/tests/Actions/Contacts/QrcodeTest.php @@ -25,7 +25,7 @@ public function test_run() $result = $output->getOutput(); - $this->assertCOntains('HTTP/1.0 404 Contact not found', $output->headers); + $this->assertContains('HTTP/1.0 404 Contact not found', $output->headers); $this->assertSame('', $result); $type = $action->check_support(); diff --git a/tests/Framework/MessageTest.php b/tests/Framework/MessageTest.php index 876771b532..0b29a8d023 100644 --- a/tests/Framework/MessageTest.php +++ b/tests/Framework/MessageTest.php @@ -94,7 +94,7 @@ class rcube_message_test extends \rcube_message { private $part_bodies = []; - public function __construct($uid, $folder = null, $is_safe = false) + public function __construct($uid, $folder = null, $is_safe = false) // @phpstan-ignore constructor.missingParentCall { $this->uid = $uid; $this->folder = $folder;