diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index b59e5d67a..9ed5e72fb 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -7,3 +7,5 @@ 21f740715b4acea791cf14958bd1076230990e32 # Update to coding-standard 1.3.2 5a42da490862ec9f0a7eef5702fc4a669d5c53b1 +# Introducing rector +4f58f1154a933711f823be65bb4d2bd4e92d0794 diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index ea5670235..0d1a2d241 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -41,64 +41,29 @@ jobs: strategy: fail-fast: false matrix: - php-versions: [ "8.0", "8.1", "8.2", "8.3", "8.4" ] + php-versions: [ "8.1", "8.2", "8.3", "8.4" ] databases: [ "mysql" ] - server-versions: [ "stable28", "stable29", "stable30", "stable31", "master" ] + server-versions: [ "stable30", "stable31", "master" ] exclude: - server-versions: "master" - php-versions: "8.0" - databases: "mysql" - - server-versions: "master" - php-versions: "8.2" - databases: "mysql" - - server-versions: "stable31" - php-versions: "8.2" - databases: "mysql" - - server-versions: "stable31" php-versions: "8.1" databases: "mysql" - - server-versions: "stable31" - php-versions: "8.0" - databases: "mysql" - server-versions: "stable30" php-versions: "8.2" databases: "mysql" - - server-versions: "stable30" - php-versions: "8.1" - databases: "mysql" - - server-versions: "stable30" - php-versions: "8.0" - databases: "mysql" - - server-versions: "stable29" - php-versions: "8.2" - databases: "mysql" - - server-versions: "stable29" - php-versions: "8.1" - databases: "mysql" - - server-versions: "stable28" - php-versions: "8.1" - databases: "mysql" - - server-versions: "stable28" - php-versions: "8.4" - databases: "mysql" - - server-versions: "stable29" - php-versions: "8.4" - databases: "mysql" - server-versions: "stable30" php-versions: "8.4" databases: "mysql" include: - - server-versions: "stable28" - php-versions: "8.2" + - server-versions: "stable30" + php-versions: "8.3" databases: "sqlite" - - server-versions: "stable28" - php-versions: "8.2" + - server-versions: "stable30" + php-versions: "8.3" databases: "pgsql" name: Integration php${{ matrix.php-versions }}-${{ matrix.databases }}-${{ matrix.server-versions }} - #container: ubuntu - services: postgres: image: postgres:14 diff --git a/.patches/php-saml-600.patch b/.patches/php-saml-600.patch new file mode 100644 index 000000000..2ebe1e098 --- /dev/null +++ b/.patches/php-saml-600.patch @@ -0,0 +1,81 @@ +SPDX-FileCopyrightText: 2024 Nextcloud GmbH +SPDX-License-Identifier: MIT +From 3628572e9916f747a450484c35c51a5164b00c54 Mon Sep 17 00:00:00 2001 +From: Arthur Schiwon +Date: Fri, 8 Nov 2024 18:05:46 +0100 +Subject: [PATCH] Include PHP 8.4 test coverage + +- also fixes deprecations on implicit null + +Signed-off-by: Arthur Schiwon +--- + .github/workflows/php-package.yml | 6 +++--- + src/Saml2/Auth.php | 2 +- + src/Saml2/Settings.php | 2 +- + src/Saml2/Utils.php | 2 +- + 4 files changed, 6 insertions(+), 6 deletions(-) + +diff --git a/.github/workflows/php-package.yml b/.github/workflows/php-package.yml +index 7840700a..6321b7ef 100644 +--- a/.github/workflows/php-package.yml ++++ b/.github/workflows/php-package.yml +@@ -16,7 +16,7 @@ jobs: + fail-fast: false + matrix: + operating-system: ['ubuntu-latest'] +- php-versions: [7.3, 7.4, 8.0, 8.1, 8.2, 8.3] ++ php-versions: [7.3, 7.4, 8.0, 8.1, 8.2, 8.3, 8.4] + steps: + - name: Setup PHP, with composer and extensions + uses: shivammathur/setup-php@v2 #https://github.com/shivammathur/setup-php +@@ -46,9 +46,9 @@ jobs: + php vendor/bin/phploc src/. + mkdir -p tests/build/dependences + php vendor/bin/pdepend --summary-xml=tests/build/logs/dependence-summary.xml --jdepend-chart=tests/build/dependences/jdepend.svg --overview-pyramid=tests/build/dependences/pyramid.svg src/. +- ++ + - name: PHP Code Sniffer + run: php vendor/bin/phpcs --standard=tests/ZendModStandard src/Saml2 demo1 demo2 endpoints tests/src +- ++ + - name: Run unit tests + run: vendor/bin/phpunit --verbose --debug +diff --git a/src/Saml2/Auth.php b/src/Saml2/Auth.php +index 35037031..a860b358 100644 +--- a/src/Saml2/Auth.php ++++ b/src/Saml2/Auth.php +@@ -171,7 +171,7 @@ class Auth + * @throws Exception + * @throws Error + */ +- public function __construct(array $settings = null, bool $spValidationOnly = false) ++ public function __construct(?array $settings = null, bool $spValidationOnly = false) + { + $this->_settings = new Settings($settings, $spValidationOnly); + } +diff --git a/src/Saml2/Settings.php b/src/Saml2/Settings.php +index 0ca095a9..c750608e 100644 +--- a/src/Saml2/Settings.php ++++ b/src/Saml2/Settings.php +@@ -120,7 +120,7 @@ class Settings + * @throws Error If any settings parameter is invalid + * @throws Exception If Settings is incorrectly supplied + */ +- public function __construct(array $settings = null,bool $spValidationOnly = false) ++ public function __construct(?array $settings = null,bool $spValidationOnly = false) + { + $this->_spValidationOnly = $spValidationOnly; + $this->_loadPaths(); +diff --git a/src/Saml2/Utils.php b/src/Saml2/Utils.php +index eea057ff..5742a063 100644 +--- a/src/Saml2/Utils.php ++++ b/src/Saml2/Utils.php +@@ -954,7 +954,7 @@ public static function getExpireTime($cacheDuration = null, $validUntil = null) + * + * @return DOMNodeList The queried nodes + */ +- public static function query(DOMDocument $dom, $query, DOMElement $context = null) ++ public static function query(DOMDocument $dom, $query, ?DOMElement $context = null) + { + $xpath = new DOMXPath($dom); + $xpath->registerNamespace('samlp', Constants::NS_SAMLP); diff --git a/Makefile b/Makefile index 880cf22a9..ba3e76146 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,7 @@ appstore: clean --exclude=.github \ --exclude=.gitignore \ --exclude=.git-blame-ignore-revs \ + --exclude=.patches \ --exclude=.php-cs-fixer.dist.php \ --exclude=.scrutinizer.yml \ --exclude=.travis.yml \ @@ -45,10 +46,12 @@ appstore: clean --exclude=/Makefile \ --exclude=/psalm.xml \ --exclude=/README.md \ + --exclude=/rector.php \ --exclude=/screenshots \ --exclude=/tests \ --exclude=/translationfiles \ - --exclude=/vendor/cweagens \ + --exclude=/vendor/cweagans \ + --exclude=/vendor-bin \ $(project_dir)/ $(sign_dir)/$(app_name) tar -czf $(build_dir)/$(app_name).tar.gz \ -C $(sign_dir) $(app_name) diff --git a/appinfo/info.xml b/appinfo/info.xml index 260757eda..c6980d991 100644 --- a/appinfo/info.xml +++ b/appinfo/info.xml @@ -20,7 +20,7 @@ The following providers are supported and tested at the moment: * Any other provider that authenticates using the environment variable While theoretically any other authentication provider implementing either one of those standards is compatible, we like to note that they are not part of any internal test matrix.]]> - 6.6.0 + 7.0.0 agpl Lukas Reschke User_SAML @@ -37,7 +37,7 @@ While theoretically any other authentication provider implementing either one of https://raw.githubusercontent.com/nextcloud/user_saml/master/screenshots/1.png https://raw.githubusercontent.com/nextcloud/user_saml/master/screenshots/2.png - + diff --git a/composer.json b/composer.json index b60e4e377..9729c03ac 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "optimize-autoloader": true, "classmap-authoritative": true, "platform": { - "php": "8.0.2" + "php": "8.1.32" }, "allow-plugins": { "cweagans/composer-patches": true, @@ -14,7 +14,7 @@ "extra": { "patches": { "onelogin/php-saml": { - "PHP 8.4 compatibility": "https://patch-diff.githubusercontent.com/raw/SAML-Toolkits/php-saml/pull/600.patch" + "PHP 8.4 compatibility": ".patches/php-saml-600.patch" } }, "bamarni-bin": { @@ -35,15 +35,17 @@ "psalm:fix": "psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MissingParamType,InvalidFalsableReturnType", "psalm:update-baseline": "psalm --threads=1 --update-baseline", "lint": "find . -name \\*.php -not -path '*/vendor/*' -print0 | xargs -0 -n1 php -l", + "rector:check": "rector --dry-run", + "rector:fix": "rector", "test:unit": "phpunit -c tests/unit/phpunit.xml" }, "require-dev": { - "phpunit/phpunit": "^9", + "phpunit/phpunit": "^9.6", "bamarni/composer-bin-plugin": "^1.8" }, "require": { "onelogin/php-saml": "^4.2", - "firebase/php-jwt": "^6.10", + "firebase/php-jwt": "^6.11", "cweagans/composer-patches": "^1.7" } } diff --git a/composer.lock b/composer.lock index 2f93d19ff..3d5d494e2 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": "c2a60442804de9eeffd93be1e2878e35", + "content-hash": "45cd7794b245c1413c81f5f5e244c09f", "packages": [ { "name": "cweagans/composer-patches", @@ -284,30 +284,30 @@ }, { "name": "doctrine/instantiator", - "version": "1.5.0", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", + "reference": "c6222283fa3f4ac679f8b9ced9a4e23f163e80d0", "shasum": "" }, "require": { - "php": "^7.1 || ^8.0" + "php": "^8.1" }, "require-dev": { - "doctrine/coding-standard": "^9 || ^11", + "doctrine/coding-standard": "^11", "ext-pdo": "*", "ext-phar": "*", - "phpbench/phpbench": "^0.16 || ^1", - "phpstan/phpstan": "^1.4", - "phpstan/phpstan-phpunit": "^1", - "phpunit/phpunit": "^7.5 || ^8.5 || ^9.5", - "vimeo/psalm": "^4.30 || ^5.4" + "phpbench/phpbench": "^1.2", + "phpstan/phpstan": "^1.9.4", + "phpstan/phpstan-phpunit": "^1.3", + "phpunit/phpunit": "^9.5.27", + "vimeo/psalm": "^5.4" }, "type": "library", "autoload": { @@ -334,7 +334,7 @@ ], "support": { "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" + "source": "https://github.com/doctrine/instantiator/tree/2.0.0" }, "funding": [ { @@ -350,20 +350,20 @@ "type": "tidelift" } ], - "time": "2022-12-30T00:15:36+00:00" + "time": "2022-12-30T00:23:10+00:00" }, { "name": "myclabs/deep-copy", - "version": "1.13.0", + "version": "1.13.1", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "024473a478be9df5fdaca2c793f2232fe788e414" + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414", - "reference": "024473a478be9df5fdaca2c793f2232fe788e414", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/1720ddd719e16cf0db4eb1c6eca108031636d46c", + "reference": "1720ddd719e16cf0db4eb1c6eca108031636d46c", "shasum": "" }, "require": { @@ -402,7 +402,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.1" }, "funding": [ { @@ -410,7 +410,7 @@ "type": "tidelift" } ], - "time": "2025-02-12T12:17:51+00:00" + "time": "2025-04-29T12:36:36+00:00" }, { "name": "nikic/php-parser", @@ -909,16 +909,16 @@ }, { "name": "phpunit/phpunit", - "version": "9.6.22", + "version": "9.6.23", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c" + "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/f80235cb4d3caa59ae09be3adf1ded27521d1a9c", - "reference": "f80235cb4d3caa59ae09be3adf1ded27521d1a9c", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", + "reference": "43d2cb18d0675c38bd44982a5d1d88f6d53d8d95", "shasum": "" }, "require": { @@ -929,7 +929,7 @@ "ext-mbstring": "*", "ext-xml": "*", "ext-xmlwriter": "*", - "myclabs/deep-copy": "^1.12.1", + "myclabs/deep-copy": "^1.13.1", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", "php": ">=7.3", @@ -992,7 +992,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/phpunit/issues", "security": "https://github.com/sebastianbergmann/phpunit/security/policy", - "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.22" + "source": "https://github.com/sebastianbergmann/phpunit/tree/9.6.23" }, "funding": [ { @@ -1003,12 +1003,20 @@ "url": "https://github.com/sebastianbergmann", "type": "github" }, + { + "url": "https://liberapay.com/sebastianbergmann", + "type": "liberapay" + }, + { + "url": "https://thanks.dev/u/gh/sebastianbergmann", + "type": "thanks_dev" + }, { "url": "https://tidelift.com/funding/github/packagist/phpunit/phpunit", "type": "tidelift" } ], - "time": "2024-12-05T13:48:26+00:00" + "time": "2025-05-02T06:40:34+00:00" }, { "name": "sebastian/cli-parser", @@ -2032,7 +2040,7 @@ "platform": {}, "platform-dev": {}, "platform-overrides": { - "php": "8.0.2" + "php": "8.1.32" }, "plugin-api-version": "2.6.0" } diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 491e9e104..d98ce5cb2 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -53,14 +53,12 @@ public function register(IRegistrationContext $context): void { $context->registerMiddleware(OnlyLoggedInMiddleware::class); $context->registerEventListener(BeforeTemplateRenderedEvent::class, LoadAdditionalScriptsListener::class); $context->registerEventListener(SabrePluginAddEvent::class, SabrePluginEventListener::class); - $context->registerService(DavPlugin::class, function (ContainerInterface $c) { - return new DavPlugin( - $c->get(ISession::class), - $c->get(IConfig::class), - $_SERVER, - $c->get(SAMLSettings::class) - ); - }); + $context->registerService(DavPlugin::class, fn (ContainerInterface $c) => new DavPlugin( + $c->get(ISession::class), + $c->get(IConfig::class), + $_SERVER, + $c->get(SAMLSettings::class) + )); } public function boot(IBootContext $context): void { @@ -81,7 +79,7 @@ public function boot(IBootContext $context): void { IEventDispatcher $dispatcher, CsrfTokenManager $csrfTokenManager, bool $isCLI, - ) { + ): void { $groupBackend = Server::get(GroupBackend::class); Server::get(IGroupManager::class)->addBackend($groupBackend); @@ -157,7 +155,7 @@ public function boot(IBootContext $context): void { ($request->getPathInfo() === '/login')) { try { $params = $request->getParams(); - } catch (\LogicException $e) { + } catch (\LogicException) { // ignore exception when PUT is called since getParams cannot parse parameters in that case } if (isset($params['direct']) && ($params['direct'] === 1 || $params['direct'] === '1')) { @@ -173,7 +171,7 @@ public function boot(IBootContext $context): void { if ($redirectSituation === true && $showLoginOptions) { try { $params = $request->getParams(); - } catch (\LogicException $e) { + } catch (\LogicException) { // ignore exception when PUT is called since getParams cannot parse parameters in that case } $redirectUrl = ''; @@ -194,7 +192,7 @@ public function boot(IBootContext $context): void { if ($redirectSituation === true) { try { $params = $request->getParams(); - } catch (\LogicException $e) { + } catch (\LogicException) { // ignore exception when PUT is called since getParams cannot parse parameters in that case } $originalUrl = ''; diff --git a/lib/Command/ConfigCreate.php b/lib/Command/ConfigCreate.php index 3b9d9953a..5625bc5ae 100644 --- a/lib/Command/ConfigCreate.php +++ b/lib/Command/ConfigCreate.php @@ -15,7 +15,7 @@ class ConfigCreate extends Base { public function __construct( - private SAMLSettings $samlSettings, + private readonly SAMLSettings $samlSettings, ) { parent::__construct(); } diff --git a/lib/Command/ConfigDelete.php b/lib/Command/ConfigDelete.php index 090e39345..362369d05 100644 --- a/lib/Command/ConfigDelete.php +++ b/lib/Command/ConfigDelete.php @@ -17,7 +17,7 @@ class ConfigDelete extends Base { public function __construct( - private SAMLSettings $samlSettings, + private readonly SAMLSettings $samlSettings, ) { parent::__construct(); } @@ -43,7 +43,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int try { $this->samlSettings->delete($pId); $output->writeln('Provider deleted.'); - } catch (Exception $e) { + } catch (Exception) { $output->writeln('Provider with id: ' . $pId . ' does not exist.'); return 1; } diff --git a/lib/Command/ConfigGet.php b/lib/Command/ConfigGet.php index 998f8c5c8..05b14e282 100644 --- a/lib/Command/ConfigGet.php +++ b/lib/Command/ConfigGet.php @@ -16,7 +16,7 @@ class ConfigGet extends Base { public function __construct( - private SAMLSettings $samlSettings, + private readonly SAMLSettings $samlSettings, ) { parent::__construct(); } diff --git a/lib/Command/ConfigSet.php b/lib/Command/ConfigSet.php index 88e8aaa84..f474b9aff 100644 --- a/lib/Command/ConfigSet.php +++ b/lib/Command/ConfigSet.php @@ -18,7 +18,7 @@ class ConfigSet extends Base { public function __construct( - private SAMLSettings $samlSettings, + private readonly SAMLSettings $samlSettings, ) { parent::__construct(); } @@ -53,7 +53,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } try { $settings = $this->samlSettings->get($pId); - } catch (Exception $e) { + } catch (Exception) { $output->writeln('Provider with id: ' . $pId . ' does not exist.'); return 1; } diff --git a/lib/Command/GetMetadata.php b/lib/Command/GetMetadata.php index 8c8f277b1..d8fd48bcf 100644 --- a/lib/Command/GetMetadata.php +++ b/lib/Command/GetMetadata.php @@ -50,9 +50,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int $settingsArray = $this->samlSettings->getOneLoginSettingsArray($idp); $settings = new Settings($settingsArray); $metadata = $settings->getSPMetadata(); - $errors = $this->callWithXmlEntityLoader(function () use ($settings, $metadata) { - return $settings->validateMetadata($metadata); - }); + $errors = $this->callWithXmlEntityLoader(fn () => $settings->validateMetadata($metadata)); if (empty($errors)) { $output->writeln($metadata); } else { diff --git a/lib/Controller/SAMLController.php b/lib/Controller/SAMLController.php index 1cbb65b6e..be05127d6 100644 --- a/lib/Controller/SAMLController.php +++ b/lib/Controller/SAMLController.php @@ -281,9 +281,7 @@ public function login(int $idp = 1): Http\RedirectResponse|Http\TemplateResponse public function getMetadata(int $idp = 1): Http\DataDownloadResponse { $settings = new Settings($this->samlSettings->getOneLoginSettingsArray($idp)); $metadata = $settings->getSPMetadata(); - $errors = $this->callWithXmlEntityLoader(function () use ($settings, $metadata) { - return $settings->validateMetadata($metadata); - }); + $errors = $this->callWithXmlEntityLoader(fn () => $settings->validateMetadata($metadata)); if (empty($errors)) { return new Http\DataDownloadResponse($metadata, 'metadata.xml', 'text/xml'); } else { @@ -516,15 +514,13 @@ private function tryProcessSLOResponse(?int $idp): array { try { $auth = new Auth($this->samlSettings->getOneLoginSettingsArray($idp)); // validator (called with processSLO()) needs an XML entity loader - $targetUrl = $this->callWithXmlEntityLoader(function () use ($auth, $idp): string { - return $auth->processSLO( - true, // do not let processSLO to delete the entire session. Let userSession->logout do the job - null, - $this->samlSettings->usesSloWebServerDecode($idp), - null, - true - ); - }); + $targetUrl = $this->callWithXmlEntityLoader(fn (): string => $auth->processSLO( + true, // do not let processSLO to delete the entire session. Let userSession->logout do the job + null, + $this->samlSettings->usesSloWebServerDecode($idp), + null, + true + )); if ($auth->getLastErrorReason() === null) { return [$targetUrl, $auth]; } diff --git a/lib/Controller/SettingsController.php b/lib/Controller/SettingsController.php index 91de792df..ba777fa0c 100644 --- a/lib/Controller/SettingsController.php +++ b/lib/Controller/SettingsController.php @@ -21,9 +21,9 @@ class SettingsController extends Controller { public function __construct( $appName, IRequest $request, - private IConfig $config, - private Admin $admin, - private SAMLSettings $samlSettings, + private readonly IConfig $config, + private readonly Admin $admin, + private readonly SAMLSettings $samlSettings, ) { parent::__construct($appName, $request); } @@ -61,12 +61,12 @@ public function getSamlProviderSettings(int $providerId): array { } foreach ($content as $setting => $details) { /* use security as category instead of security-* */ - if (strpos($category, 'security-') === 0) { + if (str_starts_with($category, 'security-')) { $category = 'security'; } // make sure we properly fetch the attribute mapping // as this is the only category that has the saml- prefix on config keys - if (strpos($category, 'attribute-mapping') === 0) { + if (str_starts_with($category, 'attribute-mapping')) { $category = 'attribute-mapping'; $key = 'saml-attribute-mapping' . '-' . $setting; } elseif ($category === 'name-id-formats') { diff --git a/lib/Controller/TimezoneController.php b/lib/Controller/TimezoneController.php index 366ab0a6d..c7ee4eab2 100644 --- a/lib/Controller/TimezoneController.php +++ b/lib/Controller/TimezoneController.php @@ -19,9 +19,9 @@ class TimezoneController extends Controller { public function __construct( $appName, IRequest $request, - private IConfig $config, + private readonly IConfig $config, private $userId, - private ISession $session, + private readonly ISession $session, ) { parent::__construct($appName, $request); } diff --git a/lib/DavPlugin.php b/lib/DavPlugin.php index 4aa0c5744..8bef4bbe8 100644 --- a/lib/DavPlugin.php +++ b/lib/DavPlugin.php @@ -20,16 +20,16 @@ class DavPlugin extends ServerPlugin { private $server; public function __construct( - private ISession $session, - private IConfig $config, + private readonly ISession $session, + private readonly IConfig $config, private array $auth, - private SAMLSettings $samlSettings, + private readonly SAMLSettings $samlSettings, ) { } public function initialize(Server $server) { // before auth - $server->on('beforeMethod:*', [$this, 'beforeMethod'], 9); + $server->on('beforeMethod:*', $this->beforeMethod(...), 9); $this->server = $server; } diff --git a/lib/Db/ConfigurationsMapper.php b/lib/Db/ConfigurationsMapper.php index c5bca1754..f2cbed2ae 100644 --- a/lib/Db/ConfigurationsMapper.php +++ b/lib/Db/ConfigurationsMapper.php @@ -54,7 +54,7 @@ public function get(int $idp): array { /** @var ConfigurationsEntity $entity */ try { $entity = $this->findEntity($qb); - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { return []; } return $entity->getConfigurationArray(); @@ -70,7 +70,7 @@ public function reserveId(): int { try { $entity = $this->findEntity($qb); $newId = $entity->getId() + 1; // autoincrement manually - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { $newId = 1; } diff --git a/lib/GroupBackend.php b/lib/GroupBackend.php index 9630f00c9..67fcd75aa 100644 --- a/lib/GroupBackend.php +++ b/lib/GroupBackend.php @@ -186,7 +186,7 @@ public function createGroup(string $gid, ?string $samlGid = null): bool { try { // Add group $builder = $this->dbc->getQueryBuilder(); - $samlGid = $samlGid ?? $gid; + $samlGid ??= $gid; $result = $builder->insert(self::TABLE_GROUPS) ->setValue('gid', $builder->createNamedParameter($gid)) ->setValue('displayname', $builder->createNamedParameter($samlGid)) diff --git a/lib/GroupManager.php b/lib/GroupManager.php index 497359e9a..0c8e7187c 100644 --- a/lib/GroupManager.php +++ b/lib/GroupManager.php @@ -30,12 +30,12 @@ class GroupManager { public function __construct( protected IDBConnection $db, - private IGroupManager $groupManager, - private GroupBackend $ownGroupBackend, - private IConfig $config, - private IEventDispatcher $dispatcher, - private IJobList $jobList, - private SAMLSettings $settings, + private readonly IGroupManager $groupManager, + private readonly GroupBackend $ownGroupBackend, + private readonly IConfig $config, + private readonly IEventDispatcher $dispatcher, + private readonly IJobList $jobList, + private readonly SAMLSettings $settings, ) { } @@ -97,9 +97,7 @@ public function handleIncomingGroups(IUser $user, array $samlGroupNames): void { protected function updateUserGroups(IUser $user, array $samlGroupNames): void { $this->translateGroupToIds($samlGroupNames); $assignedGroups = $this->groupManager->getUserGroups($user); - $assignedGroupIds = array_map(function (IGroup $group) { - return $group->getGID(); - }, $assignedGroups); + $assignedGroupIds = array_map(fn (IGroup $group) => $group->getGID(), $assignedGroups); $groupsToRemove = $this->getGroupsToRemove($samlGroupNames, $assignedGroups); $groupsToAdd = $this->getGroupsToAdd($samlGroupNames, $assignedGroupIds); $this->handleUserUnassignedFromGroups($user, $groupsToRemove); @@ -107,7 +105,7 @@ protected function updateUserGroups(IUser $user, array $samlGroupNames): void { } protected function translateGroupToIds(array &$samlGroups): void { - array_walk($samlGroups, function (&$gid) { + array_walk($samlGroups, function (&$gid): void { $altGid = $this->ownGroupBackend->groupExistsWithDifferentGid($gid); if ($altGid !== null) { $gid = $altGid; @@ -155,7 +153,7 @@ protected function handleUserAssignedToGroups(IUser $user, $groupIds): void { protected function assignUserToGroup(IUser $user, string $gid): void { try { $group = $this->findGroup($gid); - } catch (GroupNotFoundException|NonMigratableGroupException $e) { + } catch (GroupNotFoundException|NonMigratableGroupException) { $providerId = $this->settings->getProviderId(); $settings = $this->settings->get($providerId); $groupPrefix = $settings['saml-attribute-mapping-group_mapping_prefix'] ?? SAMLSettings::DEFAULT_GROUP_PREFIX; diff --git a/lib/Helper/TXmlHelper.php b/lib/Helper/TXmlHelper.php index 6d8da6c09..aca78ab90 100644 --- a/lib/Helper/TXmlHelper.php +++ b/lib/Helper/TXmlHelper.php @@ -13,13 +13,9 @@ trait TXmlHelper { * @returns mixed returns the result of the callable parameter */ public function callWithXmlEntityLoader(callable $func) { - libxml_set_external_entity_loader(static function ($public, $system) { - return $system; - }); + libxml_set_external_entity_loader(static fn ($public, $system) => $system); $result = $func(); - libxml_set_external_entity_loader(static function () { - return null; - }); + libxml_set_external_entity_loader(static fn () => null); return $result; } } diff --git a/lib/Jobs/MigrateGroups.php b/lib/Jobs/MigrateGroups.php index 6265d2121..a2402a2a6 100644 --- a/lib/Jobs/MigrateGroups.php +++ b/lib/Jobs/MigrateGroups.php @@ -51,15 +51,13 @@ protected function run($argument) { $toMigrate = $this->getGroupsToMigrate($argument['gids'], $candidates); $migrated = $this->migrateGroups($toMigrate); $this->ownGroupManager->updateCandidatePool($migrated); - } catch (\RuntimeException $e) { + } catch (\RuntimeException) { return; } } protected function migrateGroups(array $toMigrate): array { - return array_filter($toMigrate, function ($gid) { - return $this->migrateGroup($gid); - }); + return array_filter($toMigrate, fn ($gid) => $this->migrateGroup($gid)); } protected function migrateGroup(string $gid): bool { diff --git a/lib/Listener/LoadAdditionalScriptsListener.php b/lib/Listener/LoadAdditionalScriptsListener.php index dd5b29331..470f955c9 100644 --- a/lib/Listener/LoadAdditionalScriptsListener.php +++ b/lib/Listener/LoadAdditionalScriptsListener.php @@ -20,9 +20,9 @@ /** @template-implements IEventListener */ class LoadAdditionalScriptsListener implements IEventListener { public function __construct( - private ISession $session, - private IUserSession $userSession, - private IConfig $config, + private readonly ISession $session, + private readonly IUserSession $userSession, + private readonly IConfig $config, ) { } diff --git a/lib/Middleware/OnlyLoggedInMiddleware.php b/lib/Middleware/OnlyLoggedInMiddleware.php index 475d71a18..21ee180af 100644 --- a/lib/Middleware/OnlyLoggedInMiddleware.php +++ b/lib/Middleware/OnlyLoggedInMiddleware.php @@ -22,9 +22,9 @@ class OnlyLoggedInMiddleware extends Middleware { public function __construct( - private IControllerMethodReflector $reflector, - private IUserSession $userSession, - private IURLGenerator $urlGenerator, + private readonly IControllerMethodReflector $reflector, + private readonly IUserSession $userSession, + private readonly IURLGenerator $urlGenerator, ) { } diff --git a/lib/Migration/RememberLocalGroupsForPotentialMigrations.php b/lib/Migration/RememberLocalGroupsForPotentialMigrations.php index af751b197..ba61a141c 100644 --- a/lib/Migration/RememberLocalGroupsForPotentialMigrations.php +++ b/lib/Migration/RememberLocalGroupsForPotentialMigrations.php @@ -19,8 +19,8 @@ class RememberLocalGroupsForPotentialMigrations implements IRepairStep { public function __construct( - private IGroupManager $groupManager, - private IConfig $config, + private readonly IGroupManager $groupManager, + private readonly IConfig $config, ) { } @@ -45,7 +45,7 @@ public function run(IOutput $output) { try { $backend = $this->findBackend(); $groupIds = $this->findGroupIds($backend); - } catch (UnexpectedValueException $e) { + } catch (UnexpectedValueException) { return; } diff --git a/lib/Migration/TransferGroupMembers.php b/lib/Migration/TransferGroupMembers.php index 68e134241..f5c4cac6b 100644 --- a/lib/Migration/TransferGroupMembers.php +++ b/lib/Migration/TransferGroupMembers.php @@ -16,8 +16,8 @@ class TransferGroupMembers implements IRepairStep { public function __construct( - private GroupMigration $groupMigration, - private LoggerInterface $logger, + private readonly GroupMigration $groupMigration, + private readonly LoggerInterface $logger, ) { } diff --git a/lib/Migration/Version5000Date20211025124248.php b/lib/Migration/Version5000Date20211025124248.php index a151fb53d..c475d15bc 100644 --- a/lib/Migration/Version5000Date20211025124248.php +++ b/lib/Migration/Version5000Date20211025124248.php @@ -221,7 +221,7 @@ protected function fetchPrefixes(): array { if ($prefixes === false) { return [1]; // 1 is the default value for providerIds } - return array_map('intval', explode(',', $prefixes)); + return array_map('intval', explode(',', (string)$prefixes)); } protected function deletePrefixes(): void { diff --git a/lib/SAMLSettings.php b/lib/SAMLSettings.php index 670704194..7fa932d3f 100644 --- a/lib/SAMLSettings.php +++ b/lib/SAMLSettings.php @@ -75,10 +75,10 @@ class SAMLSettings { private $configurationsLoadedState = self::LOADED_NONE; public function __construct( - private IURLGenerator $urlGenerator, - private IConfig $config, - private ISession $session, - private ConfigurationsMapper $mapper, + private readonly IURLGenerator $urlGenerator, + private readonly IConfig $config, + private readonly ISession $session, + private readonly ConfigurationsMapper $mapper, ) { } diff --git a/lib/Settings/Admin.php b/lib/Settings/Admin.php index d5be17a40..c2044f243 100644 --- a/lib/Settings/Admin.php +++ b/lib/Settings/Admin.php @@ -18,10 +18,10 @@ class Admin implements ISettings { public function __construct( - private IL10N $l10n, - private Defaults $defaults, - private IConfig $config, - private SAMLSettings $samlSettings, + private readonly IL10N $l10n, + private readonly Defaults $defaults, + private readonly IConfig $config, + private readonly SAMLSettings $samlSettings, ) { } diff --git a/lib/Settings/Section.php b/lib/Settings/Section.php index 506b79942..cd267ef71 100644 --- a/lib/Settings/Section.php +++ b/lib/Settings/Section.php @@ -14,8 +14,8 @@ class Section implements IIconSection { public function __construct( - private IL10N $l, - private IURLGenerator $url, + private readonly IL10N $l, + private readonly IURLGenerator $url, ) { } diff --git a/lib/UserBackend.php b/lib/UserBackend.php index 7e356e947..9abe2bf1f 100644 --- a/lib/UserBackend.php +++ b/lib/UserBackend.php @@ -34,16 +34,16 @@ class UserBackend extends ABackend implements IApacheBackend, IUserBackend, IGet private static $backends = []; public function __construct( - private IConfig $config, - private IURLGenerator $urlGenerator, - private ISession $session, - private IDBConnection $db, - private IUserManager $userManager, - private GroupManager $groupManager, - private SAMLSettings $settings, - private LoggerInterface $logger, - private UserData $userData, - private IEventDispatcher $eventDispatcher, + private readonly IConfig $config, + private readonly IURLGenerator $urlGenerator, + private readonly ISession $session, + private readonly IDBConnection $db, + private readonly IUserManager $userManager, + private readonly GroupManager $groupManager, + private readonly SAMLSettings $settings, + private readonly LoggerInterface $logger, + private readonly UserData $userData, + private readonly IEventDispatcher $eventDispatcher, ) { } @@ -90,7 +90,7 @@ public function createUserIfNotExists(string $uid, array $attributes = []): void //if attribute's value is an absolute path take this, otherwise append it to data dir //check for / at the beginning or pattern c:\ resp. c:/ if ($home[0] !== '/' - && !(strlen($home) > 3 && ctype_alpha($home[0]) + && !(strlen((string)$home) > 3 && ctype_alpha((string)$home[0]) && $home[1] === ':' && ($home[2] === '\\' || $home[2] === '/')) ) { $home = $this->config->getSystemValueString('datadirectory', @@ -158,10 +158,7 @@ public function getHome(string $uid) { $result = $qb->executeQuery(); $users = $result->fetchAll(); $result->closeCursor(); - if (isset($users[0]['home'])) { - return $users[0]['home']; - } - return false; + return $users[0]['home'] ?? false; } /** @@ -176,9 +173,7 @@ public function getHome(string $uid) { public function getUsers($search = '', $limit = null, $offset = null) { // shamelessly duplicated from \OC\User\Database $users = $this->getDisplayNames($search, $limit, $offset); - $userIds = array_map(function ($uid) { - return (string)$uid; - }, array_keys($users)); + $userIds = array_map(fn ($uid) => (string)$uid, array_keys($users)); sort($userIds, SORT_STRING | SORT_FLAG_CASE); return $userIds; } @@ -230,10 +225,7 @@ public function getDisplayName($uid): string { $result = $qb->executeQuery(); $users = $result->fetchAll(); $result->closeCursor(); - if (isset($users[0]['displayname'])) { - return $users[0]['displayname']; - } - return $uid; + return $users[0]['displayname'] ?? $uid; } /** diff --git a/lib/UserData.php b/lib/UserData.php index 13f15c5b4..2d7de95d9 100644 --- a/lib/UserData.php +++ b/lib/UserData.php @@ -16,8 +16,8 @@ class UserData { private $attributes; public function __construct( - private UserResolver $userResolver, - private SAMLSettings $samlSettings, + private readonly UserResolver $userResolver, + private readonly SAMLSettings $samlSettings, ) { } @@ -52,7 +52,7 @@ public function getEffectiveUid(): string { $uid = $this->testEncodedObjectGUID($uid); $uid = $this->userResolver->findExistingUserId($uid, true); $this->uid = $uid; - } catch (NoUserFoundException $e) { + } catch (NoUserFoundException) { return ''; } return $uid; @@ -67,16 +67,16 @@ public function getGroups(): array { return is_array($this->attributes[$mapping]) ? $this->attributes[$mapping] - : array_map('trim', explode(',', $this->attributes[$mapping])); + : array_map('trim', explode(',', (string)$this->attributes[$mapping])); } protected function extractSamlUserId(): string { $uidMapping = $this->getUidMappingAttribute(); if ($uidMapping !== null && isset($this->attributes[$uidMapping])) { if (is_array($this->attributes[$uidMapping])) { - return trim($this->attributes[$uidMapping][0]); + return trim((string)$this->attributes[$uidMapping][0]); } else { - return trim($this->attributes[$uidMapping]); + return trim((string)$this->attributes[$uidMapping]); } } return ''; @@ -110,7 +110,7 @@ public function testEncodedObjectGUID(string $uid): string { * @see \OCA\User_LDAP\Access::convertObjectGUID2Str */ protected function convertObjectGUID2Str($oguid): string { - $hex_guid = bin2hex($oguid); + $hex_guid = bin2hex((string)$oguid); $hex_guid_to_guid_str = ''; for ($k = 1; $k <= 4; ++$k) { $hex_guid_to_guid_str .= substr($hex_guid, 8 - 2 * $k, 2); diff --git a/lib/UserResolver.php b/lib/UserResolver.php index 327fb01e3..9d9dfac02 100644 --- a/lib/UserResolver.php +++ b/lib/UserResolver.php @@ -32,7 +32,7 @@ public function findExistingUserId(string $rawUidCandidate, bool $force = false) } try { $sanitized = $this->sanitizeUserIdCandidate($rawUidCandidate); - } catch (\InvalidArgumentException $e) { + } catch (\InvalidArgumentException) { $sanitized = ''; } if ($this->userManager->userExists($sanitized)) { @@ -57,7 +57,7 @@ public function userExists(string $uid, bool $force = false): bool { try { $this->findExistingUserId($uid, $force); return true; - } catch (NoUserFoundException $e) { + } catch (NoUserFoundException) { return false; } } diff --git a/psalm.xml b/psalm.xml index a3d67bf33..ee6332947 100644 --- a/psalm.xml +++ b/psalm.xml @@ -11,7 +11,7 @@ errorBaseline="tests/psalm-baseline.xml" findUnusedBaselineEntry="true" findUnusedCode="false" - phpVersion="8.0" + phpVersion="8.1" > diff --git a/rector.php b/rector.php new file mode 100644 index 000000000..85a99654f --- /dev/null +++ b/rector.php @@ -0,0 +1,27 @@ +withPaths([ + __DIR__ . '/appinfo', + __DIR__ . '/lib', + __DIR__ . '/tests', + ]) + ->withSkip([ + __DIR__ . '/tests/integration/vendor', + ]) + // uncomment to reach your current PHP version + ->withPhpSets(php81: true) + ->withSets([ + NextcloudSets::NEXTCLOUD_30, + ]) + ->withTypeCoverageLevel(0); diff --git a/tests/integration/features/bootstrap/FeatureContext.php b/tests/integration/features/bootstrap/FeatureContext.php index 066a0396e..d5ff157a3 100644 --- a/tests/integration/features/bootstrap/FeatureContext.php +++ b/tests/integration/features/bootstrap/FeatureContext.php @@ -255,7 +255,7 @@ public function iSendAGetRequestWithQueryParamsTo($url) { public function iShouldBeRedirectedTo($targetUrl) { $redirectHeader = $this->response->getHeader('X-Guzzle-Redirect-History'); $lastUrl = $redirectHeader[count($redirectHeader) - 1]; - $url = parse_url($lastUrl); + $url = parse_url((string)$lastUrl); $targetUrl = parse_url($targetUrl); $paramsToCheck = [ 'scheme', @@ -288,7 +288,7 @@ public function iShouldBeRedirectedTo($targetUrl) { public function iShouldBeRedirectedToWithQueryParams($targetUrl) { $redirectHeader = $this->response->getHeader('X-Guzzle-Redirect-History'); $firstUrl = $redirectHeader[0]; - $firstUrlParsed = parse_url($firstUrl); + $firstUrlParsed = parse_url((string)$firstUrl); $targetUrl = parse_url($targetUrl); $paramsToCheck = [ 'scheme', @@ -303,7 +303,7 @@ public function iShouldBeRedirectedToWithQueryParams($targetUrl) { foreach ($paramsToCheck as $param) { if ($param == 'query') { foreach (explode('&', $passthroughParams) as $passthrough) { - if (!str_contains($firstUrl, $passthrough)) { + if (!str_contains((string)$firstUrl, $passthrough)) { throw new InvalidArgumentException( sprintf( 'Expected to find %s for parameter %s', @@ -395,10 +395,10 @@ public function theUserValueShouldBe(string $key, string $value): void { ] ); - $responseArray = (json_decode($this->response->getBody(), true))['ocs']; + $responseArray = (json_decode((string)$this->response->getBody(), true))['ocs']; if (!isset($responseArray['data'][$key]) || count((array)$responseArray['data'][$key]) === 0) { - if (strpos($key, '.') !== false) { + if (str_contains($key, '.')) { // support nested arrays, specify the key seperated by "."s, e.g. quota.total $keys = explode('.', $key); if (isset($responseArray['data'][$keys[0]])) { @@ -419,7 +419,7 @@ public function theUserValueShouldBe(string $key, string $value): void { $responseArray['data'][$key] = ''; } - $actualValue = $actualValue ?? $responseArray['data'][$key]; + $actualValue ??= $responseArray['data'][$key]; if (is_array($actualValue)) { // transform array to string, ensuring values are in the same order $value = explode(',', $value); @@ -464,7 +464,7 @@ public function theGroupHasExactlyTheMembers(string $group, string $memberList): ] ); - $responseArray = (json_decode($this->response->getBody(), true))['ocs']; + $responseArray = (json_decode((string)$this->response->getBody(), true))['ocs']; if ($responseArray['meta']['statuscode'] !== 200) { throw new UnexpectedValueException(sprintf('Expected 200 status code but got %d', $responseArray['meta']['statusCode'])); } @@ -683,10 +683,10 @@ public function theGroupIsDeleted(string $group) { */ public function iSendAGETRequestWithRequesttokenTo($url) { $requestToken = substr( - preg_replace( + (string)preg_replace( '/(.*)data-requesttoken="(.*)">(.*)/sm', '\2', - $this->response->getBody()->getContents() + (string)$this->response->getBody()->getContents() ), 0, 89 @@ -793,7 +793,7 @@ public function theFormMethodShouldBePost() { */ public function theResponseShouldContainTheFormWithAction($action) { $responseBody = (string)$this->response->getBody(); - if (strpos($responseBody, 'action="' . $action . '"') === false) { + if (!str_contains($responseBody, 'action="' . $action . '"')) { throw new \Exception("Expected form action '$action' not found in response"); } } @@ -806,7 +806,7 @@ public function theFormShouldContainInputFields($fields) { $domDocument = new DOMDocument(); @$domDocument->loadHTML($responseBody); $xpath = new DOMXpath($domDocument); - $fieldsArray = explode(',', $fields); + $fieldsArray = explode(',', (string)$fields); foreach ($fieldsArray as $field) { $inputElements = $xpath->query("//input[@name='" . trim($field) . "']"); if ($inputElements->length === 0) { diff --git a/tests/unit/Controller/SAMLControllerTest.php b/tests/unit/Controller/SAMLControllerTest.php index 3af9a9a48..dc06ad75e 100644 --- a/tests/unit/Controller/SAMLControllerTest.php +++ b/tests/unit/Controller/SAMLControllerTest.php @@ -77,15 +77,11 @@ protected function setUp(): void { $this->trustedDomainController = $this->createMock(ITrustedDomainHelper::class); $this->l->expects($this->any())->method('t')->willReturnCallback( - function ($param) { - return $param; - } + fn ($param) => $param ); $this->config->expects($this->any())->method('getSystemValue') - ->willReturnCallback(function ($key, $default) { - return $default; - }); + ->willReturnCallback(fn ($key, $default) => $default); $this->samlController = new SAMLController( 'user_saml', @@ -221,15 +217,10 @@ public function testLoginWithEnvVariable(array $samlUserData, string $redirect, $this->session ->expects($this->any()) ->method('get') - ->willReturnCallback(function (string $key) use ($samlUserData) { - switch ($key) { - case 'user_saml.samlUserData': - return $samlUserData; - case 'user_saml.Idp': - return 1; - default: - return null; - } + ->willReturnCallback(fn (string $key) => match ($key) { + 'user_saml.samlUserData' => $samlUserData, + 'user_saml.Idp' => 1, + default => null, }); $this->userData @@ -251,15 +242,13 @@ public function testLoginWithEnvVariable(array $samlUserData, string $redirect, $this->userData ->expects($this->any()) ->method('testEncodedObjectGUID') - ->willReturnCallback(function ($uid) { - return $uid; - }); + ->willReturnCallback(fn ($uid) => $uid); $this->userData ->expects($this->any()) ->method('getEffectiveUid') ->willReturn($userState > 0 ? 'MyUid' : ''); - if (strpos($redirect, 'notProvisioned') !== false) { + if (str_contains($redirect, 'notProvisioned')) { $this->urlGenerator ->expects($this->once()) ->method('linkToRouteAbsolute') diff --git a/tests/unit/GroupBackendTest.php b/tests/unit/GroupBackendTest.php index b51fa1a26..e866641f6 100644 --- a/tests/unit/GroupBackendTest.php +++ b/tests/unit/GroupBackendTest.php @@ -60,7 +60,7 @@ class GroupBackendTest extends TestCase { public function setUp(): void { parent::setUp(); - $this->groupBackend = new GroupBackend(\OC::$server->get(IDBConnection::class), $this->createMock(LoggerInterface::class)); + $this->groupBackend = new GroupBackend(\OCP\Server::get(IDBConnection::class), $this->createMock(LoggerInterface::class)); foreach ($this->groups as $group) { $this->groupBackend->createGroup($group['gid'], $group['saml_gid']); } @@ -73,7 +73,7 @@ public function setUp(): void { public function tearDown(): void { parent::tearDown(); - $this->groupBackend = new GroupBackend(\OC::$server->get(IDBConnection::class), $this->createMock(LoggerInterface::class)); + $this->groupBackend = new GroupBackend(\OCP\Server::get(IDBConnection::class), $this->createMock(LoggerInterface::class)); foreach ($this->users as $user) { foreach ($user['groups'] as $group) { $this->groupBackend->removeFromGroup($user['uid'], $group); diff --git a/tests/unit/GroupManagerTest.php b/tests/unit/GroupManagerTest.php index 2c4ff6720..35df5f298 100644 --- a/tests/unit/GroupManagerTest.php +++ b/tests/unit/GroupManagerTest.php @@ -120,15 +120,10 @@ public function testUpdateUserGroups() { ->willReturn([$groupA, $groupB]); $this->groupManager ->method('get') - ->willReturnCallback(function ($groupId) use ($groupA, $groupB): ?IGroup { - switch ($groupId) { - case 'groupA': - return $groupA; - case 'groupB': - return $groupB; - default: - return null; - } + ->willReturnCallback(fn ($groupId): ?IGroup => match ($groupId) { + 'groupA' => $groupA, + 'groupB' => $groupB, + default => null, }); // assert all groups are supplied by SAML backend $this->ownGroupManager @@ -308,14 +303,10 @@ public function testAssignUserToGroupsWithCollision() { // assert group exists $this->groupManager ->method('get') - ->willReturnCallback(function ($groupId) use ($groupC) { - switch ($groupId) { - case 'groupC': - return $groupC; - case 'SAML_groupC': - return $groupC; - } - return null; + ->willReturnCallback(fn ($groupId) => match ($groupId) { + 'groupC' => $groupC, + 'SAML_groupC' => $groupC, + default => null, }); // assert differnt group backend $this->ownGroupManager diff --git a/tests/unit/Settings/AdminTest.php b/tests/unit/Settings/AdminTest.php index bae4f5f4c..fbaf062eb 100644 --- a/tests/unit/Settings/AdminTest.php +++ b/tests/unit/Settings/AdminTest.php @@ -48,9 +48,7 @@ public function formDataProvider() { $this->l10n ->expects($this->any()) ->method('t') - ->willReturnCallback(function ($text, $parameters = []) { - return vsprintf($text, $parameters); - }); + ->willReturnCallback(fn ($text, $parameters = []) => vsprintf($text, $parameters)); $serviceProviderFields = [ 'x509cert' => [ diff --git a/tests/unit/UserBackendTest.php b/tests/unit/UserBackendTest.php index f6e6fd048..b9266eaa7 100644 --- a/tests/unit/UserBackendTest.php +++ b/tests/unit/UserBackendTest.php @@ -106,10 +106,9 @@ public function testUpdateAttributesWithoutAttributes() { $user = $this->createMock(IUser::class); $this->config->method('getAppValue') - ->willReturnCallback(function (string $appId, string $key, string $default) { + ->willReturnCallback(fn (string $appId, string $key, string $default) => // Unused parameters are intentionally kept for clarity - return $default; - }); + $default); $this->userManager ->expects($this->once()) @@ -139,10 +138,9 @@ public function testUpdateAttributesWithoutValidUser() { $this->getMockedBuilder(); $this->config->method('getAppValue') - ->willReturnCallback(function (string $appId, string $key, string $default) { + ->willReturnCallback(fn (string $appId, string $key, string $default) => // Unused parameters are intentionally kept for clarity - return $default; - }); + $default); $this->userManager ->expects($this->once()) @@ -221,18 +219,14 @@ public function testUpdateAttributesQuotaDefaultFallback() { $this->config->method('getAppValue') - ->willReturnCallback(function (string $appId, string $key, string $default) { + ->willReturnCallback(fn (string $appId, string $key, string $default) => // Unused $appId parameter is intentionally kept for clarity - switch ($key) { - case 'saml-attribute-mapping-email_mapping': - return 'email'; - case 'saml-attribute-mapping-displayName_mapping': - return 'displayname'; - case 'saml-attribute-mapping-quota_mapping': - return 'quota'; - } - return $default; - }); + match ($key) { + 'saml-attribute-mapping-email_mapping' => 'email', + 'saml-attribute-mapping-displayName_mapping' => 'displayname', + 'saml-attribute-mapping-quota_mapping' => 'quota', + default => $default, + }); $this->userManager ->expects($this->once()) diff --git a/tests/unit/UserBackendTest.php.orig b/tests/unit/UserBackendTest.php.orig new file mode 100644 index 000000000..c3d7040ce --- /dev/null +++ b/tests/unit/UserBackendTest.php.orig @@ -0,0 +1,288 @@ +config = $this->createMock(IConfig::class); + $this->urlGenerator = $this->createMock(IURLGenerator::class); + $this->session = $this->createMock(ISession::class); + $this->db = $this->createMock(IDBConnection::class); + $this->userManager = $this->createMock(IUserManager::class); + $this->groupManager = $this->createMock(GroupManager::class); + $this->SAMLSettings = $this->getMockBuilder(SAMLSettings::class)->disableOriginalConstructor()->getMock(); + $this->logger = $this->createMock(LoggerInterface::class); + $this->userData = $this->createMock(UserData::class); + $this->eventDispatcher = $this->createMock(IEventDispatcher::class); + } + + public function getMockedBuilder(array $mockedFunctions = []) { + if ($mockedFunctions !== []) { + $this->userBackend = $this->getMockBuilder(UserBackend::class) + ->setConstructorArgs([ + $this->config, + $this->urlGenerator, + $this->session, + $this->db, + $this->userManager, + $this->groupManager, + $this->SAMLSettings, + $this->logger, + $this->userData, + $this->eventDispatcher + ]) + ->setMethods($mockedFunctions) + ->getMock(); + } else { + $this->userBackend = new UserBackend( + $this->config, + $this->urlGenerator, + $this->session, + $this->db, + $this->userManager, + $this->groupManager, + $this->SAMLSettings, + $this->logger, + $this->userData, + $this->eventDispatcher + ); + } + } + + public function testGetBackendName() { + $this->getMockedBuilder(); + $this->assertSame('user_saml', $this->userBackend->getBackendName()); + } + + public function testUpdateAttributesWithoutAttributes() { + $this->getMockedBuilder(['getDisplayName']); + /** @var IUser|MockObject $user */ + $user = $this->createMock(IUser::class); + + $this->config->method('getAppValue') +<<<<<<< HEAD + ->willReturnCallback(function (string $appId, string $key, string $default) { + // Unused parameters are intentionally kept for clarity + return $default; + }); +======= + ->willReturnCallback(fn ($appId, $key, $default) => $default); +>>>>>>> 59039fc1 (refactor(PHP): adjust to rector fixes) + + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('ExistingUser') + ->willReturn($user); + $user + ->expects($this->once()) + ->method('getSystemEMailAddress') + ->willReturn(null); + $user + ->expects($this->never()) + ->method('setSystemEMailAddress'); + $this->userBackend + ->expects($this->once()) + ->method('getDisplayName') + ->with('ExistingUser') + ->willReturn(''); + $this->groupManager + ->expects($this->once()) + ->method('handleIncomingGroups') + ->with($user, []); + $this->userBackend->updateAttributes('ExistingUser', []); + } + + public function testUpdateAttributesWithoutValidUser() { + $this->getMockedBuilder(); + + $this->config->method('getAppValue') +<<<<<<< HEAD + ->willReturnCallback(function (string $appId, string $key, string $default) { + // Unused parameters are intentionally kept for clarity + return $default; + }); +======= + ->willReturnCallback(fn ($appId, $key, $default) => $default); +>>>>>>> 59039fc1 (refactor(PHP): adjust to rector fixes) + + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('ExistingUser') + ->willReturn(null); + $this->userBackend->updateAttributes('ExistingUser', []); + } + + public function testUpdateAttributes() { + $this->getMockedBuilder(['getDisplayName', 'setDisplayName']); + /** @var IUser|MockObject $user */ + $user = $this->createMock(IUser::class); + + // Replace at() matcher with willReturnCallback to avoid deprecation warning + $this->config + ->method('getAppValue') + ->willReturnCallback(function ($appId, $key, $default) { + if ($appId === 'user_saml') { + switch ($key) { + case 'saml-attribute-mapping-email_mapping': + return 'email'; + case 'saml-attribute-mapping-displayName_mapping': + return 'displayname'; + case 'saml-attribute-mapping-quota_mapping': + return 'quota'; + case 'saml-attribute-mapping-group_mapping': + return 'groups'; + } + } + return $default; + }); + + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('ExistingUser') + ->willReturn($user); + $user + ->expects($this->once()) + ->method('getSystemEMailAddress') + ->willReturn('old@example.com'); + $user + ->expects($this->once()) + ->method('setSystemEMailAddress') + ->with('new@example.com'); + $user + ->expects($this->once()) + ->method('setQuota') + ->with('50MB'); + $this->userBackend + ->expects($this->once()) + ->method('getDisplayName') + ->with('ExistingUser') + ->willReturn(''); + $this->userBackend + ->expects($this->once()) + ->method('setDisplayName') + ->with('ExistingUser', 'New Displayname'); + $this->groupManager + ->expects($this->once()) + ->method('handleIncomingGroups') + ->with($user, ['groupB', 'groupC']); + $this->userBackend->updateAttributes('ExistingUser', [ + 'email' => 'new@example.com', + 'displayname' => 'New Displayname', + 'quota' => '50MB', + 'groups' => ['groupB', 'groupC'], + ]); + } + + public function testUpdateAttributesQuotaDefaultFallback() { + $this->getMockedBuilder(['getDisplayName', 'setDisplayName']); + /** @var IUser|MockObject $user */ + $user = $this->createMock(IUser::class); + + + $this->config->method('getAppValue') +<<<<<<< HEAD + ->willReturnCallback(function (string $appId, string $key, string $default) { + // Unused $appId parameter is intentionally kept for clarity + switch ($key) { + case 'saml-attribute-mapping-email_mapping': + return 'email'; + case 'saml-attribute-mapping-displayName_mapping': + return 'displayname'; + case 'saml-attribute-mapping-quota_mapping': + return 'quota'; + } + return $default; +======= + ->willReturnCallback(fn ($appId, $key, $default) => match ($key) { + 'saml-attribute-mapping-email_mapping' => 'email', + 'saml-attribute-mapping-displayName_mapping' => 'displayname', + 'saml-attribute-mapping-quota_mapping' => 'quota', + default => $default, +>>>>>>> 59039fc1 (refactor(PHP): adjust to rector fixes) + }); + + $this->userManager + ->expects($this->once()) + ->method('get') + ->with('ExistingUser') + ->willReturn($user); + $user + ->expects($this->once()) + ->method('getSystemEMailAddress') + ->willReturn('old@example.com'); + $user + ->expects($this->once()) + ->method('setSystemEMailAddress') + ->with('new@example.com'); + $user + ->expects($this->once()) + ->method('setQuota') + ->with('default'); + $this->userBackend + ->expects($this->once()) + ->method('getDisplayName') + ->with('ExistingUser') + ->willReturn(''); + $this->userBackend + ->expects($this->once()) + ->method('setDisplayName') + ->with('ExistingUser', 'New Displayname'); + $this->eventDispatcher->expects($this->once()) + ->method('dispatchTyped') + ->with(new UserChangedEvent($user, 'displayName', 'New Displayname', '')); + $this->groupManager + ->expects($this->once()) + ->method('handleIncomingGroups') + ->with($user, []); + $this->userBackend->updateAttributes('ExistingUser', ['email' => 'new@example.com', 'displayname' => 'New Displayname', 'quota' => '']); + } +} diff --git a/tests/unit/bootstrap.php b/tests/unit/bootstrap.php index 4b0bb6fda..fbffdc376 100644 --- a/tests/unit/bootstrap.php +++ b/tests/unit/bootstrap.php @@ -11,7 +11,7 @@ require_once __DIR__ . '/../../../../lib/base.php'; \OC::$loader->addValidRoot(\OC::$SERVERROOT . '/tests'); \OC_App::loadApp('user_saml'); -if (!class_exists('\PHPUnit\Framework\TestCase')) { +if (!class_exists(\PHPUnit\Framework\TestCase::class)) { require_once('PHPUnit/Autoload.php'); } OC_Hook::clear(); diff --git a/vendor-bin/cs-fixer/composer.json b/vendor-bin/cs-fixer/composer.json index 4a4889dbc..7fa1a7536 100644 --- a/vendor-bin/cs-fixer/composer.json +++ b/vendor-bin/cs-fixer/composer.json @@ -4,7 +4,7 @@ }, "config": { "platform": { - "php": "8.0.2" + "php": "8.1.32" } } } diff --git a/vendor-bin/cs-fixer/composer.lock b/vendor-bin/cs-fixer/composer.lock index f1d3f6b46..9e2248636 100644 --- a/vendor-bin/cs-fixer/composer.lock +++ b/vendor-bin/cs-fixer/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": "225e4f70d13bf239dc8e575bab2232c8", + "content-hash": "d3e4cd7df3ba4a52dc869b9f25ca7727", "packages": [], "packages-dev": [ { @@ -156,7 +156,7 @@ "platform": {}, "platform-dev": {}, "platform-overrides": { - "php": "8.0.2" + "php": "8.1.32" }, "plugin-api-version": "2.6.0" } diff --git a/vendor-bin/psalm/composer.json b/vendor-bin/psalm/composer.json index 051d53ec8..b205e3442 100644 --- a/vendor-bin/psalm/composer.json +++ b/vendor-bin/psalm/composer.json @@ -6,7 +6,7 @@ }, "config": { "platform": { - "php": "8.0.2" + "php": "8.1.32" } } } diff --git a/vendor-bin/psalm/composer.lock b/vendor-bin/psalm/composer.lock index 3d889007c..bfa92e5e0 100644 --- a/vendor-bin/psalm/composer.lock +++ b/vendor-bin/psalm/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": "82e4e755c70ea5f51c40de5df7ca9b26", + "content-hash": "ed78ed32a8083cfab48ae511a90522ad", "packages": [], "packages-dev": [ { @@ -846,16 +846,16 @@ }, { "name": "phpdocumentor/reflection-docblock", - "version": "5.6.1", + "version": "5.6.2", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8" + "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8", - "reference": "e5e784149a09bd69d9a5e3b01c5cbd2e2bd653d8", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/92dde6a5919e34835c506ac8c523ef095a95ed62", + "reference": "92dde6a5919e34835c506ac8c523ef095a95ed62", "shasum": "" }, "require": { @@ -904,9 +904,9 @@ "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", "support": { "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", - "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.1" + "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.6.2" }, - "time": "2024-12-07T09:39:29+00:00" + "time": "2025-04-13T19:20:35+00:00" }, { "name": "phpdocumentor/type-resolver", @@ -1488,16 +1488,16 @@ }, { "name": "sabre/vobject", - "version": "4.5.6", + "version": "4.5.7", "source": { "type": "git", "url": "https://github.com/sabre-io/vobject.git", - "reference": "900266bb3bd448a9f7f41f82344ad0aba237cb27" + "reference": "ff22611a53782e90c97be0d0bc4a5f98a5c0a12c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sabre-io/vobject/zipball/900266bb3bd448a9f7f41f82344ad0aba237cb27", - "reference": "900266bb3bd448a9f7f41f82344ad0aba237cb27", + "url": "https://api.github.com/repos/sabre-io/vobject/zipball/ff22611a53782e90c97be0d0bc4a5f98a5c0a12c", + "reference": "ff22611a53782e90c97be0d0bc4a5f98a5c0a12c", "shasum": "" }, "require": { @@ -1507,7 +1507,7 @@ }, "require-dev": { "friendsofphp/php-cs-fixer": "~2.17.1", - "phpstan/phpstan": "^0.12 || ^1.11", + "phpstan/phpstan": "^0.12 || ^1.12 || ^2.0", "phpunit/php-invoker": "^2.0 || ^3.1", "phpunit/phpunit": "^7.5 || ^8.5 || ^9.6" }, @@ -1588,7 +1588,7 @@ "issues": "https://github.com/sabre-io/vobject/issues", "source": "https://github.com/fruux/sabre-vobject" }, - "time": "2024-10-14T11:53:54+00:00" + "time": "2025-04-17T09:22:48+00:00" }, { "name": "sabre/xml", @@ -1661,29 +1661,29 @@ }, { "name": "sebastian/diff", - "version": "4.0.6", + "version": "5.1.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/diff.git", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc" + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/ba01945089c3a293b01ba9badc29ad55b106b0bc", - "reference": "ba01945089c3a293b01ba9badc29ad55b106b0bc", + "url": "https://api.github.com/repos/sebastianbergmann/diff/zipball/c41e007b4b62af48218231d6c2275e4c9b975b2e", + "reference": "c41e007b4b62af48218231d6c2275e4c9b975b2e", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3", - "symfony/process": "^4.2 || ^5" + "phpunit/phpunit": "^10.0", + "symfony/process": "^6.4" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -1715,7 +1715,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/diff/issues", - "source": "https://github.com/sebastianbergmann/diff/tree/4.0.6" + "security": "https://github.com/sebastianbergmann/diff/security/policy", + "source": "https://github.com/sebastianbergmann/diff/tree/5.1.1" }, "funding": [ { @@ -1723,7 +1724,7 @@ "type": "github" } ], - "time": "2024-03-02T06:30:58+00:00" + "time": "2024-03-02T07:15:17+00:00" }, { "name": "spatie/array-to-xml", @@ -1795,23 +1796,24 @@ }, { "name": "symfony/console", - "version": "v6.0.19", + "version": "v6.4.21", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed" + "reference": "a3011c7b7adb58d89f6c0d822abb641d7a5f9719" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/c3ebc83d031b71c39da318ca8b7a07ecc67507ed", - "reference": "c3ebc83d031b71c39da318ca8b7a07ecc67507ed", + "url": "https://api.github.com/repos/symfony/console/zipball/a3011c7b7adb58d89f6c0d822abb641d7a5f9719", + "reference": "a3011c7b7adb58d89f6c0d822abb641d7a5f9719", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", - "symfony/service-contracts": "^1.1|^2|^3", - "symfony/string": "^5.4|^6.0" + "symfony/service-contracts": "^2.5|^3", + "symfony/string": "^5.4|^6.0|^7.0" }, "conflict": { "symfony/dependency-injection": "<5.4", @@ -1825,18 +1827,16 @@ }, "require-dev": { "psr/log": "^1|^2|^3", - "symfony/config": "^5.4|^6.0", - "symfony/dependency-injection": "^5.4|^6.0", - "symfony/event-dispatcher": "^5.4|^6.0", - "symfony/lock": "^5.4|^6.0", - "symfony/process": "^5.4|^6.0", - "symfony/var-dumper": "^5.4|^6.0" - }, - "suggest": { - "psr/log": "For using the console logger", - "symfony/event-dispatcher": "", - "symfony/lock": "", - "symfony/process": "" + "symfony/config": "^5.4|^6.0|^7.0", + "symfony/dependency-injection": "^5.4|^6.0|^7.0", + "symfony/event-dispatcher": "^5.4|^6.0|^7.0", + "symfony/http-foundation": "^6.4|^7.0", + "symfony/http-kernel": "^6.4|^7.0", + "symfony/lock": "^5.4|^6.0|^7.0", + "symfony/messenger": "^5.4|^6.0|^7.0", + "symfony/process": "^5.4|^6.0|^7.0", + "symfony/stopwatch": "^5.4|^6.0|^7.0", + "symfony/var-dumper": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -1865,12 +1865,79 @@ "homepage": "https://symfony.com", "keywords": [ "cli", - "command line", + "command-line", "console", "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.0.19" + "source": "https://github.com/symfony/console/tree/v6.4.21" + }, + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2025-04-07T15:42:41+00:00" + }, + { + "name": "symfony/deprecation-contracts", + "version": "v3.5.1", + "source": { + "type": "git", + "url": "https://github.com/symfony/deprecation-contracts.git", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "shasum": "" + }, + "require": { + "php": ">=8.1" + }, + "type": "library", + "extra": { + "thanks": { + "url": "https://github.com/symfony/contracts", + "name": "symfony/contracts" + }, + "branch-alias": { + "dev-main": "3.5-dev" + } + }, + "autoload": { + "files": [ + "function.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A generic function and convention to trigger deprecation notices", + "homepage": "https://symfony.com", + "support": { + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" }, "funding": [ { @@ -1886,27 +1953,30 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/filesystem", - "version": "v6.0.19", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "3d49eec03fda1f0fc19b7349fbbe55ebc1004214" + "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/3d49eec03fda1f0fc19b7349fbbe55ebc1004214", - "reference": "3d49eec03fda1f0fc19b7349fbbe55ebc1004214", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/4856c9cf585d5a0313d8d35afd681a526f038dd3", + "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-mbstring": "~1.8" }, + "require-dev": { + "symfony/process": "^5.4|^6.4|^7.0" + }, "type": "library", "autoload": { "psr-4": { @@ -1933,7 +2003,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v6.0.19" + "source": "https://github.com/symfony/filesystem/tree/v6.4.13" }, "funding": [ { @@ -1949,7 +2019,7 @@ "type": "tidelift" } ], - "time": "2023-01-20T17:44:14+00:00" + "time": "2024-10-25T15:07:50+00:00" }, { "name": "symfony/polyfill-ctype", @@ -2032,7 +2102,7 @@ }, { "name": "symfony/polyfill-intl-grapheme", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git", @@ -2090,7 +2160,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.32.0" }, "funding": [ { @@ -2110,7 +2180,7 @@ }, { "name": "symfony/polyfill-intl-normalizer", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git", @@ -2171,7 +2241,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.32.0" }, "funding": [ { @@ -2191,19 +2261,20 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.31.0", + "version": "v1.32.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341" + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341", - "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493", + "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493", "shasum": "" }, "require": { + "ext-iconv": "*", "php": ">=7.2" }, "provide": { @@ -2251,7 +2322,7 @@ "shim" ], "support": { - "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0" + "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.32.0" }, "funding": [ { @@ -2267,32 +2338,30 @@ "type": "tidelift" } ], - "time": "2024-09-09T11:45:10+00:00" + "time": "2024-12-23T08:48:59+00:00" }, { "name": "symfony/service-contracts", - "version": "v3.0.2", + "version": "v3.5.1", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66" + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/d78d39c1599bd1188b8e26bb341da52c3c6d8a66", - "reference": "d78d39c1599bd1188b8e26bb341da52c3c6d8a66", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", "shasum": "" }, "require": { - "php": ">=8.0.2", - "psr/container": "^2.0" + "php": ">=8.1", + "psr/container": "^1.1|^2.0", + "symfony/deprecation-contracts": "^2.5|^3" }, "conflict": { "ext-psr": "<1.1|>=2" }, - "suggest": { - "symfony/service-implementation": "" - }, "type": "library", "extra": { "thanks": { @@ -2300,13 +2369,16 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.0-dev" + "dev-main": "3.5-dev" } }, "autoload": { "psr-4": { "Symfony\\Contracts\\Service\\": "" - } + }, + "exclude-from-classmap": [ + "/Test/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -2333,7 +2405,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.0.2" + "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" }, "funding": [ { @@ -2349,37 +2421,38 @@ "type": "tidelift" } ], - "time": "2022-05-30T19:17:58+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/string", - "version": "v6.0.19", + "version": "v6.4.21", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a" + "reference": "73e2c6966a5aef1d4892873ed5322245295370c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/d9e72497367c23e08bf94176d2be45b00a9d232a", - "reference": "d9e72497367c23e08bf94176d2be45b00a9d232a", + "url": "https://api.github.com/repos/symfony/string/zipball/73e2c6966a5aef1d4892873ed5322245295370c6", + "reference": "73e2c6966a5aef1d4892873ed5322245295370c6", "shasum": "" }, "require": { - "php": ">=8.0.2", + "php": ">=8.1", "symfony/polyfill-ctype": "~1.8", "symfony/polyfill-intl-grapheme": "~1.0", "symfony/polyfill-intl-normalizer": "~1.0", "symfony/polyfill-mbstring": "~1.0" }, "conflict": { - "symfony/translation-contracts": "<2.0" + "symfony/translation-contracts": "<2.5" }, "require-dev": { - "symfony/error-handler": "^5.4|^6.0", - "symfony/http-client": "^5.4|^6.0", - "symfony/translation-contracts": "^2.0|^3.0", - "symfony/var-exporter": "^5.4|^6.0" + "symfony/error-handler": "^5.4|^6.0|^7.0", + "symfony/http-client": "^5.4|^6.0|^7.0", + "symfony/intl": "^6.2|^7.0", + "symfony/translation-contracts": "^2.5|^3.0", + "symfony/var-exporter": "^5.4|^6.0|^7.0" }, "type": "library", "autoload": { @@ -2418,7 +2491,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v6.0.19" + "source": "https://github.com/symfony/string/tree/v6.4.21" }, "funding": [ { @@ -2434,7 +2507,7 @@ "type": "tidelift" } ], - "time": "2023-01-01T08:36:10+00:00" + "time": "2025-04-18T15:23:29+00:00" }, { "name": "vimeo/psalm", @@ -2615,7 +2688,7 @@ "platform": {}, "platform-dev": {}, "platform-overrides": { - "php": "8.0.2" + "php": "8.1.32" }, "plugin-api-version": "2.6.0" } diff --git a/vendor-bin/rector/composer.json b/vendor-bin/rector/composer.json new file mode 100644 index 000000000..1398ed359 --- /dev/null +++ b/vendor-bin/rector/composer.json @@ -0,0 +1,6 @@ +{ + "require-dev": { + "rector/rector": "^2.0", + "nextcloud/rector": "^0.4.1" + } +} diff --git a/vendor-bin/rector/composer.lock b/vendor-bin/rector/composer.lock new file mode 100644 index 000000000..4a771dca3 --- /dev/null +++ b/vendor-bin/rector/composer.lock @@ -0,0 +1,508 @@ +{ + "_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": "347262bc75027c88fa21b011f732aa31", + "packages": [], + "packages-dev": [ + { + "name": "nextcloud/ocp", + "version": "v31.0.4", + "source": { + "type": "git", + "url": "https://github.com/nextcloud-deps/ocp.git", + "reference": "1fb984268039921920ade298ef5a58e8fe3de7da" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/1fb984268039921920ade298ef5a58e8fe3de7da", + "reference": "1fb984268039921920ade298ef5a58e8fe3de7da", + "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-stable31": "31.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/v31.0.4" + }, + "time": "2025-04-15T00:50:16+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.13", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "e55e03e6d4ac49cd1240907e5b08e5cd378572a9" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e55e03e6d4ac49cd1240907e5b08e5cd378572a9", + "reference": "e55e03e6d4ac49cd1240907e5b08e5cd378572a9", + "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": "2025-04-27T12:28:25+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.0.14", + "source": { + "type": "git", + "url": "https://github.com/rectorphp/rector.git", + "reference": "63923bc9383c1212476c41d8cebf58a425e6f98d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/63923bc9383c1212476c41d8cebf58a425e6f98d", + "reference": "63923bc9383c1212476c41d8cebf58a425e6f98d", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "phpstan/phpstan": "^2.1.12" + }, + "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", + "keywords": [ + "automation", + "dev", + "migration", + "refactoring" + ], + "support": { + "issues": "https://github.com/rectorphp/rector/issues", + "source": "https://github.com/rectorphp/rector/tree/2.0.14" + }, + "funding": [ + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2025-04-28T00:03:14+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.11.0", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/11cb2199493b2f8a3b53e7f19068fc6aac760991", + "reference": "11cb2199493b2f8a3b53e7f19068fc6aac760991", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "php": "^7.2 || ^8.0" + }, + "conflict": { + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<4.6.1 || 4.6.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.5.13" + }, + "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.11.0" + }, + "time": "2022-06-03T18:03:27+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.6.0" +}