diff --git a/REUSE.toml b/REUSE.toml index 894671b..97bbf23 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -12,7 +12,7 @@ SPDX-FileCopyrightText = "2017 Nextcloud GmbH and Nextcloud contributors" SPDX-License-Identifier = "AGPL-3.0-or-later" [[annotations]] -path = ["vendor-bin/csfixer/composer.json", "vendor-bin/csfixer/composer.lock", "vendor-bin/mozart/composer.json", "vendor-bin/mozart/composer.lock", "vendor-bin/phpunit/composer.json", "vendor-bin/phpunit/composer.lock", "vendor-bin/psalm/composer.json", "vendor-bin/psalm/composer.lock", "composer.lock"] +path = ["vendor-bin/csfixer/composer.json", "vendor-bin/csfixer/composer.lock", "vendor-bin/mozart/composer.json", "vendor-bin/mozart/composer.lock", "vendor-bin/phpunit/composer.json", "vendor-bin/phpunit/composer.lock", "vendor-bin/psalm/composer.json", "vendor-bin/psalm/composer.lock", "composer.lock", "vendor-bin/rector/composer.json", "vendor-bin/rector/composer.lock"] precedence = "aggregate" SPDX-FileCopyrightText = "2023 Nextcloud GmbH and Nextcloud contributors" SPDX-License-Identifier = "AGPL-3.0-or-later" diff --git a/composer.json b/composer.json index 1a92d71..1ddcd18 100644 --- a/composer.json +++ b/composer.json @@ -27,13 +27,13 @@ } }, "scripts": { - "cs:fix": "./vendor-bin/csfixer/vendor/bin/php-cs-fixer fix", - "cs:check": "./vendor-bin/csfixer/vendor/bin/php-cs-fixer fix --dry-run --diff", + "cs:fix": "php-cs-fixer fix", + "cs:check": "php-cs-fixer fix --dry-run --diff", "lint": "find . -name \\*.php -not -path './vendor/*' -not -path './tests/stubs/*' -print0 | xargs -0 -n1 php -l", - "psalm": "./vendor-bin/psalm/vendor/bin/psalm --threads=1", - "psalm:clear": "./vendor-bin/psalm/vendor/bin/psalm --clear-cache && ./vendor-bin/psalm/vendor/bin/psalm --clear-global-cache", - "psalm:fix": "./vendor-bin/psalm/vendor/bin/psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MissingParamType,InvalidFalsableReturnType", - "test:unit": "./vendor-bin/phpunit/vendor/bin/phpunit -c tests/phpunit.xml --color --fail-on-warning --fail-on-risky", + "psalm": "psalm --threads=1", + "psalm:clear": "psalm --clear-cache && psalm --clear-global-cache", + "psalm:fix": ".psalm --alter --issues=InvalidReturnType,InvalidNullableReturnType,MissingParamType,InvalidFalsableReturnType", + "test:unit": "phpunit -c tests/phpunit.xml --color --fail-on-warning --fail-on-risky", "rector": "rector && composer cs:fix", "post-install-cmd": [ "@composer bin all install --ansi", @@ -50,7 +50,7 @@ }, "extra": { "bamarni-bin": { - "bin-links": false, + "bin-links": true, "target-directory": "vendor-bin", "forward-command": true }, diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index eb03ac5..162f1e3 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -9,7 +9,6 @@ namespace OCA\GlobalSiteSelector\AppInfo; -use Closure; use Exception; use OC; use OCA\GlobalSiteSelector\GlobalSiteSelector; @@ -24,13 +23,12 @@ use OCA\GlobalSiteSelector\SetupChecks\LongJwtKeySetupCheck; use OCA\GlobalSiteSelector\Slave; use OCA\GlobalSiteSelector\UserBackend; +use OCP\Accounts\UserUpdatedEvent; use OCP\AppFramework\App; use OCP\AppFramework\Bootstrap\IBootContext; use OCP\AppFramework\Bootstrap\IBootstrap; use OCP\AppFramework\Bootstrap\IRegistrationContext; -use OCP\EventDispatcher\IEventDispatcher; use OCP\IRequest; -use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; use OCP\Security\CSP\AddContentSecurityPolicyEvent; @@ -44,7 +42,6 @@ use Psr\Container\ContainerExceptionInterface; use Psr\Container\NotFoundExceptionInterface; use Psr\Log\LoggerInterface; -use Symfony\Component\EventDispatcher\GenericEvent; use Throwable; /** @@ -63,9 +60,6 @@ public function __construct(array $urlParams = []) { parent::__construct(self::APP_ID, $urlParams); } - /** - * @param IRegistrationContext $context - */ #[\Override] public function register(IRegistrationContext $context): void { $context->registerCapability(PublicCapabilities::class); @@ -83,26 +77,12 @@ public function register(IRegistrationContext $context): void { $context->registerEventListener(UserDeletedEvent::class, UserDeleted::class); $context->registerEventListener(UserLoggedOutEvent::class, UserLoggedOut::class); $context->registerEventListener(UserChangedEvent::class, UserChanged::class); + $context->registerEventListener(UserUpdatedEvent::class, UserChanged::class); $context->registerSetupCheck(LongJwtKeySetupCheck::class); - - // It seems that AccountManager use deprecated dispatcher, let's use a deprecated listener - /** @var IEventDispatcher $eventDispatcher */ - $dispatcher = Server::get(IEventDispatcher::class); - $dispatcher->addListener( - 'OC\AccountManager::userUpdated', - function (GenericEvent $event) { - /** @var IUser $user */ - $user = $event->getSubject(); - $slave = OC::$server->get(Slave::class); - $slave->updateUser($user); - } - ); } /** - * @param IBootContext $context - * * @throws Throwable */ #[\Override] @@ -110,14 +90,14 @@ public function boot(IBootContext $context): void { $this->globalSiteSelector = $context->getAppContainer()->get(GlobalSiteSelector::class); $this->logger = $context->getServerContainer()->get(LoggerInterface::class); - $context->injectFn(Closure::fromCallable([$this, 'registerUserBackendForSlave'])); - $context->injectFn(Closure::fromCallable([$this, 'redirectToMasterLogin'])); + $context->injectFn(\Closure::fromCallable($this->registerUserBackendForSlave(...))); + $context->injectFn(\Closure::fromCallable($this->redirectToMasterLogin(...))); } /** * Register the Global Scale User Backend if we run in slave mode */ - private function registerUserBackendForSlave() { + private function registerUserBackendForSlave(): void { if (!$this->globalSiteSelector->isSlave()) { return; } @@ -144,7 +124,7 @@ private function registerUserBackendForSlave() { /** * Register the Global Scale User Backend if we run in slave mode */ - private function redirectToMasterLogin() { + private function redirectToMasterLogin(): void { if (OC::$CLI) { return; } diff --git a/lib/Command/UsersUpdate.php b/lib/Command/UsersUpdate.php index 07b806b..cdd83a0 100644 --- a/lib/Command/UsersUpdate.php +++ b/lib/Command/UsersUpdate.php @@ -15,12 +15,10 @@ use Symfony\Component\Console\Output\OutputInterface; class UsersUpdate extends Base { - private Slave $slave; - - public function __construct(Slave $slave) { + public function __construct( + private readonly Slave $slave, + ) { parent::__construct(); - - $this->slave = $slave; } /** @@ -33,12 +31,6 @@ protected function configure() { ->setDescription('update known users data to Lookup Server'); } - /** - * @param InputInterface $input - * @param OutputInterface $output - * - * @return int - */ #[\Override] protected function execute(InputInterface $input, OutputInterface $output): int { $this->slave->batchUpdate(); diff --git a/lib/Controller/MasterController.php b/lib/Controller/MasterController.php index 8c82c50..9947f20 100644 --- a/lib/Controller/MasterController.php +++ b/lib/Controller/MasterController.php @@ -12,10 +12,12 @@ use OCA\GlobalSiteSelector\Master; use OCA\GlobalSiteSelector\Vendor\Firebase\JWT\JWT; use OCA\GlobalSiteSelector\Vendor\Firebase\JWT\Key; +use OCP\AppFramework\Http\Attribute\NoCSRFRequired; +use OCP\AppFramework\Http\Attribute\PublicPage; +use OCP\AppFramework\Http\Attribute\UseSession; use OCP\AppFramework\Http\RedirectResponse; use OCP\AppFramework\OCSController; use OCP\IRequest; -use OCP\ISession; use OCP\IURLGenerator; use Psr\Log\LoggerInterface; @@ -27,40 +29,20 @@ * @package OCA\GlobalSiteSelector\Controller */ class MasterController extends OCSController { - private IURLGenerator $urlGenerator; - private ISession $session; - private GlobalSiteSelector $gss; - private Master $master; - private LoggerInterface $logger; - public function __construct( $appName, IRequest $request, - IURLGenerator $urlGenerator, - ISession $session, - GlobalSiteSelector $globalSiteSelector, - Master $master, - LoggerInterface $logger, + private readonly IURLGenerator $urlGenerator, + private readonly GlobalSiteSelector $gss, + private readonly LoggerInterface $logger, ) { parent::__construct($appName, $request); - - $this->urlGenerator = $urlGenerator; - $this->session = $session; - $this->gss = $globalSiteSelector; - $this->master = $master; - $this->logger = $logger; } - /** - * @PublicPage - * @NoCSRFRequired - * @UseSession - * - * @param string|null $jwt - * - * @return RedirectResponse - */ - public function autoLogout(?string $jwt) { + #[PublicPage] + #[NoCSRFRequired] + #[UseSession] + public function autoLogout(?string $jwt): RedirectResponse { try { if ($jwt !== null) { $key = $this->gss->getJwtKey(); diff --git a/lib/Controller/SlaveController.php b/lib/Controller/SlaveController.php index 758b7a4..32b2ce4 100644 --- a/lib/Controller/SlaveController.php +++ b/lib/Controller/SlaveController.php @@ -189,12 +189,12 @@ public function autoLogin(string $jwt): RedirectResponse { if ($result === false) { throw new \Exception('wrong username or password given for: ' . $uid); } - } catch (ExpiredException $e) { + } catch (ExpiredException) { $this->logger->info('token expired'); $response = new RedirectResponse($masterUrl); $response->throttle(); return $response; - } catch (DisabledUserException $e) { + } catch (DisabledUserException) { // user is disabled, remove from lookup server $params = ['uid' => $uid]; $this->slave->preDeleteUser($params); @@ -208,6 +208,7 @@ public function autoLogin(string $jwt): RedirectResponse { } $this->logger->debug('all good. creating session'); + /** @psalm-suppress UndefinedInterfaceMethod defined in the private implementation */ $this->userSession->createSessionToken($this->request, $uid, $uid, null, IToken::REMEMBER); // ignore the need of password validation on slaves @@ -220,7 +221,7 @@ public function autoLogin(string $jwt): RedirectResponse { $this->slaveService->updateUserById($uid); $this->logger->debug('userdata updated on lus'); - if (str_starts_with($target, 'http://') || str_starts_with($target, 'https://')) { + if (str_starts_with((string)$target, 'http://') || str_starts_with((string)$target, 'https://')) { $home = $target; } else { $home = $this->urlGenerator->getAbsoluteURL($target); @@ -260,7 +261,7 @@ public function createAppToken($jwt): DataResponse { return new DataResponse($token); } } - } catch (ExpiredException $e) { + } catch (ExpiredException) { $this->logger->info('Create app password: JWT token expired'); } catch (\Exception $e) { $this->logger->info('issue while token creation', ['exception' => $e]); @@ -274,12 +275,10 @@ public function createAppToken($jwt): DataResponse { /** * decode jwt and return the uid and the password * - * @param string $jwt * - * @return array * @throws \Exception */ - protected function decodeJwt($jwt) { + protected function decodeJwt(string $jwt): array { $key = $this->gss->getJwtKey(); $decoded = (array)JWT::decode($jwt, new Key($key, Application::JWT_ALGORITHM)); @@ -299,14 +298,11 @@ protected function decodeJwt($jwt) { } /** - * create new user if the user doesn't exist yet on the client node - * - * @param string $uid - * @param array $options + * Create new user if the user doesn't exist yet on the client node */ - protected function autoprovisionIfNeeded($uid, $options) { + protected function autoprovisionIfNeeded(string $uid, array $options) { // make sure that a valid UID is given - if (empty($uid)) { + if ($uid === '') { $this->logger->error('Uid "{uid}" is not valid.', ['app' => $this->appName, 'uid' => $uid]); throw new \InvalidArgumentException('No valid uid given. Given uid: ' . $uid); } diff --git a/lib/Db/FileRequest.php b/lib/Db/FileRequest.php index 367c4a7..fa9f79a 100644 --- a/lib/Db/FileRequest.php +++ b/lib/Db/FileRequest.php @@ -191,10 +191,11 @@ public function getTeamStorages(FederatedShare $federatedShare, string $instance */ private function getCachedMountInfoFromNodeId(int $nodeId): ?ICachedMountFileInfo { $mounts = $this->userMountCache->getMountsForFileId($nodeId); - if (empty($mounts ?? [])) { + if ($mounts === []) { $this->logger->warning('mount not found for node id ' . $nodeId); + return null; } - return reset($mounts); + return current($mounts); } } diff --git a/lib/Db/ShareRequest.php b/lib/Db/ShareRequest.php index 9ca88d3..2e861a5 100644 --- a/lib/Db/ShareRequest.php +++ b/lib/Db/ShareRequest.php @@ -57,8 +57,8 @@ public function getFederatedSharesRelatedToRemoteInstance(array $files, string $ $shares = []; while ($row = $result->fetch()) { $shareWith = $row['share_with']; - if (str_ends_with(strtolower($shareWith), '@' . strtolower($instance))) { - $shareWith = substr($shareWith, 0, -strlen('@' . $instance)); + if (str_ends_with(strtolower((string)$shareWith), '@' . strtolower($instance))) { + $shareWith = substr((string)$shareWith, 0, -strlen('@' . $instance)); } $federatedShare = new FederatedShare(); @@ -78,7 +78,7 @@ public function getFederatedSharesRelatedToRemoteInstance(array $files, string $ /** * return id and owner about a file. * - * @return array{int, string} [fileId, fileOwner] + * @return array{0?: int, 1?: string} [fileId, fileOwner] */ public function getFileOwnerFromShareId(int $shareId): array { $qb = $this->connection->getQueryBuilder(); @@ -92,7 +92,7 @@ public function getFileOwnerFromShareId(int $shareId): array { return []; } $fileId = (int)$row['file_source']; - $owner = $row['uid_owner']; + $owner = (string)$row['uid_owner']; $result->closeCursor(); return [$fileId, $owner]; diff --git a/lib/Exceptions/LocalFederatedShareException.php b/lib/Exceptions/LocalFederatedShareException.php index 60324be..9ddc8c6 100644 --- a/lib/Exceptions/LocalFederatedShareException.php +++ b/lib/Exceptions/LocalFederatedShareException.php @@ -22,7 +22,7 @@ public function __construct( parent::__construct($message, $code, $previous); } - public function getFederatedShare(): FederatedShare { + public function getFederatedShare(): ?FederatedShare { return $this->federatedShare; } } diff --git a/lib/GlobalSiteSelector.php b/lib/GlobalSiteSelector.php index 3fada41..435edbb 100644 --- a/lib/GlobalSiteSelector.php +++ b/lib/GlobalSiteSelector.php @@ -26,38 +26,27 @@ class GlobalSiteSelector { public const MIN_JWT_KEY_LENGTH = 32; public function __construct( - private IConfig $config, + private readonly IConfig $config, ) { - $this->config = $config; } /** * the global site selector can operate as 'master' or 'slave' - * - * @return string */ public function getMode(): string { return strtolower($this->config->getSystemValueString('gss.mode', self::SLAVE)); } - /** - * @return bool - */ public function isMaster(): bool { return ($this->getMode() === self::MASTER); } - /** - * @return bool - */ public function isSlave(): bool { return ($this->getMode() === self::SLAVE); } /** * get JWT key - * - * @return string */ public function getJwtKey(): string { return $this->config->getSystemValueString('gss.jwt.key', ''); @@ -75,7 +64,6 @@ public function isJwtKeyValid(): bool { /** * get the URL of the global site selector master * - * @return string * @throws MasterUrlException */ public function getMasterUrl(): string { @@ -89,8 +77,6 @@ public function getMasterUrl(): string { /** * get lookup server URL - * - * @return string */ public function getLookupServerUrl(): string { // TODO: returns exception if non-existant diff --git a/lib/Listeners/AddContentSecurityPolicyListener.php b/lib/Listeners/AddContentSecurityPolicyListener.php index 790594a..2957a62 100644 --- a/lib/Listeners/AddContentSecurityPolicyListener.php +++ b/lib/Listeners/AddContentSecurityPolicyListener.php @@ -23,9 +23,9 @@ class AddContentSecurityPolicyListener implements IEventListener { public function __construct( - private IConfig $config, - private IUserSession $userSession, - private IRequest $request, + private readonly IConfig $config, + private readonly IUserSession $userSession, + private readonly IRequest $request, ) { } diff --git a/lib/Listeners/DeletingUser.php b/lib/Listeners/DeletingUser.php index e58ad45..332b97b 100644 --- a/lib/Listeners/DeletingUser.php +++ b/lib/Listeners/DeletingUser.php @@ -21,14 +21,11 @@ class DeletingUser implements IEventListener { public function __construct( - private GlobalSiteSelector $globalSiteSelector, - private Slave $slave, + private readonly GlobalSiteSelector $globalSiteSelector, + private readonly Slave $slave, ) { } - /** - * @param Event $event - */ #[\Override] public function handle(Event $event): void { if (!$event instanceof BeforeUserDeletedEvent) { diff --git a/lib/Listeners/UserChanged.php b/lib/Listeners/UserChanged.php index bebcea0..cf626f0 100644 --- a/lib/Listeners/UserChanged.php +++ b/lib/Listeners/UserChanged.php @@ -11,23 +11,29 @@ use OCA\GlobalSiteSelector\GlobalSiteSelector; use OCA\GlobalSiteSelector\Slave; +use OCP\Accounts\UserUpdatedEvent; use OCP\EventDispatcher\Event; use OCP\EventDispatcher\IEventListener; +use OCP\Server; use OCP\User\Events\UserChangedEvent; /** - * @template-implements IEventListener + * @template-implements IEventListener */ class UserChanged implements IEventListener { public function __construct( - private GlobalSiteSelector $globalSiteSelector, - private Slave $slave, + private readonly GlobalSiteSelector $globalSiteSelector, + private readonly Slave $slave, ) { } #[\Override] public function handle(Event $event): void { + if ($event instanceof UserUpdatedEvent) { + $this->handleUpdated($event); + } + if (!$event instanceof UserChangedEvent) { return; } @@ -51,4 +57,8 @@ public function handle(Event $event): void { $this->slave->createUser($params); } } + + public function handleUpdated(UserUpdatedEvent $event): void { + $this->slave->updateUser($event->getUser()); + } } diff --git a/lib/Listeners/UserCreated.php b/lib/Listeners/UserCreated.php index fddb1be..b37a40e 100644 --- a/lib/Listeners/UserCreated.php +++ b/lib/Listeners/UserCreated.php @@ -21,14 +21,11 @@ class UserCreated implements IEventListener { public function __construct( - private GlobalSiteSelector $globalSiteSelector, - private Slave $slave, + private readonly GlobalSiteSelector $globalSiteSelector, + private readonly Slave $slave, ) { } - /** - * @param Event $event - */ #[\Override] public function handle(Event $event): void { if (!$event instanceof UserCreatedEvent) { diff --git a/lib/Listeners/UserDeleted.php b/lib/Listeners/UserDeleted.php index 6fffadf..ab84d4e 100644 --- a/lib/Listeners/UserDeleted.php +++ b/lib/Listeners/UserDeleted.php @@ -21,14 +21,11 @@ class UserDeleted implements IEventListener { public function __construct( - private GlobalSiteSelector $globalSiteSelector, - private Slave $slave, + private readonly GlobalSiteSelector $globalSiteSelector, + private readonly Slave $slave, ) { } - /** - * @param Event $event - */ #[\Override] public function handle(Event $event): void { if (!$event instanceof UserDeletedEvent) { diff --git a/lib/Listeners/UserLoggedOut.php b/lib/Listeners/UserLoggedOut.php index cd61086..ca8f684 100644 --- a/lib/Listeners/UserLoggedOut.php +++ b/lib/Listeners/UserLoggedOut.php @@ -21,14 +21,11 @@ class UserLoggedOut implements IEventListener { public function __construct( - private GlobalSiteSelector $globalSiteSelector, - private Slave $slave, + private readonly GlobalSiteSelector $globalSiteSelector, + private readonly Slave $slave, ) { } - /** - * @param Event $event - */ #[\Override] public function handle(Event $event): void { if (!$event instanceof UserLoggedOutEvent) { diff --git a/lib/Listeners/UserLoggingIn.php b/lib/Listeners/UserLoggingIn.php index 5b71773..2cf4ddc 100644 --- a/lib/Listeners/UserLoggingIn.php +++ b/lib/Listeners/UserLoggingIn.php @@ -22,15 +22,12 @@ class UserLoggingIn implements IEventListener { public function __construct( - private GlobalSiteSelector $globalSiteSelector, - private Master $master, - private LoggerInterface $logger, + private readonly GlobalSiteSelector $globalSiteSelector, + private readonly Master $master, + private readonly LoggerInterface $logger, ) { } - /** - * @param Event $event - */ #[\Override] public function handle(Event $event): void { if (!$event instanceof BeforeUserLoggedInEvent) { diff --git a/lib/Lookup.php b/lib/Lookup.php index efd40bb..13276f9 100644 --- a/lib/Lookup.php +++ b/lib/Lookup.php @@ -17,14 +17,14 @@ class Lookup { - private string $lookupServerUrl; + private readonly string $lookupServerUrl; public function __construct( - private IClientService $clientService, - private LoggerInterface $logger, - private ICloudIdManager $cloudIdManager, - private GlobalSiteSelector $gss, - private IConfig $config, + private readonly IClientService $clientService, + private readonly LoggerInterface $logger, + private readonly ICloudIdManager $cloudIdManager, + private readonly GlobalSiteSelector $gss, + private readonly IConfig $config, ) { $this->lookupServerUrl = $this->config->getSystemValueString('lookup_server', ''); } @@ -33,7 +33,6 @@ public function __construct( * try to find the exact user at the lookup server, we allow to search for * email addresses and federated cloud ids and internal UIDs. * - * @param string $uid * * @return string the url of the server where the user is located */ @@ -57,7 +56,7 @@ public function search(string &$uid, bool $matchUid = false): string { } else { $this->logger->debug('search: federationId not set for ' . $uid . ' ' . json_encode($body)); } - } catch (\InvalidArgumentException $e) { + } catch (\InvalidArgumentException) { // Nothing to do, assuming we have not found anything } @@ -70,10 +69,9 @@ public function search(string &$uid, bool $matchUid = false): string { * * @param $uid * - * @return mixed * @throws \Exception */ - protected function queryLookupServer(string $uid, bool $matchUid = false) { + protected function queryLookupServer(string $uid, bool $matchUid = false): mixed { $this->sanitizeUid($uid); $this->logger->debug('queryLookupServer: asking lookup server for: ' . $uid . ' (matchUid: ' . json_encode($matchUid) . ')'); $client = $this->clientService->newClient(); @@ -100,7 +98,7 @@ public function getUserLocation(string $address, string &$uid = ''): string { 'sanitize' => $this->getUserLocation_Sanitize($address, $uid), '', 'validate' => $this->getUserLocation_Validate($address) }; - } catch (\UnhandledMatchError $e) { + } catch (\UnhandledMatchError) { throw new \UnhandledMatchError('gss.username_format in config.php is not valid'); } } @@ -111,7 +109,7 @@ private function getUserLocation_Validate(string $address): string { $location = $cloudId->getRemote(); return rtrim($location, '/'); - } catch (\InvalidArgumentException $e) { + } catch (\InvalidArgumentException) { $this->logger->notice('(CloudIdManager) Invalid Federated Cloud ID ' . $address); throw new \InvalidArgumentException('Invalid Federated Cloud ID'); } @@ -135,10 +133,7 @@ private function getUserLocation_Ignore(string $address, ?string &$uid = ''): st /** * based on the sanitizeUsername() method from apps/user_ldap/lib/Access.php * - * @param string $address - * @param string $uid * - * @return string */ private function getUserLocation_Sanitize(string $address, string &$uid): string { $address = $this->getUserLocation_Ignore($address, $extractedUid); @@ -174,13 +169,13 @@ public function sanitizeUid(string &$uid = ''): void { $uid = preg_replace( '#&([A-Za-z])(?:acute|cedil|caron|circ|grave|orn|ring|slash|th|tilde|uml);#', '\1', $uid ); - $uid = preg_replace('#&([A-Za-z]{2})(?:lig);#', '\1', $uid); - $uid = preg_replace('#&[^;]+;#', '', $uid); + $uid = preg_replace('#&([A-Za-z]{2})(?:lig);#', '\1', (string)$uid); + $uid = preg_replace('#&[^;]+;#', '', (string)$uid); $uid = str_replace(' ', '_', $uid); $uid = preg_replace('/[^a-zA-Z0-9_.@-]/u', '', $uid); - if (strlen($uid) > 64) { - $uid = hash('sha256', $uid, false); + if (strlen((string)$uid) > 64) { + $uid = hash('sha256', (string)$uid, false); } if ($uid === '') { @@ -190,11 +185,6 @@ public function sanitizeUid(string &$uid = ''): void { } } - /** - * @param array $options - * - * @return array - */ public function configureClient(array $options): array { return array_merge( $options, diff --git a/lib/Master.php b/lib/Master.php index 1ccbcf5..65b4e73 100644 --- a/lib/Master.php +++ b/lib/Master.php @@ -58,9 +58,6 @@ public function __construct( /** * find users location and redirect them to the right server * - * @param string $uid - * @param string|null $password - * @param IApacheBackend|null $backend * * @throws ContainerExceptionInterface * @throws HintException @@ -75,7 +72,7 @@ public function handleLoginRequest( 'start handle login request', [ 'uid' => $uid, - 'backend' => ($backend === null) ? null : get_class($backend) + 'backend' => ($backend === null) ? null : $backend::class ] ); @@ -227,11 +224,9 @@ public function handleLoginRequest( * format URL * * @param string $url - * - * @return string */ - protected function normalizeLocation($url) { - if (substr($url, 0, 7) === 'http://' || substr($url, 0, 8) === 'https://') { + protected function normalizeLocation($url): string { + if (str_starts_with($url, 'http://') || str_starts_with($url, 'https://')) { return $url; } @@ -242,8 +237,6 @@ protected function normalizeLocation($url) { * search for the user and return the location of the user * * @param $uid - * - * @return string */ protected function queryLookupServer(string &$uid, bool $matchUid = false): string { return $this->lookup->search($uid, $matchUid); @@ -253,13 +246,11 @@ protected function queryLookupServer(string &$uid, bool $matchUid = false): stri * redirect user to the right Nextcloud server * * @param string $uid - * @param string $password * @param string $location * @param array $options can contain additional parameters, e.g. from SAML - * * @throws Exception */ - protected function redirectUser($uid, $password, $location, array $options = []) { + protected function redirectUser($uid, string $password, $location, array $options = []) { $isClient = $this->request->isUserAgent( [ IRequest::USER_AGENT_CLIENT_IOS, @@ -272,8 +263,8 @@ protected function redirectUser($uid, $password, $location, array $options = []) $requestUri = $this->request->getRequestUri(); // check for both possible direct webdav end-points - $isDirectWebDavAccess = strpos($requestUri, 'remote.php/webdav') !== false; - $isDirectWebDavAccess = $isDirectWebDavAccess || strpos($requestUri, 'remote.php/dav') !== false; + $isDirectWebDavAccess = str_contains($requestUri, 'remote.php/webdav'); + $isDirectWebDavAccess = $isDirectWebDavAccess || str_contains($requestUri, 'remote.php/dav'); $authHeader = $this->request->getHeader('Authorization'); $redirectWebDav = $this->appConfig->getValueBool(Application::APP_ID, ConfigLexicon::REDIRECT_WEBDAV); @@ -286,7 +277,7 @@ protected function redirectUser($uid, $password, $location, array $options = []) if ($isClient && $isDirectWebDavAccess) { $this->logger->debug('redirectUser: client direct webdav request'); $redirectUrl = $location . '/remote.php/webdav/'; - } elseif ($isClient && !$isDirectWebDavAccess) { + } elseif ($isClient) { $this->logger->debug('redirectUser: client request generating apptoken'); $appToken = $this->getAppToken($location, $uid, $password, $options); @@ -326,12 +317,10 @@ protected function redirectUser($uid, $password, $location, array $options = []) * generate JWT * * @param string $uid - * @param string $password * @param array $options * - * @return string */ - protected function createJwt($uid, $password, $options) { + protected function createJwt($uid, string $password, $options): string { if (!$this->gss->isJwtKeyValid()) { $this->logger->error( 'gss.jwt.key is too short: HS256 requires at least ' @@ -349,9 +338,7 @@ protected function createJwt($uid, $password, $options) { 'exp' => time() + 300, // expires after 5 minutes ]; - $jwt = JWT::encode($token, $this->gss->getJwtKey(), Application::JWT_ALGORITHM); - - return $jwt; + return JWT::encode($token, $this->gss->getJwtKey(), Application::JWT_ALGORITHM); } /** @@ -359,13 +346,12 @@ protected function createJwt($uid, $password, $options) { * * @param string $location * @param string $uid - * @param string $password * @param array $options * * @return string * @throws Exception */ - protected function getAppToken($location, $uid, $password, $options) { + protected function getAppToken($location, $uid, string $password, $options) { $client = $this->clientService->newClient(); $jwt = $this->createJwt($uid, $password, $options); @@ -407,13 +393,11 @@ protected function getAppToken($location, $uid, $password, $options) { * @param string $url * @param string $uid * @param string $password - * - * @return string */ - protected function buildBasicAuthUrl($url, $uid, $password) { - if (strpos($url, 'http://') === 0) { + protected function buildBasicAuthUrl($url, $uid, $password): string { + if (str_starts_with($url, 'http://')) { $protocol = 'http://'; - } elseif (strpos($url, 'https://') === 0) { + } elseif (str_starts_with($url, 'https://')) { $protocol = 'https://'; } else { // no protocol given, switch to https as default @@ -461,7 +445,7 @@ private function isPath(array $search, string $path): bool { } foreach ($search as $entry) { - if (str_starts_with($path, $entry) || str_starts_with($path, '/index.php' . $entry)) { + if (str_starts_with($path, (string)$entry) || str_starts_with($path, '/index.php' . $entry)) { return true; } } diff --git a/lib/Migration/Version0110Date20180925143400.php b/lib/Migration/Version0110Date20180925143400.php index 959726a..0688add 100644 --- a/lib/Migration/Version0110Date20180925143400.php +++ b/lib/Migration/Version0110Date20180925143400.php @@ -14,9 +14,7 @@ class Version0110Date20180925143400 extends SimpleMigrationStep { /** - * @param IOutput $output * @param \Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper` - * @param array $options * @return null|ISchemaWrapper * @since 13.0.0 */ diff --git a/lib/Model/FederatedShare.php b/lib/Model/FederatedShare.php index 6dec2dd..30beb74 100644 --- a/lib/Model/FederatedShare.php +++ b/lib/Model/FederatedShare.php @@ -23,9 +23,6 @@ class FederatedShare implements JsonSerializable { private ?LocalFile $target = null; - public function __construct() { - } - public function setId(int $id): self { $this->id = $id; return $this; @@ -133,7 +130,7 @@ public function import(array $data): self { } /** - * @return array{id: int, fileId: int, shareType: int, shareWith: string, permissions: int, target: array, remote: string, remoteId: int} + * @return array{id?: int, fileId?: int, shareType?: int, shareWith?: string, permissions?: int, target: ?LocalFile, remote?: string, remoteId?: int, bounce?: bool} */ #[\Override] public function jsonSerialize(): array { diff --git a/lib/Model/LocalFile.php b/lib/Model/LocalFile.php index 5f1b36a..4dbbd67 100644 --- a/lib/Model/LocalFile.php +++ b/lib/Model/LocalFile.php @@ -19,9 +19,6 @@ class LocalFile implements JsonSerializable { /** @var string[] */ private array $path = []; - public function __construct() { - } - public function getId(): int { return $this->id; } @@ -67,8 +64,6 @@ public function getPath(): array { /** * @param string[] $path - * - * @return $this */ public function setPath(array $path): self { $this->path = $path; diff --git a/lib/Model/LocalMount.php b/lib/Model/LocalMount.php index e5ec2a8..cf8f96b 100644 --- a/lib/Model/LocalMount.php +++ b/lib/Model/LocalMount.php @@ -16,9 +16,6 @@ class LocalMount implements JsonSerializable { private string $mountPoint = ''; private string $userId = ''; - public function __construct() { - } - public function setProviderClass(string $providerClass): self { $this->providerClass = $providerClass; return $this; diff --git a/lib/Service/GlobalScaleService.php b/lib/Service/GlobalScaleService.php index 3f8ace5..b604d9f 100644 --- a/lib/Service/GlobalScaleService.php +++ b/lib/Service/GlobalScaleService.php @@ -97,7 +97,7 @@ public function refreshTokenFromAddress(string $address): void { } $token = $this->getRemotePublicDiscovery($address)['token'] ?? ''; - if ($token === '' || strlen($token) < 5) { + if ($token === '' || strlen((string)$token) < 5) { return; } diff --git a/lib/Service/GlobalShareService.php b/lib/Service/GlobalShareService.php index 2840732..e78c618 100644 --- a/lib/Service/GlobalShareService.php +++ b/lib/Service/GlobalShareService.php @@ -115,7 +115,7 @@ public function getSharedFiles(int $fileId, int $shareId = 0, ?string $instance } // from a file id, get all parents until mount point - $files = $this->getRelatedFiles((int)$fileId); + $files = $this->getRelatedFiles($fileId); if (empty($files)) { throw new SharedFileException('file not found'); } diff --git a/lib/Service/SlaveService.php b/lib/Service/SlaveService.php index 3cfb702..ce3d0c5 100644 --- a/lib/Service/SlaveService.php +++ b/lib/Service/SlaveService.php @@ -24,36 +24,22 @@ class SlaveService { private const CACHE_DISPLAY_NAME = 'gss/displayName'; private const CACHE_DISPLAY_NAME_TTL = 3600; - - private LoggerInterface $logger; - private IClientService $clientService; - private IUserManager $userManager; - private IAccountManager $accountManager; - private IConfig $config; - private Lookup $lookup; - private string $lookupServer; - private string $operationMode; - private string $authKey; - private ICache $cacheDisplayName; - private int $cacheDisplayNameTtl; + private readonly string $lookupServer; + private readonly string $operationMode; + private readonly string $authKey; + private readonly ICache $cacheDisplayName; + private readonly int $cacheDisplayNameTtl; public function __construct( - LoggerInterface $logger, - IClientService $clientService, - IUserManager $userManager, - IAccountManager $accountManager, - IConfig $config, - Lookup $lookup, + private readonly LoggerInterface $logger, + private readonly IClientService $clientService, + private readonly IUserManager $userManager, + private readonly IAccountManager $accountManager, + private readonly IConfig $config, + private readonly Lookup $lookup, GlobalSiteSelector $gss, ICacheFactory $cacheFactory, ) { - $this->logger = $logger; - $this->clientService = $clientService; - $this->userManager = $userManager; - $this->accountManager = $accountManager; - $this->config = $config; - $this->lookup = $lookup; - $this->lookupServer = rtrim($gss->getLookupServerUrl(), '/'); $this->operationMode = $gss->getMode(); $this->authKey = $gss->getJwtKey(); @@ -72,13 +58,10 @@ public function updateUserById(string $userId): void { $this->updateUser($user); } - /** - * @param IUser $user - */ public function updateUser(IUser $user): void { try { $this->checkConfiguration(); - } catch (ConfigurationException $e) { + } catch (ConfigurationException) { return; } @@ -90,10 +73,8 @@ public function updateUser(IUser $user): void { /** * get single user's display name * - * @param string $userId * @param bool $cacheOnly - only get data from cache, do not request lus * - * @return string */ public function getUserDisplayName(string $userId, bool $cacheOnly = false): string { $userId = trim($userId, '/'); @@ -105,16 +86,12 @@ public function getUserDisplayName(string $userId, bool $cacheOnly = false): str /** * get multiple users' display name * - * @param array $userIds * @param bool $cacheOnly - only get data from cache, do not request lus * - * @return array */ public function getUsersDisplayName(array $userIds, bool $cacheOnly = false): array { return $this->getDetails( - array_map(function (string $userId): string { - return trim($userId, '/'); - }, $userIds), $cacheOnly + array_map(fn (string $userId): string => trim($userId, '/'), $userIds), $cacheOnly ); } @@ -122,10 +99,8 @@ public function getUsersDisplayName(array $userIds, bool $cacheOnly = false): ar * get details for a list of userIds from the LUS. * Will first get data from cache, and will cache data returned by lus * - * @param array $users * @param bool $cacheOnly - only get data from cache, do not request lus * - * @return array */ protected function getDetails(array $users, bool $cacheOnly = false): array { $knownDetails = []; @@ -149,7 +124,7 @@ protected function getDetails(array $users, bool $cacheOnly = false): array { true, 512, JSON_THROW_ON_ERROR ); - } catch (Exception $e) { + } catch (Exception) { // if configuration issue or request is not complete, we return known details. return $knownDetails; } @@ -196,10 +171,7 @@ protected function postLookup(string $path, array $data): void { } /** - * @param string $path - * @param array $data * - * @return string * @throws ConfigurationException */ protected function getLookup(string $path, array $data): string { @@ -222,11 +194,10 @@ protected function getLookup(string $path, array $data): string { return ''; } - return $response->getBody(); + return (string)$response->getBody(); } /** - * @return void * @throws ConfigurationException */ protected function checkConfiguration(): void { @@ -246,9 +217,7 @@ protected function checkConfiguration(): void { /** * get user data from account manager * - * @param IUser $user * - * @return array */ public function getAccountData(IUser $user): array { $data = [ // we get basic values from IUser diff --git a/lib/Slave.php b/lib/Slave.php index 9169782..ea0c106 100644 --- a/lib/Slave.php +++ b/lib/Slave.php @@ -20,40 +20,25 @@ class Slave { public const SAML_IDP = 'saml_idp'; public const OIDC_PROVIDER_ID = 'oidc_provider_id'; - - private IUserManager $userManager; - private IClientService $clientService; - private SlaveService $slaveService; - private Lookup $lookup; - private LoggerInterface $logger; private string $lookupServer; - private string $operationMode; - private string $authKey; - private GlobalSiteSelector $gss; - private IConfig $config; + private readonly string $operationMode; + private readonly string $authKey; private static array $toRemove = []; // remember users which should be removed public function __construct( - IUserManager $userManager, - IClientService $clientService, - SlaveService $slaveService, - Lookup $lookup, - GlobalSiteSelector $gss, - LoggerInterface $logger, - IConfig $config, + private readonly IUserManager $userManager, + private readonly IClientService $clientService, + private readonly SlaveService $slaveService, + private readonly Lookup $lookup, + private readonly GlobalSiteSelector $gss, + private readonly LoggerInterface $logger, + private readonly IConfig $config, ) { - $this->userManager = $userManager; - $this->clientService = $clientService; - $this->slaveService = $slaveService; - $this->lookup = $lookup; - $this->logger = $logger; - $this->lookupServer = $gss->getLookupServerUrl(); - $this->operationMode = $gss->getMode(); - $this->authKey = $gss->getJwtKey(); + $this->lookupServer = $this->gss->getLookupServerUrl(); + $this->operationMode = $this->gss->getMode(); + $this->authKey = $this->gss->getJwtKey(); $this->lookupServer = rtrim($this->lookupServer, '/'); $this->lookupServer .= '/gs/users'; - $this->gss = $gss; - $this->config = $config; } public function createUser(array $params): void { @@ -81,8 +66,6 @@ public function createUser(array $params): void { /** * update existing user if personal data change - * - * @param IUser $user */ public function updateUser(IUser $user): void { if (!$this->checkConfiguration()) { @@ -106,8 +89,6 @@ public function updateUser(IUser $user): void { * the server indicated that the admin want to remove a user, remember the * federated cloud id so that we can remove the user from the lookup server * once they were deleted - * - * @param array $params */ public function preDeleteUser(array $params): void { $uid = $params['uid']; @@ -119,8 +100,6 @@ public function preDeleteUser(array $params): void { /** * remove user from lookup server - * - * @param array $params */ public function deleteUser(array $params): void { if (!$this->checkConfiguration()) { @@ -184,8 +163,6 @@ public function batchUpdate(): void { /** * send users to the lookup server - * - * @param array $users */ protected function addUsers(array $users): void { $dataBatch = ['authKey' => $this->authKey, 'users' => $users]; @@ -217,8 +194,6 @@ protected function addUsers(array $users): void { /** * remove users from the lookup server - * - * @param array $users */ protected function removeUsers(array $users): void { $dataBatch = ['authKey' => $this->authKey, 'users' => $users]; @@ -282,8 +257,6 @@ protected function checkConfiguration(): bool { /** * Operation mode - slave or master - * - * @return string */ public function getOperationMode(): string { return $this->operationMode; @@ -292,7 +265,7 @@ public function getOperationMode(): string { /** * send user back to master */ - public function handleLogoutRequest(IUser $user) { + public function handleLogoutRequest(IUser $user): void { $token = [ 'logout' => 'true', 'saml.idp' => $this->config->getUserValue( diff --git a/lib/TokenHandler.php b/lib/TokenHandler.php index fd88179..c7fe046 100644 --- a/lib/TokenHandler.php +++ b/lib/TokenHandler.php @@ -21,8 +21,8 @@ class TokenHandler { public function __construct( - private IProvider $tokenProvider, - private ISecureRandom $random, + private readonly IProvider $tokenProvider, + private readonly ISecureRandom $random, ) { } @@ -30,10 +30,8 @@ public function __construct( * generate app token * * @param string $uid - * - * @return array */ - public function generateAppToken($uid) { + public function generateAppToken($uid): array { // generate random token $token = $this->random->generate(72, ISecureRandom::CHAR_UPPER . ISecureRandom::CHAR_LOWER . ISecureRandom::CHAR_DIGITS); $deviceToken = $this->tokenProvider->generateToken($token, $uid, $uid, null, 'Client login', IToken::PERMANENT_TOKEN); diff --git a/lib/UserBackend.php b/lib/UserBackend.php index a964433..9911e2a 100644 --- a/lib/UserBackend.php +++ b/lib/UserBackend.php @@ -31,16 +31,16 @@ class UserBackend extends ABackend implements IUserBackend, UserInterface, ICheckPasswordBackend, IGetDisplayNameBackend, ISetDisplayNameBackend, ILimitAwareCountUsersBackend { private string $dbName = 'global_scale_users'; - /** @var CappedMemoryCache $cache */ + /** @var CappedMemoryCache $cache */ private CappedMemoryCache $cache; public function __construct( - private IDBConnection $db, - private ISession $session, - private IEventDispatcher $eventDispatcher, - private IGroupManager $groupManager, - private IUserManager $userManager, - private IRootFolder $rootFolder, + private readonly IDBConnection $db, + private readonly ISession $session, + private readonly IEventDispatcher $eventDispatcher, + private readonly IGroupManager $groupManager, + private readonly IUserManager $userManager, + private readonly IRootFolder $rootFolder, ) { $this->cache = new CappedMemoryCache(); } @@ -75,7 +75,7 @@ public function createUserIfNotExists(string $uid, array $attributes): void { try { // copy skeleton \OC_Util::copySkeleton($uid, $userFolder); - } catch (NotPermittedException $ex) { + } catch (NotPermittedException) { // read only uses } @@ -100,9 +100,9 @@ public function createUserIfNotExists(string $uid, array $attributes): void { && $currentEmail !== $newEmail) { $user->setEMailAddress($newEmail); } - $currentDisplayName = (string)$this->getDisplayName($uid); + $currentDisplayName = $this->getDisplayName($uid); if ($newDisplayName !== null && $currentDisplayName !== $newDisplayName) { - $this->eventDispatcher->dispatchTyped(new UserChangedEvent($user, 'displayname', $newDisplayName, null)); + $this->eventDispatcher->dispatchTyped(new UserChangedEvent($user, 'displayname', $newDisplayName)); \OC_Hook::emit( 'OC_User', 'changeUser', [ @@ -126,7 +126,7 @@ public function createUserIfNotExists(string $uid, array $attributes): void { $groupsToRemove = array_diff($oldGroups, $newGroups); foreach ($groupsToAdd as $group) { - if (strtolower($group) === 'admin') { + if (strtolower((string)$group) === 'admin') { continue; } @@ -165,7 +165,7 @@ public function getUsers($search = '', $limit = null, $offset = null): array { $limit = $this->fixLimit($limit); $users = $this->getDisplayNames($search, $limit, $offset); - $userIds = array_map('strval', array_keys($users)); + $userIds = array_map(strval(...), array_keys($users)); sort($userIds, SORT_STRING | SORT_FLAG_CASE); return $userIds; } @@ -175,11 +175,7 @@ public function countUsers(int $limit = 0): int|false { $query = $this->db->getQueryBuilder(); $query->select($query->func()->count('uid')) ->from($this->dbName); - $result = $query->executeQuery()->fetchOne(); - if ($result === false) { - return false; - } - return $result; + return $query->executeQuery()->fetchOne(); } #[Override] @@ -203,7 +199,7 @@ public function setDisplayName(string $uid, string $displayName): bool { ->where($qb->expr()->eq('uid', $qb->createNamedParameter($uid))) ->executeStatement(); - $this->cache[$uid]['displayname'] = $displayName; + $this->cache[$uid] = ['displayname' => $displayName]; return true; } @@ -238,9 +234,9 @@ public function getDisplayNames($search = '', $limit = null, $offset = null): ar } $result = $qb->executeQuery(); $displayNames = []; - while ($row = $result->fetchAssociative()) { + while ($row = $result->fetch()) { $displayNames[(string)$row['uid']] = (string)$row['displayname']; - $this->cache[(string)$row['uid']]['displayname'] = (string)$row['displayname']; + $this->cache[(string)$row['uid']] = ['displayname' => (string)$row['displayname']]; } $result->closeCursor(); diff --git a/lib/UserDiscoveryModules/IUserDiscoveryModule.php b/lib/UserDiscoveryModules/IUserDiscoveryModule.php index 22f9391..5b170a9 100644 --- a/lib/UserDiscoveryModules/IUserDiscoveryModule.php +++ b/lib/UserDiscoveryModules/IUserDiscoveryModule.php @@ -15,8 +15,6 @@ interface IUserDiscoveryModule { * * @param array $data arbitrary data, whatever the module needs (for example for SAML we hand over the * raw data) - * - * @return string */ public function getLocation(array $data): string; } diff --git a/lib/UserDiscoveryModules/ManualUserMapping.php b/lib/UserDiscoveryModules/ManualUserMapping.php index c1da105..09c956f 100644 --- a/lib/UserDiscoveryModules/ManualUserMapping.php +++ b/lib/UserDiscoveryModules/ManualUserMapping.php @@ -28,13 +28,13 @@ * @package OCA\GlobalSiteSelector\UserDiscoveryModules */ class ManualUserMapping implements IUserDiscoveryModule { - private string $idpParameter; - private string $file; - private bool $useRegularExpressions; + private readonly string $idpParameter; + private readonly string $file; + private readonly bool $useRegularExpressions; public function __construct( IConfig $config, - private LoggerInterface $logger, + private readonly LoggerInterface $logger, ) { $this->idpParameter = $config->getSystemValueString('gss.discovery.manual.mapping.parameter', ''); $this->file = $config->getSystemValueString('gss.discovery.manual.mapping.file', ''); @@ -50,8 +50,6 @@ public function __construct( * get the initial user location * * @param array $data idp parameters - * - * @return string */ #[\Override] public function getLocation(array $data): string { @@ -62,12 +60,12 @@ public function getLocation(array $data): string { $this->logger->debug('Lookup key is: "' . $key . '"'); // regular lookup - if (!empty($key) && is_array($dictionary) && !$this->useRegularExpressions) { + if (!empty($key) && !$this->useRegularExpressions) { $location = $dictionary[$key] ?? ''; } // dictionary contains regular expressions - if (!empty($key) && is_array($dictionary) && $this->useRegularExpressions) { + if (!empty($key) && $this->useRegularExpressions) { foreach ($dictionary as $regex => $nextcloudNode) { $this->logger->debug('Testing regex: "' . $regex . '"'); if (preg_match($regex, $key) === 1) { @@ -86,10 +84,8 @@ public function getLocation(array $data): string { /** * get dictionary which maps idp parameters to nextcloud nodes - * - * @return array */ - private function getDictionary() { + private function getDictionary(): array { $dictionary = []; $isValidFile = !empty($this->file) && file_exists($this->file); if ($isValidFile) { @@ -111,7 +107,7 @@ private function getDictionary() { * * @return string */ - private function getKey($data) { + private function getKey(array $data) { $key = ''; if (!empty($this->idpParameter) && array_key_exists($this->idpParameter, $data)) { $keys = $data[$this->idpParameter]; @@ -136,9 +132,9 @@ private function getKey($data) { */ private function normalizeKey($key) { $normalized = $key; - $pos = strrpos($key, '@'); + $pos = strrpos((string)$key, '@'); if ($pos !== false) { - $normalized = substr($key, $pos + 1); + $normalized = substr((string)$key, $pos + 1); } $this->logger->debug('Normalized key: ' . $normalized); diff --git a/lib/UserDiscoveryModules/RemoteUserMapping.php b/lib/UserDiscoveryModules/RemoteUserMapping.php index dd2fb1e..f89933a 100644 --- a/lib/UserDiscoveryModules/RemoteUserMapping.php +++ b/lib/UserDiscoveryModules/RemoteUserMapping.php @@ -25,13 +25,13 @@ * 'gss.discovery.remote.secret' => 'myVeryOwnLittleSecret', */ class RemoteUserMapping implements IUserDiscoveryModule { - private string $discoveryEndpoint; - private string $discoverySecretKey; + private readonly string $discoveryEndpoint; + private readonly string $discoverySecretKey; public function __construct( - private IClientService $clientService, + private readonly IClientService $clientService, IConfig $config, - private LoggerInterface $logger, + private readonly LoggerInterface $logger, ) { $this->discoveryEndpoint = $config->getSystemValueString('gss.discovery.remote.endpoint', ''); $this->discoverySecretKey = $config->getSystemValueString('gss.discovery.remote.secret', ''); diff --git a/lib/UserDiscoveryModules/UserDiscoveryOIDC.php b/lib/UserDiscoveryModules/UserDiscoveryOIDC.php index 26570eb..36e2fbf 100644 --- a/lib/UserDiscoveryModules/UserDiscoveryOIDC.php +++ b/lib/UserDiscoveryModules/UserDiscoveryOIDC.php @@ -24,7 +24,7 @@ * @package OCA\GlobalSiteSelector\UserDiscoveryModule */ class UserDiscoveryOIDC implements IUserDiscoveryModule { - private string $tokenLocationAttribute; + private readonly string $tokenLocationAttribute; public function __construct(IConfig $config) { $this->tokenLocationAttribute = $config->getSystemValueString('gss.discovery.oidc.slave.mapping', ''); @@ -34,8 +34,6 @@ public function __construct(IConfig $config) { * read user location from OIDC token attribute * * @param array $data OIDC attributes to read the location from - * - * @return string */ #[\Override] public function getLocation(array $data): string { diff --git a/lib/UserDiscoveryModules/UserDiscoverySAML.php b/lib/UserDiscoveryModules/UserDiscoverySAML.php index 3ed69ad..54b038d 100644 --- a/lib/UserDiscoveryModules/UserDiscoverySAML.php +++ b/lib/UserDiscoveryModules/UserDiscoverySAML.php @@ -23,7 +23,7 @@ * @package OCA\GlobalSiteSelector\UserDiscoveryModule */ class UserDiscoverySAML implements IUserDiscoveryModule { - private string $idpParameter; + private readonly string $idpParameter; public function __construct(IConfig $config) { $this->idpParameter = $config->getSystemValueString('gss.discovery.saml.slave.mapping', ''); @@ -33,8 +33,6 @@ public function __construct(IConfig $config) { * read user location from SAML parameters * * @param array $data SAML Parameters to read the location from - * - * @return string */ #[\Override] public function getLocation(array $data): string { diff --git a/psalm.xml b/psalm.xml index f618437..06bd540 100644 --- a/psalm.xml +++ b/psalm.xml @@ -5,7 +5,7 @@ --> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -76,31 +38,9 @@ - - - - - - - - - - - - - - - - - - - - - - diff --git a/rector.php b/rector.php new file mode 100644 index 0000000..9137874 --- /dev/null +++ b/rector.php @@ -0,0 +1,28 @@ +withPaths([ + __DIR__ . '/lib', + __DIR__ . '/tests', + ]) + ->withSkip([ + __DIR__ . '/tests/stubs', + __DIR__ . '/lib/Vendor/Firebase', + ]) + ->withPreparedSets( + deadCode: true, + typeDeclarations: true, + )->withPhpSets( + php81: true, + )->withConfiguredRule(ClassPropertyAssignToConstructorPromotionRector::class, [ + 'inline_public' => true, + 'rename_property' => true, + ]); diff --git a/tests/stubs/icewind_streams_directory.php b/tests/stubs/icewind_streams_directory.php deleted file mode 100644 index 64c1e06..0000000 --- a/tests/stubs/icewind_streams_directory.php +++ /dev/null @@ -1,43 +0,0 @@ - - * This file is licensed under the Licensed under the MIT license: - * http://opensource.org/licenses/MIT - */ - -namespace Icewind\Streams; - -/** - * Interface for stream wrappers that implements a directory - */ -interface Directory { - /** - * @param string $path - * @param array $options - * @return bool - */ - public function dir_opendir($path, $options) - { - } - - /** - * @return string|bool - */ - public function dir_readdir() - { - } - - /** - * @return bool - */ - public function dir_closedir() - { - } - - /** - * @return bool - */ - public function dir_rewinddir() - { - } -} diff --git a/tests/stubs/icewind_streams_iteratordirectory.php b/tests/stubs/icewind_streams_iteratordirectory.php deleted file mode 100644 index 9caf54c..0000000 --- a/tests/stubs/icewind_streams_iteratordirectory.php +++ /dev/null @@ -1,86 +0,0 @@ - - * This file is licensed under the Licensed under the MIT license: - * http://opensource.org/licenses/MIT - */ - -namespace Icewind\Streams; - -/** - * Create a directory handle from an iterator or array - * - * The following options should be passed in the context when opening the stream - * [ - * 'dir' => [ - * 'array' => string[] - * 'iterator' => \Iterator - * ] - * ] - * - * Either 'array' or 'iterator' need to be set, if both are set, 'iterator' takes preference - */ -class IteratorDirectory extends WrapperHandler implements Directory { - /** - * @var resource - */ - public $context; - - /** - * @var \Iterator - */ - protected $iterator; - - /** - * Load the source from the stream context and return the context options - * - * @param string $name - * @return array - * @throws \BadMethodCallException - */ - protected function loadContext($name = null) - { - } - - /** - * @param string $path - * @param array $options - * @return bool - */ - public function dir_opendir($path, $options) - { - } - - /** - * @return string|bool - */ - public function dir_readdir() - { - } - - /** - * @return bool - */ - public function dir_closedir() - { - } - - /** - * @return bool - */ - public function dir_rewinddir() - { - } - - /** - * Creates a directory handle from the provided array or iterator - * - * @param \Iterator | array $source - * @return resource|false - * - * @throws \BadMethodCallException - */ - public static function wrap($source) - { - } -} diff --git a/tests/stubs/icewind_streams_wrapperhandler.php b/tests/stubs/icewind_streams_wrapperhandler.php deleted file mode 100644 index 136805e..0000000 --- a/tests/stubs/icewind_streams_wrapperhandler.php +++ /dev/null @@ -1,64 +0,0 @@ - - * - * @license GNU AGPL version 3 or any later version - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as - * published by the Free Software Foundation, either version 3 of the - * License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - * - */ - -namespace Icewind\Streams; - -class WrapperHandler { - /** @var resource $context */ - protected $context; - - const NO_SOURCE_DIR = 1; - - /** - * get the protocol name that is generated for the class - * @param string|null $class - * @return string - */ - public static function getProtocol($class = null) - { - } - - /** - * @param resource|int $source - * @param resource|array $context - * @param string|null $protocol deprecated, protocol is now automatically generated - * @param string|null $class deprecated, class is now automatically generated - * @return resource|false - */ - protected static function wrapSource($source, $context = [], $protocol = null, $class = null, $mode = 'r+') - { - } - - protected static function isDirectoryHandle($resource) - { - } - - /** - * Load the source from the stream context and return the context options - * - * @param string|null $name if not set, the generated protocol name is used - * @return array - * @throws \BadMethodCallException - */ - protected function loadContext($name = null) - { - } -} diff --git a/tests/stubs/oc.php b/tests/stubs/oc.php index e1c5b60..8734e22 100644 --- a/tests/stubs/oc.php +++ b/tests/stubs/oc.php @@ -6,21 +6,6 @@ * SPDX-FileCopyrightText: 2013-2016 ownCloud, Inc. * SPDX-License-Identifier: AGPL-3.0-only */ -use OC\Encryption\HookManager; -use OC\Share20\Hooks; -use OCP\EventDispatcher\IEventDispatcher; -use OCP\Group\Events\UserRemovedEvent; -use OCP\ILogger; -use OCP\IRequest; -use OCP\IURLGenerator; -use OCP\IUserSession; -use OCP\Security\Bruteforce\IThrottler; -use OCP\Server; -use OCP\Share; -use OCP\User\Events\UserChangedEvent; -use Psr\Log\LoggerInterface; -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use function OCP\Log\logger; /** * Class that is a namespace for all global OC variables @@ -28,123 +13,9 @@ * OC_autoload! */ class OC { - /** - * Associative array for autoloading. classname => filename - */ - public static array $CLASSPATH = []; - /** - * The installation path for Nextcloud on the server (e.g. /srv/http/nextcloud) - */ - public static string $SERVERROOT = ''; - /** - * the Nextcloud root path for http requests (e.g. /nextcloud) - */ - public static string $WEBROOT = ''; - /** - * The installation path array of the apps folder on the server (e.g. /srv/http/nextcloud) 'path' and - * web path in 'url' - */ - public static array $APPSROOTS = []; - - public static string $configDir; - - /** - * requested app - */ - public static string $REQUESTEDAPP = ''; - /** * check if Nextcloud runs in cli mode */ public static bool $CLI = false; - public static \OC\Autoloader $loader; - - public static \Composer\Autoload\ClassLoader $composerAutoloader; - - public static \OC\Server $server; - - /** - * @throws \RuntimeException when the 3rdparty directory is missing or - * the app path list is empty or contains an invalid path - */ - public static function initPaths(): void - { - } - - public static function checkConfig(): void - { - } - - public static function checkInstalled(\OC\SystemConfig $systemConfig): void - { - } - - public static function checkMaintenanceMode(\OC\SystemConfig $systemConfig): void - { - } - - public static function initSession(): void - { - } - - /** - * @return bool true if the session expiry should only be done by gc instead of an explicit timeout - */ - public static function hasSessionRelaxedExpiry(): bool - { - } - - /** - * Try to set some values to the required Nextcloud default - */ - public static function setRequiredIniValues(): void - { - } - - public static function init(): void - { - } - - /** - * register hooks for the cleanup of cache and bruteforce protection - */ - public static function registerCleanupHooks(\OC\SystemConfig $systemConfig): void - { - } - - /** - * register hooks for sharing - */ - public static function registerShareHooks(\OC\SystemConfig $systemConfig): void - { - } - - protected static function registerAutoloaderCache(\OC\SystemConfig $systemConfig): void - { - } - - /** - * Handle the request - */ - public static function handleRequest(): void - { - } - - /** - * Check login: apache auth, auth token, basic auth - */ - public static function handleLogin(OCP\IRequest $request): bool - { - } - - protected static function handleAuthHeaders(): void - { - } - - protected static function tryAppAPILogin(OCP\IRequest $request): bool - { - } } - -OC::init(); diff --git a/tests/stubs/oc_appframework_ocs_baseresponse.php b/tests/stubs/oc_appframework_ocs_baseresponse.php deleted file mode 100644 index b30d8ef..0000000 --- a/tests/stubs/oc_appframework_ocs_baseresponse.php +++ /dev/null @@ -1,63 +0,0 @@ - - * @template-extends Response> - */ -abstract class BaseResponse extends Response { - /** @var array */ - protected $data; - - /** @var string */ - protected $format; - - /** @var ?string */ - protected $statusMessage; - - /** @var ?int */ - protected $itemsCount; - - /** @var ?int */ - protected $itemsPerPage; - - /** - * BaseResponse constructor. - * - * @param DataResponse $dataResponse - * @param string $format - * @param string|null $statusMessage - * @param int|null $itemsCount - * @param int|null $itemsPerPage - */ - public function __construct(DataResponse $dataResponse, $format = 'xml', $statusMessage = null, $itemsCount = null, $itemsPerPage = null) - { - } - - /** - * @param array $meta - * @return string - */ - protected function renderResult(array $meta): string - { - } - - protected function toXML(array $array, \XMLWriter $writer): void - { - } - - public function getOCSStatus() - { - } -} diff --git a/tests/stubs/oc_appframework_ocs_v1response.php b/tests/stubs/oc_appframework_ocs_v1response.php deleted file mode 100644 index b0fd50b..0000000 --- a/tests/stubs/oc_appframework_ocs_v1response.php +++ /dev/null @@ -1,48 +0,0 @@ - - * @template-extends BaseResponse> - */ -class V1Response extends BaseResponse { - /** - * The V1 endpoint has very limited http status codes basically everything - * is status 200 except 401 - * - * @return int - */ - public function getStatus() - { - } - - /** - * In v1 all OK is 100 - * - * @return int - */ - public function getOCSStatus() - { - } - - /** - * Construct the meta part of the response - * And then late the base class render - * - * @return string - */ - public function render() - { - } -} diff --git a/tests/stubs/oc_appframework_utility_simplecontainer.php b/tests/stubs/oc_appframework_utility_simplecontainer.php deleted file mode 100644 index de7a442..0000000 --- a/tests/stubs/oc_appframework_utility_simplecontainer.php +++ /dev/null @@ -1,123 +0,0 @@ -|string $id - * @return T|mixed - * @psalm-template S as class-string|string - * @psalm-param S $id - * @psalm-return (S is class-string ? T : mixed) - */ - public function get(string $id): mixed - { - } - - public function has(string $id): bool - { - } - - public function resolve($name) - { - } - - public function query(string $name, bool $autoload = true) - { - } - - /** - * @param string $name - * @param mixed $value - */ - public function registerParameter($name, $value) - { - } - - /** - * The given closure is call the first time the given service is queried. - * The closure has to return the instance for the given service. - * Created instance will be cached in case $shared is true. - * - * @param string $name name of the service to register another backend for - * @param Closure $closure the closure to be called on service creation - * @param bool $shared - */ - public function registerService($name, Closure $closure, $shared = true) - { - } - - /** - * Shortcut for returning a service from a service under a different key, - * e.g. to tell the container to return a class when queried for an - * interface - * @param string $alias the alias that should be registered - * @param string $target the target that should be resolved instead - */ - public function registerAlias($alias, $target) - { - } - - /* - * @param string $name - * @return string - */ - protected function sanitizeName($name) - { - } - - /** - * @deprecated 20.0.0 use \Psr\Container\ContainerInterface::has - */ - public function offsetExists($id): bool - { - } - - /** - * @deprecated 20.0.0 use \Psr\Container\ContainerInterface::get - * @return mixed - */ - #[\ReturnTypeWillChange] - public function offsetGet($id) - { - } - - /** - * @deprecated 20.0.0 use \OCP\IContainer::registerService - */ - public function offsetSet($offset, $value): void - { - } - - /** - * @deprecated 20.0.0 - */ - public function offsetUnset($offset): void - { - } -} diff --git a/tests/stubs/oc_files_cache_cache.php b/tests/stubs/oc_files_cache_cache.php deleted file mode 100644 index 7647da6..0000000 --- a/tests/stubs/oc_files_cache_cache.php +++ /dev/null @@ -1,427 +0,0 @@ - $value] the metadata to update, only the fields provided in the array will be updated, non-provided values will remain unchanged - */ - public function update($id, array $data) - { - } - - /** - * extract query parts and params array from data array - * - * @param array $data - * @return array - */ - protected function normalizeData(array $data): array - { - } - - /** - * get the file id for a file - * - * A file id is a numeric id for a file or folder that's unique within an owncloud instance which stays the same for the lifetime of a file - * - * File ids are easiest way for apps to store references to a file since unlike paths they are not affected by renames or sharing - * - * @param string $file - * @return int - */ - public function getId($file) - { - } - - /** - * get the id of the parent folder of a file - * - * @param string $file - * @return int - */ - public function getParentId($file) - { - } - - /** - * check if a file is available in the cache - * - * @param string $file - * @return bool - */ - public function inCache($file) - { - } - - /** - * remove a file or folder from the cache - * - * when removing a folder from the cache all files and folders inside the folder will be removed as well - * - * @param string $file - */ - public function remove($file) - { - } - - /** - * Move a file or folder in the cache - * - * @param string $source - * @param string $target - */ - public function move($source, $target) - { - } - - /** - * Get the storage id and path needed for a move - * - * @param string $path - * @return array [$storageId, $internalPath] - */ - protected function getMoveInfo($path) - { - } - - protected function hasEncryptionWrapper(): bool - { - } - - /** - * Move a file or folder in the cache - * - * @param ICache $sourceCache - * @param string $sourcePath - * @param string $targetPath - * @throws \OC\DatabaseException - * @throws \Exception if the given storages have an invalid id - */ - public function moveFromCache(ICache $sourceCache, $sourcePath, $targetPath) - { - } - - /** - * remove all entries for files that are stored on the storage from the cache - */ - public function clear() - { - } - - /** - * Get the scan status of a file - * - * - Cache::NOT_FOUND: File is not in the cache - * - Cache::PARTIAL: File is not stored in the cache but some incomplete data is known - * - Cache::SHALLOW: The folder and it's direct children are in the cache but not all sub folders are fully scanned - * - Cache::COMPLETE: The file or folder, with all it's children) are fully scanned - * - * @param string $file - * - * @return int Cache::NOT_FOUND, Cache::PARTIAL, Cache::SHALLOW or Cache::COMPLETE - */ - public function getStatus($file) - { - } - - /** - * search for files matching $pattern - * - * @param string $pattern the search pattern using SQL search syntax (e.g. '%searchstring%') - * @return ICacheEntry[] an array of cache entries where the name matches the search pattern - */ - public function search($pattern) - { - } - - /** - * search for files by mimetype - * - * @param string $mimetype either a full mimetype to search ('text/plain') or only the first part of a mimetype ('image') - * where it will search for all mimetypes in the group ('image/*') - * @return ICacheEntry[] an array of cache entries where the mimetype matches the search - */ - public function searchByMime($mimetype) - { - } - - public function searchQuery(ISearchQuery $query) - { - } - - /** - * Re-calculate the folder size and the size of all parent folders - * - * @param string|boolean $path - * @param array $data (optional) meta data of the folder - */ - public function correctFolderSize($path, $data = null, $isBackgroundScan = false) - { - } - - /** - * get the incomplete count that shares parent $folder - * - * @param int $fileId the file id of the folder - * @return int - */ - public function getIncompleteChildrenCount($fileId) - { - } - - /** - * calculate the size of a folder and set it in the cache - * - * @param string $path - * @param array|null|ICacheEntry $entry (optional) meta data of the folder - * @return int|float - */ - public function calculateFolderSize($path, $entry = null) - { - } - - - /** - * inner function because we can't add new params to the public function without breaking any child classes - * - * @param string $path - * @param array|null|ICacheEntry $entry (optional) meta data of the folder - * @param bool $ignoreUnknown don't mark the folder size as unknown if any of it's children are unknown - * @return int|float - */ - protected function calculateFolderSizeInner(string $path, $entry = null, bool $ignoreUnknown = false) - { - } - - /** - * get all file ids on the files on the storage - * - * @return int[] - */ - public function getAll() - { - } - - /** - * find a folder in the cache which has not been fully scanned - * - * If multiple incomplete folders are in the cache, the one with the highest id will be returned, - * use the one with the highest id gives the best result with the background scanner, since that is most - * likely the folder where we stopped scanning previously - * - * @return string|false the path of the folder or false when no folder matched - */ - public function getIncomplete() - { - } - - /** - * get the path of a file on this storage by it's file id - * - * @param int $id the file id of the file or folder to search - * @return string|null the path of the file (relative to the storage) or null if a file with the given id does not exists within this cache - */ - public function getPathById($id) - { - } - - /** - * get the storage id of the storage for a file and the internal path of the file - * unlike getPathById this does not limit the search to files on this storage and - * instead does a global search in the cache table - * - * @param int $id - * @return array first element holding the storage id, second the path - * @deprecated 17.0.0 use getPathById() instead - */ - public static function getById($id) - { - } - - /** - * normalize the given path - * - * @param string $path - * @return string - */ - public function normalize($path) - { - } - - /** - * Copy a file or folder in the cache - * - * @param ICache $sourceCache - * @param ICacheEntry $sourceEntry - * @param string $targetPath - * @return int fileId of copied entry - */ - public function copyFromCache(ICache $sourceCache, ICacheEntry $sourceEntry, string $targetPath): int - { - } - - public function getQueryFilterForStorage(): ISearchOperator - { - } - - public function getCacheEntryFromSearchResult(ICacheEntry $rawEntry): ?ICacheEntry - { - } -} diff --git a/tests/stubs/oc_files_cache_cacheentry.php b/tests/stubs/oc_files_cache_cacheentry.php deleted file mode 100644 index a4351d9..0000000 --- a/tests/stubs/oc_files_cache_cacheentry.php +++ /dev/null @@ -1,115 +0,0 @@ - - */ - public function getMetadata(): array - { - } -} diff --git a/tests/stubs/oc_files_node_node.php b/tests/stubs/oc_files_node_node.php deleted file mode 100644 index 6f99111..0000000 --- a/tests/stubs/oc_files_node_node.php +++ /dev/null @@ -1,354 +0,0 @@ - - */ - public function getMetadata(): array - { - } -} diff --git a/tests/stubs/oc_files_objectstore_objectstorescanner.php b/tests/stubs/oc_files_objectstore_objectstorescanner.php deleted file mode 100644 index 135e924..0000000 --- a/tests/stubs/oc_files_objectstore_objectstorescanner.php +++ /dev/null @@ -1,30 +0,0 @@ -stat() . - */ -abstract class Common implements Storage, ILockingStorage, IWriteStreamStorage, IConstructableStorage { - use LocalTempFileTrait; - - protected ?Cache $cache = null; - protected ?Scanner $scanner = null; - protected ?Watcher $watcher = null; - protected ?Propagator $propagator = null; - protected $storageCache; - protected ?Updater $updater = null; - - protected array $mountOptions = []; - protected $owner = null; - - public function __construct($parameters) { - } - - protected function remove(string $path): bool - { - } - - public function is_dir(string $path): bool - { - } - - public function is_file(string $path): bool - { - } - - public function filesize(string $path): int|float|false - { - } - - public function isReadable(string $path): bool - { - } - - public function isUpdatable(string $path): bool - { - } - - public function isCreatable(string $path): bool - { - } - - public function isDeletable(string $path): bool - { - } - - public function isSharable(string $path): bool - { - } - - public function getPermissions(string $path): int - { - } - - public function filemtime(string $path): int|false - { - } - - public function file_get_contents(string $path): string|false - { - } - - public function file_put_contents(string $path, mixed $data): int|float|false - { - } - - public function rename(string $source, string $target): bool - { - } - - public function copy(string $source, string $target): bool - { - } - - public function getMimeType(string $path): string|false - { - } - - public function hash(string $type, string $path, bool $raw = false): string|false - { - } - - public function getLocalFile(string $path): string|false - { - } - - protected function searchInDir(string $query, string $dir = ''): array - { - } - - /** - * @inheritDoc - * Check if a file or folder has been updated since $time - * - * The method is only used to check if the cache needs to be updated. Storage backends that don't support checking - * the mtime should always return false here. As a result storage implementations that always return false expect - * exclusive access to the backend and will not pick up files that have been added in a way that circumvents - * Nextcloud filesystem. - */ - public function hasUpdated(string $path, int $time): bool - { - } - - protected function getCacheDependencies(): CacheDependencies - { - } - - public function getCache(string $path = '', ?IStorage $storage = null): ICache - { - } - - public function getScanner(string $path = '', ?IStorage $storage = null): IScanner - { - } - - public function getWatcher(string $path = '', ?IStorage $storage = null): IWatcher - { - } - - public function getPropagator(?IStorage $storage = null): IPropagator - { - } - - public function getUpdater(?IStorage $storage = null): IUpdater - { - } - - public function getStorageCache(?IStorage $storage = null): \OC\Files\Cache\Storage - { - } - - public function getOwner(string $path): string|false - { - } - - public function getETag(string $path): string|false - { - } - - /** - * clean a path, i.e. remove all redundant '.' and '..' - * making sure that it can't point to higher than '/' - * - * @param string $path The path to clean - * @return string cleaned path - */ - public function cleanPath(string $path): string - { - } - - /** - * Test a storage for availability - */ - public function test(): bool - { - } - - public function free_space(string $path): int|float|false - { - } - - public function isLocal(): bool - { - } - - /** - * Check if the storage is an instance of $class or is a wrapper for a storage that is an instance of $class - */ - public function instanceOfStorage(string $class): bool - { - } - - /** - * A custom storage implementation can return an url for direct download of a give file. - * - * For now the returned array can hold the parameter url - in future more attributes might follow. - */ - public function getDirectDownload(string $path): array|false - { - } - - public function verifyPath(string $path, string $fileName): void - { - } - - /** - * Get the filename validator - * (cached for performance) - */ - protected function getFilenameValidator(): IFilenameValidator - { - } - - public function setMountOptions(array $options): void - { - } - - public function getMountOption(string $name, mixed $default = null): mixed - { - } - - public function copyFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath, bool $preserveMtime = false): bool - { - } - - public function moveFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath): bool - { - } - - public function getMetaData(string $path): ?array - { - } - - public function acquireLock(string $path, int $type, ILockingProvider $provider): void - { - } - - public function releaseLock(string $path, int $type, ILockingProvider $provider): void - { - } - - public function changeLock(string $path, int $type, ILockingProvider $provider): void - { - } - - /** - * @return array [ available, last_checked ] - */ - public function getAvailability(): array - { - } - - public function setAvailability(bool $isAvailable): void - { - } - - public function setOwner(?string $user): void - { - } - - public function needsPartFile(): bool - { - } - - public function writeStream(string $path, $stream, ?int $size = null): int - { - } - - public function getDirectoryContent(string $directory): \Traversable - { - } -} diff --git a/tests/stubs/oc_files_storage_local.php b/tests/stubs/oc_files_storage_local.php deleted file mode 100644 index 7f1699d..0000000 --- a/tests/stubs/oc_files_storage_local.php +++ /dev/null @@ -1,180 +0,0 @@ - $storage, 'root' => $root] - * - * $storage: The storage that will be wrapper - * $root: The folder in the wrapped storage that will become the root folder of the wrapped storage - */ - public function __construct($arguments) - { - } - - public function getUnjailedPath(string $path): string - { - } - - /** - * This is separate from Wrapper::getWrapperStorage so we can get the jailed storage consistently even if the jail is inside another wrapper - */ - public function getUnjailedStorage(): IStorage - { - } - - - public function getJailedPath(string $path): ?string - { - } - - public function getId(): string - { - } - - public function mkdir(string $path): bool - { - } - - public function rmdir(string $path): bool - { - } - - public function opendir(string $path) - { - } - - public function is_dir(string $path): bool - { - } - - public function is_file(string $path): bool - { - } - - public function stat(string $path): array|false - { - } - - public function filetype(string $path): string|false - { - } - - public function filesize(string $path): int|float|false - { - } - - public function isCreatable(string $path): bool - { - } - - public function isReadable(string $path): bool - { - } - - public function isUpdatable(string $path): bool - { - } - - public function isDeletable(string $path): bool - { - } - - public function isSharable(string $path): bool - { - } - - public function getPermissions(string $path): int - { - } - - public function file_exists(string $path): bool - { - } - - public function filemtime(string $path): int|false - { - } - - public function file_get_contents(string $path): string|false - { - } - - public function file_put_contents(string $path, mixed $data): int|float|false - { - } - - public function unlink(string $path): bool - { - } - - public function rename(string $source, string $target): bool - { - } - - public function copy(string $source, string $target): bool - { - } - - public function fopen(string $path, string $mode) - { - } - - public function getMimeType(string $path): string|false - { - } - - public function hash(string $type, string $path, bool $raw = false): string|false - { - } - - public function free_space(string $path): int|float|false - { - } - - public function touch(string $path, ?int $mtime = null): bool - { - } - - public function getLocalFile(string $path): string|false - { - } - - public function hasUpdated(string $path, int $time): bool - { - } - - public function getCache(string $path = '', ?IStorage $storage = null): ICache - { - } - - public function getOwner(string $path): string|false - { - } - - public function getWatcher(string $path = '', ?IStorage $storage = null): IWatcher - { - } - - public function getETag(string $path): string|false - { - } - - public function getMetaData(string $path): ?array - { - } - - public function acquireLock(string $path, int $type, ILockingProvider $provider): void - { - } - - public function releaseLock(string $path, int $type, ILockingProvider $provider): void - { - } - - public function changeLock(string $path, int $type, ILockingProvider $provider): void - { - } - - /** - * Resolve the path for the source of the share - */ - public function resolvePath(string $path): array - { - } - - public function copyFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath): bool - { - } - - public function moveFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath): bool - { - } - - public function getPropagator(?IStorage $storage = null): IPropagator - { - } - - public function writeStream(string $path, $stream, ?int $size = null): int - { - } - - public function getDirectoryContent(string $directory): \Traversable - { - } -} diff --git a/tests/stubs/oc_files_storage_wrapper_permissionsmask.php b/tests/stubs/oc_files_storage_wrapper_permissionsmask.php deleted file mode 100644 index 467cb67..0000000 --- a/tests/stubs/oc_files_storage_wrapper_permissionsmask.php +++ /dev/null @@ -1,99 +0,0 @@ - $storage, 'mask' => $mask] - * - * $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 - */ - public function __construct($arguments) - { - } - - public function isUpdatable(string $path): bool - { - } - - public function isCreatable(string $path): bool - { - } - - public function isDeletable(string $path): bool - { - } - - public function isSharable(string $path): bool - { - } - - public function getPermissions(string $path): int - { - } - - public function rename(string $source, string $target): bool - { - } - - public function copy(string $source, string $target): bool - { - } - - public function touch(string $path, ?int $mtime = null): bool - { - } - - public function mkdir(string $path): bool - { - } - - public function rmdir(string $path): bool - { - } - - public function unlink(string $path): bool - { - } - - public function file_put_contents(string $path, mixed $data): int|float|false - { - } - - public function fopen(string $path, string $mode) - { - } - - public function getCache(string $path = '', ?IStorage $storage = null): \OCP\Files\Cache\ICache - { - } - - public function getMetaData(string $path): ?array - { - } - - public function getScanner(string $path = '', ?IStorage $storage = null): \OCP\Files\Cache\IScanner - { - } - - public function getDirectoryContent(string $directory): \Traversable - { - } -} diff --git a/tests/stubs/oc_files_storage_wrapper_quota.php b/tests/stubs/oc_files_storage_wrapper_quota.php deleted file mode 100644 index 8745248..0000000 --- a/tests/stubs/oc_files_storage_wrapper_quota.php +++ /dev/null @@ -1,76 +0,0 @@ - $class - * @psalm-return T|null - */ - public function getInstanceOfStorage(string $class): ?IStorage - { - } - - /** - * Pass any methods custom to specific storage implementations to the wrapped storage - * - * @return mixed - */ - public function __call(string $method, array $args) - { - } - - public function getDirectDownload(string $path): array|false - { - } - - public function getAvailability(): array - { - } - - public function setAvailability(bool $isAvailable): void - { - } - - public function verifyPath(string $path, string $fileName): void - { - } - - public function copyFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath): bool - { - } - - public function moveFromStorage(IStorage $sourceStorage, string $sourceInternalPath, string $targetInternalPath): bool - { - } - - public function getMetaData(string $path): ?array - { - } - - public function acquireLock(string $path, int $type, ILockingProvider $provider): void - { - } - - public function releaseLock(string $path, int $type, ILockingProvider $provider): void - { - } - - public function changeLock(string $path, int $type, ILockingProvider $provider): void - { - } - - public function needsPartFile(): bool - { - } - - public function writeStream(string $path, $stream, ?int $size = null): int - { - } - - public function getDirectoryContent(string $directory): \Traversable - { - } - - public function isWrapperOf(IStorage $storage): bool - { - } - - public function setOwner(?string $user): void - { - } -} diff --git a/tests/stubs/oc_files_view.php b/tests/stubs/oc_files_view.php deleted file mode 100644 index 75d108d..0000000 --- a/tests/stubs/oc_files_view.php +++ /dev/null @@ -1,663 +0,0 @@ - an array of user ids - */ - public function usersInGroup($gid, $search = '', $limit = -1, $offset = 0): array - { - } - - public function searchInGroup(string $gid, string $search = '', int $limit = -1, int $offset = 0): array - { - } - - /** - * get the number of all users matching the search string in a group - * @param string $gid - * @param string $search - * @return int - */ - public function countUsersInGroup(string $gid, string $search = ''): int - { - } - - /** - * get the number of disabled users in a group - * - * @param string $search - * - * @return int - */ - public function countDisabledInGroup(string $gid): int - { - } - - public function getDisplayName(string $gid): string - { - } - - public function getGroupDetails(string $gid): array - { - } - - /** - * {@inheritdoc} - */ - public function getGroupsDetails(array $gids): array - { - } - - public function setDisplayName(string $gid, string $displayName): bool - { - } - - /** - * Backend name to be shown in group management - * @return string the name of the backend to be shown - * @since 21.0.0 - */ - public function getBackendName(): string - { - } -} diff --git a/tests/stubs/oc_group_manager.php b/tests/stubs/oc_group_manager.php deleted file mode 100644 index d3856bf..0000000 --- a/tests/stubs/oc_group_manager.php +++ /dev/null @@ -1,226 +0,0 @@ - $gids List of groupIds for which we want to create a IGroup object - * @param array $displayNames Array containing already know display name for a groupId - * @return array - */ - protected function getGroupsObjects(array $gids, array $displayNames = []): array - { - } - - /** - * @param string $gid - * @return bool - */ - public function groupExists($gid) - { - } - - /** - * @param string $gid - * @return IGroup|null - */ - public function createGroup($gid) - { - } - - /** - * @param string $search - * @param ?int $limit - * @param ?int $offset - * @return \OC\Group\Group[] - */ - public function search(string $search, ?int $limit = null, ?int $offset = 0) - { - } - - /** - * @param IUser|null $user - * @return \OC\Group\Group[] - */ - public function getUserGroups(?IUser $user = null) - { - } - - /** - * @param string $uid the user id - * @return \OC\Group\Group[] - */ - public function getUserIdGroups(string $uid): array - { - } - - /** - * Checks if a userId is in the admin group - * - * @param string $userId - * @return bool if admin - */ - public function isAdmin($userId) - { - } - - public function isDelegatedAdmin(string $userId): bool - { - } - - /** - * Checks if a userId is in a group - * - * @param string $userId - * @param string $group - * @return bool if in group - */ - public function isInGroup($userId, $group) - { - } - - /** - * get a list of group ids for a user - * - * @param IUser $user - * @return string[] with group ids - */ - public function getUserGroupIds(IUser $user): array - { - } - - /** - * @param string $groupId - * @return ?string - */ - public function getDisplayName(string $groupId): ?string - { - } - - /** - * get an array of groupid and displayName for a user - * - * @param IUser $user - * @return array ['displayName' => displayname] - */ - public function getUserGroupNames(IUser $user) - { - } - - /** - * get a list of all display names in a group - * - * @param string $gid - * @param string $search - * @param int $limit - * @param int $offset - * @return array an array of display names (value) and user ids (key) - */ - public function displayNamesInGroup($gid, $search = '', $limit = -1, $offset = 0) - { - } - - /** - * @return \OC\SubAdmin - */ - public function getSubAdmin() - { - } -} diff --git a/tests/stubs/oc_user_user.php b/tests/stubs/oc_user_user.php deleted file mode 100644 index c2fcdf7..0000000 --- a/tests/stubs/oc_user_user.php +++ /dev/null @@ -1,299 +0,0 @@ - - */ - public function getMetadata(): array - { - } -} diff --git a/tests/stubs/oca_files_versions_expiration.php b/tests/stubs/oca_files_versions_expiration.php deleted file mode 100644 index 61b84b8..0000000 --- a/tests/stubs/oca_files_versions_expiration.php +++ /dev/null @@ -1,55 +0,0 @@ - value mapping. - * @since 29.0.0 - */ -interface IMetadataVersionBackend { - /** - * Sets a key value pair in the metadata column corresponding to the node's version. - * - * @param Node $node the node that triggered the Metadata event listener, aka, the file version - * @param int $revision the key for the json value of the metadata column - * @param string $key the key for the json value of the metadata column - * @param string $value the value that corresponds to the key in the metadata column - * @since 29.0.0 - */ - public function setMetadataValue(Node $node, int $revision, string $key, string $value): void - { - } -} diff --git a/tests/stubs/oca_files_versions_versions_ineedsyncversionbackend.php b/tests/stubs/oca_files_versions_versions_ineedsyncversionbackend.php deleted file mode 100644 index 8dd0ff5..0000000 --- a/tests/stubs/oca_files_versions_versions_ineedsyncversionbackend.php +++ /dev/null @@ -1,26 +0,0 @@ -tokenProvider = $this->createMock(IProvider::class); } - /** - * @param array $mockMathods - * @return SlaveController|\PHPUnit_Framework_MockObject_MockObject - */ - private function getInstance(array $mockMathods = []) { + private function getInstance(array $mockMathods = []): SlaveController&MockObject { return $this->getMockBuilder(SlaveController::class) ->setConstructorArgs( [ @@ -99,7 +96,7 @@ private function getInstance(array $mockMathods = []) { )->onlyMethods($mockMathods)->getMock(); } - public function testDecodeJwt() { + public function testDecodeJwt(): void { $controller = $this->getInstance(); $jwtKey = 'jwtkeybutlongenoughforsecurityasthisisnowimportant'; $encryptedPassword = 'password-encrypted'; diff --git a/tests/unit/lib/GlobalSiteSelectorTest.php b/tests/unit/lib/GlobalSiteSelectorTest.php index 1d44ccb..992396b 100644 --- a/tests/unit/lib/GlobalSiteSelectorTest.php +++ b/tests/unit/lib/GlobalSiteSelectorTest.php @@ -9,14 +9,12 @@ use OCA\GlobalSiteSelector\GlobalSiteSelector; use OCP\IConfig; +use PHPUnit\Framework\MockObject\MockObject; use Test\TestCase; class GlobalSiteSelectorTest extends TestCase { - /** @var IConfig|\PHPUnit_Framework_MockObject_MockObject */ - private $config; - - /** @var GlobalSiteSelector */ - private $gss; + private MockObject&IConfig $config; + private GlobalSiteSelector $gss; public function setUp(): void { parent::setUp(); @@ -25,7 +23,7 @@ public function setUp(): void { $this->gss = new GlobalSiteSelector($this->config); } - public function testGetMode() { + public function testGetMode(): void { $this->config->expects($this->once())->method('getSystemValueString') ->with('gss.mode', 'slave')->willReturn('result'); @@ -34,7 +32,7 @@ public function testGetMode() { $this->assertSame('result', $result); } - public function testGetJwtKey() { + public function testGetJwtKey(): void { $this->config->expects($this->once())->method('getSystemValueString') ->with('gss.jwt.key', '')->willReturn('result'); @@ -43,7 +41,7 @@ public function testGetJwtKey() { $this->assertSame('result', $result); } - public function testGetMasterUrl() { + public function testGetMasterUrl(): void { $this->config->expects($this->once())->method('getSystemValueString') ->with('gss.master.url', '')->willReturn('result'); @@ -52,7 +50,7 @@ public function testGetMasterUrl() { $this->assertSame('result', $result); } - public function testGetLookupServerUrl() { + public function testGetLookupServerUrl(): void { $this->config->expects($this->once())->method('getSystemValueString') ->with('lookup_server', '')->willReturn('result'); @@ -61,21 +59,21 @@ public function testGetLookupServerUrl() { $this->assertSame('result', $result); } - public function testIsJwtKeyValidWithShortKey() { + public function testIsJwtKeyValidWithShortKey(): void { $this->config->method('getSystemValueString') ->with('gss.jwt.key', '')->willReturn('short-key'); $this->assertFalse($this->gss->isJwtKeyValid()); } - public function testIsJwtKeyValidWithEmptyKey() { + public function testIsJwtKeyValidWithEmptyKey(): void { $this->config->method('getSystemValueString') ->with('gss.jwt.key', '')->willReturn(''); $this->assertFalse($this->gss->isJwtKeyValid()); } - public function testIsJwtKeyValidWithValidKey() { + public function testIsJwtKeyValidWithValidKey(): void { $this->config->method('getSystemValueString') ->with('gss.jwt.key', '')->willReturn('this-key-is-at-least-32-characters-long!'); diff --git a/tests/unit/lib/LookupTest.php b/tests/unit/lib/LookupTest.php index 6ed7eec..2066aac 100644 --- a/tests/unit/lib/LookupTest.php +++ b/tests/unit/lib/LookupTest.php @@ -13,15 +13,17 @@ use OCP\Federation\ICloudIdManager; use OCP\Http\Client\IClientService; use OCP\IConfig; +use PHPUnit\Framework\Attributes\DataProvider; +use PHPUnit\Framework\MockObject\MockObject; use Psr\Log\LoggerInterface; use Test\TestCase; class LookupTest extends TestCase { - private IClientService $httpClientService; - private IConfig $config; - private LoggerInterface $logger; - private ICloudIdManager $cloudIdManager; - private GlobalSiteSelector $gss; + private MockObject&IClientService $httpClientService; + private MockObject&Iconfig $config; + private MockObject&LoggerInterface $logger; + private MockObject&ICloudIdManager $cloudIdManager; + private MockObject&GlobalSiteSelector $gss; public function setUp(): void { parent::setUp(); @@ -34,12 +36,9 @@ public function setUp(): void { } /** - * get Lookup instance - * - * @param array $mockMethods - * @return Lookup|\PHPUnit_Framework_MockObject_MockObject + * Get Lookup instance */ - private function getInstance(array $mockMethods = []) { + private function getInstance(array $mockMethods = []): Lookup&MockObject { return $this->getMockBuilder(Lookup::class) ->setConstructorArgs( [ @@ -52,15 +51,8 @@ private function getInstance(array $mockMethods = []) { )->onlyMethods($mockMethods)->getMock(); } - /** - * @param string $lookupServerUrl - * @param string $lookupServerResult - * @param string $userLocation - * @param string $expected - * - * @dataProvider dataTestSearch - */ - public function testSearch($lookupServerUrl, $lookupServerResult, $userLocation, $expected) { + #[DataProvider('dataTestSearch')] + public function testSearch(string $lookupServerUrl, array $lookupServerResult, string $userLocation, string $expected): void { $this->config->expects($this->any())->method('getSystemValueString') ->with('lookup_server', '')->willReturn($lookupServerUrl); @@ -78,7 +70,7 @@ public function testSearch($lookupServerUrl, $lookupServerResult, $userLocation, $this->assertSame($expected, $result); } - public function dataTestSearch() { + public function dataTestSearch(): array { return [ ['', [], 'location', ''], ['', ['location' => 'https://nextcloud.com'], 'location', ''], diff --git a/tests/unit/lib/MasterTest.php b/tests/unit/lib/MasterTest.php index e98f973..20c8050 100644 --- a/tests/unit/lib/MasterTest.php +++ b/tests/unit/lib/MasterTest.php @@ -77,7 +77,7 @@ private function getInstance(array $mockMethods = []): Master&MockObject { )->onlyMethods($mockMethods)->getMock(); } - public function testHandleLoginRequest() { + public function testHandleLoginRequest(): void { $location = 'nextcloud.com'; $master = $this->getInstance(['queryLookupServer', 'redirectUser']); $master->expects($this->once())->method('queryLookupServer') @@ -91,7 +91,7 @@ public function testHandleLoginRequest() { $master->handleLoginRequest('user', 'password'); } - public function testHandleLoginRequestException() { + public function testHandleLoginRequestException(): void { $location = ''; $master = $this->getInstance(['queryLookupServer', 'redirectUser']); $master->expects($this->once())->method('queryLookupServer') @@ -102,7 +102,7 @@ public function testHandleLoginRequestException() { $master->handleLoginRequest('user', 'password'); } - public function testCreateJWT() { + public function testCreateJWT(): void { $uid = 'user1'; $plainPassword = 'password'; $encryptedPassword = 'password-encrypted'; @@ -126,19 +126,14 @@ public function testCreateJWT() { /** * @dataProvider dataTestBuildBasicAuthUrl - * - * @param string $url - * @param string $uid - * @param string $password - * @param string $expected */ - public function testBuildBasicAuthUrl($url, $uid, $password, $expected) { + public function testBuildBasicAuthUrl(string $url, string $uid, string $password, string $expected): void { $master = $this->getInstance(); $result = $this->invokePrivate($master, 'buildBasicAuthUrl', [$url, $uid, $password]); $this->assertSame($expected, $result); } - public function dataTestBuildBasicAuthUrl() { + public function dataTestBuildBasicAuthUrl(): array { return [ ['http://nextcloud.com', 'user', 'password', 'http://user:password@nextcloud.com'], ['https://nextcloud.com', 'user', 'password', 'https://user:password@nextcloud.com'], @@ -152,14 +147,14 @@ public function dataTestBuildBasicAuthUrl() { * @param $url * @param $expected */ - public function testNormalizeLocation($url, $expected) { + public function testNormalizeLocation(string $url, string $expected): void { $master = $this->getInstance(); $this->request->expects($this->any())->method('getServerProtocol')->willReturn('https'); $result = $this->invokePrivate($master, 'normalizeLocation', [$url]); $this->assertSame($expected, $result); } - public function dataTestNormalizeLocation() { + public function dataTestNormalizeLocation(): array { return [ ['localhost/nextcloud', 'https://localhost/nextcloud'], ['https://localhost/nextcloud', 'https://localhost/nextcloud'], diff --git a/vendor-bin/phpunit/composer.json b/vendor-bin/phpunit/composer.json index 98d735c..920a0ab 100644 --- a/vendor-bin/phpunit/composer.json +++ b/vendor-bin/phpunit/composer.json @@ -1,11 +1,11 @@ { "config": { "platform": { - "php": "8.0" + "php": "8.1" }, "sort-packages": true }, "require-dev": { - "phpunit/phpunit": "^9.6.9" + "phpunit/phpunit": "^10.0" } } diff --git a/vendor-bin/phpunit/composer.lock b/vendor-bin/phpunit/composer.lock index 2381c45..084f19c 100644 --- a/vendor-bin/phpunit/composer.lock +++ b/vendor-bin/phpunit/composer.lock @@ -4,79 +4,9 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "a603c991463a246788de8bb38a9f0150", + "content-hash": "c5e0285f4fb695883698dd02a6b8917d", "packages": [], "packages-dev": [ - { - "name": "doctrine/instantiator", - "version": "1.5.0", - "source": { - "type": "git", - "url": "https://github.com/doctrine/instantiator.git", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/0a0fa9780f5d4e507415a065172d26a98d02047b", - "reference": "0a0fa9780f5d4e507415a065172d26a98d02047b", - "shasum": "" - }, - "require": { - "php": "^7.1 || ^8.0" - }, - "require-dev": { - "doctrine/coding-standard": "^9 || ^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" - }, - "type": "library", - "autoload": { - "psr-4": { - "Doctrine\\Instantiator\\": "src/Doctrine/Instantiator/" - } - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Marco Pivetta", - "email": "ocramius@gmail.com", - "homepage": "https://ocramius.github.io/" - } - ], - "description": "A small, lightweight utility to instantiate objects in PHP without invoking their constructors", - "homepage": "https://www.doctrine-project.org/projects/instantiator.html", - "keywords": [ - "constructor", - "instantiate" - ], - "support": { - "issues": "https://github.com/doctrine/instantiator/issues", - "source": "https://github.com/doctrine/instantiator/tree/1.5.0" - }, - "funding": [ - { - "url": "https://www.doctrine-project.org/sponsorship.html", - "type": "custom" - }, - { - "url": "https://www.patreon.com/phpdoctrine", - "type": "patreon" - }, - { - "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", - "type": "tidelift" - } - ], - "time": "2022-12-30T00:15:36+00:00" - }, { "name": "myclabs/deep-copy", "version": "1.13.4", @@ -139,20 +69,19 @@ }, { "name": "nikic/php-parser", - "version": "v5.7.0", + "version": "v5.8.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82" + "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/dca41cd15c2ac9d055ad70dbfd011130757d1f82", - "reference": "dca41cd15c2ac9d055ad70dbfd011130757d1f82", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/044a6a392ff8ad0d61f14370a5fbbd0a0107152f", + "reference": "044a6a392ff8ad0d61f14370a5fbbd0a0107152f", "shasum": "" }, "require": { - "ext-ctype": "*", "ext-json": "*", "ext-tokenizer": "*", "php": ">=7.4" @@ -191,9 +120,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.7.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.8.0" }, - "time": "2025-12-06T11:56:16+00:00" + "time": "2026-07-04T14:30:18+00:00" }, { "name": "phar-io/manifest", @@ -315,16 +244,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "9.2.32", + "version": "10.1.16", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5" + "reference": "7e308268858ed6baedc8704a304727d20bc07c77" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/85402a822d1ecf1db1096959413d35e1c37cf1a5", - "reference": "85402a822d1ecf1db1096959413d35e1c37cf1a5", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77", + "reference": "7e308268858ed6baedc8704a304727d20bc07c77", "shasum": "" }, "require": { @@ -332,18 +261,18 @@ "ext-libxml": "*", "ext-xmlwriter": "*", "nikic/php-parser": "^4.19.1 || ^5.1.0", - "php": ">=7.3", - "phpunit/php-file-iterator": "^3.0.6", - "phpunit/php-text-template": "^2.0.4", - "sebastian/code-unit-reverse-lookup": "^2.0.3", - "sebastian/complexity": "^2.0.3", - "sebastian/environment": "^5.1.5", - "sebastian/lines-of-code": "^1.0.4", - "sebastian/version": "^3.0.2", + "php": ">=8.1", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-text-template": "^3.0.1", + "sebastian/code-unit-reverse-lookup": "^3.0.0", + "sebastian/complexity": "^3.2.0", + "sebastian/environment": "^6.1.0", + "sebastian/lines-of-code": "^2.0.2", + "sebastian/version": "^4.0.1", "theseer/tokenizer": "^1.2.3" }, "require-dev": { - "phpunit/phpunit": "^9.6" + "phpunit/phpunit": "^10.1" }, "suggest": { "ext-pcov": "PHP extension that provides line coverage", @@ -352,7 +281,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-main": "9.2.x-dev" + "dev-main": "10.1.x-dev" } }, "autoload": { @@ -381,7 +310,7 @@ "support": { "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", - "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/9.2.32" + "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16" }, "funding": [ { @@ -389,32 +318,32 @@ "type": "github" } ], - "time": "2024-08-22T04:23:01+00:00" + "time": "2024-08-22T04:31:57+00:00" }, { "name": "phpunit/php-file-iterator", - "version": "3.0.6", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-file-iterator.git", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf" + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", - "reference": "cf1c2e7c203ac650e352f4cc675a7021e7d1b3cf", + "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/a95037b6d9e608ba092da1b23931e537cadc3c3c", + "reference": "a95037b6d9e608ba092da1b23931e537cadc3c3c", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -441,7 +370,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-file-iterator/issues", - "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/3.0.6" + "security": "https://github.com/sebastianbergmann/php-file-iterator/security/policy", + "source": "https://github.com/sebastianbergmann/php-file-iterator/tree/4.1.0" }, "funding": [ { @@ -449,28 +379,28 @@ "type": "github" } ], - "time": "2021-12-02T12:48:52+00:00" + "time": "2023-08-31T06:24:48+00:00" }, { "name": "phpunit/php-invoker", - "version": "3.1.1", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-invoker.git", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67" + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/5a10147d0aaf65b58940a0b72f71c9ac0423cc67", - "reference": "5a10147d0aaf65b58940a0b72f71c9ac0423cc67", + "url": "https://api.github.com/repos/sebastianbergmann/php-invoker/zipball/f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", + "reference": "f5e568ba02fa5ba0ddd0f618391d5a9ea50b06d7", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { "ext-pcntl": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "suggest": { "ext-pcntl": "*" @@ -478,7 +408,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.1-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -504,7 +434,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-invoker/issues", - "source": "https://github.com/sebastianbergmann/php-invoker/tree/3.1.1" + "source": "https://github.com/sebastianbergmann/php-invoker/tree/4.0.0" }, "funding": [ { @@ -512,32 +442,32 @@ "type": "github" } ], - "time": "2020-09-28T05:58:55+00:00" + "time": "2023-02-03T06:56:09+00:00" }, { "name": "phpunit/php-text-template", - "version": "2.0.4", + "version": "3.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-text-template.git", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28" + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", - "reference": "5da5f67fc95621df9ff4c4e5a84d6a8a2acf7c28", + "url": "https://api.github.com/repos/sebastianbergmann/php-text-template/zipball/0c7b06ff49e3d5072f057eb1fa59258bf287a748", + "reference": "0c7b06ff49e3d5072f057eb1fa59258bf287a748", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -563,7 +493,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-text-template/issues", - "source": "https://github.com/sebastianbergmann/php-text-template/tree/2.0.4" + "security": "https://github.com/sebastianbergmann/php-text-template/security/policy", + "source": "https://github.com/sebastianbergmann/php-text-template/tree/3.0.1" }, "funding": [ { @@ -571,32 +502,32 @@ "type": "github" } ], - "time": "2020-10-26T05:33:50+00:00" + "time": "2023-08-31T14:07:24+00:00" }, { "name": "phpunit/php-timer", - "version": "5.0.3", + "version": "6.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2" + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", - "reference": "5a63ce20ed1b5bf577850e2c4e87f4aa902afbd2", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/e2a2d67966e740530f4a3343fe2e030ffdc1161d", + "reference": "e2a2d67966e740530f4a3343fe2e030ffdc1161d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -622,7 +553,7 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/php-timer/issues", - "source": "https://github.com/sebastianbergmann/php-timer/tree/5.0.3" + "source": "https://github.com/sebastianbergmann/php-timer/tree/6.0.0" }, "funding": [ { @@ -630,54 +561,52 @@ "type": "github" } ], - "time": "2020-10-26T13:16:10+00:00" + "time": "2023-02-03T06:57:52+00:00" }, { "name": "phpunit/phpunit", - "version": "9.6.33", + "version": "10.5.64", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "fea06253ecc0a32faf787bd31b261f56f351d049" + "reference": "0e8c1d19cea35ad97d4887f363d07c78e30fbf06" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/fea06253ecc0a32faf787bd31b261f56f351d049", - "reference": "fea06253ecc0a32faf787bd31b261f56f351d049", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/0e8c1d19cea35ad97d4887f363d07c78e30fbf06", + "reference": "0e8c1d19cea35ad97d4887f363d07c78e30fbf06", "shasum": "" }, "require": { - "doctrine/instantiator": "^1.5.0 || ^2", "ext-dom": "*", + "ext-filter": "*", "ext-json": "*", "ext-libxml": "*", "ext-mbstring": "*", - "ext-xml": "*", "ext-xmlwriter": "*", "myclabs/deep-copy": "^1.13.4", "phar-io/manifest": "^2.0.4", "phar-io/version": "^3.2.1", - "php": ">=7.3", - "phpunit/php-code-coverage": "^9.2.32", - "phpunit/php-file-iterator": "^3.0.6", - "phpunit/php-invoker": "^3.1.1", - "phpunit/php-text-template": "^2.0.4", - "phpunit/php-timer": "^5.0.3", - "sebastian/cli-parser": "^1.0.2", - "sebastian/code-unit": "^1.0.8", - "sebastian/comparator": "^4.0.10", - "sebastian/diff": "^4.0.6", - "sebastian/environment": "^5.1.5", - "sebastian/exporter": "^4.0.8", - "sebastian/global-state": "^5.0.8", - "sebastian/object-enumerator": "^4.0.4", - "sebastian/resource-operations": "^3.0.4", - "sebastian/type": "^3.2.1", - "sebastian/version": "^3.0.2" + "php": ">=8.1", + "phpunit/php-code-coverage": "^10.1.16", + "phpunit/php-file-iterator": "^4.1.0", + "phpunit/php-invoker": "^4.0.0", + "phpunit/php-text-template": "^3.0.1", + "phpunit/php-timer": "^6.0.0", + "sebastian/cli-parser": "^2.0.1", + "sebastian/code-unit": "^2.0.0", + "sebastian/comparator": "^5.0.5", + "sebastian/diff": "^5.1.1", + "sebastian/environment": "^6.1.0", + "sebastian/exporter": "^5.1.4", + "sebastian/global-state": "^6.0.2", + "sebastian/object-enumerator": "^5.0.0", + "sebastian/recursion-context": "^5.0.1", + "sebastian/type": "^4.0.0", + "sebastian/version": "^4.0.1" }, "suggest": { - "ext-soap": "To be able to generate mocks based on WSDL files", - "ext-xdebug": "PHP extension that provides line coverage as well as branch and path coverage" + "ext-soap": "To be able to generate mocks based on WSDL files" }, "bin": [ "phpunit" @@ -685,7 +614,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "9.6-dev" + "dev-main": "10.5-dev" } }, "autoload": { @@ -717,56 +646,40 @@ "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.33" + "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.64" }, "funding": [ { - "url": "https://phpunit.de/sponsors.html", - "type": "custom" - }, - { - "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" + "url": "https://phpunit.de/sponsoring.html", + "type": "other" } ], - "time": "2026-01-27T05:25:09+00:00" + "time": "2026-07-06T14:50:35+00:00" }, { "name": "sebastian/cli-parser", - "version": "1.0.2", + "version": "2.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/cli-parser.git", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b" + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/2b56bea83a09de3ac06bb18b92f068e60cc6f50b", - "reference": "2b56bea83a09de3ac06bb18b92f068e60cc6f50b", + "url": "https://api.github.com/repos/sebastianbergmann/cli-parser/zipball/c34583b87e7b7a8055bf6c450c2c77ce32a24084", + "reference": "c34583b87e7b7a8055bf6c450c2c77ce32a24084", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -789,7 +702,8 @@ "homepage": "https://github.com/sebastianbergmann/cli-parser", "support": { "issues": "https://github.com/sebastianbergmann/cli-parser/issues", - "source": "https://github.com/sebastianbergmann/cli-parser/tree/1.0.2" + "security": "https://github.com/sebastianbergmann/cli-parser/security/policy", + "source": "https://github.com/sebastianbergmann/cli-parser/tree/2.0.1" }, "funding": [ { @@ -797,32 +711,32 @@ "type": "github" } ], - "time": "2024-03-02T06:27:43+00:00" + "time": "2024-03-02T07:12:49+00:00" }, { "name": "sebastian/code-unit", - "version": "1.0.8", + "version": "2.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit.git", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120" + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/1fc9f64c0927627ef78ba436c9b17d967e68e120", - "reference": "1fc9f64c0927627ef78ba436c9b17d967e68e120", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit/zipball/a81fee9eef0b7a76af11d121767abc44c104e503", + "reference": "a81fee9eef0b7a76af11d121767abc44c104e503", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -845,7 +759,7 @@ "homepage": "https://github.com/sebastianbergmann/code-unit", "support": { "issues": "https://github.com/sebastianbergmann/code-unit/issues", - "source": "https://github.com/sebastianbergmann/code-unit/tree/1.0.8" + "source": "https://github.com/sebastianbergmann/code-unit/tree/2.0.0" }, "funding": [ { @@ -853,32 +767,32 @@ "type": "github" } ], - "time": "2020-10-26T13:08:54+00:00" + "time": "2023-02-03T06:58:43+00:00" }, { "name": "sebastian/code-unit-reverse-lookup", - "version": "2.0.3", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/code-unit-reverse-lookup.git", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5" + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", - "reference": "ac91f01ccec49fb77bdc6fd1e548bc70f7faa3e5", + "url": "https://api.github.com/repos/sebastianbergmann/code-unit-reverse-lookup/zipball/5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", + "reference": "5e3a687f7d8ae33fb362c5c0743794bbb2420a1d", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -900,7 +814,7 @@ "homepage": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/", "support": { "issues": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/issues", - "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/2.0.3" + "source": "https://github.com/sebastianbergmann/code-unit-reverse-lookup/tree/3.0.0" }, "funding": [ { @@ -908,34 +822,36 @@ "type": "github" } ], - "time": "2020-09-28T05:30:19+00:00" + "time": "2023-02-03T06:59:15+00:00" }, { "name": "sebastian/comparator", - "version": "4.0.10", + "version": "5.0.5", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/comparator.git", - "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d" + "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/e4df00b9b3571187db2831ae9aada2c6efbd715d", - "reference": "e4df00b9b3571187db2831ae9aada2c6efbd715d", + "url": "https://api.github.com/repos/sebastianbergmann/comparator/zipball/55dfef806eb7dfeb6e7a6935601fef866f8ca48d", + "reference": "55dfef806eb7dfeb6e7a6935601fef866f8ca48d", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/diff": "^4.0", - "sebastian/exporter": "^4.0" + "ext-dom": "*", + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/diff": "^5.0", + "sebastian/exporter": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -974,7 +890,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/comparator/issues", - "source": "https://github.com/sebastianbergmann/comparator/tree/4.0.10" + "security": "https://github.com/sebastianbergmann/comparator/security/policy", + "source": "https://github.com/sebastianbergmann/comparator/tree/5.0.5" }, "funding": [ { @@ -994,33 +911,33 @@ "type": "tidelift" } ], - "time": "2026-01-24T09:22:56+00:00" + "time": "2026-01-24T09:25:16+00:00" }, { "name": "sebastian/complexity", - "version": "2.0.3", + "version": "3.2.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/complexity.git", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a" + "reference": "68ff824baeae169ec9f2137158ee529584553799" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/25f207c40d62b8b7aa32f5ab026c53561964053a", - "reference": "25f207c40d62b8b7aa32f5ab026c53561964053a", + "url": "https://api.github.com/repos/sebastianbergmann/complexity/zipball/68ff824baeae169ec9f2137158ee529584553799", + "reference": "68ff824baeae169ec9f2137158ee529584553799", "shasum": "" }, "require": { "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.2-dev" } }, "autoload": { @@ -1043,7 +960,8 @@ "homepage": "https://github.com/sebastianbergmann/complexity", "support": { "issues": "https://github.com/sebastianbergmann/complexity/issues", - "source": "https://github.com/sebastianbergmann/complexity/tree/2.0.3" + "security": "https://github.com/sebastianbergmann/complexity/security/policy", + "source": "https://github.com/sebastianbergmann/complexity/tree/3.2.0" }, "funding": [ { @@ -1051,33 +969,33 @@ "type": "github" } ], - "time": "2023-12-22T06:19:30+00:00" + "time": "2023-12-21T08:37:17+00:00" }, { "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": { @@ -1109,7 +1027,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": [ { @@ -1117,27 +1036,27 @@ "type": "github" } ], - "time": "2024-03-02T06:30:58+00:00" + "time": "2024-03-02T07:15:17+00:00" }, { "name": "sebastian/environment", - "version": "5.1.5", + "version": "6.1.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed" + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", - "reference": "830c43a844f1f8d5b7a1f6d6076b784454d8b7ed", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/8074dbcd93529b357029f5cc5058fd3e43666984", + "reference": "8074dbcd93529b357029f5cc5058fd3e43666984", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "suggest": { "ext-posix": "*" @@ -1145,7 +1064,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "5.1-dev" + "dev-main": "6.1-dev" } }, "autoload": { @@ -1164,7 +1083,7 @@ } ], "description": "Provides functionality to handle HHVM/PHP environments", - "homepage": "http://www.github.com/sebastianbergmann/environment", + "homepage": "https://github.com/sebastianbergmann/environment", "keywords": [ "Xdebug", "environment", @@ -1172,7 +1091,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/environment/issues", - "source": "https://github.com/sebastianbergmann/environment/tree/5.1.5" + "security": "https://github.com/sebastianbergmann/environment/security/policy", + "source": "https://github.com/sebastianbergmann/environment/tree/6.1.0" }, "funding": [ { @@ -1180,34 +1100,34 @@ "type": "github" } ], - "time": "2023-02-03T06:03:51+00:00" + "time": "2024-03-23T08:47:14+00:00" }, { "name": "sebastian/exporter", - "version": "4.0.8", + "version": "5.1.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/exporter.git", - "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c" + "reference": "0735b90f4da94969541dac1da743446e276defa6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/14c6ba52f95a36c3d27c835d65efc7123c446e8c", - "reference": "14c6ba52f95a36c3d27c835d65efc7123c446e8c", + "url": "https://api.github.com/repos/sebastianbergmann/exporter/zipball/0735b90f4da94969541dac1da743446e276defa6", + "reference": "0735b90f4da94969541dac1da743446e276defa6", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/recursion-context": "^4.0" + "ext-mbstring": "*", + "php": ">=8.1", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "ext-mbstring": "*", - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.1-dev" } }, "autoload": { @@ -1249,7 +1169,8 @@ ], "support": { "issues": "https://github.com/sebastianbergmann/exporter/issues", - "source": "https://github.com/sebastianbergmann/exporter/tree/4.0.8" + "security": "https://github.com/sebastianbergmann/exporter/security/policy", + "source": "https://github.com/sebastianbergmann/exporter/tree/5.1.4" }, "funding": [ { @@ -1269,38 +1190,35 @@ "type": "tidelift" } ], - "time": "2025-09-24T06:03:27+00:00" + "time": "2025-09-24T06:09:11+00:00" }, { "name": "sebastian/global-state", - "version": "5.0.8", + "version": "6.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/global-state.git", - "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6" + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/b6781316bdcd28260904e7cc18ec983d0d2ef4f6", - "reference": "b6781316bdcd28260904e7cc18ec983d0d2ef4f6", + "url": "https://api.github.com/repos/sebastianbergmann/global-state/zipball/987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", + "reference": "987bafff24ecc4c9ac418cab1145b96dd6e9cbd9", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { "ext-dom": "*", - "phpunit/phpunit": "^9.3" - }, - "suggest": { - "ext-uopz": "*" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "5.0-dev" + "dev-main": "6.0-dev" } }, "autoload": { @@ -1319,59 +1237,48 @@ } ], "description": "Snapshotting of global state", - "homepage": "http://www.github.com/sebastianbergmann/global-state", + "homepage": "https://www.github.com/sebastianbergmann/global-state", "keywords": [ "global state" ], "support": { "issues": "https://github.com/sebastianbergmann/global-state/issues", - "source": "https://github.com/sebastianbergmann/global-state/tree/5.0.8" + "security": "https://github.com/sebastianbergmann/global-state/security/policy", + "source": "https://github.com/sebastianbergmann/global-state/tree/6.0.2" }, "funding": [ { "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/sebastian/global-state", - "type": "tidelift" } ], - "time": "2025-08-10T07:10:35+00:00" + "time": "2024-03-02T07:19:19+00:00" }, { "name": "sebastian/lines-of-code", - "version": "1.0.4", + "version": "2.0.2", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/lines-of-code.git", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5" + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/e1e4a170560925c26d424b6a03aed157e7dcc5c5", - "reference": "e1e4a170560925c26d424b6a03aed157e7dcc5c5", + "url": "https://api.github.com/repos/sebastianbergmann/lines-of-code/zipball/856e7f6a75a84e339195d48c556f23be2ebf75d0", + "reference": "856e7f6a75a84e339195d48c556f23be2ebf75d0", "shasum": "" }, "require": { "nikic/php-parser": "^4.18 || ^5.0", - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-main": "2.0-dev" } }, "autoload": { @@ -1394,7 +1301,8 @@ "homepage": "https://github.com/sebastianbergmann/lines-of-code", "support": { "issues": "https://github.com/sebastianbergmann/lines-of-code/issues", - "source": "https://github.com/sebastianbergmann/lines-of-code/tree/1.0.4" + "security": "https://github.com/sebastianbergmann/lines-of-code/security/policy", + "source": "https://github.com/sebastianbergmann/lines-of-code/tree/2.0.2" }, "funding": [ { @@ -1402,34 +1310,34 @@ "type": "github" } ], - "time": "2023-12-22T06:20:34+00:00" + "time": "2023-12-21T08:38:20+00:00" }, { "name": "sebastian/object-enumerator", - "version": "4.0.4", + "version": "5.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-enumerator.git", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71" + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/5c9eeac41b290a3712d88851518825ad78f45c71", - "reference": "5c9eeac41b290a3712d88851518825ad78f45c71", + "url": "https://api.github.com/repos/sebastianbergmann/object-enumerator/zipball/202d0e344a580d7f7d04b3fafce6933e59dae906", + "reference": "202d0e344a580d7f7d04b3fafce6933e59dae906", "shasum": "" }, "require": { - "php": ">=7.3", - "sebastian/object-reflector": "^2.0", - "sebastian/recursion-context": "^4.0" + "php": ">=8.1", + "sebastian/object-reflector": "^3.0", + "sebastian/recursion-context": "^5.0" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -1451,7 +1359,7 @@ "homepage": "https://github.com/sebastianbergmann/object-enumerator/", "support": { "issues": "https://github.com/sebastianbergmann/object-enumerator/issues", - "source": "https://github.com/sebastianbergmann/object-enumerator/tree/4.0.4" + "source": "https://github.com/sebastianbergmann/object-enumerator/tree/5.0.0" }, "funding": [ { @@ -1459,32 +1367,32 @@ "type": "github" } ], - "time": "2020-10-26T13:12:34+00:00" + "time": "2023-02-03T07:08:32+00:00" }, { "name": "sebastian/object-reflector", - "version": "2.0.4", + "version": "3.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/object-reflector.git", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7" + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", - "reference": "b4f479ebdbf63ac605d183ece17d8d7fe49c15c7", + "url": "https://api.github.com/repos/sebastianbergmann/object-reflector/zipball/24ed13d98130f0e7122df55d06c5c4942a577957", + "reference": "24ed13d98130f0e7122df55d06c5c4942a577957", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.0-dev" + "dev-main": "3.0-dev" } }, "autoload": { @@ -1506,7 +1414,7 @@ "homepage": "https://github.com/sebastianbergmann/object-reflector/", "support": { "issues": "https://github.com/sebastianbergmann/object-reflector/issues", - "source": "https://github.com/sebastianbergmann/object-reflector/tree/2.0.4" + "source": "https://github.com/sebastianbergmann/object-reflector/tree/3.0.0" }, "funding": [ { @@ -1514,32 +1422,32 @@ "type": "github" } ], - "time": "2020-10-26T13:14:26+00:00" + "time": "2023-02-03T07:06:18+00:00" }, { "name": "sebastian/recursion-context", - "version": "4.0.6", + "version": "5.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/recursion-context.git", - "reference": "539c6691e0623af6dc6f9c20384c120f963465a0" + "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/539c6691e0623af6dc6f9c20384c120f963465a0", - "reference": "539c6691e0623af6dc6f9c20384c120f963465a0", + "url": "https://api.github.com/repos/sebastianbergmann/recursion-context/zipball/47e34210757a2f37a97dcd207d032e1b01e64c7a", + "reference": "47e34210757a2f37a97dcd207d032e1b01e64c7a", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.3" + "phpunit/phpunit": "^10.5" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.0-dev" + "dev-main": "5.0-dev" } }, "autoload": { @@ -1569,7 +1477,8 @@ "homepage": "https://github.com/sebastianbergmann/recursion-context", "support": { "issues": "https://github.com/sebastianbergmann/recursion-context/issues", - "source": "https://github.com/sebastianbergmann/recursion-context/tree/4.0.6" + "security": "https://github.com/sebastianbergmann/recursion-context/security/policy", + "source": "https://github.com/sebastianbergmann/recursion-context/tree/5.0.1" }, "funding": [ { @@ -1589,86 +1498,32 @@ "type": "tidelift" } ], - "time": "2025-08-10T06:57:39+00:00" - }, - { - "name": "sebastian/resource-operations", - "version": "3.0.4", - "source": { - "type": "git", - "url": "https://github.com/sebastianbergmann/resource-operations.git", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/resource-operations/zipball/05d5692a7993ecccd56a03e40cd7e5b09b1d404e", - "reference": "05d5692a7993ecccd56a03e40cd7e5b09b1d404e", - "shasum": "" - }, - "require": { - "php": ">=7.3" - }, - "require-dev": { - "phpunit/phpunit": "^9.0" - }, - "type": "library", - "extra": { - "branch-alias": { - "dev-main": "3.0-dev" - } - }, - "autoload": { - "classmap": [ - "src/" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "BSD-3-Clause" - ], - "authors": [ - { - "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de" - } - ], - "description": "Provides a list of PHP built-in functions that operate on resources", - "homepage": "https://www.github.com/sebastianbergmann/resource-operations", - "support": { - "source": "https://github.com/sebastianbergmann/resource-operations/tree/3.0.4" - }, - "funding": [ - { - "url": "https://github.com/sebastianbergmann", - "type": "github" - } - ], - "time": "2024-03-14T16:00:52+00:00" + "time": "2025-08-10T07:50:56+00:00" }, { "name": "sebastian/type", - "version": "3.2.1", + "version": "4.0.0", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/type.git", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7" + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", - "reference": "75e2c2a32f5e0b3aef905b9ed0b179b953b3d7c7", + "url": "https://api.github.com/repos/sebastianbergmann/type/zipball/462699a16464c3944eefc02ebdd77882bd3925bf", + "reference": "462699a16464c3944eefc02ebdd77882bd3925bf", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "require-dev": { - "phpunit/phpunit": "^9.5" + "phpunit/phpunit": "^10.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -1691,7 +1546,7 @@ "homepage": "https://github.com/sebastianbergmann/type", "support": { "issues": "https://github.com/sebastianbergmann/type/issues", - "source": "https://github.com/sebastianbergmann/type/tree/3.2.1" + "source": "https://github.com/sebastianbergmann/type/tree/4.0.0" }, "funding": [ { @@ -1699,29 +1554,29 @@ "type": "github" } ], - "time": "2023-02-03T06:13:03+00:00" + "time": "2023-02-03T07:10:45+00:00" }, { "name": "sebastian/version", - "version": "3.0.2", + "version": "4.0.1", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/version.git", - "reference": "c6c1022351a901512170118436c764e473f6de8c" + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c6c1022351a901512170118436c764e473f6de8c", - "reference": "c6c1022351a901512170118436c764e473f6de8c", + "url": "https://api.github.com/repos/sebastianbergmann/version/zipball/c51fa83a5d8f43f1402e3f32a005e6262244ef17", + "reference": "c51fa83a5d8f43f1402e3f32a005e6262244ef17", "shasum": "" }, "require": { - "php": ">=7.3" + "php": ">=8.1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-main": "4.0-dev" } }, "autoload": { @@ -1744,7 +1599,7 @@ "homepage": "https://github.com/sebastianbergmann/version", "support": { "issues": "https://github.com/sebastianbergmann/version/issues", - "source": "https://github.com/sebastianbergmann/version/tree/3.0.2" + "source": "https://github.com/sebastianbergmann/version/tree/4.0.1" }, "funding": [ { @@ -1752,7 +1607,7 @@ "type": "github" } ], - "time": "2020-09-28T06:39:44+00:00" + "time": "2023-02-07T11:34:05+00:00" }, { "name": "theseer/tokenizer", @@ -1813,7 +1668,7 @@ "platform": {}, "platform-dev": {}, "platform-overrides": { - "php": "8.0" + "php": "8.1" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.9.0" } diff --git a/vendor-bin/rector/composer.json b/vendor-bin/rector/composer.json new file mode 100644 index 0000000..9472ac7 --- /dev/null +++ b/vendor-bin/rector/composer.json @@ -0,0 +1,5 @@ +{ + "require-dev": { + "rector/rector": "^2.5" + } +} diff --git a/vendor-bin/rector/composer.lock b/vendor-bin/rector/composer.lock new file mode 100644 index 0000000..fa8270c --- /dev/null +++ b/vendor-bin/rector/composer.lock @@ -0,0 +1,143 @@ +{ + "_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": "1ad304cbb5861653bcb22b2c664487c8", + "packages": [], + "packages-dev": [ + { + "name": "phpstan/phpstan", + "version": "2.2.5", + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/909c1e5fef7989ac0d0c1c5c42e32a5c4f6198a0", + "reference": "909c1e5fef7989ac0d0c1c5c42e32a5c4f6198a0", + "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" + ], + "authors": [ + { + "name": "Ondřej Mirtes" + }, + { + "name": "Markus Staab" + }, + { + "name": "Vincent Langlet" + } + ], + "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-07-05T06:31:06+00:00" + }, + { + "name": "rector/rector", + "version": "2.5.7", + "source": { + "type": "git", + "url": "https://github.com/rectorphp/rector.git", + "reference": "ba22f8c087848278fed6b4910d4cf1108096d8d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/ba22f8c087848278fed6b4910d4cf1108096d8d3", + "reference": "ba22f8c087848278fed6b4910d4cf1108096d8d3", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "phpstan/phpstan": "^2.2.2" + }, + "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.5.7" + }, + "funding": [ + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2026-07-13T15:24:18+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.9.0" +}