diff --git a/composer.json b/composer.json
index 69f0afc09..8218e1abc 100644
--- a/composer.json
+++ b/composer.json
@@ -37,7 +37,7 @@
"psalm:dev": "@psalm",
"psalm:update-baseline": "psalm --threads=1 --update-baseline",
"rector:check": "rector --dry-run --clear-cache",
- "rector:fix": "rector",
+ "rector:fix": "rector && php-cs-fixer fix",
"test:unit": "phpunit -c tests/Unit/phpunit.xml --colors=always --fail-on-warning --fail-on-risky --display-deprecations --display-phpunit-deprecations",
"test:integration": "cd tests/Integration && ./run.sh"
},
diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php
index 1186c17a9..a88308dd4 100644
--- a/lib/AppInfo/Application.php
+++ b/lib/AppInfo/Application.php
@@ -52,7 +52,7 @@ public function register(IRegistrationContext $context): void {
#[\Override]
public function boot(IBootContext $context): void {
- $context->injectFn(\Closure::fromCallable([$this, 'registerApp']));
+ $context->injectFn($this->registerApp(...));
}
public function registerApp(IManager $notificationManager): void {
diff --git a/lib/BackgroundJob/GenerateUserSettings.php b/lib/BackgroundJob/GenerateUserSettings.php
index 1d4ac3096..3e5b859a2 100644
--- a/lib/BackgroundJob/GenerateUserSettings.php
+++ b/lib/BackgroundJob/GenerateUserSettings.php
@@ -19,9 +19,9 @@
class GenerateUserSettings extends TimedJob {
public function __construct(
ITimeFactory $time,
- private IDBConnection $connection,
- private IUserManager $userManager,
- private SettingsMapper $settingsMapper,
+ private readonly IDBConnection $connection,
+ private readonly IUserManager $userManager,
+ private readonly SettingsMapper $settingsMapper,
) {
parent::__construct($time);
diff --git a/lib/BackgroundJob/SendNotificationMails.php b/lib/BackgroundJob/SendNotificationMails.php
index f05e2dc8d..b476644eb 100644
--- a/lib/BackgroundJob/SendNotificationMails.php
+++ b/lib/BackgroundJob/SendNotificationMails.php
@@ -15,8 +15,8 @@
class SendNotificationMails extends TimedJob {
public function __construct(
ITimeFactory $timeFactory,
- private MailNotifications $mailNotifications,
- private bool $isCLI,
+ private readonly MailNotifications $mailNotifications,
+ private readonly bool $isCLI,
) {
parent::__construct($timeFactory);
}
diff --git a/lib/Controller/PushController.php b/lib/Controller/PushController.php
index 9595e5295..3fd9d829a 100644
--- a/lib/Controller/PushController.php
+++ b/lib/Controller/PushController.php
@@ -140,7 +140,7 @@ public function registerDevice(string $pushTokenHash, string $devicePublicKey, s
return new DataResponse([
'publicKey' => $key->getPublic(),
'deviceIdentifier' => $deviceIdentifier,
- 'signature' => base64_encode($signature),
+ 'signature' => base64_encode((string)$signature),
], $created ? Http::STATUS_CREATED : Http::STATUS_OK);
}
diff --git a/lib/Handler.php b/lib/Handler.php
index b69246d76..282122d23 100644
--- a/lib/Handler.php
+++ b/lib/Handler.php
@@ -335,10 +335,10 @@ protected function notificationFromRow(array $row): INotification {
->setUser($row['user'])
->setDateTime($dateTime)
->setObject($row['object_type'], $row['object_id'])
- ->setSubject($row['subject'], (array)json_decode($row['subject_parameters'], true));
+ ->setSubject($row['subject'], (array)json_decode((string)$row['subject_parameters'], true));
if ($row['message'] !== '' && $row['message'] !== null) {
- $notification->setMessage($row['message'], (array)json_decode($row['message_parameters'], true));
+ $notification->setMessage($row['message'], (array)json_decode((string)$row['message_parameters'], true));
}
if ($row['link'] !== '' && $row['link'] !== null) {
$notification->setLink($row['link']);
@@ -347,7 +347,7 @@ protected function notificationFromRow(array $row): INotification {
$notification->setIcon($row['icon']);
}
- $actions = (array)json_decode($row['actions'], true);
+ $actions = (array)json_decode((string)$row['actions'], true);
foreach ($actions as $actionData) {
$action = $notification->createAction();
$action->setLabel($actionData['label'])
diff --git a/lib/Listener/UserCreatedListener.php b/lib/Listener/UserCreatedListener.php
index 9adcaced1..46d261156 100644
--- a/lib/Listener/UserCreatedListener.php
+++ b/lib/Listener/UserCreatedListener.php
@@ -19,7 +19,7 @@
*/
class UserCreatedListener implements IEventListener {
public function __construct(
- private SettingsMapper $settingsMapper,
+ private readonly SettingsMapper $settingsMapper,
) {
}
diff --git a/lib/Listener/UserDeletedListener.php b/lib/Listener/UserDeletedListener.php
index 4558a028a..fac34c013 100644
--- a/lib/Listener/UserDeletedListener.php
+++ b/lib/Listener/UserDeletedListener.php
@@ -20,8 +20,8 @@
*/
class UserDeletedListener implements IEventListener {
public function __construct(
- private Handler $handler,
- private SettingsMapper $settingsMapper,
+ private readonly Handler $handler,
+ private readonly SettingsMapper $settingsMapper,
) {
}
diff --git a/lib/Notifier/AdminNotifications.php b/lib/Notifier/AdminNotifications.php
index 702845e1f..bee830e96 100644
--- a/lib/Notifier/AdminNotifications.php
+++ b/lib/Notifier/AdminNotifications.php
@@ -77,12 +77,12 @@ public function prepare(INotification $notification, string $languageCode): INot
}
}
- $path1 = rtrim($file1->getPath(), '/');
+ $path1 = rtrim((string)$file1->getPath(), '/');
if (str_starts_with($path1, '/' . $notification->getUser() . '/files/')) {
// Remove /user/files/...
[,,, $path1] = explode('/', $path1, 4);
}
- $path2 = rtrim($file2->getPath(), '/');
+ $path2 = rtrim((string)$file2->getPath(), '/');
if (str_starts_with($path2, '/' . $notification->getUser() . '/files/')) {
// Remove /user/files/...
[,,, $path2] = explode('/', $path2, 4);
diff --git a/lib/Push.php b/lib/Push.php
index 1a2c9163d..c6c3f57ec 100644
--- a/lib/Push.php
+++ b/lib/Push.php
@@ -208,7 +208,7 @@ public function filterWebPushDeviceList(array $devices, string $app): array {
}
$devices = array_values(array_filter($devices, function ($device) use ($app) {
- $appTypes = explode(',', $device['app_types']);
+ $appTypes = explode(',', (string)$device['app_types']);
return $device['activated'] && (\in_array($app, $appTypes)
|| (\in_array('all', $appTypes) && !\in_array('-' . $app, $appTypes)));
}));
@@ -364,7 +364,7 @@ public function pushToDevice(int $id, INotification $notification): void {
$notification = $this->notificationManager->prepare($notification, $language);
} catch (AlreadyProcessedException|IncompleteParsedNotificationException|\InvalidArgumentException $e) {
// FIXME remove \InvalidArgumentException in Nextcloud 39
- $this->printInfo('Error when preparing notification for push: ' . get_class($e));
+ $this->printInfo('Error when preparing notification for push: ' . $e::class);
return;
} finally {
$this->notificationManager->setPreparingPushNotification(false);
@@ -442,8 +442,8 @@ public function proxyPushToDevice(int $id, IUser $user, array $devices, INotific
$userKey = $this->keyManager->getKey($user);
- $this->printInfo('Private user key size: ' . strlen($userKey->getPrivate()));
- $this->printInfo('Public user key size: ' . strlen($userKey->getPublic()));
+ $this->printInfo('Private user key size: ' . strlen((string)$userKey->getPrivate()));
+ $this->printInfo('Public user key size: ' . strlen((string)$userKey->getPublic()));
$this->printInfo('');
$this->printInfo('Found ' . count($devices) . ' devices registered for push notifications');
@@ -623,7 +623,7 @@ public function proxyPushDeleteToDevice(string $userId, IUser $user, array $devi
foreach ($devices as $device) {
$device['token'] = (int)$device['token'];
try {
- $proxyServer = rtrim($device['proxyserver'], '/');
+ $proxyServer = rtrim((string)$device['proxyserver'], '/');
if (!isset($this->payloadsToSend[$proxyServer])) {
$this->payloadsToSend[$proxyServer] = [];
}
@@ -964,7 +964,7 @@ protected function encryptAndSign(Key $userKey, array $device, int $id, INotific
$priority = $ret['urgency'];
$type = $ret['type'];
- $this->printInfo('Device public key size: ' . strlen($device['devicepublickey']));
+ $this->printInfo('Device public key size: ' . strlen((string)$device['devicepublickey']));
$this->printInfo('Data to encrypt is: ' . json_encode($data));
$padding = $this->appConfig->getAppValueString('push_encryption_padding', 'PKCS1') === 'OAEP' ? OPENSSL_PKCS1_OAEP_PADDING : OPENSSL_PKCS1_PADDING;
@@ -980,8 +980,8 @@ protected function encryptAndSign(Key $userKey, array $device, int $id, INotific
} else {
$this->printInfo('Failed to signed encrypted push subject');
}
- $base64EncryptedSubject = base64_encode($encryptedSubject);
- $base64Signature = base64_encode($signature);
+ $base64EncryptedSubject = base64_encode((string)$encryptedSubject);
+ $base64Signature = base64_encode((string)$signature);
return [
'deviceIdentifier' => $device['deviceidentifier'],
@@ -1014,8 +1014,8 @@ protected function encryptAndSignDelete(Key $userKey, array $device, ?array $ids
}
openssl_sign($encryptedSubject, $signature, $userKey->getPrivate(), OPENSSL_ALGO_SHA512);
- $base64EncryptedSubject = base64_encode($encryptedSubject);
- $base64Signature = base64_encode($signature);
+ $base64EncryptedSubject = base64_encode((string)$encryptedSubject);
+ $base64Signature = base64_encode((string)$signature);
return [
'remaining' => $remainingIds,
diff --git a/lib/Service/ClientService.php b/lib/Service/ClientService.php
index 2aab39045..a8bb3ccac 100644
--- a/lib/Service/ClientService.php
+++ b/lib/Service/ClientService.php
@@ -36,7 +36,7 @@ public function hasTalkDesktop(string $userId, int $maxAge = 0): bool {
$result = $query->executeQuery();
while ($row = $result->fetch()) {
- if (preg_match('/ \(Talk Desktop Client - [A-Za-z ]+\)$/', $row['name'])) {
+ if (preg_match('/ \(Talk Desktop Client - [A-Za-z ]+\)$/', (string)$row['name'])) {
$result->closeCursor();
return true;
}
diff --git a/lib/Settings/AdminSection.php b/lib/Settings/AdminSection.php
index f02e89251..b28fd210c 100644
--- a/lib/Settings/AdminSection.php
+++ b/lib/Settings/AdminSection.php
@@ -15,8 +15,8 @@
class AdminSection implements IIconSection {
public function __construct(
- private IURLGenerator $url,
- private IL10N $l,
+ private readonly IURLGenerator $url,
+ private readonly IL10N $l,
) {
}
diff --git a/lib/Settings/SetupWarningOnRateLimitReached.php b/lib/Settings/SetupWarningOnRateLimitReached.php
index da2241ff4..ff321c76a 100644
--- a/lib/Settings/SetupWarningOnRateLimitReached.php
+++ b/lib/Settings/SetupWarningOnRateLimitReached.php
@@ -17,9 +17,9 @@
class SetupWarningOnRateLimitReached implements ISetupCheck {
public function __construct(
- private IAppConfig $appConfig,
- private ITimeFactory $timeFactory,
- private IL10N $l,
+ private readonly IAppConfig $appConfig,
+ private readonly ITimeFactory $timeFactory,
+ private readonly IL10N $l,
) {
}
diff --git a/rector.php b/rector.php
index a550530e1..ea3f95571 100644
--- a/rector.php
+++ b/rector.php
@@ -6,7 +6,9 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
+use Nextcloud\Rector\Set\NextcloudSets;
use Rector\Config\RectorConfig;
+use Rector\PHPUnit\Set\PHPUnitSetList;
return RectorConfig::configure()
->withPaths([
@@ -16,5 +18,12 @@
__DIR__ . '/tests/Integration',
__DIR__ . '/tests/Unit',
])
- ->withPhpSets(php81: true)
+ ->withSkipPath(__DIR__ . '/lib/autoload')
+ ->withSkipPath(__DIR__ . '/lib/Vendor')
+ ->withSkipPath(__DIR__ . '/tests/Integration/vendor')
+ ->withPhpSets(php82: true)
+ ->withSets([
+ PHPUnitSetList::PHPUNIT_110,
+ NextcloudSets::NEXTCLOUD_34,
+ ])
->withTypeCoverageLevel(0);
diff --git a/tests/Integration/features/bootstrap/CommandLineTrait.php b/tests/Integration/features/bootstrap/CommandLineTrait.php
index 0f43cec23..b5bb88779 100644
--- a/tests/Integration/features/bootstrap/CommandLineTrait.php
+++ b/tests/Integration/features/bootstrap/CommandLineTrait.php
@@ -43,7 +43,7 @@ public function runOcc($args = [], $env = []) {
'maintenance:mode',
], true);
- $args = array_map(fn ($arg) => escapeshellarg($arg), $args);
+ $args = array_map(escapeshellarg(...), $args);
$args[] = '--no-ansi';
$argString = implode(' ', $args);
diff --git a/tests/Integration/features/bootstrap/FeatureContext.php b/tests/Integration/features/bootstrap/FeatureContext.php
index ce23caaaa..04cd9c61c 100644
--- a/tests/Integration/features/bootstrap/FeatureContext.php
+++ b/tests/Integration/features/bootstrap/FeatureContext.php
@@ -256,7 +256,7 @@ public function validateResponseAndSignature(string $verify): void {
Assert::assertNotEmpty($response['signature'], 'Signature should not be empty');
if ($verify === 'verify') {
- $result = openssl_verify($response['deviceIdentifier'], base64_decode($response['signature']), $response['publicKey'], OPENSSL_ALGO_SHA512);
+ $result = openssl_verify($response['deviceIdentifier'], base64_decode((string)$response['signature']), $response['publicKey'], OPENSSL_ALGO_SHA512);
Assert::assertEquals(true, $result, 'Failed to verify the signature');
} else {
/**
@@ -320,8 +320,8 @@ protected function generateWebPushKeys(): void {
]);
$details = openssl_pkey_get_details($key);
// Build uncompressed public key: 0x04 || x || y (65 bytes)
- $x = str_pad($details['ec']['x'], 32, "\0", STR_PAD_LEFT);
- $y = str_pad($details['ec']['y'], 32, "\0", STR_PAD_LEFT);
+ $x = str_pad((string)$details['ec']['x'], 32, "\0", STR_PAD_LEFT);
+ $y = str_pad((string)$details['ec']['y'], 32, "\0", STR_PAD_LEFT);
$uncompressed = "\x04" . $x . $y;
$this->webPushPublicKey = rtrim(strtr(base64_encode($uncompressed), '+/', '-_'), '=');
diff --git a/tests/psalm-baseline.xml b/tests/psalm-baseline.xml
index 0903b6e8a..001c57eeb 100644
--- a/tests/psalm-baseline.xml
+++ b/tests/psalm-baseline.xml
@@ -1,6 +1,9 @@
+
+
+
identityProof]]>
tokenProvider]]>
diff --git a/vendor-bin/rector/composer.json b/vendor-bin/rector/composer.json
index cfeb9354b..9bb0d3024 100644
--- a/vendor-bin/rector/composer.json
+++ b/vendor-bin/rector/composer.json
@@ -1,12 +1,18 @@
{
"config": {
"platform": {
- "php": "8.1"
+ "php": "8.2"
},
"sort-packages": true
},
"require-dev": {
- "nextcloud/rector": "^0.5",
+ "nextcloud/rector": "^0.5.1",
"rector/rector": "^2.4"
+ },
+ "autoload": {
+ "psr-4": {
+ "OCP\\": "vendor-bin/nextcloud-ocp/vendor/nextcloud/ocp/OCP/",
+ "NCU\\": "vendor-bin/nextcloud-ocp/vendor/nextcloud/ocp/NCU/"
+ }
}
}
diff --git a/vendor-bin/rector/composer.lock b/vendor-bin/rector/composer.lock
index 753d16b00..07aca8e54 100644
--- a/vendor-bin/rector/composer.lock
+++ b/vendor-bin/rector/composer.lock
@@ -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": "342f641322d4e7f615d9c83bb79d7be8",
+ "content-hash": "0df11b0a078245f304e5627372d1fb41",
"packages": [],
"packages-dev": [
{
@@ -57,16 +57,16 @@
},
{
"name": "nextcloud/rector",
- "version": "v0.5.0",
+ "version": "v0.5.1",
"source": {
"type": "git",
"url": "https://github.com/nextcloud-libraries/rector.git",
- "reference": "27bff78af53633d9b77ed8af17b27af73e8f67e9"
+ "reference": "d9c4cf53d9bce0fa95edc87cb093307958317e28"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/nextcloud-libraries/rector/zipball/27bff78af53633d9b77ed8af17b27af73e8f67e9",
- "reference": "27bff78af53633d9b77ed8af17b27af73e8f67e9",
+ "url": "https://api.github.com/repos/nextcloud-libraries/rector/zipball/d9c4cf53d9bce0fa95edc87cb093307958317e28",
+ "reference": "d9c4cf53d9bce0fa95edc87cb093307958317e28",
"shasum": ""
},
"require": {
@@ -116,9 +116,9 @@
],
"support": {
"issues": "https://github.com/nextcloud-libraries/rector/issues",
- "source": "https://github.com/nextcloud-libraries/rector/tree/v0.5.0"
+ "source": "https://github.com/nextcloud-libraries/rector/tree/v0.5.1"
},
- "time": "2026-04-28T08:20:44+00:00"
+ "time": "2026-05-08T07:32:27+00:00"
},
{
"name": "phpstan/phpstan",