From 18416df97b5eb32d01c5a91a334573b256c316a7 Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Fri, 6 Feb 2026 16:48:30 +0100 Subject: [PATCH 1/4] refactor: Modernize code with rector Signed-off-by: Carl Schwan --- composer.json | 9 +- composer.lock | 62 +++++++- lib/AppConfigOverwrite.php | 2 +- lib/AppInfo/Application.php | 2 +- lib/AppWhitelist.php | 54 +++---- lib/BackgroundJob/TransferJob.php | 14 +- lib/Capabilities.php | 2 +- lib/Command/AddCommand.php | 39 +++--- lib/Command/ListCommand.php | 14 +- lib/Config.php | 10 +- lib/Controller/APIController.php | 55 ++------ lib/Controller/SettingsController.php | 7 +- lib/Controller/UsersController.php | 30 ++-- lib/FilteredNavigationManager.php | 8 +- lib/FilteredSettingsManager.php | 18 +-- lib/GroupBackend.php | 20 +-- lib/GuestManager.php | 39 +++--- lib/Hooks.php | 27 ++-- .../BeforeTemplateRenderedListener.php | 2 +- .../BeforeUserManagementRenderedListener.php | 3 - .../LoadAdditionalScriptsListener.php | 5 +- lib/Listener/ShareAutoAcceptListener.php | 6 +- lib/Listener/UserChangedListener.php | 4 +- lib/Mail.php | 20 ++- lib/Notifications/Notifier.php | 6 +- lib/Repair/ResetEmails.php | 7 +- lib/RestrictionManager.php | 36 ++--- lib/Service/InviteService.php | 10 +- lib/Settings/Admin.php | 8 -- lib/Settings/Section.php | 4 - lib/Storage/DirMask.php | 16 +-- lib/Storage/ReadOnlyJail.php | 1 - lib/TransferService.php | 12 +- lib/UserBackend.php | 25 ++-- rector.php | 27 ++++ .../features/bootstrap/GuestsContext.php | 42 +++--- tests/stub.php | 10 ++ tests/unit/AppWhitelistTest.php | 7 +- tests/unit/Command/AddCommandTest.php | 18 ++- tests/unit/ConfigTest.php | 41 +++--- tests/unit/Controller/UsersControllerTest.php | 41 +++--- tests/unit/GroupBackendTest.php | 25 ++-- tests/unit/GuestManagerTest.php | 37 ++--- tests/unit/Storage/DirMaskTest.php | 2 +- tests/unit/UserBackendTest.php | 9 +- vendor-bin/rector/composer.json | 5 + vendor-bin/rector/composer.lock | 132 ++++++++++++++++++ 47 files changed, 533 insertions(+), 440 deletions(-) create mode 100644 rector.php create mode 100644 vendor-bin/rector/composer.json create mode 100644 vendor-bin/rector/composer.lock diff --git a/composer.json b/composer.json index ead4d519..7c6a633c 100644 --- a/composer.json +++ b/composer.json @@ -17,6 +17,9 @@ } }, "scripts": { + "post-install-cmd": [ + "@composer bin all install --ansi" + ], "lint": "find . -name \\*.php -not -path './vendor/*' -print0 | xargs -0 -n1 php -l", "cs:check": "php-cs-fixer fix --dry-run --diff", "cs:fix": "php-cs-fixer fix", @@ -25,10 +28,12 @@ "psalm:update-baseline:force": "psalm --threads=1 --update-baseline --set-baseline=tests/psalm-baseline.xml", "psalm:clear": "psalm --clear-cache && psalm --clear-global-cache", "psalm:fix": "psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockParamType,MismatchingDocblockReturnType,MissingParamType,InvalidFalsableReturnType", - "test:unit": "vendor/bin/phpunit -c phpunit.xml" + "test:unit": "vendor/bin/phpunit -c phpunit.xml", + "rector": "rector && composer cs:fix" }, "require": { - "php": ">=8.1 <=8.4" + "php": ">=8.1 <=8.4", + "bamarni/composer-bin-plugin": "^1.9" }, "require-dev": { "nextcloud/coding-standard": "^1.3.2", diff --git a/composer.lock b/composer.lock index d0630f10..3de8f104 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,66 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "e07f01cc499f035d121ce1707c77c474", - "packages": [], + "content-hash": "db99fa2035652ab63b49b50c2d180848", + "packages": [ + { + "name": "bamarni/composer-bin-plugin", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/bamarni/composer-bin-plugin.git", + "reference": "641d0663f5ac270b1aeec4337b7856f76204df47" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/bamarni/composer-bin-plugin/zipball/641d0663f5ac270b1aeec4337b7856f76204df47", + "reference": "641d0663f5ac270b1aeec4337b7856f76204df47", + "shasum": "" + }, + "require": { + "composer-plugin-api": "^2.0", + "php": "^7.2.5 || ^8.0" + }, + "require-dev": { + "composer/composer": "^2.2.26", + "ext-json": "*", + "phpstan/extension-installer": "^1.1", + "phpstan/phpstan": "^1.8 || ^2.0", + "phpstan/phpstan-phpunit": "^1.1 || ^2.0", + "phpunit/phpunit": "^8.5 || ^9.6 || ^10.0", + "symfony/console": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", + "symfony/finder": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0", + "symfony/process": "^2.8.52 || ^3.4.35 || ^4.4 || ^5.0 || ^6.0" + }, + "type": "composer-plugin", + "extra": { + "class": "Bamarni\\Composer\\Bin\\BamarniBinPlugin" + }, + "autoload": { + "psr-4": { + "Bamarni\\Composer\\Bin\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "No conflicts for your bin dependencies", + "keywords": [ + "composer", + "conflict", + "dependency", + "executable", + "isolation", + "tool" + ], + "support": { + "issues": "https://github.com/bamarni/composer-bin-plugin/issues", + "source": "https://github.com/bamarni/composer-bin-plugin/tree/1.9.1" + }, + "time": "2026-02-04T10:18:12+00:00" + } + ], "packages-dev": [ { "name": "amphp/amp", diff --git a/lib/AppConfigOverwrite.php b/lib/AppConfigOverwrite.php index c9a09df8..0f59417d 100644 --- a/lib/AppConfigOverwrite.php +++ b/lib/AppConfigOverwrite.php @@ -13,7 +13,7 @@ class AppConfigOverwrite extends AppConfig { /** @var string[][] */ - private $overWrite = []; + private array $overWrite = []; public function setOverwrite(array $overwrite): void { $this->overWrite = $overwrite; diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index fdec67c9..622b29be 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -81,7 +81,7 @@ private function setupGuestRestrictions(ContainerInterface $container, Container $restrictionManager->verifyAccess(); $restrictionManager->setupRestrictions(); } else { - $userSession->listen('\OC\User', 'postLogin', function () use ($restrictionManager) { + $userSession->listen('\OC\User', 'postLogin', function () use ($restrictionManager): void { $restrictionManager->verifyAccess(); $restrictionManager->setupRestrictions(); }); diff --git a/lib/AppWhitelist.php b/lib/AppWhitelist.php index e5cbd09c..0d7cee42 100644 --- a/lib/AppWhitelist.php +++ b/lib/AppWhitelist.php @@ -22,8 +22,8 @@ * @package OCA\Guests */ class AppWhitelist { - private string $baseUrl; - private int $baseUrlLength; + private readonly string $baseUrl; + private readonly int $baseUrlLength; public const WHITELIST_ALWAYS = ',core,theming,settings,avatar,files,heartbeat,dav,guests,impersonate,accessibility,terms_of_service,dashboard,weather_status,user_status,apporder,twofactor_totp,twofactor_webauthn,twofactor_backupcodes,twofactor_nextcloud_notification'; @@ -31,21 +31,14 @@ class AppWhitelist { /** * AppWhitelist constructor. - * - * @param Config $config - * @param GuestManager $guestManager - * @param IL10N $l10n - * @param IAppManager $appManager - * @param IURLGenerator $urlGenerator - * @param LoggerInterface $logger */ public function __construct( IURLGenerator $urlGenerator, - private Config $config, - private GuestManager $guestManager, - private IL10N $l10n, - private IAppManager $appManager, - private LoggerInterface $logger, + private readonly Config $config, + private readonly GuestManager $guestManager, + private readonly IL10N $l10n, + private readonly IAppManager $appManager, + private readonly LoggerInterface $logger, ) { $this->baseUrl = $urlGenerator->getBaseUrl(); $this->baseUrlLength = strlen($this->baseUrl); @@ -62,9 +55,6 @@ public function isWhitelistEnabled(): bool { return $this->config->useWhitelist(); } - /** - * @param false|string $url - */ public function isUrlAllowed(IUser $user, string|false $url): bool { if ($this->guestManager->isGuest($user) && $this->isWhitelistEnabled()) { $app = $this->getRequestedApp($url); @@ -98,45 +88,43 @@ public function verifyAccess(IUser $user, IRequest $request): void { /** * Core has \OC::$REQUESTEDAPP but it isn't set until the routes are matched * taken from \OC\Route\Router::match() - * - * @param false|string $url */ private function getRequestedApp(string|false $url): string { if (substr($url, 0, $this->baseUrlLength) === $this->baseUrl) { $url = substr($url, $this->baseUrlLength); } - if (strpos($url, '/index.php/') === 0) { + if (str_starts_with($url, '/index.php/')) { $url = substr($url, 10); } - if (substr($url, 0, 6) === '/apps/') { + if (str_starts_with($url, '/apps/')) { // empty string / 'apps' / $app / rest of the route [, , $app,] = explode('/', $url, 4); return \OC_App::cleanAppId($app); } elseif ($url === '/cron.php') { return 'core'; - } elseif (substr($url, 0, 6) === '/core/') { + } elseif (str_starts_with($url, '/core/')) { return 'core'; - } elseif (substr($url, 0, 4) === '/js/') { + } elseif (str_starts_with($url, '/js/')) { return 'core'; - } elseif (substr($url, 0, 5) === '/css/') { + } elseif (str_starts_with($url, '/css/')) { return 'core'; - } elseif (substr($url, 0, 6) === '/login') { + } elseif (str_starts_with($url, '/login')) { return 'core'; - } elseif (substr($url, 0, 7) === '/logout') { + } elseif (str_starts_with($url, '/logout')) { return 'core'; - } elseif (substr($url, 0, 3) === '/f/') { + } elseif (str_starts_with($url, '/f/')) { return 'files'; - } elseif (substr($url, 0, 8) === '/webdav/') { + } elseif (str_starts_with($url, '/webdav/')) { return 'dav'; - } elseif (substr($url, 0, 5) === '/dav/') { + } elseif (str_starts_with($url, '/dav/')) { return 'dav'; - } elseif (substr($url, 0, 6) === '/call/') { + } elseif (str_starts_with($url, '/call/')) { return 'spreed'; - } elseif (substr($url, 0, 10) === '/settings/') { + } elseif (str_starts_with($url, '/settings/')) { return 'settings'; - } elseif (substr($url, 0, 8) === '/avatar/') { + } elseif (str_starts_with($url, '/avatar/')) { return 'avatar'; - } elseif (substr($url, 0, 10) === '/heartbeat') { + } elseif (str_starts_with($url, '/heartbeat')) { return 'heartbeat'; } return 'core'; diff --git a/lib/BackgroundJob/TransferJob.php b/lib/BackgroundJob/TransferJob.php index f74f9e6b..cb336c22 100644 --- a/lib/BackgroundJob/TransferJob.php +++ b/lib/BackgroundJob/TransferJob.php @@ -25,13 +25,13 @@ class TransferJob extends QueuedJob { public function __construct( ITimeFactory $time, - private IUserManager $userManager, - private ISecureRandom $secureRandom, - private NotificationManager $notificationManager, - private IURLGenerator $urlGenerator, - private TransferService $transferService, - private TransferMapper $transferMapper, - private LoggerInterface $logger, + private readonly IUserManager $userManager, + private readonly ISecureRandom $secureRandom, + private readonly NotificationManager $notificationManager, + private readonly IURLGenerator $urlGenerator, + private readonly TransferService $transferService, + private readonly TransferMapper $transferMapper, + private readonly LoggerInterface $logger, ) { parent::__construct($time); } diff --git a/lib/Capabilities.php b/lib/Capabilities.php index b3d2f64f..1e562620 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -19,7 +19,7 @@ class Capabilities implements ICapability { /** * @inheritDoc */ - public function getCapabilities() { + public function getCapabilities(): array { return [ 'guests' => [ 'enabled' => true, diff --git a/lib/Command/AddCommand.php b/lib/Command/AddCommand.php index d046208e..6802d09d 100644 --- a/lib/Command/AddCommand.php +++ b/lib/Command/AddCommand.php @@ -12,6 +12,7 @@ use OCP\IUser; use OCP\IUserManager; use OCP\Mail\IMailer; +use Override; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputArgument; @@ -21,21 +22,16 @@ use Symfony\Component\Console\Question\Question; class AddCommand extends Command { - /** @var IUserManager */ - private $userManager; - /** @var GuestManager */ - private $guestManager; - /** @var IMailer */ - private $mailer; - - public function __construct(IUserManager $userManager, IMailer $mailer, GuestManager $guestManager) { + public function __construct( + private readonly IUserManager $userManager, + private readonly IMailer $mailer, + private readonly GuestManager $guestManager, + ) { parent::__construct(); - $this->userManager = $userManager; - $this->guestManager = $guestManager; - $this->mailer = $mailer; } - protected function configure() { + #[Override] + protected function configure(): void { $this ->setName('guests:add') ->setDescription('Add a new guest account') @@ -78,24 +74,25 @@ protected function configure() { parent::configure(); } - protected function execute(InputInterface $input, OutputInterface $output) { + #[Override] + protected function execute(InputInterface $input, OutputInterface $output): int { $creatorUser = $this->userManager->get($input->getArgument('created-by')); if ($creatorUser === null) { $output->writeln('The user "' . $input->getArgument('created-by') . '" does not exist.'); - return 1; + return self::FAILURE; } // same behavior like in the UsersController $uid = $input->getArgument('email'); if ($this->userManager->userExists($uid)) { $output->writeln('The user "' . $uid . '" already exists.'); - return 1; + return self::FAILURE; } $email = $input->getArgument('email'); if (!$this->mailer->validateMailAddress($email)) { $output->writeln('Invalid email address "' . $email . '".'); - return 1; + return self::FAILURE; } $password = null; @@ -104,7 +101,7 @@ protected function execute(InputInterface $input, OutputInterface $output) { $password = getenv('OC_PASS'); if (!$password) { $output->writeln('--password-from-env given, but OC_PASS is empty!'); - return 1; + return self::FAILURE; } } elseif ($input->isInteractive()) { /** @var QuestionHelper $helper */ @@ -120,11 +117,11 @@ protected function execute(InputInterface $input, OutputInterface $output) { if ($password !== $confirm) { $output->writeln('Passwords did not match!'); - return 1; + return self::FAILURE; } } else { $output->writeln('Interactive input or --password-from-env is needed for entering a password!'); - return 1; + return self::FAILURE; } } @@ -139,10 +136,10 @@ protected function execute(InputInterface $input, OutputInterface $output) { if ($user instanceof IUser) { $output->writeln('The guest account user "' . $user->getUID() . '" was created successfully'); - return 0; + return self::SUCCESS; } else { $output->writeln('An error occurred while creating the user'); - return 1; + return self::FAILURE; } } } diff --git a/lib/Command/ListCommand.php b/lib/Command/ListCommand.php index 45e705b3..0fc9371e 100644 --- a/lib/Command/ListCommand.php +++ b/lib/Command/ListCommand.php @@ -10,18 +10,19 @@ use OC\Core\Command\Base; use OCA\Guests\GuestManager; +use Override; use Symfony\Component\Console\Helper\Table; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Output\OutputInterface; class ListCommand extends Base { - private $guestManager; - - public function __construct(GuestManager $guestManager) { + public function __construct( + private readonly GuestManager $guestManager, + ) { parent::__construct(); - $this->guestManager = $guestManager; } + #[Override] protected function configure(): void { $this ->setName('guests:list') @@ -29,6 +30,7 @@ protected function configure(): void { parent::configure(); } + #[Override] protected function execute(InputInterface $input, OutputInterface $output): int { $guests = $this->guestManager->getGuestsInfo(); @@ -39,7 +41,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } else { $output->writeln('No guests created'); } - return 0; + return self::SUCCESS; } if ($outputType === self::OUTPUT_FORMAT_JSON || $outputType === self::OUTPUT_FORMAT_JSON_PRETTY) { @@ -50,6 +52,6 @@ protected function execute(InputInterface $input, OutputInterface $output): int $table->setRows($guests); $table->render(); } - return 0; + return self::SUCCESS; } } diff --git a/lib/Config.php b/lib/Config.php index 3b5c5fea..eecbe8be 100644 --- a/lib/Config.php +++ b/lib/Config.php @@ -16,11 +16,11 @@ class Config { public function __construct( - private IConfig $config, - private IAppConfig $appConfig, - private ISubAdmin $subAdmin, - private IUserSession $userSession, - private IGroupManager $groupManager, + private readonly IConfig $config, + private readonly IAppConfig $appConfig, + private readonly ISubAdmin $subAdmin, + private readonly IUserSession $userSession, + private readonly IGroupManager $groupManager, ) { } diff --git a/lib/Controller/APIController.php b/lib/Controller/APIController.php index b187160e..e3b57477 100644 --- a/lib/Controller/APIController.php +++ b/lib/Controller/APIController.php @@ -10,7 +10,7 @@ use OC\L10N\Factory; use OCA\Guests\AppInfo\Application; -use OCA\Guests\Config; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; use OCP\Group\ISubAdmin; @@ -21,41 +21,18 @@ use OCP\L10N\IFactory; class APIController extends OCSController { - - /** @var Config */ - private $config; - - /** @var IFactory */ - private $l10nFactory; - - /** @var IUserSession */ - private $userSession; - - /** @var ISubAdmin */ - private $subAdmin; - - /** @var IGroupManager */ - private $groupManager; - public function __construct( IRequest $request, - IUserSession $userSession, - Config $config, - IFactory $l10nFactory, - ISubAdmin $subAdmin, - IGroupManager $groupManager, + private readonly IUserSession $userSession, + private readonly \OCA\Guests\Config $config, + private readonly IFactory $l10nFactory, + private readonly ISubAdmin $subAdmin, + private readonly IGroupManager $groupManager, ) { parent::__construct(Application::APP_ID, $request); - $this->userSession = $userSession; - $this->config = $config; - $this->l10nFactory = $l10nFactory; - $this->subAdmin = $subAdmin; - $this->groupManager = $groupManager; } - /** - * @NoAdminRequired - */ + #[NoAdminRequired] public function languages(): DataResponse { $languageCodes = $this->l10nFactory->findAvailableLanguages('guests'); @@ -95,7 +72,7 @@ public function languages(): DataResponse { ksort($commonLanguages); // sort now by displayed language not the iso-code - usort($languages, function ($a, $b) { + usort($languages, function (array $a, array $b): int { if ($a['code'] === $a['name'] && $b['code'] !== $b['name']) { // If a doesn't have a name, but b does, list b before a return 1; @@ -105,7 +82,7 @@ public function languages(): DataResponse { return -1; } // Otherwise compare the names - return strcmp($a['name'], $b['name']); + return strcmp((string)$a['name'], (string)$b['name']); }); return new DataResponse([ @@ -115,9 +92,7 @@ public function languages(): DataResponse { ]); } - /** - * @NoAdminRequired - */ + #[NoAdminRequired] public function groups(): DataResponse { $user = $this->userSession->getUser(); if ($this->groupManager->isAdmin($user->getUID())) { @@ -125,12 +100,10 @@ public function groups(): DataResponse { } else { $groups = $this->subAdmin->getSubAdminsGroups($user); } - $groups = array_values(array_map(function (IGroup $group) { - return [ - 'gid' => $group->getGID(), - 'name' => $group->getDisplayName(), - ]; - }, $groups)); + $groups = array_values(array_map(fn (IGroup $group): array => [ + 'gid' => $group->getGID(), + 'name' => $group->getDisplayName(), + ], $groups)); return new DataResponse([ 'required' => $this->config->isSharingRestrictedToGroup(), diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index 2a6613c6..92132aae 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -25,8 +25,8 @@ class SettingsController extends Controller { public function __construct( IRequest $request, - private Config $config, - private AppWhitelist $appWhitelist, + private readonly Config $config, + private readonly AppWhitelist $appWhitelist, ) { parent::__construct(Application::APP_ID, $request); } @@ -57,12 +57,11 @@ public function getConfig(): DataResponse { * @param $whitelist string[] * @param $allowExternalStorage bool * @param $hideUsers bool - * @return DataResponse */ public function setConfig(bool $useWhitelist, array $whitelist, bool $allowExternalStorage, bool $hideUsers, array $createRestrictedToGroup): DataResponse { $newWhitelist = []; foreach ($whitelist as $app) { - $newWhitelist[] = trim($app); + $newWhitelist[] = trim((string)$app); } $this->config->setUseWhitelist($useWhitelist); $this->config->setAppWhitelist($newWhitelist); diff --git a/lib/Controller/UsersController.php b/lib/Controller/UsersController.php index e3d02583..f009f7d2 100644 --- a/lib/Controller/UsersController.php +++ b/lib/Controller/UsersController.php @@ -33,29 +33,23 @@ class UsersController extends OCSController { public function __construct( string $appName, IRequest $request, - private IUserManager $userManager, - private IL10N $l10n, - private Config $config, - private IMailer $mailer, - private GuestManager $guestManager, - private IUserSession $userSession, - private ISubAdmin $subAdmin, - private IGroupManager $groupManager, - private TransferService $transferService, - private TransferMapper $transferMapper, - private InviteService $inviteService, + private readonly IUserManager $userManager, + private readonly IL10N $l10n, + private readonly Config $config, + private readonly IMailer $mailer, + private readonly GuestManager $guestManager, + private readonly IUserSession $userSession, + private readonly ISubAdmin $subAdmin, + private readonly IGroupManager $groupManager, + private readonly TransferService $transferService, + private readonly TransferMapper $transferMapper, + private readonly InviteService $inviteService, ) { parent::__construct($appName, $request); } /** * @NoAdminRequired - * - * @param string $email - * @param string $displayName - * @param string $language - * @param array $groups - * @return DataResponse */ public function create(string $email, string $displayName, string $language, array $groups, bool $sendInvite = true): DataResponse { $errorMessages = []; @@ -220,7 +214,7 @@ public function transfer(string $guestUserId, string $targetUserId): DataRespons try { $transfer = $this->transferMapper->getByTarget($targetUserId); - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { // Allow as this just means there is no pending transfer } diff --git a/lib/FilteredNavigationManager.php b/lib/FilteredNavigationManager.php index 650b6a38..1b3aedd2 100644 --- a/lib/FilteredNavigationManager.php +++ b/lib/FilteredNavigationManager.php @@ -14,16 +14,16 @@ class FilteredNavigationManager extends NavigationManager { public function __construct( - private IUser $user, - private INavigationManager $navigationManager, - private AppWhitelist $whitelist, + private readonly IUser $user, + private readonly INavigationManager $navigationManager, + private readonly AppWhitelist $whitelist, ) { } public function getAll(string $type = 'link'): array { $items = $this->navigationManager->getAll($type); - return array_filter($items, [$this, 'isEntryWhitelisted']); + return array_filter($items, $this->isEntryWhitelisted(...)); } private function isEntryWhitelisted(array $item): bool { diff --git a/lib/FilteredSettingsManager.php b/lib/FilteredSettingsManager.php index f3b17ea7..5ce8712b 100644 --- a/lib/FilteredSettingsManager.php +++ b/lib/FilteredSettingsManager.php @@ -15,12 +15,12 @@ class FilteredSettingsManager implements IManager { /** @var IManager */ private $manager; - /** @var AppWhitelist */ - private $appWhitelist; - public function __construct(IManager $manager, AppWhitelist $appWhitelist) { + public function __construct( + IManager $manager, + private readonly \OCA\Guests\AppWhitelist $appWhitelist, + ) { $this->manager = $manager; - $this->appWhitelist = $appWhitelist; } private function isSettingAllowed(string $setting): bool { @@ -28,17 +28,11 @@ private function isSettingAllowed(string $setting): bool { return $this->appWhitelist->isAppWhitelisted($appId); } - /** - * @return void - */ - public function registerSection(string $type, string $section) { + public function registerSection(string $type, string $section): void { $this->manager->registerSection($type, $section); } - /** - * @return void - */ - public function registerSetting(string $type, string $setting) { + public function registerSetting(string $type, string $setting): void { if (!$this->isSettingAllowed($setting)) { return; } diff --git a/lib/GroupBackend.php b/lib/GroupBackend.php index 3371d2c5..02758f46 100644 --- a/lib/GroupBackend.php +++ b/lib/GroupBackend.php @@ -20,31 +20,19 @@ * @package OCA\Guests */ class GroupBackend extends ABackend implements ICountUsersBackend, IGroupDetailsBackend, IHideFromCollaborationBackend { - /** @var GuestManager */ - private $guestManager; - /** @var string[] */ private $guestMembers = []; - /** @var string */ - private $groupName; - - /** @var Config */ - private $config; - /** @var IUserSession */ private $userSession; public function __construct( - GuestManager $guestManager, - Config $config, + private readonly \OCA\Guests\GuestManager $guestManager, + private readonly \OCA\Guests\Config $config, IUserSession $userSession, - string $groupName = 'guest_app', + private readonly string $groupName = 'guest_app', ) { - $this->guestManager = $guestManager; - $this->config = $config; $this->userSession = $userSession; - $this->groupName = $groupName; } private function getMembers(): array { @@ -60,7 +48,6 @@ private function getMembers(): array { * * @param string $uid uid of the user * @param string $gid gid of the group - * @return bool * @since 4.5.0 * * Checks whether the user is member of a group or not. @@ -106,7 +93,6 @@ public function getGroups($search = '', $limit = -1, $offset = 0): array { * check if a group exists * * @param string $gid - * @return bool * @since 4.5.0 */ public function groupExists($gid): bool { diff --git a/lib/GuestManager.php b/lib/GuestManager.php index 1ba6911a..0bc13d12 100644 --- a/lib/GuestManager.php +++ b/lib/GuestManager.php @@ -22,21 +22,20 @@ class GuestManager { public function __construct( - private IConfig $config, - private UserBackend $userBackend, - private ISecureRandom $secureRandom, - private ICrypto $crypto, - private IManager $shareManager, - private IDBConnection $connection, - private IUserSession $userSession, - private IEventDispatcher $eventDispatcher, - private IUserManager $userManager, + private readonly IConfig $config, + private readonly UserBackend $userBackend, + private readonly ISecureRandom $secureRandom, + private readonly ICrypto $crypto, + private readonly IManager $shareManager, + private readonly IDBConnection $connection, + private readonly IUserSession $userSession, + private readonly IEventDispatcher $eventDispatcher, + private readonly IUserManager $userManager, ) { } /** * @param IUser|string $user - * @return bool */ public function isGuest($user = null): bool { if (is_null($user)) { @@ -115,7 +114,7 @@ public function getGuestsInfo(): array { $guests = array_keys($displayNames); $shareCounts = $this->getShareCountForUsers($guests); $createdBy = $this->config->getUserValueForUsers('guests', 'created_by', $guests); - return array_map(function ($uid) use ($createdBy, $displayNames, $shareCounts) { + return array_map(function (int|string $uid) use ($createdBy, $displayNames, $shareCounts): array { $allSharesCount = count(array_merge( $this->shareManager->getSharedWith($uid, IShare::TYPE_USER, null, -1, 0), $this->shareManager->getSharedWith($uid, IShare::TYPE_GROUP, null, -1, 0), @@ -127,7 +126,7 @@ public function getGuestsInfo(): array { 'email' => $uid, 'display_name' => $displayNames[$uid] ?? $uid, 'created_by' => $createdBy[$uid] ?? '', - 'share_count' => isset($shareCounts[$uid]) ? $shareCounts[$uid] : 0, + 'share_count' => $shareCounts[$uid] ?? 0, 'share_count_with_circles' => $allSharesCount, ]; }, $guests); @@ -158,15 +157,13 @@ public function getGuestInfo(string $userId): array { $this->shareManager->getSharedWith($userId, IShare::TYPE_ROOM, null, -1, 0) ); return [ - 'shares' => array_map(function (IShare $share) { - return [ - 'id' => $share->getId(), - 'shared_by' => $share->getSharedBy(), - 'mime_type' => $share->getNodeCacheEntry()->getMimeType(), - 'name' => $share->getNodeCacheEntry()->getName(), - 'time' => $share->getShareTime()->getTimestamp(), - ]; - }, $shares), + 'shares' => array_map(fn (IShare $share): array => [ + 'id' => $share->getId(), + 'shared_by' => $share->getSharedBy(), + 'mime_type' => $share->getNodeCacheEntry()->getMimeType(), + 'name' => $share->getNodeCacheEntry()->getName(), + 'time' => $share->getShareTime()->getTimestamp(), + ], $shares), ]; } } diff --git a/lib/Hooks.php b/lib/Hooks.php index e2b31146..33bba82d 100644 --- a/lib/Hooks.php +++ b/lib/Hooks.php @@ -12,31 +12,26 @@ use OCA\Guests\AppInfo\Application; use OCA\Guests\Service\InviteService; use OCA\Guests\Storage\ReadOnlyJail; -use OCP\AppFramework\IAppContainer; use OCP\Constants; use OCP\Files\Storage\IStorage; use OCP\IConfig; use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; -use OCP\Security\ICrypto; use OCP\Share\Events\ShareCreatedEvent; use OCP\User\Events\UserFirstTimeLoggedInEvent; use Psr\Log\LoggerInterface; class Hooks { public function __construct( - private LoggerInterface $logger, - private IUserSession $userSession, - private Mail $mail, - private IUserManager $userManager, - private IConfig $config, - private ICrypto $crypto, - private GuestManager $guestManager, - private UserBackend $userBackend, - private IAppContainer $container, - private TransferService $transferService, - private InviteService $inviteService, + private readonly LoggerInterface $logger, + private readonly IUserSession $userSession, + private readonly IUserManager $userManager, + private readonly IConfig $config, + private readonly GuestManager $guestManager, + private readonly UserBackend $userBackend, + private readonly TransferService $transferService, + private readonly InviteService $inviteService, ) { } @@ -66,7 +61,7 @@ public function handlePostShare(ShareCreatedEvent $event): void { $user = $this->userSession->getUser(); - $targetUser = $this->userManager->get($shareWith); + $this->userManager->get($shareWith); if (!$user) { throw new \Exception( @@ -87,7 +82,7 @@ public function setupReadonlyFilesystem(array $params): void { $user = $this->userManager->get($uid); if ($user && $this->guestManager->isGuest($user)) { - Filesystem::addStorageWrapper('guests.readonly', function ($mountPoint, IStorage $storage) use ($uid) { + Filesystem::addStorageWrapper('guests.readonly', function ($mountPoint, IStorage $storage) use ($uid): \OCA\Guests\Storage\ReadOnlyJail|\OCP\Files\Storage\IStorage { if ($mountPoint === "/$uid/") { return new ReadOnlyJail([ 'storage' => $storage, @@ -121,7 +116,7 @@ public function handleFirstLogin(UserFirstTimeLoggedInEvent $event): void { return; } - if (strtolower($email) === strtolower($user->getUID())) { + if (strtolower($email) === strtolower((string)$user->getUID())) { // This is the guest user, logging in for the very first time return; } diff --git a/lib/Listener/BeforeTemplateRenderedListener.php b/lib/Listener/BeforeTemplateRenderedListener.php index 440c565b..8821e55f 100644 --- a/lib/Listener/BeforeTemplateRenderedListener.php +++ b/lib/Listener/BeforeTemplateRenderedListener.php @@ -21,7 +21,7 @@ */ class BeforeTemplateRenderedListener implements IEventListener { public function __construct( - private Config $config, + private readonly Config $config, ) { } diff --git a/lib/Listener/BeforeUserManagementRenderedListener.php b/lib/Listener/BeforeUserManagementRenderedListener.php index 83807049..28eb6bb9 100644 --- a/lib/Listener/BeforeUserManagementRenderedListener.php +++ b/lib/Listener/BeforeUserManagementRenderedListener.php @@ -18,9 +18,6 @@ * @template-implements IEventListener */ class BeforeUserManagementRenderedListener implements IEventListener { - /** - * @param Event $event - */ public function handle(Event $event): void { if (!($event instanceof BeforeTemplateRenderedEvent)) { return; diff --git a/lib/Listener/LoadAdditionalScriptsListener.php b/lib/Listener/LoadAdditionalScriptsListener.php index c3855aac..3efd452b 100644 --- a/lib/Listener/LoadAdditionalScriptsListener.php +++ b/lib/Listener/LoadAdditionalScriptsListener.php @@ -22,13 +22,10 @@ class LoadAdditionalScriptsListener implements IEventListener { public function __construct( - private Config $config, + private readonly Config $config, ) { } - /** - * @param Event $event - */ public function handle(Event $event): void { // If the user cannot create guests, we don't need to load the script if (!$this->config->canCreateGuests()) { diff --git a/lib/Listener/ShareAutoAcceptListener.php b/lib/Listener/ShareAutoAcceptListener.php index 6d24a638..395fb5c6 100644 --- a/lib/Listener/ShareAutoAcceptListener.php +++ b/lib/Listener/ShareAutoAcceptListener.php @@ -23,9 +23,9 @@ class ShareAutoAcceptListener implements IEventListener { public function __construct( - private IUserManager $userManager, - private ShareManager $shareManager, - private LoggerInterface $logger, + private readonly IUserManager $userManager, + private readonly ShareManager $shareManager, + private readonly LoggerInterface $logger, ) { } diff --git a/lib/Listener/UserChangedListener.php b/lib/Listener/UserChangedListener.php index 28b68912..d8cc9d3c 100644 --- a/lib/Listener/UserChangedListener.php +++ b/lib/Listener/UserChangedListener.php @@ -43,13 +43,13 @@ public function handle(Event $event): void { return; } - $guestEmail = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'email', strtolower($user->getUID())); + $guestEmail = $this->config->getUserValue($user->getUID(), Application::APP_ID, 'email', strtolower((string)$user->getUID())); if ($event->getValue() === $guestEmail) { return; } $allowChange = false; - if (strtolower($event->getValue()) === strtolower($user->getUID())) { + if (strtolower($event->getValue()) === strtolower((string)$user->getUID())) { $allowChange = true; } elseif ($this->userSession->getUser() !== $user) { $allowChange = true; diff --git a/lib/Mail.php b/lib/Mail.php index 92afbbce..4fcf51bf 100644 --- a/lib/Mail.php +++ b/lib/Mail.php @@ -9,7 +9,6 @@ namespace OCA\Guests; use OCP\Defaults; -use OCP\IConfig; use OCP\IL10N; use OCP\IURLGenerator; use OCP\IUserManager; @@ -18,19 +17,16 @@ use OCP\Mail\IMailer; use OCP\Share; use OCP\Util; -use Psr\Log\LoggerInterface; class Mail { public function __construct( - private IConfig $config, - private LoggerInterface $logger, - private IUserSession $userSession, - private IMailer $mailer, - private Defaults $defaults, - private IFactory $l10nFactory, - private IUserManager $userManager, - private IURLGenerator $urlGenerator, + private readonly IUserSession $userSession, + private readonly IMailer $mailer, + private readonly Defaults $defaults, + private readonly IFactory $l10nFactory, + private readonly IUserManager $userManager, + private readonly IURLGenerator $urlGenerator, ) { } @@ -60,7 +56,7 @@ public function sendGuestInviteMail(string $uid, string $guest, string $token, s $replyTo = $this->userManager->get($uid)->getEMailAddress(); $senderDisplayName = $this->userSession->getUser()->getDisplayName(); - if (empty($share)) { + if (!$share instanceof \OCP\Share\IShare) { [ $subject, $emailTemplate ] = $this->composeInviteMessage($senderDisplayName, $guestEmail, $passwordLink, $l10n); } else { [ $subject, $emailTemplate ] = $this->composeShareMessage($share, $senderDisplayName, $guestEmail, $passwordLink, $l10n); @@ -85,7 +81,7 @@ public function sendGuestInviteMail(string $uid, string $guest, string $token, s } $this->mailer->send($message); - } catch (\Exception $e) { + } catch (\Exception) { throw new \Exception($l10n->t( 'Couldn\'t send reset email. Please contact your administrator.' )); diff --git a/lib/Notifications/Notifier.php b/lib/Notifications/Notifier.php index e0f41530..eea72f88 100644 --- a/lib/Notifications/Notifier.php +++ b/lib/Notifications/Notifier.php @@ -19,9 +19,9 @@ class Notifier implements INotifier { public function __construct( - private IFactory $factory, - private IURLGenerator $url, - private IUserManager $userManager, + private readonly IFactory $factory, + private readonly IURLGenerator $url, + private readonly IUserManager $userManager, ) { } diff --git a/lib/Repair/ResetEmails.php b/lib/Repair/ResetEmails.php index 27b79933..824f5215 100644 --- a/lib/Repair/ResetEmails.php +++ b/lib/Repair/ResetEmails.php @@ -31,10 +31,7 @@ public function getName(): string { return 'Reset the email of all guest accounts'; } - /** - * @return void - */ - public function run(IOutput $output) { + public function run(IOutput $output): void { if ($this->appConfig->getValueBool('guests', 'allow_email_change', false, true)) { return; } @@ -47,7 +44,7 @@ public function run(IOutput $output) { continue; } - $expectedEmail = $this->config->getUserValue($guestId, Application::APP_ID, 'email', strtolower($guestId)); + $expectedEmail = $this->config->getUserValue($guestId, Application::APP_ID, 'email', strtolower((string)$guestId)); $currentEmail = $guest->getSystemEMailAddress() ?? ''; if (strtolower($currentEmail) !== $expectedEmail) { diff --git a/lib/RestrictionManager.php b/lib/RestrictionManager.php index f161d0d7..d8df4a0c 100644 --- a/lib/RestrictionManager.php +++ b/lib/RestrictionManager.php @@ -23,16 +23,16 @@ class RestrictionManager { public function __construct( - private AppWhitelist $whitelist, - private IRequest $request, - private IUserSession $userSession, - private IServerContainer $server, - private Hooks $hooks, - private GuestManager $guestManager, - private IMountProviderCollection $mountProviderCollection, - private Config $config, - private UserBackend $userBackend, - private LoggerInterface $logger, + private readonly AppWhitelist $whitelist, + private readonly IRequest $request, + private readonly IUserSession $userSession, + private readonly IServerContainer $server, + private readonly Hooks $hooks, + private readonly GuestManager $guestManager, + private readonly IMountProviderCollection $mountProviderCollection, + private readonly Config $config, + private readonly UserBackend $userBackend, + private readonly LoggerInterface $logger, ) { } @@ -52,22 +52,16 @@ public function setupRestrictions(): void { if ($this->guestManager->isGuest($user)) { \OCP\Util::connectHook('OC_Filesystem', 'preSetup', $this->hooks, 'setupReadonlyFilesystem'); if (!$this->config->allowExternalStorage()) { - $this->mountProviderCollection->registerMountFilter(function (IMountPoint $mountPoint, IUser $user) { - return !($mountPoint instanceof ExternalMountPoint && $this->guestManager->isGuest($user)); - }); + $this->mountProviderCollection->registerMountFilter(fn (IMountPoint $mountPoint, IUser $user): bool => !($mountPoint instanceof ExternalMountPoint && $this->guestManager->isGuest($user))); } /** @var NavigationManager $navManager */ $navManager = \OCP\Server::get(INavigationManager::class); - $this->server->registerService(INavigationManager::class, function () use ($navManager, $user) { - return new FilteredNavigationManager($user, $navManager, $this->whitelist); - }); + $this->server->registerService(INavigationManager::class, fn (): \OCA\Guests\FilteredNavigationManager => new FilteredNavigationManager($user, $navManager, $this->whitelist)); $settingsManager = $this->server->get(IManager::class); - $this->server->registerService(IManager::class, function () use ($settingsManager) { - return new FilteredSettingsManager($settingsManager, $this->whitelist); - }); + $this->server->registerService(IManager::class, fn (): \OCA\Guests\FilteredSettingsManager => new FilteredSettingsManager($settingsManager, $this->whitelist)); } } @@ -86,9 +80,7 @@ public function lateSetupRestrictions(): void { ] ]); - $this->server->registerService(AppConfig::class, function () use ($appConfig) { - return $appConfig; - }); + $this->server->registerService(AppConfig::class, fn () => $appConfig); } } } diff --git a/lib/Service/InviteService.php b/lib/Service/InviteService.php index 71269b51..7a804a89 100644 --- a/lib/Service/InviteService.php +++ b/lib/Service/InviteService.php @@ -18,10 +18,10 @@ class InviteService { public function __construct( - private LoggerInterface $logger, - private IConfig $config, - private ICrypto $crypto, - private Mail $mail, + private readonly LoggerInterface $logger, + private readonly IConfig $config, + private readonly ICrypto $crypto, + private readonly Mail $mail, ) { } @@ -49,7 +49,7 @@ public function sendInvite(string $userId, string $guest, ?IShare $share = null) if ($share) { $share->setMailSend(false); } - } catch (DoesNotExistException $ex) { + } catch (DoesNotExistException) { $this->logger->error("'$guest' does not exist"); } catch (\Exception $e) { $this->logger->error('Failed to send guest activation mail', ['exception' => $e]); diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index 9019336f..5792db9e 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -8,18 +8,10 @@ namespace OCA\Guests\Settings; -use OCA\Guests\AppWhitelist; use OCP\AppFramework\Http\TemplateResponse; use OCP\Util; class Admin implements \OCP\Settings\ISettings { - /** @var AppWhitelist */ - private $appWhitelist; - - public function __construct(AppWhitelist $appWhitelist) { - $this->appWhitelist = $appWhitelist; - } - /** * {@inheritdoc} */ diff --git a/lib/Settings/Section.php b/lib/Settings/Section.php index e579b59f..74dc4f96 100644 --- a/lib/Settings/Section.php +++ b/lib/Settings/Section.php @@ -17,10 +17,6 @@ class Section implements IIconSection { /** @var IURLGenerator */ private $url; - /** - * @param IURLGenerator $url - * @param IL10N $l - */ public function __construct(IURLGenerator $url, IL10N $l) { $this->url = $url; $this->l = $l; diff --git a/lib/Storage/DirMask.php b/lib/Storage/DirMask.php index 113ca50b..7d8d76b1 100644 --- a/lib/Storage/DirMask.php +++ b/lib/Storage/DirMask.php @@ -22,11 +22,11 @@ class DirMask extends PermissionsMask { /** * @var string the dir that should be masked */ - private $path; + private readonly string $path; /** * @var int remember length */ - private $pathLength; + private readonly int $pathLength; private $mask; @@ -39,8 +39,8 @@ class DirMask extends PermissionsMask { */ public function __construct($arguments) { parent::__construct($arguments); - $this->path = rtrim($arguments['path'], '/'); - $this->pathLength = strlen($arguments['path']); + $this->path = rtrim((string)$arguments['path'], '/'); + $this->pathLength = strlen((string)$arguments['path']); $this->mask = $arguments['mask']; } @@ -97,7 +97,7 @@ public function rename($source, $target): bool { return $this->storage->rename($source, $target); } } else { - $parent = dirname($target); + $parent = dirname((string)$target); if ($parent === '.') { $parent = ''; } @@ -117,7 +117,7 @@ public function copy($source, $target): bool { return $this->storage->copy($source, $target); } } else { - $parent = dirname($target); + $parent = dirname((string)$target); if ($parent === '.') { $parent = ''; } @@ -182,8 +182,6 @@ public function getCache($path = '', $storage = null): ICache { $storage = $this; } $sourceCache = $this->storage->getCache($path, $storage); - return new DirMaskCache($sourceCache, $this->mask, function (string $path) { - return $this->checkPath($path); - }); + return new DirMaskCache($sourceCache, $this->mask, fn (string $path): bool => $this->checkPath($path)); } } diff --git a/lib/Storage/ReadOnlyJail.php b/lib/Storage/ReadOnlyJail.php index d79629fb..36988562 100644 --- a/lib/Storage/ReadOnlyJail.php +++ b/lib/Storage/ReadOnlyJail.php @@ -14,7 +14,6 @@ class ReadOnlyJail extends DirMask { /** * @param string $path - * @return bool */ public function isDeletable($path): bool { if (pathinfo($path, PATHINFO_EXTENSION) === 'part') { diff --git a/lib/TransferService.php b/lib/TransferService.php index 4ff0ac3f..7a3647ab 100644 --- a/lib/TransferService.php +++ b/lib/TransferService.php @@ -26,12 +26,12 @@ class TransferService { public function __construct( - private ContainerInterface $container, - private IShareManager $shareManager, - private INotificationManager $notificationManager, - private IJobList $jobList, - private TransferMapper $transferMapper, - private LoggerInterface $logger, + private readonly ContainerInterface $container, + private readonly IShareManager $shareManager, + private readonly INotificationManager $notificationManager, + private readonly IJobList $jobList, + private readonly TransferMapper $transferMapper, + private readonly LoggerInterface $logger, ) { } diff --git a/lib/UserBackend.php b/lib/UserBackend.php index 70f1072e..61f03846 100644 --- a/lib/UserBackend.php +++ b/lib/UserBackend.php @@ -38,14 +38,13 @@ class UserBackend extends ABackend implements IPasswordHashBackend { /** @var CappedMemoryCache */ private $cache; - /** @var bool */ - private $allowListing = true; + private bool $allowListing = true; public function __construct( - private IEventDispatcher $eventDispatcher, - private IDBConnection $dbConn, - private Config $config, - private IHasher $hasher, + private readonly IEventDispatcher $eventDispatcher, + private readonly IDBConnection $dbConn, + private readonly Config $config, + private readonly IHasher $hasher, ) { $this->cache = new CappedMemoryCache(); } @@ -257,7 +256,7 @@ public function getDisplayNames($search = '', $limit = null, $offset = null): ar * returns the user id or false */ public function checkPassword(string $loginName, string $password) { - if (strpos($loginName, '@') === false) { + if (!str_contains($loginName, '@')) { return false; } @@ -296,7 +295,7 @@ public function checkPassword(string $loginName, string $password) { private function loadUser($uid): bool { // guests $uid could be NULL or '' // or is not an email anyway - if (strpos($uid, '@') === false) { + if (!str_contains($uid, '@')) { $this->cache[$uid] = false; return false; } @@ -339,9 +338,7 @@ private function loadUser($uid): bool { */ public function getUsers($search = '', $limit = null, $offset = null): array { $users = $this->getDisplayNames($search, $limit, $offset); - $userIds = array_map(function ($uid) { - return (string)$uid; - }, array_keys($users)); + $userIds = array_map(fn (int|string $uid): string => (string)$uid, array_keys($users)); sort($userIds, SORT_STRING | SORT_FLAG_CASE); return $userIds; } @@ -350,7 +347,6 @@ public function getUsers($search = '', $limit = null, $offset = null): array { * check if a user exists * * @param string $uid the username - * @return bool */ public function userExists($uid): bool { $this->loadUser($uid); @@ -371,9 +367,6 @@ public function getHome(string $uid) { return false; } - /** - * @return bool - */ public function hasUserListings(): bool { return true; } @@ -416,7 +409,7 @@ public function getBackendName(): string { } public function getRealUID(string $uid): string { - if (strpos($uid, '@') === false) { + if (!str_contains($uid, '@')) { throw new \RuntimeException($uid . ' does not exist'); } diff --git a/rector.php b/rector.php new file mode 100644 index 00000000..484e82f3 --- /dev/null +++ b/rector.php @@ -0,0 +1,27 @@ +withPaths([ + __DIR__ . '/lib', + __DIR__ . '/tests', + ]) + ->withSkip([ + __DIR__ . '/tests/stubs', + ]) + ->withPreparedSets( + deadCode: true, + typeDeclarations: true, + )->withPhpSets( + php82: true, + )->withConfiguredRule(ClassPropertyAssignToConstructorPromotionRector::class, [ + 'inline_public' => true, + 'rename_property' => true, + ]); diff --git a/tests/integration/features/bootstrap/GuestsContext.php b/tests/integration/features/bootstrap/GuestsContext.php index 1d6919e0..ae52c25c 100644 --- a/tests/integration/features/bootstrap/GuestsContext.php +++ b/tests/integration/features/bootstrap/GuestsContext.php @@ -19,22 +19,18 @@ class GuestsContext implements Context, SnippetAcceptingContext { use Webdav; - /** @var array */ - private $createdGuests = []; + private array $createdGuests = []; - public function prepareUserNameAsFrontend($guestDisplayName, $guestEmail) { - $emailDomain = preg_split('/\./', preg_split('/@/', $guestEmail, null, null)[1], null, null); - $userName = $guestDisplayName . '_' . $emailDomain[0] . '_' . $emailDomain[1]; - return $userName; + public function prepareUserNameAsFrontend(string $guestDisplayName, $guestEmail) { + $emailDomain = preg_split('/\./', (string)preg_split('/@/', (string)$guestEmail, 0, null)[1], 0, null); + return $guestDisplayName . '_' . $emailDomain[0] . '_' . $emailDomain[1]; } /** * @Given user :user creates guest user :guestDisplayName with email :guestEmail * @param string $user - * @param string $guestDisplayName - * @param string $guestEmail */ - public function userCreatedAGuestUser($user, $guestDisplayName, $guestEmail) { + public function userCreatedAGuestUser($user, string $guestDisplayName, string $guestEmail): void { $fullUrl = substr($this->baseUrl, 0, -4) . '/index.php/apps/guests/users'; //Replicating frontend behaviour $userName = $this->prepareUserNameAsFrontend($guestDisplayName, $guestEmail); @@ -62,7 +58,7 @@ public function userCreatedAGuestUser($user, $guestDisplayName, $guestEmail) { * @Then check that user :user is a guest * @param string $guestDisplayName */ - public function checkGuestUser($guestDisplayName) { + public function checkGuestUser($guestDisplayName): void { $userName = $this->prepareUserNameAsFrontend($guestDisplayName, $this->createdGuests[$guestDisplayName]); $this->checkThatUserBelongsToGroup($userName, 'guest_app'); } @@ -71,41 +67,39 @@ public function checkGuestUser($guestDisplayName) { * @Then guest user :user is deleted * @param string $guestDisplayName */ - public function deleteGuestUser($guestDisplayName) { + public function deleteGuestUser($guestDisplayName): void { $userName = $this->prepareUserNameAsFrontend($guestDisplayName, $this->createdGuests[$guestDisplayName]); $this->deleteUser($userName); } /*Processes the body of an email sent and gets the reset password url It depends on the content of the email*/ - public function extractResetPasswordUrl($emailBody) { + public function extractResetPasswordUrl($emailBody): string { $knownString = 'Activate your guest account at ownCloud by setting a password: '; $nextString = 'Then view it'; - $posKnownString = strpos($emailBody, $knownString); - $posNextString = strpos($emailBody, $nextString, $posKnownString + strlen($knownString)); - $urlResetPasswd = substr($emailBody, + $posKnownString = strpos((string)$emailBody, $knownString); + $posNextString = strpos((string)$emailBody, $nextString, $posKnownString + strlen($knownString)); + $urlResetPasswd = substr((string)$emailBody, $posKnownString + strlen($knownString), $posNextString - ($posKnownString + strlen($knownString))); $urlResetPasswd = preg_replace('/[\s]+/mu', ' ', $urlResetPasswd); $urlResetPasswd = str_replace('=', '', $urlResetPasswd); - $urlResetPasswd = str_replace(' ', '', $urlResetPasswd); - return $urlResetPasswd; + return str_replace(' ', '', $urlResetPasswd); } /*Function to prepare the set password url from the reset password form one*/ - public function getSetPasswordUrl($urlResetPasswd) { - $resetUrlParts = explode('/', $urlResetPasswd); + public function getSetPasswordUrl($urlResetPasswd): string { + $resetUrlParts = explode('/', (string)$urlResetPasswd); array_splice($resetUrlParts, 5, 2, 'set'); - $urlSetPasswd = implode('/', $resetUrlParts); - return $urlSetPasswd; + return implode('/', $resetUrlParts); } /** * @Given guest user :user sets its password * @param string $guestDisplayName */ - public function guestUserSetsItsPassword($guestDisplayName) { - $userName = $this->prepareUserNameAsFrontend($guestDisplayName, $this->createdGuests[$guestDisplayName]); + public function guestUserSetsItsPassword($guestDisplayName): void { + $this->prepareUserNameAsFrontend($guestDisplayName, $this->createdGuests[$guestDisplayName]); $emails = $this->getEmails(); $lastEmailBody = $emails->items[0]->Content->Body; $resetPwUrl = $this->extractResetPasswordUrl($lastEmailBody); @@ -127,7 +121,7 @@ public function guestUserSetsItsPassword($guestDisplayName) { * @BeforeScenario * @AfterScenario */ - public function cleanupGuests() { + public function cleanupGuests(): void { foreach ($this->createdGuests as $displayName => $email) { $this->deleteGuestUser($displayName); } diff --git a/tests/stub.php b/tests/stub.php index 5c805e5b..2019005b 100644 --- a/tests/stub.php +++ b/tests/stub.php @@ -379,7 +379,17 @@ public static function cacheEntryFromData($data, IMimeTypeLoader $mimetypeLoader class CacheWrapper extends Cache { } class CachePermissionsMask extends CacheWrapper { +<<<<<<< HEAD public function __construct(\OCP\Files\Cache\ICache $cache, int $mask) { +||||||| parent of 417a8e5 (refactor: Modernize code with rector) + /** + * @param \OCP\Files\Cache\ICache $cache + * @param int $mask + */ + public function __construct($cache, $mask) { +======= + public function __construct() { +>>>>>>> 417a8e5 (refactor: Modernize code with rector) } protected function formatCacheEntry($entry) { diff --git a/tests/unit/AppWhitelistTest.php b/tests/unit/AppWhitelistTest.php index 2d8c4f6d..dbc09a83 100644 --- a/tests/unit/AppWhitelistTest.php +++ b/tests/unit/AppWhitelistTest.php @@ -26,8 +26,7 @@ class AppWhitelistTest extends TestCase { private IAppManager&MockObject $appManager; private IURLGenerator&MockObject $urlGenerator; - /** @var AppWhitelist */ - private $appWhitelist; + private ?\OCA\Guests\AppWhitelist $appWhitelist = null; protected function setUp(): void { parent::setUp(); @@ -50,7 +49,7 @@ protected function setUp(): void { ); } - public function testIsUrlAllowed() { + public function testIsUrlAllowed(): void { $this->config->method('getAppWhitelist') ->willReturn(['foo', 'bar']); $this->config->method('useWhitelist') @@ -63,7 +62,7 @@ public function testIsUrlAllowed() { $this->assertTrue($this->appWhitelist->isUrlAllowed($user, '/apps/foo/...')); } - public function testIsUrlAllowedNoWhitelist() { + public function testIsUrlAllowedNoWhitelist(): void { $this->config->method('getAppWhitelist') ->willReturn(['foo', 'bar']); $this->config->method('useWhitelist') diff --git a/tests/unit/Command/AddCommandTest.php b/tests/unit/Command/AddCommandTest.php index 52ba38fc..1ae63b31 100644 --- a/tests/unit/Command/AddCommandTest.php +++ b/tests/unit/Command/AddCommandTest.php @@ -25,10 +25,8 @@ class AddCommandTest extends TestCase { private $guestManager; /** @var IMailer|MockObject */ private $mailer; - /** @var AddCommand */ - private $command; - /** @var CommandTester */ - private $commandTester; + private ?\OCA\Guests\Command\AddCommand $command = null; + private ?\Symfony\Component\Console\Tester\CommandTester $commandTester = null; protected function setUp(): void { parent::setUp(); @@ -69,7 +67,7 @@ public function createGuestDataProvider() { /** * @dataProvider createGuestDataProvider */ - public function testCreateGuest($commandArgs) { + public function testCreateGuest($commandArgs): void { $createdByUser = $this->createMock(IUser::class); $password = 'guest-password'; @@ -101,8 +99,8 @@ public function testCreateGuest($commandArgs) { $createdByUser, 'guestid@example.com', 'guestid@example.com', - isset($commandArgs['--display-name']) ? $commandArgs['--display-name'] : '', - isset($commandArgs['--language']) ? $commandArgs['--language'] : '', + $commandArgs['--display-name'] ?? '', + $commandArgs['--language'] ?? '', $password ) ->willReturn($guestUser); @@ -113,7 +111,7 @@ public function testCreateGuest($commandArgs) { $this->assertStringContainsString('The guest account user "guestid" was created successfully', $output); } - public function testCreateGuestCreatorNotFound() { + public function testCreateGuestCreatorNotFound(): void { $this->userManager->expects($this->once()) ->method('get') ->with('creator') @@ -129,7 +127,7 @@ public function testCreateGuestCreatorNotFound() { $this->assertEquals(1, $this->commandTester->getStatusCode()); } - public function testCreateGuestAlreadyExists() { + public function testCreateGuestAlreadyExists(): void { $this->userManager->expects($this->once()) ->method('get') ->with('creator') @@ -150,7 +148,7 @@ public function testCreateGuestAlreadyExists() { $this->assertEquals(1, $this->commandTester->getStatusCode()); } - public function testCreateGuestInvalidEmail() { + public function testCreateGuestInvalidEmail(): void { $this->userManager->expects($this->once()) ->method('get') ->with('creator') diff --git a/tests/unit/ConfigTest.php b/tests/unit/ConfigTest.php index d0c0116c..566bd030 100644 --- a/tests/unit/ConfigTest.php +++ b/tests/unit/ConfigTest.php @@ -32,8 +32,7 @@ class ConfigTest extends TestCase { /** @var IGroupManager|MockObject */ private $groupManager; - /** @var Config */ - private $guestConfig; + private ?\OCA\Guests\Config $guestConfig = null; protected function setUp(): void { parent::setUp(); @@ -53,7 +52,7 @@ protected function setUp(): void { ); } - public function testAllowExternalStorage() { + public function testAllowExternalStorage(): void { $this->appConfig->method('getAppValueBool') ->with('allow_external_storage', false) ->willReturn(true); @@ -61,7 +60,7 @@ public function testAllowExternalStorage() { $this->assertTrue($this->guestConfig->allowExternalStorage()); } - public function testSetAllowExternalStorage() { + public function testSetAllowExternalStorage(): void { $this->appConfig->expects($this->exactly(2)) ->method('setAppValueBool') ->with('allow_external_storage', true); @@ -70,7 +69,7 @@ public function testSetAllowExternalStorage() { $this->guestConfig->setAllowExternalStorage('true'); } - public function testHideOtherUsers() { + public function testHideOtherUsers(): void { $this->appConfig->method('getAppValueBool') ->with('hide_users', true) ->willReturn(false); @@ -78,7 +77,7 @@ public function testHideOtherUsers() { $this->assertFalse($this->guestConfig->hideOtherUsers()); } - public function testSetHideOtherUsers() { + public function testSetHideOtherUsers(): void { $this->appConfig->expects($this->exactly(2)) ->method('setAppValueBool') ->with('hide_users', true); @@ -87,7 +86,7 @@ public function testSetHideOtherUsers() { $this->guestConfig->setHideOtherUsers('true'); } - public function testGetHome() { + public function testGetHome(): void { $this->config->method('getSystemValue') ->with('datadirectory', \OC::$SERVERROOT . '/data') ->willReturn('/custom/path'); @@ -95,7 +94,7 @@ public function testGetHome() { $this->assertEquals('/custom/path/test_user', $this->guestConfig->getHome('test_user')); } - public function testUseWhitelist() { + public function testUseWhitelist(): void { $this->appConfig->method('getAppValueBool') ->with('usewhitelist', true) ->willReturn(false); @@ -103,7 +102,7 @@ public function testUseWhitelist() { $this->assertFalse($this->guestConfig->useWhitelist()); } - public function testSetUseWhitelist() { + public function testSetUseWhitelist(): void { $this->appConfig->expects($this->exactly(2)) ->method('setAppValueBool') ->with('usewhitelist', true); @@ -112,7 +111,7 @@ public function testSetUseWhitelist() { $this->guestConfig->setUseWhitelist('true'); } - public function testGetAppWhitelist() { + public function testGetAppWhitelist(): void { $this->appConfig->method('getAppValueString') ->with('whitelist', AppWhitelist::DEFAULT_WHITELIST) ->willReturn('app1,app2,app3'); @@ -120,7 +119,7 @@ public function testGetAppWhitelist() { $this->assertEquals(['app1', 'app2', 'app3'], $this->guestConfig->getAppWhitelist()); } - public function testSetAppWhitelistArray() { + public function testSetAppWhitelistArray(): void { $this->appConfig->expects($this->exactly(2)) ->method('setAppValueString') ->with('whitelist', 'app1,app2,app3'); @@ -129,7 +128,7 @@ public function testSetAppWhitelistArray() { $this->guestConfig->setAppWhitelist('app1,app2,app3'); } - public function testIsSharingRestrictedToGroup() { + public function testIsSharingRestrictedToGroup(): void { $this->config->method('getAppValue') ->with('core', 'shareapi_only_share_with_group_members', 'no') ->willReturn('yes'); @@ -137,7 +136,7 @@ public function testIsSharingRestrictedToGroup() { $this->assertTrue($this->guestConfig->isSharingRestrictedToGroup()); } - public function testIsSharingNotRestrictedToGroup() { + public function testIsSharingNotRestrictedToGroup(): void { $this->config->method('getAppValue') ->with('core', 'shareapi_only_share_with_group_members', 'no') ->willReturn('no'); @@ -145,14 +144,14 @@ public function testIsSharingNotRestrictedToGroup() { $this->assertFalse($this->guestConfig->isSharingRestrictedToGroup()); } - public function testCanCreateGuestsNoUser() { + public function testCanCreateGuestsNoUser(): void { $this->userSession->method('getUser') ->willReturn(null); $this->assertFalse($this->guestConfig->canCreateGuests()); } - public function testCanCreateGuestsWithGroupRestrictionNoMatch() { + public function testCanCreateGuestsWithGroupRestrictionNoMatch(): void { $user = $this->createMock(IUser::class); $this->userSession->method('getUser') ->willReturn($user); @@ -168,7 +167,7 @@ public function testCanCreateGuestsWithGroupRestrictionNoMatch() { $this->assertFalse($this->guestConfig->canCreateGuests()); } - public function testCanCreateGuestsWithGroupRestrictionWithMatch() { + public function testCanCreateGuestsWithGroupRestrictionWithMatch(): void { $user = $this->createMock(IUser::class); $this->userSession->method('getUser') ->willReturn($user); @@ -188,7 +187,7 @@ public function testCanCreateGuestsWithGroupRestrictionWithMatch() { $this->assertTrue($this->guestConfig->canCreateGuests()); } - public function testCanCreateGuestsWithSharingRestrictedButIsSubAdmin() { + public function testCanCreateGuestsWithSharingRestrictedButIsSubAdmin(): void { $user = $this->createMock(IUser::class); $this->userSession->method('getUser') ->willReturn($user); @@ -208,7 +207,7 @@ public function testCanCreateGuestsWithSharingRestrictedButIsSubAdmin() { $this->assertTrue($this->guestConfig->canCreateGuests()); } - public function testCanCreateGuestsWithSharingRestrictedNotSubAdmin() { + public function testCanCreateGuestsWithSharingRestrictedNotSubAdmin(): void { $user = $this->createMock(IUser::class); $this->userSession->method('getUser') ->willReturn($user); @@ -228,7 +227,7 @@ public function testCanCreateGuestsWithSharingRestrictedNotSubAdmin() { $this->assertFalse($this->guestConfig->canCreateGuests()); } - public function testGetCreateRestrictedToGroupEmpty() { + public function testGetCreateRestrictedToGroupEmpty(): void { $this->appConfig->method('getAppValueArray') ->with('create_restricted_to_group', []) ->willReturn([]); @@ -236,7 +235,7 @@ public function testGetCreateRestrictedToGroupEmpty() { $this->assertEquals([], $this->guestConfig->getCreateRestrictedToGroup()); } - public function testGetCreateRestrictedToGroupWithAdmin() { + public function testGetCreateRestrictedToGroupWithAdmin(): void { $this->appConfig->method('getAppValueArray') ->with('create_restricted_to_group', []) ->willReturn(['admin', 'group1']); @@ -244,7 +243,7 @@ public function testGetCreateRestrictedToGroupWithAdmin() { $this->assertEquals(['admin', 'group1'], $this->guestConfig->getCreateRestrictedToGroup()); } - public function testSetCreateRestrictedToGroup() { + public function testSetCreateRestrictedToGroup(): void { $this->appConfig->expects($this->once()) ->method('setAppValueArray') ->with('create_restricted_to_group', ['group1', 'group2']); diff --git a/tests/unit/Controller/UsersControllerTest.php b/tests/unit/Controller/UsersControllerTest.php index b5ca18b9..0f42c5ba 100644 --- a/tests/unit/Controller/UsersControllerTest.php +++ b/tests/unit/Controller/UsersControllerTest.php @@ -38,7 +38,7 @@ class UsersControllerTest extends TestCase { /** @var IL10N|MockObject */ private $l10n; /** @var Config|MockObject */ - private $guestsConfig; + private ?\OCA\Guests\Config $guestsConfig = null; /** @var IMailer|MockObject */ private $mailer; /** @var GuestManager|MockObject */ @@ -60,8 +60,7 @@ class UsersControllerTest extends TestCase { /** @var InviteService|MockObject */ private $inviteService; - /** @var UsersController */ - private $controller; + private ?\OCA\Guests\Controller\UsersController $controller = null; protected function setUp(): void { parent::setUp(); @@ -89,9 +88,7 @@ protected function setUp(): void { ); $this->l10n->method('t') - ->willReturnCallback(function ($text) { - return $text; - }); + ->willReturnCallback(fn ($text) => $text); $this->controller = new UsersController( 'guests', @@ -113,7 +110,7 @@ protected function setUp(): void { /** * Test that creation fails when the current user is a guest. */ - public function testCreateWhenCurrentUserIsGuest() { + public function testCreateWhenCurrentUserIsGuest(): void { $currentUser = $this->createMock(IUser::class); $this->userSession->method('getUser') ->willReturn($currentUser); @@ -133,7 +130,7 @@ public function testCreateWhenCurrentUserIsGuest() { /** * Test that creation fails when the user is not logged in. */ - public function testCreateFailsWithNoUserSession() { + public function testCreateFailsWithNoUserSession(): void { // Mock user session to return null (no logged-in user) $this->userSession->method('getUser') ->willReturn(null); @@ -149,7 +146,7 @@ public function testCreateFailsWithNoUserSession() { /** * Test that creation fails when user is not in allowed groups */ - public function testCreateFailsWhenUserNotInAllowedGroups() { + public function testCreateFailsWhenUserNotInAllowedGroups(): void { // Mock current user $currentUser = $this->createMock(IUser::class); $currentUser->method('getUID') @@ -180,7 +177,7 @@ public function testCreateFailsWhenUserNotInAllowedGroups() { /** * Test that admin users can always create guests regardless of group restrictions */ - public function testCreateSucceedsForAdminDespiteGroupRestrictions() { + public function testCreateSucceedsForAdminDespiteGroupRestrictions(): void { // Mock current user $currentUser = $this->createMock(IUser::class); $currentUser->method('getUID') @@ -232,7 +229,7 @@ public function testCreateSucceedsForAdminDespiteGroupRestrictions() { /** * Test that creation succeeds when user is in one of the allowed groups */ - public function testCreateSucceedsWhenUserInAllowedGroup() { + public function testCreateSucceedsWhenUserInAllowedGroup(): void { // Mock current user $currentUser = $this->createMock(IUser::class); $currentUser->method('getUID') @@ -279,7 +276,7 @@ public function testCreateSucceedsWhenUserInAllowedGroup() { /** * Test that SubAdmin can create guests when sharing is restricted to group */ - public function testCreateSucceedsForSubAdminWhenSharingIsRestricted() { + public function testCreateSucceedsForSubAdminWhenSharingIsRestricted(): void { // Mock current user $currentUser = $this->createMock(IUser::class); $currentUser->method('getUID') @@ -344,7 +341,7 @@ public function testCreateSucceedsForSubAdminWhenSharingIsRestricted() { /** * Test that non-SubAdmin cannot create guests when sharing is restricted to group */ - public function testCreateFailsForNonSubAdminWhenSharingIsRestricted() { + public function testCreateFailsForNonSubAdminWhenSharingIsRestricted(): void { // Mock current user $currentUser = $this->createMock(IUser::class); $currentUser->method('getUID') @@ -380,7 +377,7 @@ public function testCreateFailsForNonSubAdminWhenSharingIsRestricted() { /** * Test that creation succeeds when there are no restrictions */ - public function testCreateSucceedsWhenNoRestrictions() { + public function testCreateSucceedsWhenNoRestrictions(): void { // Mock current user $currentUser = $this->createMock(IUser::class); $currentUser->method('getUID') @@ -427,7 +424,7 @@ public function testCreateSucceedsWhenNoRestrictions() { /** * Test that creation fails when sharing is restricted to group but no groups are provided */ - public function testCreateWhenSharingRestrictedToGroupButNoGroups() { + public function testCreateWhenSharingRestrictedToGroupButNoGroups(): void { $currentUser = $this->createMock(IUser::class); $currentUser->method('getUID') ->willReturn('admin_user'); @@ -465,7 +462,7 @@ public function testCreateWhenSharingRestrictedToGroupButNoGroups() { /** * Test that creation fails when group does not exist */ - public function testCreateWithNonExistentGroup() { + public function testCreateWithNonExistentGroup(): void { $currentUser = $this->createMock(IUser::class); $currentUser->method('getUID') ->willReturn('admin_user'); @@ -502,7 +499,7 @@ public function testCreateWithNonExistentGroup() { /** * Test that creation fails when user is subadmin, but is not a subadmin of the group */ - public function testCreateWithGroupButNotSubAdmin() { + public function testCreateWithGroupButNotSubAdmin(): void { $currentUser = $this->createMock(IUser::class); $currentUser->method('getUID') ->willReturn('current_user'); @@ -551,7 +548,7 @@ public function testCreateWithGroupButNotSubAdmin() { /** * Test that creation fails when email is invalid */ - public function testCreateWithInvalidEmail() { + public function testCreateWithInvalidEmail(): void { $currentUser = $this->createMock(IUser::class); $currentUser->method('getUID') ->willReturn('current_user'); @@ -580,7 +577,7 @@ public function testCreateWithInvalidEmail() { /** * Test that creation fails when user with the same email already exists */ - public function testCreateWithExistingEmailUser() { + public function testCreateWithExistingEmailUser(): void { $currentUser = $this->createMock(IUser::class); $currentUser->method('getUID') ->willReturn('current_user'); @@ -610,7 +607,7 @@ public function testCreateWithExistingEmailUser() { /** * Test that creation fails when user with the same username already exists */ - public function testCreateWithExistingUsernameUser() { + public function testCreateWithExistingUsernameUser(): void { $currentUser = $this->createMock(IUser::class); $currentUser->method('getUID') ->willReturn('current_user'); @@ -646,7 +643,7 @@ public function testCreateWithExistingUsernameUser() { * Enforcing group restrictions won't have any effect * since the user is a subadmin and can create guests anyway. */ - public function testCreateSuccessWithGroupsAsSubadmin() { + public function testCreateSuccessWithGroupsAsSubadmin(): void { $currentUser = $this->createMock(IUser::class); $currentUser->method('getUID') ->willReturn('current_user'); @@ -731,7 +728,7 @@ public function testCreateSuccessWithGroupsAsSubadmin() { * This is a generic test to ensure that the controller * handles exceptions correctly. */ - public function testCreateException() { + public function testCreateException(): void { $currentUser = $this->createMock(IUser::class); $currentUser->method('getUID') ->willReturn('current_user'); diff --git a/tests/unit/GroupBackendTest.php b/tests/unit/GroupBackendTest.php index e4382fa3..c0596c9d 100644 --- a/tests/unit/GroupBackendTest.php +++ b/tests/unit/GroupBackendTest.php @@ -24,8 +24,7 @@ class GroupBackendTest extends TestCase { /** @var IUserSession|MockObject */ private $userSession; - /** @var GroupBackend */ - private $backend; + private ?\OCA\Guests\GroupBackend $backend = null; protected function setUp(): void { parent::setUp(); @@ -41,7 +40,7 @@ protected function setUp(): void { ); } - private function setUID(string $uid) { + private function setUID(string $uid): void { $user = $this->createMock(IUser::class); $user->method('getUID') ->willReturn($uid); @@ -50,12 +49,12 @@ private function setUID(string $uid) { ->willReturn($user); } - private function setGuests(array $uids) { + private function setGuests(array $uids): void { $this->guestManager->method('listGuests') ->willReturn($uids); $this->guestManager->method('isGuest') - ->willReturnCallback(function ($uid) use ($uids) { + ->willReturnCallback(function ($uid) use ($uids): bool { if ($uid === null) { $user = $this->userSession->getUser(); if ($user) { @@ -67,19 +66,19 @@ private function setGuests(array $uids) { }); } - public function testUsersInDifferentGroup() { + public function testUsersInDifferentGroup(): void { $this->setGuests(['foo', 'bar']); $this->assertEquals([], $this->backend->usersInGroup('foo')); } - public function testUsersInGroup() { + public function testUsersInGroup(): void { $this->setGuests(['foo', 'bar']); $this->assertEquals(['foo', 'bar'], $this->backend->usersInGroup('guest_app')); } - public function testUsersInGroupHideOthersAsGuest() { + public function testUsersInGroupHideOthersAsGuest(): void { $this->setGuests(['foo', 'bar']); $this->setUID('foo'); @@ -90,7 +89,7 @@ public function testUsersInGroupHideOthersAsGuest() { $this->assertEquals(['foo'], $this->backend->usersInGroup('guest_app')); } - public function testUsersInGroupHideOthersAsNonGuest() { + public function testUsersInGroupHideOthersAsNonGuest(): void { $this->setGuests(['foo', 'bar']); $this->setUID('someone'); @@ -101,14 +100,14 @@ public function testUsersInGroupHideOthersAsNonGuest() { $this->assertEquals(['foo', 'bar'], $this->backend->usersInGroup('guest_app')); } - public function testInGroup() { + public function testInGroup(): void { $this->setGuests(['foo', 'bar']); $this->assertTrue($this->backend->inGroup('foo', 'guest_app')); $this->assertFalse($this->backend->inGroup('other', 'guest_app')); } - public function testInGroupHideOthers() { + public function testInGroupHideOthers(): void { $this->setGuests(['foo', 'bar']); $this->setUID('foo'); @@ -121,14 +120,14 @@ public function testInGroupHideOthers() { $this->assertFalse($this->backend->inGroup('other', 'guest_app')); } - public function testGetUserGroups() { + public function testGetUserGroups(): void { $this->setGuests(['foo', 'bar']); $this->assertEquals(['guest_app'], $this->backend->getUserGroups('foo')); $this->assertEquals([], $this->backend->getUserGroups('other')); } - public function testGetUserGroupsHideOthers() { + public function testGetUserGroupsHideOthers(): void { $this->setGuests(['foo', 'bar']); $this->setUID('foo'); diff --git a/tests/unit/GuestManagerTest.php b/tests/unit/GuestManagerTest.php index 696958a1..b586e466 100644 --- a/tests/unit/GuestManagerTest.php +++ b/tests/unit/GuestManagerTest.php @@ -42,8 +42,7 @@ class GuestManagerTest extends TestCase { /** @var IEventDispatcher|MockObject */ private $eventDispatcher; - /** @var GuestManager */ - private $guestManager; + private ?\OCA\Guests\GuestManager $guestManager = null; protected function setUp(): void { parent::setUp(); @@ -54,14 +53,10 @@ protected function setUp(): void { $this->config = $this->createMock(IConfig::class); $this->random = $this->createMock(ISecureRandom::class); $this->random->method('generate') - ->willReturnCallback(function ($count) { - return str_repeat('4', $count); - }); + ->willReturnCallback(fn ($count) => str_repeat('4', $count)); $this->crypto = $this->createMock(ICrypto::class); $this->crypto->method('encrypt') - ->willReturnCallback(function ($plain) { - return $plain; - }); + ->willReturnCallback(fn ($plain) => $plain); $this->shareManager = $this->createMock(IManager::class); $this->conneciton = $this->createMock(IDBConnection::class); $this->eventDispatcher = $this->createMock(IEventDispatcher::class); @@ -79,21 +74,17 @@ protected function setUp(): void { ); } - public function testIsGuestString() { + public function testIsGuestString(): void { $this->userBackend->method('userExists') - ->willReturnCallback(function ($uid) { - return $uid === 'test_guest'; - }); + ->willReturnCallback(fn ($uid): bool => $uid === 'test_guest'); $this->assertTrue($this->guestManager->isGuest('test_guest')); $this->assertFalse($this->guestManager->isGuest('foo')); } - public function testIsGuestObject() { + public function testIsGuestObject(): void { $this->userBackend->method('userExists') - ->willReturnCallback(function ($uid) { - return $uid === 'test_guest'; - }); + ->willReturnCallback(fn ($uid): bool => $uid === 'test_guest'); $user = $this->createMock(IUser::class); $user->method('getUID') @@ -107,11 +98,9 @@ public function testIsGuestObject() { $this->assertFalse($this->guestManager->isGuest($user)); } - public function testIsGuestNull() { + public function testIsGuestNull(): void { $this->userBackend->method('userExists') - ->willReturnCallback(function ($uid) { - return $uid === 'test_guest'; - }); + ->willReturnCallback(fn ($uid): bool => $uid === 'test_guest'); $user = $this->createMock(IUser::class); $user->method('getUID') @@ -135,10 +124,10 @@ public function testIsGuestNull() { $this->assertFalse($this->guestManager->isGuest($user)); } - public function testCreateGuest() { + public function testCreateGuest(): void { $setValues = []; $this->config->method('setUserValue') - ->willReturnCallback(function ($user, $app, $key, $value) use (&$setValues) { + ->willReturnCallback(function ($user, $app, $key, $value) use (&$setValues): void { if (!isset($setValues[$app])) { $setValues[$app] = []; } @@ -160,11 +149,11 @@ public function testCreateGuest() { ->method('setDisplayName') ->with('Example Guest'); $guestUser->method('setSystemEMailAddress') - ->willReturnCallback(function ($email) { + ->willReturnCallback(function ($email): void { $this->config->setUserValue('guest@example.com', 'settings', 'email', $email); }); $guestUser->method('setQuota') - ->willReturnCallback(function ($quota) { + ->willReturnCallback(function ($quota): void { $this->config->setUserValue('guest@example.com', 'files', 'quota', $quota); }); diff --git a/tests/unit/Storage/DirMaskTest.php b/tests/unit/Storage/DirMaskTest.php index 4f5a4b5f..2b0313c1 100644 --- a/tests/unit/Storage/DirMaskTest.php +++ b/tests/unit/Storage/DirMaskTest.php @@ -17,7 +17,7 @@ * @group DB */ class DirMaskTest extends TestCase { - public function testReadonlyDir() { + public function testReadonlyDir(): void { $storage = new Temporary([]); $storage->mkdir('readonly'); diff --git a/tests/unit/UserBackendTest.php b/tests/unit/UserBackendTest.php index 5f14fd5d..e2926566 100644 --- a/tests/unit/UserBackendTest.php +++ b/tests/unit/UserBackendTest.php @@ -21,10 +21,9 @@ class UserBackendTest extends TestCase { /** @var Config|MockObject */ private $config; - /** @var UserBackend */ - private $backend; + private ?\OCA\Guests\UserBackend $backend = null; - private function clearGuests() { + private function clearGuests(): void { $query = \OC::$server->getDatabaseConnection()->getQueryBuilder(); $query->delete('guests_users')->executeStatement(); @@ -51,14 +50,14 @@ protected function tearDown(): void { parent::tearDown(); } - public function testCreate() { + public function testCreate(): void { $this->backend->createUser('foo@example.tld', 'bar'); $this->assertTrue($this->backend->userExists('foo@example.tld')); $this->assertEquals(['foo@example.tld'], $this->backend->getUsers()); } - public function testNoListing() { + public function testNoListing(): void { $this->backend->createUser('foo@example.tld', 'bar'); $this->assertTrue($this->backend->userExists('foo@example.tld')); diff --git a/vendor-bin/rector/composer.json b/vendor-bin/rector/composer.json new file mode 100644 index 00000000..8592ef65 --- /dev/null +++ b/vendor-bin/rector/composer.json @@ -0,0 +1,5 @@ +{ + "require-dev": { + "rector/rector": "^2.0" + } +} diff --git a/vendor-bin/rector/composer.lock b/vendor-bin/rector/composer.lock new file mode 100644 index 00000000..5ccbd7b2 --- /dev/null +++ b/vendor-bin/rector/composer.lock @@ -0,0 +1,132 @@ +{ + "_readme": [ + "This file locks the dependencies of your project to a known state", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", + "This file is @generated automatically" + ], + "content-hash": "57211dc5c619d183df6361f5d7d57fe5", + "packages": [], + "packages-dev": [ + { + "name": "phpstan/phpstan", + "version": "2.1.36", + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/2132e5e2361d11d40af4c17faa16f043269a4cf3", + "reference": "2132e5e2361d11d40af4c17faa16f043269a4cf3", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "docs": "https://phpstan.org/user-guide/getting-started", + "forum": "https://github.com/phpstan/phpstan/discussions", + "issues": "https://github.com/phpstan/phpstan/issues", + "security": "https://github.com/phpstan/phpstan/security/policy", + "source": "https://github.com/phpstan/phpstan-src" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + } + ], + "time": "2026-01-21T13:58:26+00:00" + }, + { + "name": "rector/rector", + "version": "2.3.4", + "source": { + "type": "git", + "url": "https://github.com/rectorphp/rector.git", + "reference": "9227d7a24b0f23ae941057509364f948d5da9ab2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/9227d7a24b0f23ae941057509364f948d5da9ab2", + "reference": "9227d7a24b0f23ae941057509364f948d5da9ab2", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "phpstan/phpstan": "^2.1.36" + }, + "conflict": { + "rector/rector-doctrine": "*", + "rector/rector-downgrade-php": "*", + "rector/rector-phpunit": "*", + "rector/rector-symfony": "*" + }, + "suggest": { + "ext-dom": "To manipulate phpunit.xml via the custom-rule command" + }, + "bin": [ + "bin/rector" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Instant Upgrade and Automated Refactoring of any PHP code", + "homepage": "https://getrector.com/", + "keywords": [ + "automation", + "dev", + "migration", + "refactoring" + ], + "support": { + "issues": "https://github.com/rectorphp/rector/issues", + "source": "https://github.com/rectorphp/rector/tree/2.3.4" + }, + "funding": [ + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2026-01-21T14:49:03+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +} From 9d9513f03bde1eb61d2d88078056a18bff3b847d Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Fri, 6 Feb 2026 16:59:53 +0100 Subject: [PATCH 2/4] refactor(rector): Run with nextcloud set Signed-off-by: Carl Schwan --- REUSE.toml | 2 +- lib/Controller/APIController.php | 3 +- lib/Controller/UsersController.php | 7 +- lib/FilteredSettingsManager.php | 11 +- lib/GroupBackend.php | 12 +- lib/Hooks.php | 2 +- lib/Mail.php | 8 +- lib/RestrictionManager.php | 10 +- lib/Settings/Admin.php | 3 +- lib/Storage/DirMask.php | 13 +- lib/Storage/DirMaskCache.php | 7 +- rector.php | 13 +- .../features/bootstrap/GuestsContext.php | 16 +- tests/stub.php | 10 - tests/unit/AppWhitelistTest.php | 2 +- tests/unit/Command/AddCommandTest.php | 4 +- tests/unit/ConfigTest.php | 2 +- tests/unit/Controller/UsersControllerTest.php | 4 +- tests/unit/GroupBackendTest.php | 2 +- tests/unit/GuestManagerTest.php | 2 +- tests/unit/UserBackendTest.php | 11 +- vendor-bin/rector/composer.json | 3 +- vendor-bin/rector/composer.lock | 376 +++++++++++++++++- 23 files changed, 443 insertions(+), 80 deletions(-) diff --git a/REUSE.toml b/REUSE.toml index d5d8eee9..533b7089 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -30,7 +30,7 @@ SPDX-FileCopyrightText = "2018 Nextcloud GmbH and Nextcloud contributors" SPDX-License-Identifier = "AGPL-3.0-or-later" [[annotations]] -path = ["composer.json", "composer.lock"] +path = ["composer.json", "composer.lock", "vendor-bin/*/composer.json", "vendor-bin/*/composer.lock"] precedence = "aggregate" SPDX-FileCopyrightText = "2019 Nextcloud GmbH and Nextcloud contributors" SPDX-License-Identifier = "AGPL-3.0-or-later" diff --git a/lib/Controller/APIController.php b/lib/Controller/APIController.php index e3b57477..1641f493 100644 --- a/lib/Controller/APIController.php +++ b/lib/Controller/APIController.php @@ -10,6 +10,7 @@ use OC\L10N\Factory; use OCA\Guests\AppInfo\Application; +use OCA\Guests\Config; use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; @@ -24,7 +25,7 @@ class APIController extends OCSController { public function __construct( IRequest $request, private readonly IUserSession $userSession, - private readonly \OCA\Guests\Config $config, + private readonly Config $config, private readonly IFactory $l10nFactory, private readonly ISubAdmin $subAdmin, private readonly IGroupManager $groupManager, diff --git a/lib/Controller/UsersController.php b/lib/Controller/UsersController.php index f009f7d2..660dd16d 100644 --- a/lib/Controller/UsersController.php +++ b/lib/Controller/UsersController.php @@ -18,6 +18,7 @@ use OCA\Guests\TransferService; use OCP\AppFramework\Db\DoesNotExistException; use OCP\AppFramework\Http; +use OCP\AppFramework\Http\Attribute\NoAdminRequired; use OCP\AppFramework\Http\DataResponse; use OCP\AppFramework\OCSController; use OCP\Group\ISubAdmin; @@ -48,9 +49,7 @@ public function __construct( parent::__construct($appName, $request); } - /** - * @NoAdminRequired - */ + #[NoAdminRequired] public function create(string $email, string $displayName, string $language, array $groups, bool $sendInvite = true): DataResponse { $errorMessages = []; $currentUser = $this->userSession->getUser(); @@ -208,7 +207,7 @@ public function transfer(string $guestUserId, string $targetUserId): DataRespons try { $transfer = $this->transferMapper->getBySource($sourceUser->getUID()); - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { // Allow as this just means there is no pending transfer } diff --git a/lib/FilteredSettingsManager.php b/lib/FilteredSettingsManager.php index 5ce8712b..0c1843ce 100644 --- a/lib/FilteredSettingsManager.php +++ b/lib/FilteredSettingsManager.php @@ -7,24 +7,21 @@ namespace OCA\Guests; +use OC\AppFramework\App; use OCP\IUser; use OCP\Settings\IIconSection; use OCP\Settings\IManager; class FilteredSettingsManager implements IManager { - /** @var IManager */ - private $manager; - public function __construct( - IManager $manager, - private readonly \OCA\Guests\AppWhitelist $appWhitelist, + private readonly IManager $manager, + private readonly AppWhitelist $appWhitelist, ) { - $this->manager = $manager; } private function isSettingAllowed(string $setting): bool { - $appId = \OC\AppFramework\App::getAppIdForClass($setting); + $appId = App::getAppIdForClass($setting); return $this->appWhitelist->isAppWhitelisted($appId); } diff --git a/lib/GroupBackend.php b/lib/GroupBackend.php index 02758f46..e5aac896 100644 --- a/lib/GroupBackend.php +++ b/lib/GroupBackend.php @@ -21,18 +21,14 @@ */ class GroupBackend extends ABackend implements ICountUsersBackend, IGroupDetailsBackend, IHideFromCollaborationBackend { /** @var string[] */ - private $guestMembers = []; - - /** @var IUserSession */ - private $userSession; + private array $guestMembers = []; public function __construct( - private readonly \OCA\Guests\GuestManager $guestManager, - private readonly \OCA\Guests\Config $config, - IUserSession $userSession, + private readonly GuestManager $guestManager, + private readonly Config $config, + private readonly IUserSession $userSession, private readonly string $groupName = 'guest_app', ) { - $this->userSession = $userSession; } private function getMembers(): array { diff --git a/lib/Hooks.php b/lib/Hooks.php index 33bba82d..398863bd 100644 --- a/lib/Hooks.php +++ b/lib/Hooks.php @@ -82,7 +82,7 @@ public function setupReadonlyFilesystem(array $params): void { $user = $this->userManager->get($uid); if ($user && $this->guestManager->isGuest($user)) { - Filesystem::addStorageWrapper('guests.readonly', function ($mountPoint, IStorage $storage) use ($uid): \OCA\Guests\Storage\ReadOnlyJail|\OCP\Files\Storage\IStorage { + Filesystem::addStorageWrapper('guests.readonly', function ($mountPoint, IStorage $storage) use ($uid): ReadOnlyJail|IStorage { if ($mountPoint === "/$uid/") { return new ReadOnlyJail([ 'storage' => $storage, diff --git a/lib/Mail.php b/lib/Mail.php index 4fcf51bf..7f12949e 100644 --- a/lib/Mail.php +++ b/lib/Mail.php @@ -15,7 +15,7 @@ use OCP\IUserSession; use OCP\L10N\IFactory; use OCP\Mail\IMailer; -use OCP\Share; +use OCP\Share\IShare; use OCP\Util; class Mail { @@ -37,7 +37,7 @@ public function __construct( * @param $uid * @throws \Exception */ - public function sendGuestInviteMail(string $uid, string $guest, string $token, string $language = '', ?Share\IShare $share = null): void { + public function sendGuestInviteMail(string $uid, string $guest, string $token, string $language = '', ?IShare $share = null): void { if ($language === '') { $language = null; } @@ -56,7 +56,7 @@ public function sendGuestInviteMail(string $uid, string $guest, string $token, s $replyTo = $this->userManager->get($uid)->getEMailAddress(); $senderDisplayName = $this->userSession->getUser()->getDisplayName(); - if (!$share instanceof \OCP\Share\IShare) { + if (!$share instanceof IShare) { [ $subject, $emailTemplate ] = $this->composeInviteMessage($senderDisplayName, $guestEmail, $passwordLink, $l10n); } else { [ $subject, $emailTemplate ] = $this->composeShareMessage($share, $senderDisplayName, $guestEmail, $passwordLink, $l10n); @@ -88,7 +88,7 @@ public function sendGuestInviteMail(string $uid, string $guest, string $token, s } } - private function composeShareMessage(Share\IShare $share, string $senderDisplayName, string $guestEmail, string $passwordLink, IL10N $l10n): array { + private function composeShareMessage(IShare $share, string $senderDisplayName, string $guestEmail, string $passwordLink, IL10N $l10n): array { $filename = trim($share->getTarget(), '/'); $subject = $l10n->t('%s shared a file with you', [$senderDisplayName]); $expiration = $share->getExpirationDate(); diff --git a/lib/RestrictionManager.php b/lib/RestrictionManager.php index d8df4a0c..e3f68901 100644 --- a/lib/RestrictionManager.php +++ b/lib/RestrictionManager.php @@ -17,7 +17,9 @@ use OCP\IServerContainer; use OCP\IUser; use OCP\IUserSession; +use OCP\Server; use OCP\Settings\IManager; +use OCP\Util; use Psr\Log\LoggerInterface; class RestrictionManager { @@ -50,18 +52,18 @@ public function setupRestrictions(): void { } if ($this->guestManager->isGuest($user)) { - \OCP\Util::connectHook('OC_Filesystem', 'preSetup', $this->hooks, 'setupReadonlyFilesystem'); + Util::connectHook('OC_Filesystem', 'preSetup', $this->hooks, 'setupReadonlyFilesystem'); if (!$this->config->allowExternalStorage()) { $this->mountProviderCollection->registerMountFilter(fn (IMountPoint $mountPoint, IUser $user): bool => !($mountPoint instanceof ExternalMountPoint && $this->guestManager->isGuest($user))); } /** @var NavigationManager $navManager */ - $navManager = \OCP\Server::get(INavigationManager::class); + $navManager = Server::get(INavigationManager::class); - $this->server->registerService(INavigationManager::class, fn (): \OCA\Guests\FilteredNavigationManager => new FilteredNavigationManager($user, $navManager, $this->whitelist)); + $this->server->registerService(INavigationManager::class, fn (): FilteredNavigationManager => new FilteredNavigationManager($user, $navManager, $this->whitelist)); $settingsManager = $this->server->get(IManager::class); - $this->server->registerService(IManager::class, fn (): \OCA\Guests\FilteredSettingsManager => new FilteredSettingsManager($settingsManager, $this->whitelist)); + $this->server->registerService(IManager::class, fn (): FilteredSettingsManager => new FilteredSettingsManager($settingsManager, $this->whitelist)); } } diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index 5792db9e..5e46dfb8 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -9,9 +9,10 @@ namespace OCA\Guests\Settings; use OCP\AppFramework\Http\TemplateResponse; +use OCP\Settings\ISettings; use OCP\Util; -class Admin implements \OCP\Settings\ISettings { +class Admin implements ISettings { /** * {@inheritdoc} */ diff --git a/lib/Storage/DirMask.php b/lib/Storage/DirMask.php index 7d8d76b1..2694ee05 100644 --- a/lib/Storage/DirMask.php +++ b/lib/Storage/DirMask.php @@ -28,20 +28,17 @@ class DirMask extends PermissionsMask { */ private readonly int $pathLength; - private $mask; - /** - * @param array $arguments ['storage' => $storage, 'mask' => $mask, 'path' => $path] + * @param array $parameters ['storage' => $storage, 'mask' => $mask, 'path' => $path] * * $storage: The storage the permissions mask should be applied on * $mask: The permission bits that should be kept, a combination of the \OCP\Constant::PERMISSION_ constants * $path: The path relative to the storage root that should be masked */ - public function __construct($arguments) { - parent::__construct($arguments); - $this->path = rtrim((string)$arguments['path'], '/'); - $this->pathLength = strlen((string)$arguments['path']); - $this->mask = $arguments['mask']; + public function __construct($parameters) { + parent::__construct($parameters); + $this->path = rtrim((string)$parameters['path'], '/'); + $this->pathLength = strlen((string)$parameters['path']); } protected function checkPath(string $path): bool { diff --git a/lib/Storage/DirMaskCache.php b/lib/Storage/DirMaskCache.php index f5f03dd3..f804a1b6 100644 --- a/lib/Storage/DirMaskCache.php +++ b/lib/Storage/DirMaskCache.php @@ -9,15 +9,12 @@ namespace OCA\Guests\Storage; use OC\Files\Cache\Wrapper\CachePermissionsMask; +use OCP\Files\Cache\ICache; class DirMaskCache extends CachePermissionsMask { private $checkPath; - /** - * @param \OCP\Files\Cache\ICache $cache - * @param int $mask - */ - public function __construct($cache, $mask, callable $checkPath) { + public function __construct(ICache $cache, int $mask, callable $checkPath) { parent::__construct($cache, $mask); $this->checkPath = $checkPath; } diff --git a/rector.php b/rector.php index 484e82f3..bd8e9077 100644 --- a/rector.php +++ b/rector.php @@ -5,8 +5,10 @@ * SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ +use Nextcloud\Rector\Set\NextcloudSets; use Rector\Config\RectorConfig; use Rector\Php80\Rector\Class_\ClassPropertyAssignToConstructorPromotionRector; +use Rector\PHPUnit\Set\PHPUnitSetList; return RectorConfig::configure() ->withPaths([ @@ -14,14 +16,21 @@ __DIR__ . '/tests', ]) ->withSkip([ - __DIR__ . '/tests/stubs', + __DIR__ . '/tests/stub.php', ]) + ->withImportNames( + importShortClasses: false, + ) ->withPreparedSets( deadCode: true, typeDeclarations: true, )->withPhpSets( - php82: true, + php81: true, )->withConfiguredRule(ClassPropertyAssignToConstructorPromotionRector::class, [ 'inline_public' => true, 'rename_property' => true, + ]) + ->withSets([ + NextcloudSets::NEXTCLOUD_30, + PHPUnitSetList::PHPUNIT_100, ]); diff --git a/tests/integration/features/bootstrap/GuestsContext.php b/tests/integration/features/bootstrap/GuestsContext.php index ae52c25c..41b8602e 100644 --- a/tests/integration/features/bootstrap/GuestsContext.php +++ b/tests/integration/features/bootstrap/GuestsContext.php @@ -5,10 +5,11 @@ * SPDX-FileCopyrightText: 2017 ownCloud GmbH * SPDX-License-Identifier: AGPL-3.0-only AND (AGPL-3.0-or-later OR AGPL-3.0-only) */ - use Behat\Behat\Context\Context; use Behat\Behat\Context\SnippetAcceptingContext; use GuzzleHttp\Client; +use GuzzleHttp\Exception\BadResponseException; +use GuzzleHttp\Exception\ClientException; require __DIR__ . '/../../vendor/autoload.php'; @@ -47,7 +48,7 @@ public function userCreatedAGuestUser($user, string $guestDisplayName, string $g try { $this->response = $client->send($request); - } catch (\GuzzleHttp\Exception\BadResponseException $e) { + } catch (BadResponseException $e) { // 4xx and 5xx responses cause an exception $this->response = $e->getResponse(); } @@ -56,18 +57,16 @@ public function userCreatedAGuestUser($user, string $guestDisplayName, string $g /** * @Then check that user :user is a guest - * @param string $guestDisplayName */ - public function checkGuestUser($guestDisplayName): void { + public function checkGuestUser(string $guestDisplayName): void { $userName = $this->prepareUserNameAsFrontend($guestDisplayName, $this->createdGuests[$guestDisplayName]); $this->checkThatUserBelongsToGroup($userName, 'guest_app'); } /** * @Then guest user :user is deleted - * @param string $guestDisplayName */ - public function deleteGuestUser($guestDisplayName): void { + public function deleteGuestUser(string $guestDisplayName): void { $userName = $this->prepareUserNameAsFrontend($guestDisplayName, $this->createdGuests[$guestDisplayName]); $this->deleteUser($userName); } @@ -96,9 +95,8 @@ public function getSetPasswordUrl($urlResetPasswd): string { /** * @Given guest user :user sets its password - * @param string $guestDisplayName */ - public function guestUserSetsItsPassword($guestDisplayName): void { + public function guestUserSetsItsPassword(string $guestDisplayName): void { $this->prepareUserNameAsFrontend($guestDisplayName, $this->createdGuests[$guestDisplayName]); $emails = $this->getEmails(); $lastEmailBody = $emails->items[0]->Content->Body; @@ -112,7 +110,7 @@ public function guestUserSetsItsPassword($guestDisplayName): void { ]; try { $this->response = $client->send($client->createRequest('POST', $urlSetPasswd, $options)); - } catch (\GuzzleHttp\Exception\ClientException $ex) { + } catch (ClientException $ex) { $this->response = $ex->getResponse(); } } diff --git a/tests/stub.php b/tests/stub.php index 2019005b..5c805e5b 100644 --- a/tests/stub.php +++ b/tests/stub.php @@ -379,17 +379,7 @@ public static function cacheEntryFromData($data, IMimeTypeLoader $mimetypeLoader class CacheWrapper extends Cache { } class CachePermissionsMask extends CacheWrapper { -<<<<<<< HEAD public function __construct(\OCP\Files\Cache\ICache $cache, int $mask) { -||||||| parent of 417a8e5 (refactor: Modernize code with rector) - /** - * @param \OCP\Files\Cache\ICache $cache - * @param int $mask - */ - public function __construct($cache, $mask) { -======= - public function __construct() { ->>>>>>> 417a8e5 (refactor: Modernize code with rector) } protected function formatCacheEntry($entry) { diff --git a/tests/unit/AppWhitelistTest.php b/tests/unit/AppWhitelistTest.php index dbc09a83..2dcb32e3 100644 --- a/tests/unit/AppWhitelistTest.php +++ b/tests/unit/AppWhitelistTest.php @@ -26,7 +26,7 @@ class AppWhitelistTest extends TestCase { private IAppManager&MockObject $appManager; private IURLGenerator&MockObject $urlGenerator; - private ?\OCA\Guests\AppWhitelist $appWhitelist = null; + private ?AppWhitelist $appWhitelist = null; protected function setUp(): void { parent::setUp(); diff --git a/tests/unit/Command/AddCommandTest.php b/tests/unit/Command/AddCommandTest.php index 1ae63b31..70c716d1 100644 --- a/tests/unit/Command/AddCommandTest.php +++ b/tests/unit/Command/AddCommandTest.php @@ -25,8 +25,8 @@ class AddCommandTest extends TestCase { private $guestManager; /** @var IMailer|MockObject */ private $mailer; - private ?\OCA\Guests\Command\AddCommand $command = null; - private ?\Symfony\Component\Console\Tester\CommandTester $commandTester = null; + private ?AddCommand $command = null; + private ?CommandTester $commandTester = null; protected function setUp(): void { parent::setUp(); diff --git a/tests/unit/ConfigTest.php b/tests/unit/ConfigTest.php index 566bd030..797a5245 100644 --- a/tests/unit/ConfigTest.php +++ b/tests/unit/ConfigTest.php @@ -32,7 +32,7 @@ class ConfigTest extends TestCase { /** @var IGroupManager|MockObject */ private $groupManager; - private ?\OCA\Guests\Config $guestConfig = null; + private ?Config $guestConfig = null; protected function setUp(): void { parent::setUp(); diff --git a/tests/unit/Controller/UsersControllerTest.php b/tests/unit/Controller/UsersControllerTest.php index 0f42c5ba..c21cd986 100644 --- a/tests/unit/Controller/UsersControllerTest.php +++ b/tests/unit/Controller/UsersControllerTest.php @@ -38,7 +38,7 @@ class UsersControllerTest extends TestCase { /** @var IL10N|MockObject */ private $l10n; /** @var Config|MockObject */ - private ?\OCA\Guests\Config $guestsConfig = null; + private ?Config $guestsConfig = null; /** @var IMailer|MockObject */ private $mailer; /** @var GuestManager|MockObject */ @@ -60,7 +60,7 @@ class UsersControllerTest extends TestCase { /** @var InviteService|MockObject */ private $inviteService; - private ?\OCA\Guests\Controller\UsersController $controller = null; + private ?UsersController $controller = null; protected function setUp(): void { parent::setUp(); diff --git a/tests/unit/GroupBackendTest.php b/tests/unit/GroupBackendTest.php index c0596c9d..c364b2d3 100644 --- a/tests/unit/GroupBackendTest.php +++ b/tests/unit/GroupBackendTest.php @@ -24,7 +24,7 @@ class GroupBackendTest extends TestCase { /** @var IUserSession|MockObject */ private $userSession; - private ?\OCA\Guests\GroupBackend $backend = null; + private ?GroupBackend $backend = null; protected function setUp(): void { parent::setUp(); diff --git a/tests/unit/GuestManagerTest.php b/tests/unit/GuestManagerTest.php index b586e466..bdd5c45f 100644 --- a/tests/unit/GuestManagerTest.php +++ b/tests/unit/GuestManagerTest.php @@ -42,7 +42,7 @@ class GuestManagerTest extends TestCase { /** @var IEventDispatcher|MockObject */ private $eventDispatcher; - private ?\OCA\Guests\GuestManager $guestManager = null; + private ?GuestManager $guestManager = null; protected function setUp(): void { parent::setUp(); diff --git a/tests/unit/UserBackendTest.php b/tests/unit/UserBackendTest.php index e2926566..423921e1 100644 --- a/tests/unit/UserBackendTest.php +++ b/tests/unit/UserBackendTest.php @@ -11,6 +11,9 @@ use OCA\Guests\Config; use OCA\Guests\UserBackend; use OCP\EventDispatcher\IEventDispatcher; +use OCP\IDBConnection; +use OCP\Security\IHasher; +use OCP\Server; use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; @@ -21,10 +24,10 @@ class UserBackendTest extends TestCase { /** @var Config|MockObject */ private $config; - private ?\OCA\Guests\UserBackend $backend = null; + private ?UserBackend $backend = null; private function clearGuests(): void { - $query = \OC::$server->getDatabaseConnection()->getQueryBuilder(); + $query = Server::get(IDBConnection::class)->getQueryBuilder(); $query->delete('guests_users')->executeStatement(); } @@ -38,9 +41,9 @@ protected function setUp(): void { $this->backend = new UserBackend( $this->createMock(IEventDispatcher::class), - \OC::$server->getDatabaseConnection(), + Server::get(IDBConnection::class), $this->config, - \OC::$server->getHasher() + Server::get(IHasher::class) ); } diff --git a/vendor-bin/rector/composer.json b/vendor-bin/rector/composer.json index 8592ef65..88f1e65e 100644 --- a/vendor-bin/rector/composer.json +++ b/vendor-bin/rector/composer.json @@ -1,5 +1,6 @@ { "require-dev": { - "rector/rector": "^2.0" + "rector/rector": "^2.0", + "nextcloud/rector": "^0.4.1" } } diff --git a/vendor-bin/rector/composer.lock b/vendor-bin/rector/composer.lock index 5ccbd7b2..5f6b688f 100644 --- a/vendor-bin/rector/composer.lock +++ b/vendor-bin/rector/composer.lock @@ -4,9 +4,122 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "57211dc5c619d183df6361f5d7d57fe5", + "content-hash": "347262bc75027c88fa21b011f732aa31", "packages": [], "packages-dev": [ + { + "name": "nextcloud/ocp", + "version": "v32.0.5", + "source": { + "type": "git", + "url": "https://github.com/nextcloud-deps/ocp.git", + "reference": "a79703d9f38e964b003ae1cc805b6531d142fa93" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/a79703d9f38e964b003ae1cc805b6531d142fa93", + "reference": "a79703d9f38e964b003ae1cc805b6531d142fa93", + "shasum": "" + }, + "require": { + "php": "~8.1 || ~8.2 || ~8.3 || ~8.4", + "psr/clock": "^1.0", + "psr/container": "^2.0.2", + "psr/event-dispatcher": "^1.0", + "psr/log": "^3.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-stable32": "32.0.0-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "AGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Christoph Wurst", + "email": "christoph@winzerhof-wurst.at" + }, + { + "name": "Joas Schilling", + "email": "coding@schilljs.com" + } + ], + "description": "Composer package containing Nextcloud's public OCP API and the unstable NCU API", + "support": { + "issues": "https://github.com/nextcloud-deps/ocp/issues", + "source": "https://github.com/nextcloud-deps/ocp/tree/v32.0.5" + }, + "time": "2026-01-09T00:57:52+00:00" + }, + { + "name": "nextcloud/rector", + "version": "v0.4.1", + "source": { + "type": "git", + "url": "https://github.com/nextcloud-libraries/rector.git", + "reference": "9c5c78cc323537ec6dba5b3cd9c422ff9524d8cf" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nextcloud-libraries/rector/zipball/9c5c78cc323537ec6dba5b3cd9c422ff9524d8cf", + "reference": "9c5c78cc323537ec6dba5b3cd9c422ff9524d8cf", + "shasum": "" + }, + "require": { + "nextcloud/ocp": ">=27", + "php": "^8.1", + "rector/rector": "^2.0.4", + "webmozart/assert": "^1.11" + }, + "require-dev": { + "phpunit/phpunit": "^10.5", + "ramsey/devtools": "^2.0" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/devtools": { + "memory-limit": "-1", + "command-prefix": "dev" + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "OCP\\": "vendor/nextcloud/ocp/OCP", + "Nextcloud\\Rector\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "AGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Christoph Wurst", + "email": "christoph@winzerhof-wurst.at", + "homepage": "https://wuc.me" + } + ], + "description": "Rector upgrade rules for Nextcloud", + "keywords": [ + "nextcloud", + "refactoring" + ], + "support": { + "issues": "https://github.com/nextcloud-libraries/rector/issues", + "source": "https://github.com/nextcloud-libraries/rector/tree/v0.4.1" + }, + "time": "2025-03-31T15:27:10+00:00" + }, { "name": "phpstan/phpstan", "version": "2.1.36", @@ -60,6 +173,207 @@ ], "time": "2026-01-21T13:58:26+00:00" }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, { "name": "rector/rector", "version": "2.3.4", @@ -119,6 +433,64 @@ } ], "time": "2026-01-21T14:49:03+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.12.1", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "9be6926d8b485f55b9229203f962b51ed377ba68" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68", + "reference": "9be6926d8b485f55b9229203f962b51ed377ba68", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-date": "*", + "ext-filter": "*", + "php": "^7.2 || ^8.0" + }, + "suggest": { + "ext-intl": "", + "ext-simplexml": "", + "ext-spl": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.12.1" + }, + "time": "2025-10-29T15:56:20+00:00" } ], "aliases": [], @@ -128,5 +500,5 @@ "prefer-lowest": false, "platform": {}, "platform-dev": {}, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } From 8c80648806216ade92b6f42b90250b30e3d60e8e Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Fri, 6 Feb 2026 17:43:06 +0100 Subject: [PATCH 3/4] fix(ci): Bump dependencies Signed-off-by: Carl Schwan --- composer.json | 1 + composer.lock | 1024 ++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 1023 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 7c6a633c..7b4758bb 100644 --- a/composer.json +++ b/composer.json @@ -40,6 +40,7 @@ "nextcloud/ocp": "dev-stable30", "php-parallel-lint/php-parallel-lint": "^1.2", "phpunit/phpunit": "^9", + "roave/security-advisories": "dev-latest", "vimeo/psalm": "^5.26.1" } } diff --git a/composer.lock b/composer.lock index 3de8f104..e7b3ca36 100644 --- a/composer.lock +++ b/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": "db99fa2035652ab63b49b50c2d180848", + "content-hash": "bd67fe00f7fd0429dbf88a05d45a43c6", "packages": [ { "name": "bamarni/composer-bin-plugin", @@ -2146,6 +2146,1025 @@ }, "time": "2021-07-14T16:41:46+00:00" }, + { + "name": "roave/security-advisories", + "version": "dev-latest", + "source": { + "type": "git", + "url": "https://github.com/Roave/SecurityAdvisories.git", + "reference": "7ea2d110787f6807213e27a1255c6b858ad99d89" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Roave/SecurityAdvisories/zipball/7ea2d110787f6807213e27a1255c6b858ad99d89", + "reference": "7ea2d110787f6807213e27a1255c6b858ad99d89", + "shasum": "" + }, + "conflict": { + "3f/pygmentize": "<1.2", + "adaptcms/adaptcms": "<=1.3", + "admidio/admidio": "<=4.3.16", + "adodb/adodb-php": "<=5.22.9", + "aheinze/cockpit": "<2.2", + "aimeos/ai-admin-graphql": ">=2022.04.1,<2022.10.10|>=2023.04.1,<2023.10.6|>=2024.04.1,<2024.07.2", + "aimeos/ai-admin-jsonadm": "<2020.10.13|>=2021.04.1,<2021.10.6|>=2022.04.1,<2022.10.3|>=2023.04.1,<2023.10.4|==2024.04.1", + "aimeos/ai-client-html": ">=2020.04.1,<2020.10.27|>=2021.04.1,<2021.10.22|>=2022.04.1,<2022.10.13|>=2023.04.1,<2023.10.15|>=2024.04.1,<2024.04.7", + "aimeos/ai-cms-grapesjs": ">=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.9|>=2023.04.1,<2023.10.15|>=2024.04.1,<2024.10.8|>=2025.04.1,<2025.10.2", + "aimeos/ai-controller-frontend": "<2020.10.15|>=2021.04.1,<2021.10.8|>=2022.04.1,<2022.10.8|>=2023.04.1,<2023.10.9|==2024.04.1", + "aimeos/aimeos-core": ">=2022.04.1,<2022.10.17|>=2023.04.1,<2023.10.17|>=2024.04.1,<2024.04.7", + "aimeos/aimeos-laravel": "==2021.10", + "aimeos/aimeos-typo3": "<19.10.12|>=20,<20.10.5", + "airesvsg/acf-to-rest-api": "<=3.1", + "akaunting/akaunting": "<2.1.13", + "akeneo/pim-community-dev": "<5.0.119|>=6,<6.0.53", + "alextselegidis/easyappointments": "<=1.5.2", + "alexusmai/laravel-file-manager": "<=3.3.1", + "algolia/algoliasearch-magento-2": "<=3.16.1|>=3.17.0.0-beta1,<=3.17.1", + "alt-design/alt-redirect": "<1.6.4", + "altcha-org/altcha": "<1.3.1", + "alterphp/easyadmin-extension-bundle": ">=1.2,<1.2.11|>=1.3,<1.3.1", + "amazing/media2click": ">=1,<1.3.3", + "ameos/ameos_tarteaucitron": "<1.2.23", + "amphp/artax": "<1.0.6|>=2,<2.0.6", + "amphp/http": "<=1.7.2|>=2,<=2.1", + "amphp/http-client": ">=4,<4.4", + "anchorcms/anchor-cms": "<=0.12.7", + "andreapollastri/cipi": "<=3.1.15", + "andrewhaine/silverstripe-form-capture": ">=0.2,<=0.2.3|>=1,<1.0.2|>=2,<2.2.5", + "aoe/restler": "<1.7.1", + "apache-solr-for-typo3/solr": "<2.8.3", + "apereo/phpcas": "<1.6", + "api-platform/core": "<3.4.17|>=4,<4.0.22|>=4.1,<4.1.5", + "api-platform/graphql": "<3.4.17|>=4,<4.0.22|>=4.1,<4.1.5", + "appwrite/server-ce": "<=1.2.1", + "arc/web": "<3", + "area17/twill": "<1.2.5|>=2,<2.5.3", + "artesaos/seotools": "<0.17.2", + "asymmetricrypt/asymmetricrypt": "<9.9.99", + "athlon1600/php-proxy": "<=5.1", + "athlon1600/php-proxy-app": "<=3", + "athlon1600/youtube-downloader": "<=4", + "austintoddj/canvas": "<=3.4.2", + "auth0/auth0-php": ">=3.3,<8.18", + "auth0/login": "<7.20", + "auth0/symfony": "<=5.5", + "auth0/wordpress": "<=5.4", + "automad/automad": "<2.0.0.0-alpha5", + "automattic/jetpack": "<9.8", + "awesome-support/awesome-support": "<=6.0.7", + "aws/aws-sdk-php": "<3.368", + "azuracast/azuracast": "<=0.23.1", + "b13/seo_basics": "<0.8.2", + "backdrop/backdrop": "<=1.32", + "backpack/crud": "<3.4.9", + "backpack/filemanager": "<2.0.2|>=3,<3.0.9", + "bacula-web/bacula-web": "<9.7.1", + "badaso/core": "<=2.9.11", + "bagisto/bagisto": "<2.3.10", + "barrelstrength/sprout-base-email": "<1.2.7", + "barrelstrength/sprout-forms": "<3.9", + "barryvdh/laravel-translation-manager": "<0.6.8", + "barzahlen/barzahlen-php": "<2.0.1", + "baserproject/basercms": "<=5.1.1", + "bassjobsen/bootstrap-3-typeahead": ">4.0.2", + "bbpress/bbpress": "<2.6.5", + "bcit-ci/codeigniter": "<3.1.3", + "bcosca/fatfree": "<3.7.2", + "bedita/bedita": "<4", + "bednee/cooluri": "<1.0.30", + "bigfork/silverstripe-form-capture": ">=3,<3.1.1", + "billz/raspap-webgui": "<3.3.6", + "binarytorch/larecipe": "<2.8.1", + "bk2k/bootstrap-package": ">=7.1,<7.1.2|>=8,<8.0.8|>=9,<9.0.4|>=9.1,<9.1.3|>=10,<10.0.10|>=11,<11.0.3", + "blueimp/jquery-file-upload": "==6.4.4", + "bmarshall511/wordpress_zero_spam": "<5.2.13", + "bolt/bolt": "<3.7.2", + "bolt/core": "<=4.2", + "born05/craft-twofactorauthentication": "<3.3.4", + "bottelet/flarepoint": "<2.2.1", + "bref/bref": "<2.1.17", + "brightlocal/phpwhois": "<=4.2.5", + "brotkrueml/codehighlight": "<2.7", + "brotkrueml/schema": "<1.13.1|>=2,<2.5.1", + "brotkrueml/typo3-matomo-integration": "<1.3.2", + "buddypress/buddypress": "<7.2.1", + "bugsnag/bugsnag-laravel": ">=2,<2.0.2", + "bvbmedia/multishop": "<2.0.39", + "bytefury/crater": "<6.0.2", + "cachethq/cachet": "<2.5.1", + "cadmium-org/cadmium-cms": "<=0.4.9", + "cakephp/cakephp": "<3.10.3|>=4,<4.0.10|>=4.1,<4.1.4|>=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10|>=5.2.10,<5.2.12|==5.3", + "cakephp/database": ">=4.2,<4.2.12|>=4.3,<4.3.11|>=4.4,<4.4.10", + "cardgate/magento2": "<2.0.33", + "cardgate/woocommerce": "<=3.1.15", + "cart2quote/module-quotation": ">=4.1.6,<=4.4.5|>=5,<5.4.4", + "cart2quote/module-quotation-encoded": ">=4.1.6,<=4.4.5|>=5,<5.4.4", + "cartalyst/sentry": "<=2.1.6", + "catfan/medoo": "<1.7.5", + "causal/oidc": "<4", + "cecil/cecil": "<7.47.1", + "centreon/centreon": "<22.10.15", + "cesnet/simplesamlphp-module-proxystatistics": "<3.1", + "chriskacerguis/codeigniter-restserver": "<=2.7.1", + "chrome-php/chrome": "<1.14", + "ci4-cms-erp/ci4ms": "<0.28.5", + "civicrm/civicrm-core": ">=4.2,<4.2.9|>=4.3,<4.3.3", + "ckeditor/ckeditor": "<4.25", + "clickstorm/cs-seo": ">=6,<6.8|>=7,<7.5|>=8,<8.4|>=9,<9.3", + "co-stack/fal_sftp": "<0.2.6", + "cockpit-hq/cockpit": "<2.11.4", + "code16/sharp": "<9.11.1", + "codeception/codeception": "<3.1.3|>=4,<4.1.22", + "codeigniter/framework": "<3.1.10", + "codeigniter4/framework": "<4.6.2", + "codeigniter4/shield": "<1.0.0.0-beta8", + "codiad/codiad": "<=2.8.4", + "codingms/additional-tca": ">=1.7,<1.15.17|>=1.16,<1.16.9", + "codingms/modules": "<4.3.11|>=5,<5.7.4|>=6,<6.4.2|>=7,<7.5.5", + "commerceteam/commerce": ">=0.9.6,<0.9.9", + "components/jquery": ">=1.0.3,<3.5", + "composer/composer": "<1.10.27|>=2,<2.2.26|>=2.3,<2.9.3", + "concrete5/concrete5": "<9.4.3", + "concrete5/core": "<8.5.8|>=9,<9.1", + "contao-components/mediaelement": ">=2.14.2,<2.21.1", + "contao/comments-bundle": ">=2,<4.13.40|>=5.0.0.0-RC1-dev,<5.3.4", + "contao/contao": ">=3,<3.5.37|>=4,<4.4.56|>=4.5,<4.13.56|>=5,<5.3.38|>=5.4.0.0-RC1-dev,<5.6.1", + "contao/core": "<3.5.39", + "contao/core-bundle": "<4.13.57|>=5,<5.3.42|>=5.4,<5.6.5", + "contao/listing-bundle": ">=3,<=3.5.30|>=4,<4.4.8", + "contao/managed-edition": "<=1.5", + "coreshop/core-shop": "<4.1.9", + "corveda/phpsandbox": "<1.3.5", + "cosenary/instagram": "<=2.3", + "couleurcitron/tarteaucitron-wp": "<0.3", + "cpsit/typo3-mailqueue": "<0.4.3|>=0.5,<0.5.1", + "craftcms/cms": "<=4.16.16|>=5,<=5.8.20", + "craftcms/commerce": ">=4.0.0.0-RC1-dev,<=4.10|>=5,<=5.5.1", + "craftcms/composer": ">=4.0.0.0-RC1-dev,<=4.10|>=5.0.0.0-RC1-dev,<=5.5.1", + "croogo/croogo": "<=4.0.7", + "cuyz/valinor": "<0.12", + "czim/file-handling": "<1.5|>=2,<2.3", + "czproject/git-php": "<4.0.3", + "damienharper/auditor-bundle": "<5.2.6", + "dapphp/securimage": "<3.6.6", + "darylldoyle/safe-svg": "<1.9.10", + "datadog/dd-trace": ">=0.30,<0.30.2", + "datahihi1/tiny-env": "<1.0.3|>=1.0.9,<1.0.11", + "datatables/datatables": "<1.10.10", + "david-garcia/phpwhois": "<=4.3.1", + "dbrisinajumi/d2files": "<1", + "dcat/laravel-admin": "<=2.1.3|==2.2.0.0-beta|==2.2.2.0-beta", + "derhansen/fe_change_pwd": "<2.0.5|>=3,<3.0.3", + "derhansen/sf_event_mgt": "<4.3.1|>=5,<5.1.1|>=7,<7.4", + "desperado/xml-bundle": "<=0.1.7", + "dev-lancer/minecraft-motd-parser": "<=1.0.5", + "devcode-it/openstamanager": "<=2.9.8", + "devgroup/dotplant": "<2020.09.14-dev", + "digimix/wp-svg-upload": "<=1", + "directmailteam/direct-mail": "<6.0.3|>=7,<7.0.3|>=8,<9.5.2", + "dl/yag": "<3.0.1", + "dmk/webkitpdf": "<1.1.4", + "dnadesign/silverstripe-elemental": "<5.3.12", + "doctrine/annotations": "<1.2.7", + "doctrine/cache": ">=1,<1.3.2|>=1.4,<1.4.2", + "doctrine/common": "<2.4.3|>=2.5,<2.5.1", + "doctrine/dbal": ">=2,<2.0.8|>=2.1,<2.1.2|>=3,<3.1.4", + "doctrine/doctrine-bundle": "<1.5.2", + "doctrine/doctrine-module": "<0.7.2", + "doctrine/mongodb-odm": "<1.0.2", + "doctrine/mongodb-odm-bundle": "<3.0.1", + "doctrine/orm": ">=1,<1.2.4|>=2,<2.4.8|>=2.5,<2.5.1|>=2.8.3,<2.8.4", + "dolibarr/dolibarr": "<21.0.3", + "dompdf/dompdf": "<2.0.4", + "doublethreedigital/guest-entries": "<3.1.2", + "drupal-pattern-lab/unified-twig-extensions": "<=0.1", + "drupal/access_code": "<2.0.5", + "drupal/acquia_dam": "<1.1.5", + "drupal/admin_audit_trail": "<1.0.5", + "drupal/ai": "<1.0.5", + "drupal/alogin": "<2.0.6", + "drupal/cache_utility": "<1.2.1", + "drupal/civictheme": "<1.12", + "drupal/commerce_alphabank_redirect": "<1.0.3", + "drupal/commerce_eurobank_redirect": "<2.1.1", + "drupal/config_split": "<1.10|>=2,<2.0.2", + "drupal/core": ">=6,<6.38|>=7,<7.103|>=8,<10.4.9|>=10.5,<10.5.6|>=11,<11.1.9|>=11.2,<11.2.8", + "drupal/core-recommended": ">=7,<7.102|>=8,<10.2.11|>=10.3,<10.3.9|>=11,<11.0.8", + "drupal/currency": "<3.5", + "drupal/drupal": ">=5,<5.11|>=6,<6.38|>=7,<7.102|>=8,<10.2.11|>=10.3,<10.3.9|>=11,<11.0.8", + "drupal/email_tfa": "<2.0.6", + "drupal/formatter_suite": "<2.1", + "drupal/gdpr": "<3.0.1|>=3.1,<3.1.2", + "drupal/google_tag": "<1.8|>=2,<2.0.8", + "drupal/ignition": "<1.0.4", + "drupal/json_field": "<1.5", + "drupal/lightgallery": "<1.6", + "drupal/link_field_display_mode_formatter": "<1.6", + "drupal/matomo": "<1.24", + "drupal/oauth2_client": "<4.1.3", + "drupal/oauth2_server": "<2.1", + "drupal/obfuscate": "<2.0.1", + "drupal/plausible_tracking": "<1.0.2", + "drupal/quick_node_block": "<2", + "drupal/rapidoc_elements_field_formatter": "<1.0.1", + "drupal/reverse_proxy_header": "<1.1.2", + "drupal/simple_multistep": "<2", + "drupal/simple_oauth": ">=6,<6.0.7", + "drupal/spamspan": "<3.2.1", + "drupal/tfa": "<1.10", + "drupal/umami_analytics": "<1.0.1", + "duncanmcclean/guest-entries": "<3.1.2", + "dweeves/magmi": "<=0.7.24", + "ec-cube/ec-cube": "<2.4.4|>=2.11,<=2.17.1|>=3,<=3.0.18.0-patch4|>=4,<=4.1.2", + "ecodev/newsletter": "<=4", + "ectouch/ectouch": "<=2.7.2", + "egroupware/egroupware": "<23.1.20260113|>=26.0.20251208,<26.0.20260113", + "elefant/cms": "<2.0.7", + "elgg/elgg": "<3.3.24|>=4,<4.0.5", + "elijaa/phpmemcacheadmin": "<=1.3", + "elmsln/haxcms": "<11.0.14", + "encore/laravel-admin": "<=1.8.19", + "endroid/qr-code-bundle": "<3.4.2", + "enhavo/enhavo-app": "<=0.13.1", + "enshrined/svg-sanitize": "<0.22", + "erusev/parsedown": "<1.7.2", + "ether/logs": "<3.0.4", + "evolutioncms/evolution": "<=3.2.3", + "exceedone/exment": "<4.4.3|>=5,<5.0.3", + "exceedone/laravel-admin": "<2.2.3|==3", + "ezsystems/demobundle": ">=5.4,<5.4.6.1-dev", + "ezsystems/ez-support-tools": ">=2.2,<2.2.3", + "ezsystems/ezdemo-ls-extension": ">=5.4,<5.4.2.1-dev", + "ezsystems/ezfind-ls": ">=5.3,<5.3.6.1-dev|>=5.4,<5.4.11.1-dev|>=2017.12,<2017.12.0.1-dev", + "ezsystems/ezplatform": "<=1.13.6|>=2,<=2.5.24", + "ezsystems/ezplatform-admin-ui": ">=1.3,<1.3.5|>=1.4,<1.4.6|>=1.5,<1.5.29|>=2.3,<2.3.39|>=3.3,<3.3.39", + "ezsystems/ezplatform-admin-ui-assets": ">=4,<4.2.1|>=5,<5.0.1|>=5.1,<5.1.1|>=5.3.0.0-beta1,<5.3.5", + "ezsystems/ezplatform-graphql": ">=1.0.0.0-RC1-dev,<1.0.13|>=2.0.0.0-beta1,<2.3.12", + "ezsystems/ezplatform-http-cache": "<2.3.16", + "ezsystems/ezplatform-kernel": "<=1.2.5|>=1.3,<1.3.35", + "ezsystems/ezplatform-rest": ">=1.2,<=1.2.2|>=1.3,<1.3.8", + "ezsystems/ezplatform-richtext": ">=2.3,<2.3.26|>=3.3,<3.3.40", + "ezsystems/ezplatform-solr-search-engine": ">=1.7,<1.7.12|>=2,<2.0.2|>=3.3,<3.3.15", + "ezsystems/ezplatform-user": ">=1,<1.0.1", + "ezsystems/ezpublish-kernel": "<=6.13.8.1|>=7,<7.5.31", + "ezsystems/ezpublish-legacy": "<=2017.12.7.3|>=2018.6,<=2019.03.5.1", + "ezsystems/platform-ui-assets-bundle": ">=4.2,<4.2.3", + "ezsystems/repository-forms": ">=2.3,<2.3.2.1-dev|>=2.5,<2.5.15", + "ezyang/htmlpurifier": "<=4.2", + "facade/ignition": "<1.16.15|>=2,<2.4.2|>=2.5,<2.5.2", + "facturascripts/facturascripts": "<2025.81", + "fastly/magento2": "<1.2.26", + "feehi/cms": "<=2.1.1", + "feehi/feehicms": "<=2.1.1", + "fenom/fenom": "<=2.12.1", + "filament/actions": ">=3.2,<3.2.123", + "filament/filament": ">=4,<4.3.1", + "filament/infolists": ">=3,<3.2.115", + "filament/tables": ">=3,<3.2.115", + "filegator/filegator": "<7.8", + "filp/whoops": "<2.1.13", + "fineuploader/php-traditional-server": "<=1.2.2", + "firebase/php-jwt": "<6", + "fisharebest/webtrees": "<=2.1.18", + "fixpunkt/fp-masterquiz": "<2.2.1|>=3,<3.5.2", + "fixpunkt/fp-newsletter": "<1.1.1|>=1.2,<2.1.2|>=2.2,<3.2.6", + "flarum/core": "<1.8.10", + "flarum/flarum": "<0.1.0.0-beta8", + "flarum/framework": "<1.8.10", + "flarum/mentions": "<1.6.3", + "flarum/sticky": ">=0.1.0.0-beta14,<=0.1.0.0-beta15", + "flarum/tags": "<=0.1.0.0-beta13", + "floriangaerber/magnesium": "<0.3.1", + "fluidtypo3/vhs": "<5.1.1", + "fof/byobu": ">=0.3.0.0-beta2,<1.1.7", + "fof/pretty-mail": "<=1.1.2", + "fof/upload": "<1.2.3", + "foodcoopshop/foodcoopshop": ">=3.2,<3.6.1", + "fooman/tcpdf": "<6.2.22", + "forkcms/forkcms": "<5.11.1", + "fossar/tcpdf-parser": "<6.2.22", + "francoisjacquet/rosariosis": "<=11.5.1", + "frappant/frp-form-answers": "<3.1.2|>=4,<4.0.2", + "friendsofsymfony/oauth2-php": "<1.3", + "friendsofsymfony/rest-bundle": ">=1.2,<1.2.2", + "friendsofsymfony/user-bundle": ">=1,<1.3.5", + "friendsofsymfony1/swiftmailer": ">=4,<5.4.13|>=6,<6.2.5", + "friendsofsymfony1/symfony1": ">=1.1,<1.5.19", + "friendsoftypo3/mediace": ">=7.6.2,<7.6.5", + "friendsoftypo3/openid": ">=4.5,<4.5.31|>=4.7,<4.7.16|>=6,<6.0.11|>=6.1,<6.1.6", + "froala/wysiwyg-editor": "<=4.3", + "froxlor/froxlor": "<=2.2.5", + "frozennode/administrator": "<=5.0.12", + "fuel/core": "<1.8.1", + "funadmin/funadmin": "<=5.0.2", + "gaoming13/wechat-php-sdk": "<=1.10.2", + "genix/cms": "<=1.1.11", + "georgringer/news": "<1.3.3", + "geshi/geshi": "<=1.0.9.1", + "getformwork/formwork": "<2.2", + "getgrav/grav": "<1.11.0.0-beta1", + "getkirby/cms": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1|>=5,<=5.2.1", + "getkirby/kirby": "<3.9.8.3-dev|>=3.10,<3.10.1.2-dev|>=4,<4.7.1", + "getkirby/panel": "<2.5.14", + "getkirby/starterkit": "<=3.7.0.2", + "gilacms/gila": "<=1.15.4", + "gleez/cms": "<=1.3|==2", + "globalpayments/php-sdk": "<2", + "goalgorilla/open_social": "<12.3.11|>=12.4,<12.4.10|>=13.0.0.0-alpha1,<13.0.0.0-alpha11", + "gogentooss/samlbase": "<1.2.7", + "google/protobuf": "<3.4", + "gos/web-socket-bundle": "<1.10.4|>=2,<2.6.1|>=3,<3.3", + "gp247/core": "<1.1.24", + "gree/jose": "<2.2.1", + "gregwar/rst": "<1.0.3", + "grumpydictator/firefly-iii": "<6.1.17", + "gugoan/economizzer": "<=0.9.0.0-beta1", + "guzzlehttp/guzzle": "<6.5.8|>=7,<7.4.5", + "guzzlehttp/oauth-subscriber": "<0.8.1", + "guzzlehttp/psr7": "<1.9.1|>=2,<2.4.5", + "haffner/jh_captcha": "<=2.1.3|>=3,<=3.0.2", + "handcraftedinthealps/goodby-csv": "<1.4.3", + "harvesthq/chosen": "<1.8.7", + "helloxz/imgurl": "<=2.31", + "hhxsv5/laravel-s": "<3.7.36", + "hillelcoren/invoice-ninja": "<5.3.35", + "himiklab/yii2-jqgrid-widget": "<1.0.8", + "hjue/justwriting": "<=1", + "hov/jobfair": "<1.0.13|>=2,<2.0.2", + "httpsoft/http-message": "<1.0.12", + "hyn/multi-tenant": ">=5.6,<5.7.2", + "ibexa/admin-ui": ">=4.2,<4.2.3|>=4.6,<4.6.25|>=5,<5.0.3", + "ibexa/admin-ui-assets": ">=4.6.0.0-alpha1,<4.6.21", + "ibexa/core": ">=4,<4.0.7|>=4.1,<4.1.4|>=4.2,<4.2.3|>=4.5,<4.5.6|>=4.6,<4.6.2", + "ibexa/fieldtype-richtext": ">=4.6,<4.6.25|>=5,<5.0.3", + "ibexa/graphql": ">=2.5,<2.5.31|>=3.3,<3.3.28|>=4.2,<4.2.3", + "ibexa/http-cache": ">=4.6,<4.6.14", + "ibexa/post-install": "<1.0.16|>=4.6,<4.6.14", + "ibexa/solr": ">=4.5,<4.5.4", + "ibexa/user": ">=4,<4.4.3|>=5,<5.0.4", + "icecoder/icecoder": "<=8.1", + "idno/known": "<=1.3.1", + "ilicmiljan/secure-props": ">=1.2,<1.2.2", + "illuminate/auth": "<5.5.10", + "illuminate/cookie": ">=4,<=4.0.11|>=4.1,<6.18.31|>=7,<7.22.4", + "illuminate/database": "<6.20.26|>=7,<7.30.5|>=8,<8.40", + "illuminate/encryption": ">=4,<=4.0.11|>=4.1,<=4.1.31|>=4.2,<=4.2.22|>=5,<=5.0.35|>=5.1,<=5.1.46|>=5.2,<=5.2.45|>=5.3,<=5.3.31|>=5.4,<=5.4.36|>=5.5,<5.5.40|>=5.6,<5.6.15", + "illuminate/view": "<6.20.42|>=7,<7.30.6|>=8,<8.75", + "imdbphp/imdbphp": "<=5.1.1", + "impresscms/impresscms": "<=1.4.5", + "impresspages/impresspages": "<1.0.13", + "in2code/femanager": "<6.4.2|>=7,<7.5.3|>=8,<8.3.1", + "in2code/ipandlanguageredirect": "<5.1.2", + "in2code/lux": "<17.6.1|>=18,<24.0.2", + "in2code/powermail": "<7.5.1|>=8,<8.5.1|>=9,<10.9.1|>=11,<12.5.3|==13", + "innologi/typo3-appointments": "<2.0.6", + "intelliants/subrion": "<4.2.2", + "inter-mediator/inter-mediator": "==5.5", + "ipl/web": "<0.10.1", + "islandora/crayfish": "<4.1", + "islandora/islandora": ">=2,<2.4.1", + "ivankristianto/phpwhois": "<=4.3", + "jackalope/jackalope-doctrine-dbal": "<1.7.4", + "jambagecom/div2007": "<0.10.2", + "james-heinrich/getid3": "<1.9.21", + "james-heinrich/phpthumb": "<=1.7.23", + "jasig/phpcas": "<1.3.3", + "jbartels/wec-map": "<3.0.3", + "jcbrand/converse.js": "<3.3.3", + "joelbutcher/socialstream": "<5.6|>=6,<6.2", + "johnbillion/wp-crontrol": "<1.16.2|>=1.17,<1.19.2", + "joomla/application": "<1.0.13", + "joomla/archive": "<1.1.12|>=2,<2.0.1", + "joomla/database": ">=1,<2.2|>=3,<3.4", + "joomla/filesystem": "<1.6.2|>=2,<2.0.1", + "joomla/filter": "<2.0.6|>=3,<3.0.5|==4", + "joomla/framework": "<1.5.7|>=2.5.4,<=3.8.12", + "joomla/input": ">=2,<2.0.2", + "joomla/joomla-cms": "<3.9.12|>=4,<4.4.13|>=5,<5.2.6", + "joomla/joomla-platform": "<1.5.4", + "joomla/session": "<1.3.1", + "joyqi/hyper-down": "<=2.4.27", + "jsdecena/laracom": "<2.0.9", + "jsmitty12/phpwhois": "<5.1", + "juzaweb/cms": "<=3.4.2", + "jweiland/events2": "<8.3.8|>=9,<9.0.6", + "jweiland/kk-downloader": "<1.2.2", + "kazist/phpwhois": "<=4.2.6", + "kelvinmo/simplexrd": "<3.1.1", + "kevinpapst/kimai2": "<1.16.7", + "khodakhah/nodcms": "<=3", + "kimai/kimai": "<2.46", + "kitodo/presentation": "<3.2.3|>=3.3,<3.3.4", + "klaviyo/magento2-extension": ">=1,<3", + "knplabs/knp-snappy": "<=1.4.2", + "kohana/core": "<3.3.3", + "koillection/koillection": "<1.6.12", + "krayin/laravel-crm": "<=1.3", + "kreait/firebase-php": ">=3.2,<3.8.1", + "kumbiaphp/kumbiapp": "<=1.1.1", + "la-haute-societe/tcpdf": "<6.2.22", + "laminas/laminas-diactoros": "<2.18.1|==2.19|==2.20|==2.21|==2.22|==2.23|>=2.24,<2.24.2|>=2.25,<2.25.2", + "laminas/laminas-form": "<2.17.1|>=3,<3.0.2|>=3.1,<3.1.1", + "laminas/laminas-http": "<2.14.2", + "lara-zeus/artemis": ">=1,<=1.0.6", + "lara-zeus/dynamic-dashboard": ">=3,<=3.0.1", + "laravel/fortify": "<1.11.1", + "laravel/framework": "<10.48.29|>=11,<11.44.1|>=12,<12.1.1", + "laravel/laravel": ">=5.4,<5.4.22", + "laravel/pulse": "<1.3.1", + "laravel/reverb": "<1.7", + "laravel/socialite": ">=1,<2.0.10", + "latte/latte": "<2.10.8", + "lavalite/cms": "<=10.1", + "lavitto/typo3-form-to-database": "<2.2.5|>=3,<3.2.2|>=4,<4.2.3|>=5,<5.0.2", + "lcobucci/jwt": ">=3.4,<3.4.6|>=4,<4.0.4|>=4.1,<4.1.5", + "league/commonmark": "<2.7", + "league/flysystem": "<1.1.4|>=2,<2.1.1", + "league/oauth2-server": ">=8.3.2,<8.4.2|>=8.5,<8.5.3", + "leantime/leantime": "<3.3", + "lexik/jwt-authentication-bundle": "<2.10.7|>=2.11,<2.11.3", + "libreform/libreform": ">=2,<=2.0.8", + "librenms/librenms": "<25.12", + "liftkit/database": "<2.13.2", + "lightsaml/lightsaml": "<1.3.5", + "limesurvey/limesurvey": "<6.5.12", + "livehelperchat/livehelperchat": "<=3.91", + "livewire-filemanager/filemanager": "<=1.0.4", + "livewire/livewire": "<2.12.7|>=3.0.0.0-beta1,<3.6.4", + "livewire/volt": "<1.7", + "lms/routes": "<2.1.1", + "localizationteam/l10nmgr": "<7.4|>=8,<8.7|>=9,<9.2", + "lomkit/laravel-rest-api": "<2.13", + "luracast/restler": "<3.1", + "luyadev/yii-helpers": "<1.2.1", + "macropay-solutions/laravel-crud-wizard-free": "<3.4.17", + "maestroerror/php-heic-to-jpg": "<1.0.5", + "magento/community-edition": "<2.4.6.0-patch13|>=2.4.7.0-beta1,<2.4.7.0-patch8|>=2.4.8.0-beta1,<2.4.8.0-patch3|>=2.4.9.0-alpha1,<2.4.9.0-alpha3|==2.4.9", + "magento/core": "<=1.9.4.5", + "magento/magento1ce": "<1.9.4.3-dev", + "magento/magento1ee": ">=1,<1.14.4.3-dev", + "magento/product-community-edition": "<2.4.4.0-patch9|>=2.4.5,<2.4.5.0-patch8|>=2.4.6,<2.4.6.0-patch6|>=2.4.7,<2.4.7.0-patch1", + "magento/project-community-edition": "<=2.0.2", + "magneto/core": "<1.9.4.4-dev", + "mahocommerce/maho": "<25.9", + "maikuolan/phpmussel": ">=1,<1.6", + "mainwp/mainwp": "<=4.4.3.3", + "manogi/nova-tiptap": "<=3.2.6", + "mantisbt/mantisbt": "<2.27.2", + "marcwillmann/turn": "<0.3.3", + "marshmallow/nova-tiptap": "<5.7", + "matomo/matomo": "<1.11", + "matyhtf/framework": "<3.0.6", + "mautic/core": "<5.2.9|>=6,<6.0.7", + "mautic/core-lib": ">=1.0.0.0-beta,<4.4.13|>=5.0.0.0-alpha,<5.1.1", + "mautic/grapes-js-builder-bundle": ">=4,<4.4.18|>=5,<5.2.9|>=6,<6.0.7", + "maximebf/debugbar": "<1.19", + "mdanter/ecc": "<2", + "mediawiki/abuse-filter": "<1.39.9|>=1.40,<1.41.3|>=1.42,<1.42.2", + "mediawiki/cargo": "<3.8.3", + "mediawiki/core": "<1.39.5|==1.40", + "mediawiki/data-transfer": ">=1.39,<1.39.11|>=1.41,<1.41.3|>=1.42,<1.42.2", + "mediawiki/matomo": "<2.4.3", + "mediawiki/semantic-media-wiki": "<4.0.2", + "mehrwert/phpmyadmin": "<3.2", + "melisplatform/melis-asset-manager": "<5.0.1", + "melisplatform/melis-cms": "<5.3.4", + "melisplatform/melis-cms-slider": "<5.3.1", + "melisplatform/melis-core": "<5.3.11", + "melisplatform/melis-front": "<5.0.1", + "mezzio/mezzio-swoole": "<3.7|>=4,<4.3", + "mgallegos/laravel-jqgrid": "<=1.3", + "microsoft/microsoft-graph": ">=1.16,<1.109.1|>=2,<2.0.1", + "microsoft/microsoft-graph-beta": "<2.0.1", + "microsoft/microsoft-graph-core": "<2.0.2", + "microweber/microweber": "<2.0.20", + "mikehaertl/php-shellcommand": "<1.6.1", + "mineadmin/mineadmin": "<=3.0.9", + "miniorange/miniorange-saml": "<1.4.3", + "mittwald/typo3_forum": "<1.2.1", + "mobiledetect/mobiledetectlib": "<2.8.32", + "modx/revolution": "<=3.1", + "mojo42/jirafeau": "<4.4", + "mongodb/mongodb": ">=1,<1.9.2", + "mongodb/mongodb-extension": "<1.21.2", + "monolog/monolog": ">=1.8,<1.12", + "moodle/moodle": "<4.4.12|>=4.5.0.0-beta,<4.5.8|>=5.0.0.0-beta,<5.0.4|>=5.1.0.0-beta,<5.1.1", + "moonshine/moonshine": "<=3.12.5", + "mos/cimage": "<0.7.19", + "movim/moxl": ">=0.8,<=0.10", + "movingbytes/social-network": "<=1.2.1", + "mpdf/mpdf": "<=7.1.7", + "munkireport/comment": "<4", + "munkireport/managedinstalls": "<2.6", + "munkireport/munki_facts": "<1.5", + "munkireport/reportdata": "<3.5", + "munkireport/softwareupdate": "<1.6", + "mustache/mustache": ">=2,<2.14.1", + "mwdelaney/wp-enable-svg": "<=0.2", + "namshi/jose": "<2.2", + "nasirkhan/laravel-starter": "<11.11", + "nategood/httpful": "<1", + "neoan3-apps/template": "<1.1.1", + "neorazorx/facturascripts": "<2022.04", + "neos/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "neos/form": ">=1.2,<4.3.3|>=5,<5.0.9|>=5.1,<5.1.3", + "neos/media-browser": "<7.3.19|>=8,<8.0.16|>=8.1,<8.1.11|>=8.2,<8.2.11|>=8.3,<8.3.9", + "neos/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<5.3.10|>=7,<7.0.9|>=7.1,<7.1.7|>=7.2,<7.2.6|>=7.3,<7.3.4|>=8,<8.0.2", + "neos/swiftmailer": "<5.4.5", + "nesbot/carbon": "<2.72.6|>=3,<3.8.4", + "netcarver/textile": "<=4.1.2", + "netgen/tagsbundle": ">=3.4,<3.4.11|>=4,<4.0.15", + "nette/application": ">=2,<2.0.19|>=2.1,<2.1.13|>=2.2,<2.2.10|>=2.3,<2.3.14|>=2.4,<2.4.16|>=3,<3.0.6", + "nette/nette": ">=2,<2.0.19|>=2.1,<2.1.13", + "neuron-core/neuron-ai": "<=2.8.11", + "nilsteampassnet/teampass": "<3.1.3.1-dev", + "nitsan/ns-backup": "<13.0.1", + "nonfiction/nterchange": "<4.1.1", + "notrinos/notrinos-erp": "<=0.7", + "noumo/easyii": "<=0.9", + "novaksolutions/infusionsoft-php-sdk": "<1", + "novosga/novosga": "<=2.2.12", + "nukeviet/nukeviet": "<4.5.02", + "nyholm/psr7": "<1.6.1", + "nystudio107/craft-seomatic": "<3.4.12", + "nzedb/nzedb": "<0.8", + "nzo/url-encryptor-bundle": ">=4,<4.3.2|>=5,<5.0.1", + "october/backend": "<1.1.2", + "october/cms": "<1.0.469|==1.0.469|==1.0.471|==1.1.1", + "october/october": "<3.7.5", + "october/rain": "<1.0.472|>=1.1,<1.1.2", + "october/system": "<=3.7.12|>=4,<=4.0.11", + "oliverklee/phpunit": "<3.5.15", + "omeka/omeka-s": "<4.0.3", + "onelogin/php-saml": "<2.21.1|>=3,<3.8.1|>=4,<4.3.1", + "oneup/uploader-bundle": ">=1,<1.9.3|>=2,<2.1.5", + "open-web-analytics/open-web-analytics": "<1.8.1", + "opencart/opencart": ">=0", + "openid/php-openid": "<2.3", + "openmage/magento-lts": "<20.16.1", + "opensolutions/vimbadmin": "<=3.0.15", + "opensource-workshop/connect-cms": "<1.8.7|>=2,<2.4.7", + "orchid/platform": ">=8,<14.43", + "oro/calendar-bundle": ">=4.2,<=4.2.6|>=5,<=5.0.6|>=5.1,<5.1.1", + "oro/commerce": ">=4.1,<5.0.11|>=5.1,<5.1.1", + "oro/crm": ">=1.7,<1.7.4|>=3.1,<4.1.17|>=4.2,<4.2.7", + "oro/crm-call-bundle": ">=4.2,<=4.2.5|>=5,<5.0.4|>=5.1,<5.1.1", + "oro/customer-portal": ">=4.1,<=4.1.13|>=4.2,<=4.2.10|>=5,<=5.0.11|>=5.1,<=5.1.3", + "oro/platform": ">=1.7,<1.7.4|>=3.1,<3.1.29|>=4.1,<4.1.17|>=4.2,<=4.2.10|>=5,<=5.0.12|>=5.1,<=5.1.3", + "oveleon/contao-cookiebar": "<1.16.3|>=2,<2.1.3", + "oxid-esales/oxideshop-ce": "<=7.0.5", + "oxid-esales/paymorrow-module": ">=1,<1.0.2|>=2,<2.0.1", + "packbackbooks/lti-1-3-php-library": "<5", + "padraic/humbug_get_contents": "<1.1.2", + "pagarme/pagarme-php": "<3", + "pagekit/pagekit": "<=1.0.18", + "paragonie/ecc": "<2.0.1", + "paragonie/random_compat": "<2", + "paragonie/sodium_compat": "<1.24|>=2,<2.5", + "passbolt/passbolt_api": "<4.6.2", + "paypal/adaptivepayments-sdk-php": "<=3.9.2", + "paypal/invoice-sdk-php": "<=3.9", + "paypal/merchant-sdk-php": "<3.12", + "paypal/permissions-sdk-php": "<=3.9.1", + "pear/archive_tar": "<1.4.14", + "pear/auth": "<1.2.4", + "pear/crypt_gpg": "<1.6.7", + "pear/http_request2": "<2.7", + "pear/pear": "<=1.10.1", + "pegasus/google-for-jobs": "<1.5.1|>=2,<2.1.1", + "personnummer/personnummer": "<3.0.2", + "ph7software/ph7builder": "<=17.9.1", + "phanan/koel": "<5.1.4", + "phenx/php-svg-lib": "<0.5.2", + "php-censor/php-censor": "<2.0.13|>=2.1,<2.1.5", + "php-mod/curl": "<2.3.2", + "phpbb/phpbb": "<3.3.11", + "phpems/phpems": ">=6,<=6.1.3", + "phpfastcache/phpfastcache": "<6.1.5|>=7,<7.1.2|>=8,<8.0.7", + "phpmailer/phpmailer": "<6.5", + "phpmussel/phpmussel": ">=1,<1.6", + "phpmyadmin/phpmyadmin": "<5.2.2", + "phpmyfaq/phpmyfaq": "<=4.0.16", + "phpoffice/common": "<0.2.9", + "phpoffice/math": "<=0.2", + "phpoffice/phpexcel": "<=1.8.2", + "phpoffice/phpspreadsheet": "<1.30|>=2,<2.1.12|>=2.2,<2.4|>=3,<3.10|>=4,<5", + "phppgadmin/phppgadmin": "<=7.13", + "phpseclib/phpseclib": "<2.0.47|>=3,<3.0.36", + "phpservermon/phpservermon": "<3.6", + "phpsysinfo/phpsysinfo": "<3.4.3", + "phpunit/phpunit": "<8.5.52|>=9,<9.6.33|>=10,<10.5.62|>=11,<11.5.50|>=12,<12.5.8", + "phpwhois/phpwhois": "<=4.2.5", + "phpxmlrpc/extras": "<0.6.1", + "phpxmlrpc/phpxmlrpc": "<4.9.2", + "pi/pi": "<=2.5", + "pimcore/admin-ui-classic-bundle": "<=1.7.15|>=2.0.0.0-RC1-dev,<=2.2.2", + "pimcore/customer-management-framework-bundle": "<4.2.1", + "pimcore/data-hub": "<1.2.4", + "pimcore/data-importer": "<1.8.9|>=1.9,<1.9.3", + "pimcore/demo": "<10.3", + "pimcore/ecommerce-framework-bundle": "<1.0.10", + "pimcore/perspective-editor": "<1.5.1", + "pimcore/pimcore": "<=11.5.13|>=12.0.0.0-RC1-dev,<12.3.1", + "pimcore/web2print-tools-bundle": "<=5.2.1|>=6.0.0.0-RC1-dev,<=6.1", + "piwik/piwik": "<1.11", + "pixelfed/pixelfed": "<0.12.5", + "plotly/plotly.js": "<2.25.2", + "pocketmine/bedrock-protocol": "<8.0.2", + "pocketmine/pocketmine-mp": "<5.32.1", + "pocketmine/raklib": ">=0.14,<0.14.6|>=0.15,<0.15.1", + "pressbooks/pressbooks": "<5.18", + "prestashop/autoupgrade": ">=4,<4.10.1", + "prestashop/blockreassurance": "<=5.1.3", + "prestashop/blockwishlist": ">=2,<2.1.1", + "prestashop/contactform": ">=1.0.1,<4.3", + "prestashop/gamification": "<2.3.2", + "prestashop/prestashop": "<8.2.4|>=9.0.0.0-alpha1,<9.0.3", + "prestashop/productcomments": "<5.0.2", + "prestashop/ps_checkout": "<4.4.1|>=5,<5.0.5", + "prestashop/ps_contactinfo": "<=3.3.2", + "prestashop/ps_emailsubscription": "<2.6.1", + "prestashop/ps_facetedsearch": "<3.4.1", + "prestashop/ps_linklist": "<3.1", + "privatebin/privatebin": "<1.4|>=1.5,<1.7.4|>=1.7.7,<2.0.3", + "processwire/processwire": "<=3.0.246", + "propel/propel": ">=2.0.0.0-alpha1,<=2.0.0.0-alpha7", + "propel/propel1": ">=1,<=1.7.1", + "psy/psysh": "<=0.11.22|>=0.12,<=0.12.18", + "pterodactyl/panel": "<1.12", + "ptheofan/yii2-statemachine": ">=2.0.0.0-RC1-dev,<=2", + "ptrofimov/beanstalk_console": "<1.7.14", + "pubnub/pubnub": "<6.1", + "punktde/pt_extbase": "<1.5.1", + "pusher/pusher-php-server": "<2.2.1", + "pwweb/laravel-core": "<=0.3.6.0-beta", + "pxlrbt/filament-excel": "<1.1.14|>=2.0.0.0-alpha,<2.3.3", + "pyrocms/pyrocms": "<=3.9.1", + "qcubed/qcubed": "<=3.1.1", + "quickapps/cms": "<=2.0.0.0-beta2", + "rainlab/blog-plugin": "<1.4.1", + "rainlab/debugbar-plugin": "<3.1", + "rainlab/user-plugin": "<=1.4.5", + "rankmath/seo-by-rank-math": "<=1.0.95", + "rap2hpoutre/laravel-log-viewer": "<0.13", + "react/http": ">=0.7,<1.9", + "really-simple-plugins/complianz-gdpr": "<6.4.2", + "redaxo/source": "<=5.20.1", + "remdex/livehelperchat": "<4.29", + "renolit/reint-downloadmanager": "<4.0.2|>=5,<5.0.1", + "reportico-web/reportico": "<=8.1", + "rhukster/dom-sanitizer": "<1.0.7", + "rmccue/requests": ">=1.6,<1.8", + "robrichards/xmlseclibs": "<=3.1.3", + "roots/soil": "<4.1", + "roundcube/roundcubemail": "<1.5.10|>=1.6,<1.6.11", + "rudloff/alltube": "<3.0.3", + "rudloff/rtmpdump-bin": "<=2.3.1", + "s-cart/core": "<=9.0.5", + "s-cart/s-cart": "<6.9", + "sabberworm/php-css-parser": ">=1,<1.0.1|>=2,<2.0.1|>=3,<3.0.1|>=4,<4.0.1|>=5,<5.0.9|>=5.1,<5.1.3|>=5.2,<5.2.1|>=6,<6.0.2|>=7,<7.0.4|>=8,<8.0.1|>=8.1,<8.1.1|>=8.2,<8.2.1|>=8.3,<8.3.1", + "sabre/dav": ">=1.6,<1.7.11|>=1.8,<1.8.9", + "samwilson/unlinked-wikibase": "<1.42", + "scheb/two-factor-bundle": "<3.26|>=4,<4.11", + "sensiolabs/connect": "<4.2.3", + "serluck/phpwhois": "<=4.2.6", + "setasign/fpdi": "<2.6.4", + "sfroemken/url_redirect": "<=1.2.1", + "sheng/yiicms": "<1.2.1", + "shopware/core": "<6.6.10.9-dev|>=6.7,<6.7.6.1-dev", + "shopware/platform": "<6.6.10.7-dev|>=6.7,<6.7.3.1-dev", + "shopware/production": "<=6.3.5.2", + "shopware/shopware": "<=5.7.17|>=6.4.6,<6.6.10.10-dev|>=6.7,<6.7.6.1-dev", + "shopware/storefront": "<6.6.10.10-dev|>=6.7,<6.7.5.1-dev", + "shopxo/shopxo": "<=6.4", + "showdoc/showdoc": "<2.10.4", + "shuchkin/simplexlsx": ">=1.0.12,<1.1.13", + "silverstripe-australia/advancedreports": ">=1,<=2", + "silverstripe/admin": "<1.13.19|>=2,<2.1.8", + "silverstripe/assets": ">=1,<1.11.1", + "silverstripe/cms": "<4.11.3", + "silverstripe/comments": ">=1.3,<3.1.1", + "silverstripe/forum": "<=0.6.1|>=0.7,<=0.7.3", + "silverstripe/framework": "<5.3.23", + "silverstripe/graphql": ">=2,<2.0.5|>=3,<3.8.2|>=4,<4.3.7|>=5,<5.1.3", + "silverstripe/hybridsessions": ">=1,<2.4.1|>=2.5,<2.5.1", + "silverstripe/recipe-cms": ">=4.5,<4.5.3", + "silverstripe/registry": ">=2.1,<2.1.2|>=2.2,<2.2.1", + "silverstripe/reports": "<5.2.3", + "silverstripe/restfulserver": ">=1,<1.0.9|>=2,<2.0.4|>=2.1,<2.1.2", + "silverstripe/silverstripe-omnipay": "<2.5.2|>=3,<3.0.2|>=3.1,<3.1.4|>=3.2,<3.2.1", + "silverstripe/subsites": ">=2,<2.6.1", + "silverstripe/taxonomy": ">=1.3,<1.3.1|>=2,<2.0.1", + "silverstripe/userforms": "<3|>=5,<5.4.2", + "silverstripe/versioned-admin": ">=1,<1.11.1", + "simogeo/filemanager": "<=2.5", + "simple-updates/phpwhois": "<=1", + "simplesamlphp/saml2": "<=4.16.15|>=5.0.0.0-alpha1,<=5.0.0.0-alpha19", + "simplesamlphp/saml2-legacy": "<=4.16.15", + "simplesamlphp/simplesamlphp": "<1.18.6", + "simplesamlphp/simplesamlphp-module-infocard": "<1.0.1", + "simplesamlphp/simplesamlphp-module-openid": "<1", + "simplesamlphp/simplesamlphp-module-openidprovider": "<0.9", + "simplesamlphp/xml-common": "<1.20", + "simplesamlphp/xml-security": "==1.6.11", + "simplito/elliptic-php": "<1.0.6", + "sitegeist/fluid-components": "<3.5", + "sjbr/sr-feuser-register": "<2.6.2|>=5.1,<12.5", + "sjbr/sr-freecap": "<2.4.6|>=2.5,<2.5.3", + "sjbr/static-info-tables": "<2.3.1", + "slim/psr7": "<1.4.1|>=1.5,<1.5.1|>=1.6,<1.6.1", + "slim/slim": "<2.6", + "slub/slub-events": "<3.0.3", + "smarty/smarty": "<4.5.3|>=5,<5.1.1", + "snipe/snipe-it": "<=8.3.4", + "socalnick/scn-social-auth": "<1.15.2", + "socialiteproviders/steam": "<1.1", + "solspace/craft-freeform": "<4.1.29|>=5,<=5.14.6", + "soosyze/soosyze": "<=2", + "spatie/browsershot": "<5.0.5", + "spatie/image-optimizer": "<1.7.3", + "spencer14420/sp-php-email-handler": "<1", + "spipu/html2pdf": "<5.2.8", + "spiral/roadrunner": "<2025.1", + "spoon/library": "<1.4.1", + "spoonity/tcpdf": "<6.2.22", + "squizlabs/php_codesniffer": ">=1,<2.8.1|>=3,<3.0.1", + "ssddanbrown/bookstack": "<24.05.1", + "starcitizentools/citizen-skin": ">=1.9.4,<3.9", + "starcitizentools/short-description": ">=4,<4.0.1", + "starcitizentools/tabber-neue": ">=1.9.1,<2.7.2|>=3,<3.1.1", + "starcitizenwiki/embedvideo": "<=4", + "statamic/cms": "<=5.22", + "stormpath/sdk": "<9.9.99", + "studio-42/elfinder": "<=2.1.64", + "studiomitte/friendlycaptcha": "<0.1.4", + "subhh/libconnect": "<7.0.8|>=8,<8.1", + "sukohi/surpass": "<1", + "sulu/form-bundle": ">=2,<2.5.3", + "sulu/sulu": "<1.6.44|>=2,<2.5.25|>=2.6,<2.6.9|>=3.0.0.0-alpha1,<3.0.0.0-alpha3", + "sumocoders/framework-user-bundle": "<1.4", + "superbig/craft-audit": "<3.0.2", + "svewap/a21glossary": "<=0.4.10", + "swag/paypal": "<5.4.4", + "swiftmailer/swiftmailer": "<6.2.5", + "swiftyedit/swiftyedit": "<1.2", + "sylius/admin-bundle": ">=1,<1.0.17|>=1.1,<1.1.9|>=1.2,<1.2.2", + "sylius/grid": ">=1,<1.1.19|>=1.2,<1.2.18|>=1.3,<1.3.13|>=1.4,<1.4.5|>=1.5,<1.5.1", + "sylius/grid-bundle": "<1.10.1", + "sylius/paypal-plugin": "<1.6.2|>=1.7,<1.7.2|>=2,<2.0.2", + "sylius/resource-bundle": ">=1,<1.3.14|>=1.4,<1.4.7|>=1.5,<1.5.2|>=1.6,<1.6.4", + "sylius/sylius": "<1.12.19|>=1.13.0.0-alpha1,<1.13.4", + "symbiote/silverstripe-multivaluefield": ">=3,<3.1", + "symbiote/silverstripe-queuedjobs": ">=3,<3.0.2|>=3.1,<3.1.4|>=4,<4.0.7|>=4.1,<4.1.2|>=4.2,<4.2.4|>=4.3,<4.3.3|>=4.4,<4.4.3|>=4.5,<4.5.1|>=4.6,<4.6.4", + "symbiote/silverstripe-seed": "<6.0.3", + "symbiote/silverstripe-versionedfiles": "<=2.0.3", + "symfont/process": ">=0", + "symfony/cache": ">=3.1,<3.4.35|>=4,<4.2.12|>=4.3,<4.3.8", + "symfony/dependency-injection": ">=2,<2.0.17|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/error-handler": ">=4.4,<4.4.4|>=5,<5.0.4", + "symfony/form": ">=2.3,<2.3.35|>=2.4,<2.6.12|>=2.7,<2.7.50|>=2.8,<2.8.49|>=3,<3.4.20|>=4,<4.0.15|>=4.1,<4.1.9|>=4.2,<4.2.1", + "symfony/framework-bundle": ">=2,<2.3.18|>=2.4,<2.4.8|>=2.5,<2.5.2|>=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7|>=5.3.14,<5.3.15|>=5.4.3,<5.4.4|>=6.0.3,<6.0.4", + "symfony/http-client": ">=4.3,<5.4.47|>=6,<6.4.15|>=7,<7.1.8", + "symfony/http-foundation": "<5.4.50|>=6,<6.4.29|>=7,<7.3.7", + "symfony/http-kernel": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.2.6", + "symfony/intl": ">=2.7,<2.7.38|>=2.8,<2.8.31|>=3,<3.2.14|>=3.3,<3.3.13", + "symfony/maker-bundle": ">=1.27,<1.29.2|>=1.30,<1.31.1", + "symfony/mime": ">=4.3,<4.3.8", + "symfony/phpunit-bridge": ">=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/polyfill": ">=1,<1.10", + "symfony/polyfill-php55": ">=1,<1.10", + "symfony/process": "<5.4.51|>=6,<6.4.33|>=7,<7.1.7|>=7.3,<7.3.11|>=7.4,<7.4.5|>=8,<8.0.5", + "symfony/proxy-manager-bridge": ">=2.7,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.1.12|>=4.2,<4.2.7", + "symfony/routing": ">=2,<2.0.19", + "symfony/runtime": ">=5.3,<5.4.46|>=6,<6.4.14|>=7,<7.1.7", + "symfony/security": ">=2,<2.7.51|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.8", + "symfony/security-bundle": ">=2,<4.4.50|>=5,<5.4.20|>=6,<6.0.20|>=6.1,<6.1.12|>=6.2,<6.4.10|>=7,<7.0.10|>=7.1,<7.1.3", + "symfony/security-core": ">=2.4,<2.6.13|>=2.7,<2.7.9|>=2.7.30,<2.7.32|>=2.8,<3.4.49|>=4,<4.4.24|>=5,<5.2.9", + "symfony/security-csrf": ">=2.4,<2.7.48|>=2.8,<2.8.41|>=3,<3.3.17|>=3.4,<3.4.11|>=4,<4.0.11", + "symfony/security-guard": ">=2.8,<3.4.48|>=4,<4.4.23|>=5,<5.2.8", + "symfony/security-http": ">=2.3,<2.3.41|>=2.4,<2.7.51|>=2.8,<2.8.50|>=3,<3.4.26|>=4,<4.2.12|>=4.3,<4.3.8|>=4.4,<4.4.7|>=5,<5.0.7|>=5.1,<5.2.8|>=5.3,<5.4.47|>=6,<6.4.15|>=7,<7.1.8", + "symfony/serializer": ">=2,<2.0.11|>=4.1,<4.4.35|>=5,<5.3.12", + "symfony/symfony": "<5.4.51|>=6,<6.4.33|>=7,<7.3.11|>=7.4,<7.4.5|>=8,<8.0.5", + "symfony/translation": ">=2,<2.0.17", + "symfony/twig-bridge": ">=2,<4.4.51|>=5,<5.4.31|>=6,<6.3.8", + "symfony/ux-autocomplete": "<2.11.2", + "symfony/ux-live-component": "<2.25.1", + "symfony/ux-twig-component": "<2.25.1", + "symfony/validator": "<5.4.43|>=6,<6.4.11|>=7,<7.1.4", + "symfony/var-exporter": ">=4.2,<4.2.12|>=4.3,<4.3.8", + "symfony/web-profiler-bundle": ">=2,<2.3.19|>=2.4,<2.4.9|>=2.5,<2.5.4", + "symfony/webhook": ">=6.3,<6.3.8", + "symfony/yaml": ">=2,<2.0.22|>=2.1,<2.1.7|>=2.2.0.0-beta1,<2.2.0.0-beta2", + "symphonycms/symphony-2": "<2.6.4", + "t3/dce": "<0.11.5|>=2.2,<2.6.2", + "t3g/svg-sanitizer": "<1.0.3", + "t3s/content-consent": "<1.0.3|>=2,<2.0.2", + "tastyigniter/tastyigniter": "<4", + "tcg/voyager": "<=1.8", + "tecnickcom/tc-lib-pdf-font": "<2.6.4", + "tecnickcom/tcpdf": "<6.8", + "terminal42/contao-tablelookupwizard": "<3.3.5", + "thelia/backoffice-default-template": ">=2.1,<2.1.2", + "thelia/thelia": ">=2.1,<2.1.3", + "theonedemon/phpwhois": "<=4.2.5", + "thinkcmf/thinkcmf": "<6.0.8", + "thorsten/phpmyfaq": "<=4.0.16|>=4.1.0.0-alpha,<=4.1.0.0-beta2", + "tikiwiki/tiki-manager": "<=17.1", + "timber/timber": ">=0.16.6,<1.23.1|>=1.24,<1.24.1|>=2,<2.1", + "tinymce/tinymce": "<7.2", + "tinymighty/wiki-seo": "<1.2.2", + "titon/framework": "<9.9.99", + "tltneon/lgsl": "<7", + "tobiasbg/tablepress": "<=2.0.0.0-RC1", + "topthink/framework": "<6.0.17|>=6.1,<=8.0.4", + "topthink/think": "<=6.1.1", + "topthink/thinkphp": "<=3.2.3|>=6.1.3,<=8.0.4", + "torrentpier/torrentpier": "<=2.8.8", + "tpwd/ke_search": "<4.0.3|>=4.1,<4.6.6|>=5,<5.0.2", + "tribalsystems/zenario": "<=9.7.61188", + "truckersmp/phpwhois": "<=4.3.1", + "ttskch/pagination-service-provider": "<1", + "twbs/bootstrap": "<3.4.1|>=4,<4.3.1", + "twig/twig": "<3.11.2|>=3.12,<3.14.1|>=3.16,<3.19", + "typo3/cms": "<9.5.29|>=10,<10.4.35|>=11,<11.5.23|>=12,<12.2", + "typo3/cms-backend": "<4.1.14|>=4.2,<4.2.15|>=4.3,<4.3.7|>=4.4,<4.4.4|>=7,<=7.6.50|>=8,<=8.7.39|>=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", + "typo3/cms-belog": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", + "typo3/cms-beuser": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-core": "<=8.7.56|>=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", + "typo3/cms-dashboard": ">=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/cms-extbase": "<6.2.24|>=7,<7.6.8|==8.1.1", + "typo3/cms-extensionmanager": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", + "typo3/cms-felogin": ">=4.2,<4.2.3", + "typo3/cms-fluid": "<4.3.4|>=4.4,<4.4.1", + "typo3/cms-form": ">=8,<=8.7.39|>=9,<=9.5.24|>=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", + "typo3/cms-frontend": "<4.3.9|>=4.4,<4.4.5", + "typo3/cms-indexed-search": ">=10,<=10.4.47|>=11,<=11.5.41|>=12,<=12.4.24|>=13,<=13.4.2", + "typo3/cms-install": "<4.1.14|>=4.2,<4.2.16|>=4.3,<4.3.9|>=4.4,<4.4.5|>=12.2,<12.4.8|==13.4.2", + "typo3/cms-lowlevel": ">=11,<=11.5.41", + "typo3/cms-recordlist": ">=11,<11.5.48", + "typo3/cms-recycler": ">=9,<9.5.55|>=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", + "typo3/cms-redirects": ">=10,<=10.4.54|>=11,<=11.5.48|>=12,<=12.4.40|>=13,<=13.4.22|>=14,<=14.0.1", + "typo3/cms-rte-ckeditor": ">=9.5,<9.5.42|>=10,<10.4.39|>=11,<11.5.30", + "typo3/cms-scheduler": ">=11,<=11.5.41", + "typo3/cms-setup": ">=9,<=9.5.50|>=10,<=10.4.49|>=11,<=11.5.43|>=12,<=12.4.30|>=13,<=13.4.11", + "typo3/cms-webhooks": ">=12,<=12.4.30|>=13,<=13.4.11", + "typo3/cms-workspaces": ">=9,<9.5.55|>=10,<10.4.54|>=11,<11.5.48|>=12,<12.4.37|>=13,<13.4.18", + "typo3/flow": ">=1,<1.0.4|>=1.1,<1.1.1|>=2,<2.0.1|>=2.3,<2.3.16|>=3,<3.0.12|>=3.1,<3.1.10|>=3.2,<3.2.13|>=3.3,<3.3.13|>=4,<4.0.6", + "typo3/html-sanitizer": ">=1,<=1.5.2|>=2,<=2.1.3", + "typo3/neos": ">=1.1,<1.1.3|>=1.2,<1.2.13|>=2,<2.0.4|>=2.3,<2.3.99|>=3,<3.0.20|>=3.1,<3.1.18|>=3.2,<3.2.14|>=3.3,<3.3.23|>=4,<4.0.17|>=4.1,<4.1.16|>=4.2,<4.2.12|>=4.3,<4.3.3", + "typo3/phar-stream-wrapper": ">=1,<2.1.1|>=3,<3.1.1", + "typo3/swiftmailer": ">=4.1,<4.1.99|>=5.4,<5.4.5", + "typo3fluid/fluid": ">=2,<2.0.8|>=2.1,<2.1.7|>=2.2,<2.2.4|>=2.3,<2.3.7|>=2.4,<2.4.4|>=2.5,<2.5.11|>=2.6,<2.6.10", + "ua-parser/uap-php": "<3.8", + "uasoft-indonesia/badaso": "<=2.9.7", + "unisharp/laravel-filemanager": "<2.9.1", + "universal-omega/dynamic-page-list3": "<3.6.4", + "unopim/unopim": "<=0.3", + "userfrosting/userfrosting": ">=0.3.1,<4.6.3", + "usmanhalalit/pixie": "<1.0.3|>=2,<2.0.2", + "uvdesk/community-skeleton": "<=1.1.1", + "uvdesk/core-framework": "<=1.1.1", + "vanilla/safecurl": "<0.9.2", + "verbb/comments": "<1.5.5", + "verbb/formie": "<=2.1.43", + "verbb/image-resizer": "<2.0.9", + "verbb/knock-knock": "<1.2.8", + "verot/class.upload.php": "<=2.1.6", + "vertexvaar/falsftp": "<0.2.6", + "villagedefrance/opencart-overclocked": "<=1.11.1", + "vova07/yii2-fileapi-widget": "<0.1.9", + "vrana/adminer": "<=4.8.1", + "vufind/vufind": ">=2,<9.1.1", + "waldhacker/hcaptcha": "<2.1.2", + "wallabag/tcpdf": "<6.2.22", + "wallabag/wallabag": "<2.6.11", + "wanglelecc/laracms": "<=1.0.3", + "wapplersystems/a21glossary": "<=0.4.10", + "web-auth/webauthn-framework": ">=3.3,<3.3.4|>=4.5,<4.9", + "web-auth/webauthn-lib": ">=4.5,<4.9", + "web-feet/coastercms": "==5.5", + "web-tp3/wec_map": "<3.0.3", + "webbuilders-group/silverstripe-kapost-bridge": "<0.4", + "webcoast/deferred-image-processing": "<1.0.2", + "webklex/laravel-imap": "<5.3", + "webklex/php-imap": "<5.3", + "webpa/webpa": "<3.1.2", + "webreinvent/vaahcms": "<=2.3.1", + "wikibase/wikibase": "<=1.39.3", + "wikimedia/parsoid": "<0.12.2", + "willdurand/js-translation-bundle": "<2.1.1", + "winter/wn-backend-module": "<1.2.4", + "winter/wn-cms-module": "<=1.2.9", + "winter/wn-dusk-plugin": "<2.1", + "winter/wn-system-module": "<1.2.4", + "wintercms/winter": "<=1.2.3", + "wireui/wireui": "<1.19.3|>=2,<2.1.3", + "woocommerce/woocommerce": "<6.6|>=8.8,<8.8.5|>=8.9,<8.9.3", + "wp-cli/wp-cli": ">=0.12,<2.5", + "wp-graphql/wp-graphql": "<=1.14.5", + "wp-premium/gravityforms": "<2.4.21", + "wpanel/wpanel4-cms": "<=4.3.1", + "wpcloud/wp-stateless": "<3.2", + "wpglobus/wpglobus": "<=1.9.6", + "wwbn/avideo": "<14.3", + "xataface/xataface": "<3", + "xpressengine/xpressengine": "<3.0.15", + "yab/quarx": "<2.4.5", + "yeswiki/yeswiki": "<=4.5.4", + "yetiforce/yetiforce-crm": "<6.5", + "yidashi/yii2cmf": "<=2", + "yii2mod/yii2-cms": "<1.9.2", + "yiisoft/yii": "<1.1.31", + "yiisoft/yii2": "<2.0.52", + "yiisoft/yii2-authclient": "<2.2.15", + "yiisoft/yii2-bootstrap": "<2.0.4", + "yiisoft/yii2-dev": "<=2.0.45", + "yiisoft/yii2-elasticsearch": "<2.0.5", + "yiisoft/yii2-gii": "<=2.2.4", + "yiisoft/yii2-jui": "<2.0.4", + "yiisoft/yii2-redis": "<2.0.20", + "yikesinc/yikes-inc-easy-mailchimp-extender": "<6.8.6", + "yoast-seo-for-typo3/yoast_seo": "<7.2.3", + "yourls/yourls": "<=1.10.2", + "yuan1994/tpadmin": "<=1.3.12", + "yungifez/skuul": "<=2.6.5", + "z-push/z-push-dev": "<2.7.6", + "zencart/zencart": "<=1.5.7.0-beta", + "zendesk/zendesk_api_client_php": "<2.2.11", + "zendframework/zend-cache": ">=2.4,<2.4.8|>=2.5,<2.5.3", + "zendframework/zend-captcha": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-crypt": ">=2,<2.4.9|>=2.5,<2.5.2", + "zendframework/zend-db": "<2.2.10|>=2.3,<2.3.5", + "zendframework/zend-developer-tools": ">=1.2.2,<1.2.3", + "zendframework/zend-diactoros": "<1.8.4", + "zendframework/zend-feed": "<2.10.3", + "zendframework/zend-form": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-http": "<2.8.1", + "zendframework/zend-json": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zend-ldap": ">=2,<2.0.99|>=2.1,<2.1.99|>=2.2,<2.2.8|>=2.3,<2.3.3", + "zendframework/zend-mail": "<2.4.11|>=2.5,<2.7.2", + "zendframework/zend-navigation": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-session": ">=2,<2.2.9|>=2.3,<2.3.4", + "zendframework/zend-validator": ">=2.3,<2.3.6", + "zendframework/zend-view": ">=2,<2.2.7|>=2.3,<2.3.1", + "zendframework/zend-xmlrpc": ">=2.1,<2.1.6|>=2.2,<2.2.6", + "zendframework/zendframework": "<=3", + "zendframework/zendframework1": "<1.12.20", + "zendframework/zendopenid": "<2.0.2", + "zendframework/zendrest": "<2.0.2", + "zendframework/zendservice-amazon": "<2.0.3", + "zendframework/zendservice-api": "<1", + "zendframework/zendservice-audioscrobbler": "<2.0.2", + "zendframework/zendservice-nirvanix": "<2.0.2", + "zendframework/zendservice-slideshare": "<2.0.2", + "zendframework/zendservice-technorati": "<2.0.2", + "zendframework/zendservice-windowsazure": "<2.0.2", + "zendframework/zendxml": ">=1,<1.0.1", + "zenstruck/collection": "<0.2.1", + "zetacomponents/mail": "<1.8.2", + "zf-commons/zfc-user": "<1.2.2", + "zfcampus/zf-apigility-doctrine": ">=1,<1.0.3", + "zfr/zfr-oauth2-server-module": "<0.1.2", + "zoujingli/thinkadmin": "<=6.1.53" + }, + "default-branch": true, + "type": "metapackage", + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Marco Pivetta", + "email": "ocramius@gmail.com", + "role": "maintainer" + }, + { + "name": "Ilya Tribusean", + "email": "slash3b@gmail.com", + "role": "maintainer" + } + ], + "description": "Prevents installation of composer packages with known security vulnerabilities: no API, simply require it", + "keywords": [ + "dev" + ], + "support": { + "issues": "https://github.com/Roave/SecurityAdvisories/issues", + "source": "https://github.com/Roave/SecurityAdvisories/tree/latest" + }, + "funding": [ + { + "url": "https://github.com/Ocramius", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/roave/security-advisories", + "type": "tidelift" + } + ], + "time": "2026-02-05T22:08:29+00:00" + }, { "name": "sebastian/cli-parser", "version": "1.0.2", @@ -4193,7 +5212,8 @@ "aliases": [], "minimum-stability": "stable", "stability-flags": { - "nextcloud/ocp": 20 + "nextcloud/ocp": 20, + "roave/security-advisories": 20 }, "prefer-stable": false, "prefer-lowest": false, From 485fa1d8961413cda4e14db8b90f2040499d4212 Mon Sep 17 00:00:00 2001 From: Carl Schwan Date: Fri, 6 Feb 2026 19:07:49 +0100 Subject: [PATCH 4/4] fix(psalm): Fix psalm with NC 33 Signed-off-by: Carl Schwan --- lib/AppInfo/Application.php | 5 ++- lib/FilteredSettingsManager.php | 1 + lib/GuestManager.php | 5 ++- lib/Hooks.php | 2 +- lib/Repair/ResetEmails.php | 2 +- lib/Service/InviteService.php | 2 +- lib/Storage/DirMask.php | 2 +- lib/Storage/DirMaskCache.php | 19 ++++---- lib/UserBackend.php | 6 +-- .../features/bootstrap/GuestsContext.php | 12 ++--- tests/unit/Controller/UsersControllerTest.php | 45 +++++++------------ 11 files changed, 47 insertions(+), 54 deletions(-) diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 622b29be..cbec91c3 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -65,9 +65,10 @@ public function boot(IBootContext $context): void { } private function setupGuestManagement(ContainerInterface $container, ContainerInterface $server): void { + /** @var Hooks $hookManager */ $hookManager = $container->get(Hooks::class); - $server->get(IEventDispatcher::class)->addListener(ShareCreatedEvent::class, [$hookManager, 'handlePostShare']); - $server->get(IEventDispatcher::class)->addListener(UserFirstTimeLoggedInEvent::class, [$hookManager, 'handleFirstLogin']); + $server->get(IEventDispatcher::class)->addListener(ShareCreatedEvent::class, $hookManager->handlePostShare(...)); + $server->get(IEventDispatcher::class)->addListener(UserFirstTimeLoggedInEvent::class, $hookManager->handleFirstLogin(...)); } private function setupGuestRestrictions(ContainerInterface $container, ContainerInterface $server): void { diff --git a/lib/FilteredSettingsManager.php b/lib/FilteredSettingsManager.php index 0c1843ce..c0206b8e 100644 --- a/lib/FilteredSettingsManager.php +++ b/lib/FilteredSettingsManager.php @@ -66,6 +66,7 @@ public function getSection(string $type, string $sectionId): ?IIconSection { } public function getAdminDelegatedSettings(): array { + /** @psalm-suppress RedundantCondition we support older version of Server */ if (method_exists($this->manager, 'getAdminDelegatedSettings')) { return $this->manager->getAdminDelegatedSettings(); } diff --git a/lib/GuestManager.php b/lib/GuestManager.php index 0bc13d12..e0b1fadb 100644 --- a/lib/GuestManager.php +++ b/lib/GuestManager.php @@ -105,6 +105,9 @@ public function createGuest(?IUser $createdBy, string $userId, string $email, st return $user; } + /** + * @return list + */ public function listGuests(): array { return $this->userBackend->getUsers(); } @@ -114,7 +117,7 @@ public function getGuestsInfo(): array { $guests = array_keys($displayNames); $shareCounts = $this->getShareCountForUsers($guests); $createdBy = $this->config->getUserValueForUsers('guests', 'created_by', $guests); - return array_map(function (int|string $uid) use ($createdBy, $displayNames, $shareCounts): array { + return array_map(function (string $uid) use ($createdBy, $displayNames, $shareCounts): array { $allSharesCount = count(array_merge( $this->shareManager->getSharedWith($uid, IShare::TYPE_USER, null, -1, 0), $this->shareManager->getSharedWith($uid, IShare::TYPE_GROUP, null, -1, 0), diff --git a/lib/Hooks.php b/lib/Hooks.php index 398863bd..a8f7888d 100644 --- a/lib/Hooks.php +++ b/lib/Hooks.php @@ -50,7 +50,7 @@ public function handlePostShare(ShareCreatedEvent $event): void { return; } - if (!($share->getNodeType() === 'folder' || $share->getNodeType() === 'file')) { + if ($share->getNodeType() !== 'folder' && $share->getNodeType() !== 'file') { $this->logger->debug( 'ignoring share for itemType ' . $share->getNodeType(), ['app' => Application::APP_ID] diff --git a/lib/Repair/ResetEmails.php b/lib/Repair/ResetEmails.php index 824f5215..b9c560da 100644 --- a/lib/Repair/ResetEmails.php +++ b/lib/Repair/ResetEmails.php @@ -44,7 +44,7 @@ public function run(IOutput $output): void { continue; } - $expectedEmail = $this->config->getUserValue($guestId, Application::APP_ID, 'email', strtolower((string)$guestId)); + $expectedEmail = $this->config->getUserValue($guestId, Application::APP_ID, 'email', strtolower($guestId)); $currentEmail = $guest->getSystemEMailAddress() ?? ''; if (strtolower($currentEmail) !== $expectedEmail) { diff --git a/lib/Service/InviteService.php b/lib/Service/InviteService.php index 7a804a89..1316a02a 100644 --- a/lib/Service/InviteService.php +++ b/lib/Service/InviteService.php @@ -33,7 +33,7 @@ public function sendInvite(string $userId, string $guest, ?IShare $share = null) } try { - // user has not yet activated his account + // user has not yet activated their account $decryptedToken = $this->crypto->decrypt($passwordToken, strtolower($guest) . $this->config->getSystemValue('secret')); [, $token] = explode(':', $decryptedToken); $lang = $this->config->getUserValue($guest, 'core', 'lang', ''); diff --git a/lib/Storage/DirMask.php b/lib/Storage/DirMask.php index 2694ee05..9b02bed6 100644 --- a/lib/Storage/DirMask.php +++ b/lib/Storage/DirMask.php @@ -179,6 +179,6 @@ public function getCache($path = '', $storage = null): ICache { $storage = $this; } $sourceCache = $this->storage->getCache($path, $storage); - return new DirMaskCache($sourceCache, $this->mask, fn (string $path): bool => $this->checkPath($path)); + return new DirMaskCache($sourceCache, $this->mask, $this->checkPath(...)); } } diff --git a/lib/Storage/DirMaskCache.php b/lib/Storage/DirMaskCache.php index f804a1b6..f65db450 100644 --- a/lib/Storage/DirMaskCache.php +++ b/lib/Storage/DirMaskCache.php @@ -8,21 +8,24 @@ namespace OCA\Guests\Storage; +use Closure; use OC\Files\Cache\Wrapper\CachePermissionsMask; use OCP\Files\Cache\ICache; +use OCP\Files\Cache\ICacheEntry; class DirMaskCache extends CachePermissionsMask { - private $checkPath; - - public function __construct(ICache $cache, int $mask, callable $checkPath) { + /** + * @param Closure(string $path): bool $checkPath + */ + public function __construct( + ICache $cache, + int $mask, + private readonly Closure $checkPath, + ) { parent::__construct($cache, $mask); - $this->checkPath = $checkPath; } - /** - * @psalm-suppress MethodSignatureMustProvideReturnType - */ - protected function formatCacheEntry($entry) { + protected function formatCacheEntry($entry): ICacheEntry|false { $checkPath = $this->checkPath; if ($checkPath($entry['path'])) { return parent::formatCacheEntry($entry); diff --git a/lib/UserBackend.php b/lib/UserBackend.php index 61f03846..17c9d10c 100644 --- a/lib/UserBackend.php +++ b/lib/UserBackend.php @@ -205,7 +205,7 @@ public function getDisplayName($uid): string { * @param string $search * @param int|null $limit * @param int|null $offset - * @return array an array of all displayNames (value) and the corresponding uids (key) + * @return array an array of all displayNames (value) and the corresponding uids (key) */ public function getDisplayNames($search = '', $limit = null, $offset = null): array { if (!$this->allowListing) { @@ -334,11 +334,11 @@ private function loadUser($uid): bool { * @param string $search * @param null|int $limit * @param null|int $offset - * @return string[] an array of all uids + * @return list an array of all uids */ public function getUsers($search = '', $limit = null, $offset = null): array { $users = $this->getDisplayNames($search, $limit, $offset); - $userIds = array_map(fn (int|string $uid): string => (string)$uid, array_keys($users)); + $userIds = array_keys($users); sort($userIds, SORT_STRING | SORT_FLAG_CASE); return $userIds; } diff --git a/tests/integration/features/bootstrap/GuestsContext.php b/tests/integration/features/bootstrap/GuestsContext.php index 41b8602e..b2f2442b 100644 --- a/tests/integration/features/bootstrap/GuestsContext.php +++ b/tests/integration/features/bootstrap/GuestsContext.php @@ -73,12 +73,12 @@ public function deleteGuestUser(string $guestDisplayName): void { /*Processes the body of an email sent and gets the reset password url It depends on the content of the email*/ - public function extractResetPasswordUrl($emailBody): string { + public function extractResetPasswordUrl(string $emailBody): string { $knownString = 'Activate your guest account at ownCloud by setting a password: '; $nextString = 'Then view it'; - $posKnownString = strpos((string)$emailBody, $knownString); - $posNextString = strpos((string)$emailBody, $nextString, $posKnownString + strlen($knownString)); - $urlResetPasswd = substr((string)$emailBody, + $posKnownString = strpos($emailBody, $knownString); + $posNextString = strpos($emailBody, $nextString, $posKnownString + strlen($knownString)); + $urlResetPasswd = substr($emailBody, $posKnownString + strlen($knownString), $posNextString - ($posKnownString + strlen($knownString))); $urlResetPasswd = preg_replace('/[\s]+/mu', ' ', $urlResetPasswd); @@ -87,8 +87,8 @@ public function extractResetPasswordUrl($emailBody): string { } /*Function to prepare the set password url from the reset password form one*/ - public function getSetPasswordUrl($urlResetPasswd): string { - $resetUrlParts = explode('/', (string)$urlResetPasswd); + public function getSetPasswordUrl(string $urlResetPasswd): string { + $resetUrlParts = explode('/', $urlResetPasswd); array_splice($resetUrlParts, 5, 2, 'set'); return implode('/', $resetUrlParts); } diff --git a/tests/unit/Controller/UsersControllerTest.php b/tests/unit/Controller/UsersControllerTest.php index c21cd986..b6858a19 100644 --- a/tests/unit/Controller/UsersControllerTest.php +++ b/tests/unit/Controller/UsersControllerTest.php @@ -31,36 +31,21 @@ use Test\TestCase; class UsersControllerTest extends TestCase { - /** @var IRequest|MockObject */ - private $request; - /** @var IUserManager|MockObject */ - private $userManager; - /** @var IL10N|MockObject */ - private $l10n; - /** @var Config|MockObject */ - private ?Config $guestsConfig = null; - /** @var IMailer|MockObject */ - private $mailer; - /** @var GuestManager|MockObject */ - private $guestManager; - /** @var IUserSession|MockObject */ - private $userSession; - /** @var ISubAdmin|MockObject */ - private $subAdmin; - /** @var IGroupManager|MockObject */ - private $groupManager; - /** @var TransferService|MockObject */ - private $transferService; - /** @var TransferMapper|MockObject */ - private $transferMapper; - /** @var IAppConfig|MockObject */ - private $appConfig; - /** @var IConfig|MockObject */ - private $config; - /** @var InviteService|MockObject */ - private $inviteService; - - private ?UsersController $controller = null; + private IRequest&MockObject $request; + private IUserManager&MockObject $userManager; + private IL10N&MockObject $l10n; + private Config $guestsConfig; + private IMailer&MockObject $mailer; + private GuestManager&MockObject $guestManager; + private IUserSession&MockObject $userSession; + private ISubAdmin&MockObject $subAdmin; + private IGroupManager&MockObject $groupManager; + private TransferService&MockObject $transferService; + private TransferMapper&MockObject $transferMapper; + private IAppConfig&MockObject $appConfig; + private IConfig&MockObject $config; + private InviteService&MockObject $inviteService; + private UsersController $controller; protected function setUp(): void { parent::setUp();