From 9e2720cddc8bf7dab092e3ebc1f0369915760f7a Mon Sep 17 00:00:00 2001 From: Yassine Guedidi Date: Sat, 5 Apr 2025 14:01:48 +0200 Subject: [PATCH] Modernize to PHP 8.1 --- rector.php | 6 +----- src/Command/CleanDuplicatesCommand.php | 4 ++-- src/Command/InstallCommand.php | 2 +- src/Controller/ConfigController.php | 2 +- src/Controller/EntryController.php | 4 ++-- src/Controller/TagController.php | 6 +++--- src/Doctrine/JsonArrayType.php | 2 +- src/Entity/User.php | 2 +- src/Helper/DownloadImages.php | 4 ++-- src/Helper/TagsAssigner.php | 2 +- src/Import/ChromeImport.php | 2 +- src/Import/FirefoxImport.php | 2 +- src/Import/PinboardImport.php | 2 +- src/Operator/PHP/Matches.php | 2 +- src/Operator/PHP/NotMatches.php | 2 +- src/Operator/PHP/PatternMatches.php | 2 +- src/SiteConfig/GrabySiteConfigBuilder.php | 4 ++-- src/SiteConfig/LoginFormAuthenticator.php | 4 ++-- src/Twig/WallabagExtension.php | 16 ++++++++-------- tests/Controller/Api/DeveloperControllerTest.php | 2 +- tests/Controller/ConfigControllerTest.php | 4 ++-- tests/Controller/EntryControllerTest.php | 2 +- tests/Controller/ExportControllerTest.php | 8 ++++---- tests/Controller/FeedControllerTest.php | 2 +- tests/Helper/ContentProxyTest.php | 4 ++-- tests/functions.php | 8 ++++---- 26 files changed, 48 insertions(+), 52 deletions(-) diff --git a/rector.php b/rector.php index 0b8e5af6e..1500a8cf6 100644 --- a/rector.php +++ b/rector.php @@ -4,7 +4,6 @@ declare(strict_types=1); use Rector\Config\RectorConfig; use Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector; -use Rector\Php81\Rector\Property\ReadOnlyPropertyRector; return RectorConfig::configure() ->withPaths([ @@ -19,13 +18,10 @@ return RectorConfig::configure() ->withConfiguredRule(ClassPropertyAssignToConstructorPromotionRector::class, [ 'inline_public' => true, ]) - ->withRules([ - ReadOnlyPropertyRector::class, - ]) ->withSkip([ ClassPropertyAssignToConstructorPromotionRector::class => [ __DIR__ . '/src/Entity/*', ], ]) - ->withPhpSets(php80: true) + ->withPhpSets(php81: true) ->withTypeCoverageLevel(0); diff --git a/src/Command/CleanDuplicatesCommand.php b/src/Command/CleanDuplicatesCommand.php index 73e272961..6d68f00de 100644 --- a/src/Command/CleanDuplicatesCommand.php +++ b/src/Command/CleanDuplicatesCommand.php @@ -100,8 +100,8 @@ class CleanDuplicatesCommand extends Command private function similarUrl($url) { - if (\in_array(substr($url, -1), ['/', '#'], true)) { // get rid of "/" and "#" and the end of urls - return substr($url, 0, \strlen($url)); + if (\in_array(substr((string) $url, -1), ['/', '#'], true)) { // get rid of "/" and "#" and the end of urls + return substr((string) $url, 0, \strlen((string) $url)); } return $url; diff --git a/src/Command/InstallCommand.php b/src/Command/InstallCommand.php index fd6802b0c..026bb4e8e 100644 --- a/src/Command/InstallCommand.php +++ b/src/Command/InstallCommand.php @@ -144,7 +144,7 @@ class InstallCommand extends Command // return version should be like "PostgreSQL 9.5.4 on x86_64-apple-darwin15.6.0, compiled by Apple LLVM version 8.0.0 (clang-800.0.38), 64-bit" $version = $conn->executeQuery('SELECT version();')->fetchOne(); - preg_match('/PostgreSQL ([0-9\.]+)/i', $version, $matches); + preg_match('/PostgreSQL ([0-9\.]+)/i', (string) $version, $matches); if (isset($matches[1]) & version_compare($matches[1], '9.2.0', '<')) { $fulfilled = false; diff --git a/src/Controller/ConfigController.php b/src/Controller/ConfigController.php index 0d3e344d4..00bb6ea35 100644 --- a/src/Controller/ConfigController.php +++ b/src/Controller/ConfigController.php @@ -350,7 +350,7 @@ class ConfigController extends AbstractController $backupCodes = (new BackupCodes())->toArray(); $backupCodesHashed = array_map( - fn ($backupCode) => password_hash($backupCode, \PASSWORD_DEFAULT), + fn ($backupCode) => password_hash((string) $backupCode, \PASSWORD_DEFAULT), $backupCodes ); diff --git a/src/Controller/EntryController.php b/src/Controller/EntryController.php index c5c25289b..40bbd2c7d 100644 --- a/src/Controller/EntryController.php +++ b/src/Controller/EntryController.php @@ -67,7 +67,7 @@ class EntryController extends AbstractController $action = 'tag'; if (isset($values['tags'])) { - $labels = array_filter(explode(',', $values['tags']), + $labels = array_filter(explode(',', (string) $values['tags']), function ($v) { $v = trim($v); @@ -616,7 +616,7 @@ class EntryController extends AbstractController */ private function showEntries($type, Request $request, $page) { - $searchTerm = (isset($request->query->all('search_entry')['term']) ? trim($request->query->all('search_entry')['term']) : ''); + $searchTerm = (isset($request->query->all('search_entry')['term']) ? trim((string) $request->query->all('search_entry')['term']) : ''); $currentRoute = $request->query->get('currentRoute') ?? ''; $currentEntryId = $request->attributes->getInt('id'); diff --git a/src/Controller/TagController.php b/src/Controller/TagController.php index 9a3db5360..97854edbf 100644 --- a/src/Controller/TagController.php +++ b/src/Controller/TagController.php @@ -45,10 +45,10 @@ class TagController extends AbstractController $form->handleRequest($request); $tags = $form->get('label')->getData() ?? ''; - $tagsExploded = explode(',', $tags); + $tagsExploded = explode(',', (string) $tags); // avoid too much tag to be added - if (\count($tagsExploded) >= NewTagType::MAX_TAGS || \strlen($tags) >= NewTagType::MAX_LENGTH) { + if (\count($tagsExploded) >= NewTagType::MAX_TAGS || \strlen((string) $tags) >= NewTagType::MAX_LENGTH) { $message = $translator->trans('flashes.tag.notice.too_much_tags', [ '%tags%' => NewTagType::MAX_TAGS, '%characters%' => NewTagType::MAX_LENGTH, @@ -250,7 +250,7 @@ class TagController extends AbstractController // check to avoid duplicate tags creation foreach ($this->entityManager->getUnitOfWork()->getScheduledEntityInsertions() as $entity) { - if ($entity instanceof Tag && strtolower($entity->getLabel()) === strtolower($filter)) { + if ($entity instanceof Tag && strtolower($entity->getLabel()) === strtolower((string) $filter)) { continue 2; } $this->entityManager->persist($entry); diff --git a/src/Doctrine/JsonArrayType.php b/src/Doctrine/JsonArrayType.php index 8925c1201..0f2a80e58 100644 --- a/src/Doctrine/JsonArrayType.php +++ b/src/Doctrine/JsonArrayType.php @@ -22,7 +22,7 @@ class JsonArrayType extends JsonType $value = \is_resource($value) ? stream_get_contents($value) : $value; - return json_decode($value, true); + return json_decode((string) $value, true); } public function getName(): string diff --git a/src/Entity/User.php b/src/Entity/User.php index 5146b47dc..752f02da6 100644 --- a/src/Entity/User.php +++ b/src/Entity/User.php @@ -383,7 +383,7 @@ class User extends BaseUser implements EmailTwoFactorInterface, GoogleTwoFactorI foreach ($this->backupCodes as $key => $backupCode) { // backup code are hashed using `password_hash` // see ConfigController->otpAppAction - if (password_verify($code, $backupCode)) { + if (password_verify($code, (string) $backupCode)) { return $key; } } diff --git a/src/Helper/DownloadImages.php b/src/Helper/DownloadImages.php index afce04c90..156100dc4 100644 --- a/src/Helper/DownloadImages.php +++ b/src/Helper/DownloadImages.php @@ -25,7 +25,7 @@ class DownloadImages $wallabagUrl, private readonly LoggerInterface $logger, ) { - $this->wallabagUrl = rtrim($wallabagUrl, '/'); + $this->wallabagUrl = rtrim((string) $wallabagUrl, '/'); $this->mimeTypes = new MimeTypes(); $this->setFolder(); @@ -291,7 +291,7 @@ class DownloadImages preg_match_all($pattern, $srcsetAttribute, $matches); $srcset = \call_user_func_array('array_merge', $matches); - $srcsetUrls = array_map(fn ($src) => trim(explode(' ', $src, 2)[0]), $srcset); + $srcsetUrls = array_map(fn ($src) => trim(explode(' ', (string) $src, 2)[0]), $srcset); $urls = array_merge($srcsetUrls, $urls); } diff --git a/src/Helper/TagsAssigner.php b/src/Helper/TagsAssigner.php index 20c787a37..470c53b86 100644 --- a/src/Helper/TagsAssigner.php +++ b/src/Helper/TagsAssigner.php @@ -39,7 +39,7 @@ class TagsAssigner } foreach ($tags as $label) { - $label = trim(mb_convert_case($label, \MB_CASE_LOWER)); + $label = trim(mb_convert_case((string) $label, \MB_CASE_LOWER)); // avoid empty tag if ('' === $label) { diff --git a/src/Import/ChromeImport.php b/src/Import/ChromeImport.php index 27ae96221..20333c269 100644 --- a/src/Import/ChromeImport.php +++ b/src/Import/ChromeImport.php @@ -39,7 +39,7 @@ class ChromeImport extends BrowserImport 'is_archived' => (int) $this->markAsRead, 'is_starred' => false, 'tags' => '', - 'created_at' => substr($entry['date_added'], 0, 10), + 'created_at' => substr((string) $entry['date_added'], 0, 10), ]; if (\array_key_exists('tags', $entry) && '' !== $entry['tags']) { diff --git a/src/Import/FirefoxImport.php b/src/Import/FirefoxImport.php index 2dba50d6a..efd9d2052 100644 --- a/src/Import/FirefoxImport.php +++ b/src/Import/FirefoxImport.php @@ -39,7 +39,7 @@ class FirefoxImport extends BrowserImport 'is_archived' => (int) $this->markAsRead, 'is_starred' => false, 'tags' => '', - 'created_at' => substr($entry['dateAdded'], 0, 10), + 'created_at' => substr((string) $entry['dateAdded'], 0, 10), ]; if (\array_key_exists('tags', $entry) && '' !== $entry['tags']) { diff --git a/src/Import/PinboardImport.php b/src/Import/PinboardImport.php index f5da3f768..fa0bcfe3d 100644 --- a/src/Import/PinboardImport.php +++ b/src/Import/PinboardImport.php @@ -95,7 +95,7 @@ class PinboardImport extends AbstractImport 'is_archived' => ('no' === $importedEntry['toread']) || $this->markAsRead, 'is_starred' => false, 'created_at' => $importedEntry['time'], - 'tags' => explode(' ', $importedEntry['tags']), + 'tags' => explode(' ', (string) $importedEntry['tags']), ]; $entry = new Entry($this->user); diff --git a/src/Operator/PHP/Matches.php b/src/Operator/PHP/Matches.php index 0d3f2bfab..c1c57b95f 100644 --- a/src/Operator/PHP/Matches.php +++ b/src/Operator/PHP/Matches.php @@ -20,6 +20,6 @@ class Matches return false; } - return false !== stripos($subject, (string) $pattern); + return false !== stripos((string) $subject, (string) $pattern); } } diff --git a/src/Operator/PHP/NotMatches.php b/src/Operator/PHP/NotMatches.php index 49556815c..ba36247f8 100644 --- a/src/Operator/PHP/NotMatches.php +++ b/src/Operator/PHP/NotMatches.php @@ -20,6 +20,6 @@ class NotMatches return true; } - return false === stripos($subject, (string) $pattern); + return false === stripos((string) $subject, (string) $pattern); } } diff --git a/src/Operator/PHP/PatternMatches.php b/src/Operator/PHP/PatternMatches.php index 9c2aede3a..9321286e5 100644 --- a/src/Operator/PHP/PatternMatches.php +++ b/src/Operator/PHP/PatternMatches.php @@ -16,7 +16,7 @@ class PatternMatches { public function __invoke($subject, $pattern) { - $count = preg_match("`$pattern`i", $subject); + $count = preg_match("`$pattern`i", (string) $subject); return \is_int($count) && $count > 0; } diff --git a/src/SiteConfig/GrabySiteConfigBuilder.php b/src/SiteConfig/GrabySiteConfigBuilder.php index 422e54fa0..91b143402 100644 --- a/src/SiteConfig/GrabySiteConfigBuilder.php +++ b/src/SiteConfig/GrabySiteConfigBuilder.php @@ -95,11 +95,11 @@ class GrabySiteConfigBuilder implements SiteConfigBuilder $extraFields = []; foreach ($extraFieldsStrings as $extraField) { - if (!str_contains($extraField, '=')) { + if (!str_contains((string) $extraField, '=')) { continue; } - [$fieldName, $fieldValue] = explode('=', $extraField, 2); + [$fieldName, $fieldValue] = explode('=', (string) $extraField, 2); $extraFields[$fieldName] = $fieldValue; } diff --git a/src/SiteConfig/LoginFormAuthenticator.php b/src/SiteConfig/LoginFormAuthenticator.php index f50ea3a1c..5afd89648 100644 --- a/src/SiteConfig/LoginFormAuthenticator.php +++ b/src/SiteConfig/LoginFormAuthenticator.php @@ -98,9 +98,9 @@ class LoginFormAuthenticator $extraFields = []; foreach ($siteConfig->getExtraFields() as $fieldName => $fieldValue) { - if (str_starts_with($fieldValue, '@=')) { + if (str_starts_with((string) $fieldValue, '@=')) { $fieldValue = $this->expressionLanguage->evaluate( - substr($fieldValue, 2), + substr((string) $fieldValue, 2), [ 'config' => $siteConfig, ] diff --git a/src/Twig/WallabagExtension.php b/src/Twig/WallabagExtension.php index 81cbffbc5..604b5c526 100644 --- a/src/Twig/WallabagExtension.php +++ b/src/Twig/WallabagExtension.php @@ -34,20 +34,20 @@ class WallabagExtension extends AbstractExtension implements GlobalsInterface public function getFilters(): array { return [ - new TwigFilter('removeWww', [$this, 'removeWww']), - new TwigFilter('removeScheme', [$this, 'removeScheme']), - new TwigFilter('removeSchemeAndWww', [$this, 'removeSchemeAndWww']), + new TwigFilter('removeWww', $this->removeWww(...)), + new TwigFilter('removeScheme', $this->removeScheme(...)), + new TwigFilter('removeSchemeAndWww', $this->removeSchemeAndWww(...)), ]; } public function getFunctions(): array { return [ - new TwigFunction('count_entries', [$this, 'countEntries']), - new TwigFunction('count_tags', [$this, 'countTags']), - new TwigFunction('display_stats', [$this, 'displayStats']), - new TwigFunction('asset_file_exists', [$this, 'assetFileExists']), - new TwigFunction('theme_class', [$this, 'themeClass']), + new TwigFunction('count_entries', $this->countEntries(...)), + new TwigFunction('count_tags', $this->countTags(...)), + new TwigFunction('display_stats', $this->displayStats(...)), + new TwigFunction('asset_file_exists', $this->assetFileExists(...)), + new TwigFunction('theme_class', $this->themeClass(...)), ]; } diff --git a/tests/Controller/Api/DeveloperControllerTest.php b/tests/Controller/Api/DeveloperControllerTest.php index f37923121..ab0b62d7d 100644 --- a/tests/Controller/Api/DeveloperControllerTest.php +++ b/tests/Controller/Api/DeveloperControllerTest.php @@ -50,7 +50,7 @@ class DeveloperControllerTest extends WallabagTestCase $this->assertSame(200, $client->getResponse()->getStatusCode()); - $data = json_decode($client->getResponse()->getContent(), true); + $data = json_decode((string) $client->getResponse()->getContent(), true); $this->assertArrayHasKey('access_token', $data); $this->assertArrayHasKey('expires_in', $data); $this->assertArrayHasKey('token_type', $data); diff --git a/tests/Controller/ConfigControllerTest.php b/tests/Controller/ConfigControllerTest.php index 3e097994c..301ece136 100644 --- a/tests/Controller/ConfigControllerTest.php +++ b/tests/Controller/ConfigControllerTest.php @@ -351,7 +351,7 @@ class ConfigControllerTest extends WallabagTestCase ); $this->assertSame(200, $client->getResponse()->getStatusCode()); - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode((string) $client->getResponse()->getContent(), true); $this->assertArrayHasKey('token', $content); } @@ -1296,7 +1296,7 @@ class ConfigControllerTest extends WallabagTestCase $this->assertSame('attachment; filename="tagging_rules_admin.json"', $headers->get('content-disposition')); $this->assertSame('UTF-8', $headers->get('content-transfer-encoding')); - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode((string) $client->getResponse()->getContent(), true); $this->assertCount(4, $content); $this->assertSame('content matches "spurs"', $content[0]['rule']); diff --git a/tests/Controller/EntryControllerTest.php b/tests/Controller/EntryControllerTest.php index dd1a33c3f..b7d020a80 100644 --- a/tests/Controller/EntryControllerTest.php +++ b/tests/Controller/EntryControllerTest.php @@ -1283,7 +1283,7 @@ class EntryControllerTest extends WallabagTestCase $this->assertSame($url, $entry->getUrl()); $this->assertStringContainsString('Comment Hidalgo', $entry->getTitle()); // instead of checking for the filename (which might change) check that the image is now local - $this->assertStringContainsString(rtrim($client->getContainer()->getParameter('domain_name'), '/') . '/assets/images/', $entry->getContent()); + $this->assertStringContainsString(rtrim((string) $client->getContainer()->getParameter('domain_name'), '/') . '/assets/images/', $entry->getContent()); $client->getContainer()->get(Config::class)->set('download_images_enabled', 0); } diff --git a/tests/Controller/ExportControllerTest.php b/tests/Controller/ExportControllerTest.php index bb8e6995f..0a5c56c2e 100644 --- a/tests/Controller/ExportControllerTest.php +++ b/tests/Controller/ExportControllerTest.php @@ -177,7 +177,7 @@ class ExportControllerTest extends WallabagTestCase $this->assertSame('attachment; filename="Archive articles.csv"', $headers->get('content-disposition')); $this->assertSame('UTF-8', $headers->get('content-transfer-encoding')); - $csv = str_getcsv($client->getResponse()->getContent(), "\n"); + $csv = str_getcsv((string) $client->getResponse()->getContent(), "\n"); $this->assertGreaterThan(1, $csv); // +1 for title line @@ -216,7 +216,7 @@ class ExportControllerTest extends WallabagTestCase $this->assertSame('attachment; filename="' . $this->getSanitizedFilename($contentInDB->getTitle()) . '.json"', $headers->get('content-disposition')); $this->assertSame('UTF-8', $headers->get('content-transfer-encoding')); - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode((string) $client->getResponse()->getContent(), true); $this->assertArrayHasKey('id', $content[0]); $this->assertArrayHasKey('title', $content[0]); $this->assertArrayHasKey('url', $content[0]); @@ -262,7 +262,7 @@ class ExportControllerTest extends WallabagTestCase $this->assertSame('attachment; filename="Search entry search articles.json"', $headers->get('content-disposition')); $this->assertSame('UTF-8', $headers->get('content-transfer-encoding')); - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode((string) $client->getResponse()->getContent(), true); $this->assertCount(1, $content); $this->tearDownForJsonExportFromSearch(); @@ -339,7 +339,7 @@ class ExportControllerTest extends WallabagTestCase $this->assertSame('attachment; filename="Same domain articles.json"', $headers->get('content-disposition')); $this->assertSame('UTF-8', $headers->get('content-transfer-encoding')); - $content = json_decode($client->getResponse()->getContent(), true); + $content = json_decode((string) $client->getResponse()->getContent(), true); $this->assertCount(4, $content); } diff --git a/tests/Controller/FeedControllerTest.php b/tests/Controller/FeedControllerTest.php index 80cdeabb4..0359e8888 100644 --- a/tests/Controller/FeedControllerTest.php +++ b/tests/Controller/FeedControllerTest.php @@ -36,7 +36,7 @@ class FeedControllerTest extends WallabagTestCase $this->assertSame('admin', $xpath->query('/a:feed/a:author/a:name')->item(0)->nodeValue); $this->assertSame(1, $xpath->query('/a:feed/a:subtitle')->length); - if (null !== $tagValue && str_starts_with($type, 'tag')) { + if (null !== $tagValue && str_starts_with((string) $type, 'tag')) { $this->assertSame('wallabag — ' . $type . ' ' . $tagValue . ' feed', $xpath->query('/a:feed/a:title')->item(0)->nodeValue); $this->assertSame('Atom feed for entries tagged with ' . $tagValue, $xpath->query('/a:feed/a:subtitle')->item(0)->nodeValue); } else { diff --git a/tests/Helper/ContentProxyTest.php b/tests/Helper/ContentProxyTest.php index 18e349135..075c66cf7 100644 --- a/tests/Helper/ContentProxyTest.php +++ b/tests/Helper/ContentProxyTest.php @@ -1074,7 +1074,7 @@ class ContentProxyTest extends TestCase private function strToHex($string) { $hex = ''; - for ($i = 0; $i < \strlen($string); ++$i) { + for ($i = 0; $i < \strlen((string) $string); ++$i) { $ord = \ord($string[$i]); $hexCode = dechex($ord); $hex .= substr('0' . $hexCode, -2); @@ -1093,7 +1093,7 @@ class ContentProxyTest extends TestCase private function hexToStr($hex) { $string = ''; - for ($i = 0; $i < \strlen($hex) - 1; $i += 2) { + for ($i = 0; $i < \strlen((string) $hex) - 1; $i += 2) { $string .= \chr(hexdec($hex[$i] . $hex[$i + 1])); } diff --git a/tests/functions.php b/tests/functions.php index a9b8881a7..02ab70fe7 100644 --- a/tests/functions.php +++ b/tests/functions.php @@ -11,19 +11,19 @@ function isPartialRun(): bool { foreach ($_SERVER['argv'] as $arg) { - if (str_starts_with($arg, '--filter')) { + if (str_starts_with((string) $arg, '--filter')) { return true; } - if (str_starts_with($arg, '--testsuite')) { + if (str_starts_with((string) $arg, '--testsuite')) { return true; } - if (str_starts_with($arg, '--group')) { + if (str_starts_with((string) $arg, '--group')) { return true; } - if (str_starts_with($arg, '--exclude-group')) { + if (str_starts_with((string) $arg, '--exclude-group')) { return true; } }