diff --git a/composer.json b/composer.json index 982060bd0..24333de29 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,8 @@ "test:unit": "phpunit --display-all-issues -c tests/phpunit.xml", "test:integration": "phpunit --display-all-issues -c tests/phpunit.integration.xml", "psalm": "psalm --no-cache", - "openapi": "generate-spec" + "openapi": "generate-spec", + "rector": "./vendor/bin/rector process" }, "require-dev": { "bamarni/composer-bin-plugin": "^1.8" diff --git a/lib/Activity/ActivityManager.php b/lib/Activity/ActivityManager.php index 5e842d854..aed130f59 100644 --- a/lib/Activity/ActivityManager.php +++ b/lib/Activity/ActivityManager.php @@ -16,10 +16,10 @@ class ActivityManager { public function __construct( protected string $appName, - private ?string $userId, - private IManager $manager, - private IGroupManager $groupManager, - private CirclesService $circlesService, + private readonly ?string $userId, + private readonly IManager $manager, + private readonly IGroupManager $groupManager, + private readonly CirclesService $circlesService, ) { } diff --git a/lib/Activity/Filter.php b/lib/Activity/Filter.php index dd6cd3381..17010a1cf 100644 --- a/lib/Activity/Filter.php +++ b/lib/Activity/Filter.php @@ -14,8 +14,8 @@ class Filter implements IFilter { public function __construct( protected string $appName, - private IL10N $l10n, - private IURLGenerator $urlGenerator, + private readonly IL10N $l10n, + private readonly IURLGenerator $urlGenerator, ) { } diff --git a/lib/Activity/Provider.php b/lib/Activity/Provider.php index 56f3d8339..edd4e1f44 100644 --- a/lib/Activity/Provider.php +++ b/lib/Activity/Provider.php @@ -20,21 +20,19 @@ use OCP\IURLGenerator; use OCP\IUserManager; use OCP\L10N\IFactory; -use OCP\RichObjectStrings\IValidator; use Psr\Log\LoggerInterface; class Provider implements IProvider { public function __construct( protected string $appName, - private FormMapper $formMapper, - private IEventMerger $eventMerger, - private IGroupManager $groupManager, - private LoggerInterface $logger, - private IURLGenerator $urlGenerator, - private IUserManager $userManager, - private IFactory $l10nFactory, - private IValidator $validator, - private CirclesService $circlesService, + private readonly FormMapper $formMapper, + private readonly IEventMerger $eventMerger, + private readonly IGroupManager $groupManager, + private readonly LoggerInterface $logger, + private readonly IURLGenerator $urlGenerator, + private readonly IUserManager $userManager, + private readonly IFactory $l10nFactory, + private readonly CirclesService $circlesService, ) { } @@ -113,32 +111,27 @@ public function parseSubjectString(string $subjectString, array $parameters): st * @return array */ public function getRichParams(IL10N $l10n, string $subject, array $params): array { - switch ($subject) { - case ActivityConstants::SUBJECT_NEWSHARE: - return [ - 'user' => $this->getRichUser($l10n, $params['userId']), - 'formTitle' => $this->getRichFormTitle($params['formTitle'], $params['formHash']) - ]; - case ActivityConstants::SUBJECT_NEWGROUPSHARE: - return [ - 'user' => $this->getRichUser($l10n, $params['userId']), - 'formTitle' => $this->getRichFormTitle($params['formTitle'], $params['formHash']), - 'group' => $this->getRichGroup($params['groupId']) - ]; - case ActivityConstants::SUBJECT_NEWCIRCLESHARE: - return [ - 'user' => $this->getRichUser($l10n, $params['userId']), - 'formTitle' => $this->getRichFormTitle($params['formTitle'], $params['formHash']), - 'circle' => $this->getRichCircle($params['circleId']) - ]; - case ActivityConstants::SUBJECT_NEWSUBMISSION: - return [ - 'user' => $this->getRichUser($l10n, $params['userId']), - 'formTitle' => $this->getRichFormTitle($params['formTitle'], $params['formHash'], 'results') - ]; - default: - return []; - } + return match ($subject) { + ActivityConstants::SUBJECT_NEWSHARE => [ + 'user' => $this->getRichUser($l10n, $params['userId']), + 'formTitle' => $this->getRichFormTitle($params['formTitle'], $params['formHash']) + ], + ActivityConstants::SUBJECT_NEWGROUPSHARE => [ + 'user' => $this->getRichUser($l10n, $params['userId']), + 'formTitle' => $this->getRichFormTitle($params['formTitle'], $params['formHash']), + 'group' => $this->getRichGroup($params['groupId']) + ], + ActivityConstants::SUBJECT_NEWCIRCLESHARE => [ + 'user' => $this->getRichUser($l10n, $params['userId']), + 'formTitle' => $this->getRichFormTitle($params['formTitle'], $params['formHash']), + 'circle' => $this->getRichCircle($params['circleId']) + ], + ActivityConstants::SUBJECT_NEWSUBMISSION => [ + 'user' => $this->getRichUser($l10n, $params['userId']), + 'formTitle' => $this->getRichFormTitle($params['formTitle'], $params['formHash'], 'results') + ], + default => [], + }; } /** @@ -148,7 +141,7 @@ public function getRichParams(IL10N $l10n, string $subject, array $params): arra */ public function getRichUser(IL10N $l10n, string $userId): array { // Special handling for anonyomous users - if (substr($userId, 0, 10) === 'anon-user-') { + if (str_starts_with($userId, 'anon-user-')) { return [ 'type' => 'highlight', 'id' => $userId, @@ -198,7 +191,7 @@ public function getRichGroup(string $groupId): array { /** * Turn a circleId into a rich-circle array. * - * @param string $groupId + * @param string $circleId * @return array */ public function getRichCircle(string $circleId): array { @@ -240,7 +233,7 @@ public function getRichFormTitle(string $formTitle, string $formHash, string $ro if ($route !== '') { $formLink .= '/' . $route; } - } catch (IMapperException $e) { + } catch (IMapperException) { // Ignore if not found, just use stored title } @@ -260,14 +253,10 @@ public function getRichFormTitle(string $formTitle, string $formHash, string $ro * @return string */ public function getEventIcon(string $subject): string { - switch ($subject) { - case ActivityConstants::SUBJECT_NEWSHARE: - case ActivityConstants::SUBJECT_NEWGROUPSHARE: - return $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/shared.svg')); - case ActivityConstants::SUBJECT_NEWSUBMISSION: - return $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/add.svg')); - default: - return $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('forms', 'forms-dark.svg')); - } + return match ($subject) { + ActivityConstants::SUBJECT_NEWSHARE, ActivityConstants::SUBJECT_NEWGROUPSHARE => $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/shared.svg')), + ActivityConstants::SUBJECT_NEWSUBMISSION => $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('core', 'actions/add.svg')), + default => $this->urlGenerator->getAbsoluteURL($this->urlGenerator->imagePath('forms', 'forms-dark.svg')), + }; } } diff --git a/lib/Analytics/AnalyticsDatasource.php b/lib/Analytics/AnalyticsDatasource.php index 04936d149..62f520b4b 100644 --- a/lib/Analytics/AnalyticsDatasource.php +++ b/lib/Analytics/AnalyticsDatasource.php @@ -18,10 +18,10 @@ class AnalyticsDatasource implements IDatasource { public function __construct( protected ?string $userId, - private IL10N $l10n, - private FormMapper $formMapper, - private FormsService $formsService, - private SubmissionService $submissionService, + private readonly IL10N $l10n, + private readonly FormMapper $formMapper, + private readonly FormsService $formsService, + private readonly SubmissionService $submissionService, ) { } diff --git a/lib/BackgroundJob/CleanupUploadedFilesJob.php b/lib/BackgroundJob/CleanupUploadedFilesJob.php index 0acb49e35..d4c18342e 100644 --- a/lib/BackgroundJob/CleanupUploadedFilesJob.php +++ b/lib/BackgroundJob/CleanupUploadedFilesJob.php @@ -21,10 +21,10 @@ class CleanupUploadedFilesJob extends TimedJob { private const FILE_LIFETIME = '-1 hour'; public function __construct( - private IRootFolder $rootFolder, - private FormMapper $formMapper, - private UploadedFileMapper $uploadedFileMapper, - private LoggerInterface $logger, + private readonly IRootFolder $rootFolder, + private readonly FormMapper $formMapper, + private readonly UploadedFileMapper $uploadedFileMapper, + private readonly LoggerInterface $logger, ITimeFactory $time, ) { parent::__construct($time); diff --git a/lib/BackgroundJob/DeleteQuestionFoldersJob.php b/lib/BackgroundJob/DeleteQuestionFoldersJob.php index 28c5123aa..34e75a599 100644 --- a/lib/BackgroundJob/DeleteQuestionFoldersJob.php +++ b/lib/BackgroundJob/DeleteQuestionFoldersJob.php @@ -17,8 +17,8 @@ class DeleteQuestionFoldersJob extends QueuedJob { public function __construct( ITimeFactory $time, - private FilePathHelper $filePathHelper, - private LoggerInterface $logger, + private readonly FilePathHelper $filePathHelper, + private readonly LoggerInterface $logger, ) { parent::__construct($time); } @@ -56,7 +56,7 @@ public function run($argument): void { continue; } foreach ($submissionFolder->getDirectoryListing() as $questionFolder) { - if (str_starts_with($questionFolder->getName(), $questionFolderPrefix)) { + if (str_starts_with((string)$questionFolder->getName(), $questionFolderPrefix)) { $questionFolder->delete(); $deletedCount++; } diff --git a/lib/BackgroundJob/SendConfirmationMailJob.php b/lib/BackgroundJob/SendConfirmationMailJob.php index fe8a42294..4b65a9019 100644 --- a/lib/BackgroundJob/SendConfirmationMailJob.php +++ b/lib/BackgroundJob/SendConfirmationMailJob.php @@ -18,9 +18,9 @@ class SendConfirmationMailJob extends QueuedJob { public function __construct( ITimeFactory $time, - private IMailer $mailer, - private LoggerInterface $logger, - private Defaults $defaults, + private readonly IMailer $mailer, + private readonly LoggerInterface $logger, + private readonly Defaults $defaults, ) { parent::__construct($time); } diff --git a/lib/BackgroundJob/SyncSubmissionsWithLinkedFileJob.php b/lib/BackgroundJob/SyncSubmissionsWithLinkedFileJob.php index 9e11d0c65..ee0fc04cc 100644 --- a/lib/BackgroundJob/SyncSubmissionsWithLinkedFileJob.php +++ b/lib/BackgroundJob/SyncSubmissionsWithLinkedFileJob.php @@ -24,13 +24,13 @@ class SyncSubmissionsWithLinkedFileJob extends QueuedJob { public function __construct( ITimeFactory $time, - private FormMapper $formMapper, - private FormsService $formsService, - private SubmissionService $submissionService, - private LoggerInterface $logger, - private IUserManager $userManager, - private IUserSession $userSession, - private IJobList $jobList, + private readonly FormMapper $formMapper, + private readonly FormsService $formsService, + private readonly SubmissionService $submissionService, + private readonly LoggerInterface $logger, + private readonly IUserManager $userManager, + private readonly IUserSession $userSession, + private readonly IJobList $jobList, ) { parent::__construct($time); } @@ -54,7 +54,7 @@ public function run($argument): void { $filePath = $this->formsService->getFilePath($form); $this->submissionService->writeFileToCloud($form, $filePath, $fileFormat, $ownerId); - } catch (NotFoundException $e) { + } catch (NotFoundException) { $this->logger->notice('Form {formId} linked to a file that doesn\'t exist anymore', [ 'formId' => $formId ]); @@ -85,6 +85,6 @@ public function run($argument): void { * Calculates exponential delay (cubic growth) in seconds. */ private function nextAttempt(int $numberOfAttempt): int { - return $this->time->getTime() + pow($numberOfAttempt, 3) * 60; + return $this->time->getTime() + $numberOfAttempt ** 3 * 60; } } diff --git a/lib/BackgroundJob/UserDeletedJob.php b/lib/BackgroundJob/UserDeletedJob.php index 9d57801dc..4ed0c5675 100644 --- a/lib/BackgroundJob/UserDeletedJob.php +++ b/lib/BackgroundJob/UserDeletedJob.php @@ -15,9 +15,9 @@ class UserDeletedJob extends QueuedJob { public function __construct( - private FormMapper $formMapper, + private readonly FormMapper $formMapper, ITimeFactory $time, - private LoggerInterface $logger, + private readonly LoggerInterface $logger, ) { parent::__construct($time); } diff --git a/lib/Capabilities.php b/lib/Capabilities.php index 6c25e2c0d..770f1b6be 100644 --- a/lib/Capabilities.php +++ b/lib/Capabilities.php @@ -12,7 +12,7 @@ class Capabilities implements ICapability { public function __construct( - private IAppManager $appManager, + private readonly IAppManager $appManager, ) { } diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php index 38de3d93d..2494afbab 100644 --- a/lib/Controller/ApiController.php +++ b/lib/Controller/ApiController.php @@ -18,7 +18,6 @@ use OCA\Forms\Db\OptionMapper; use OCA\Forms\Db\Question; use OCA\Forms\Db\QuestionMapper; -use OCA\Forms\Db\ShareMapper; use OCA\Forms\Db\Submission; use OCA\Forms\Db\SubmissionMapper; use OCA\Forms\Db\UploadedFile; @@ -69,29 +68,28 @@ * @psalm-import-type FormsUploadedFile from ResponseDefinitions */ class ApiController extends OCSController { - private ?IUser $currentUser; + private readonly ?IUser $currentUser; public function __construct( string $appName, IRequest $request, IUserSession $userSession, - private AnswerMapper $answerMapper, - private FormMapper $formMapper, - private OptionMapper $optionMapper, - private QuestionMapper $questionMapper, - private ShareMapper $shareMapper, - private SubmissionMapper $submissionMapper, - private ConfirmationEmailService $confirmationEmailService, - private ConfigService $configService, - private FormsService $formsService, - private SubmissionService $submissionService, - private IL10N $l10n, - private LoggerInterface $logger, - private IUserManager $userManager, - private IRootFolder $rootFolder, - private UploadedFileMapper $uploadedFileMapper, - private IMimeTypeDetector $mimeTypeDetector, - private IJobList $jobList, + private readonly AnswerMapper $answerMapper, + private readonly FormMapper $formMapper, + private readonly OptionMapper $optionMapper, + private readonly QuestionMapper $questionMapper, + private readonly SubmissionMapper $submissionMapper, + private readonly ConfirmationEmailService $confirmationEmailService, + private readonly ConfigService $configService, + private readonly FormsService $formsService, + private readonly SubmissionService $submissionService, + private readonly IL10N $l10n, + private readonly LoggerInterface $logger, + private readonly IUserManager $userManager, + private readonly IRootFolder $rootFolder, + private readonly UploadedFileMapper $uploadedFileMapper, + private readonly IMimeTypeDetector $mimeTypeDetector, + private readonly IJobList $jobList, ) { parent::__construct($appName, $request); $this->currentUser = $userSession->getUser(); @@ -135,7 +133,7 @@ public function getForms(string $type = 'owned'): DataResponse { } } elseif ($type === 'shared') { $forms = $this->formsService->getSharedForms($this->currentUser); - $result = array_values(array_map(fn (Form $form): array => $this->formsService->getPartialFormArray($form), $forms)); + $result = array_values(array_map($this->formsService->getPartialFormArray(...), $forms)); } else { throw new OCSBadRequestException('wrong form type supplied'); } @@ -335,7 +333,7 @@ public function updateForm(int $formId, array $keyValuePairs): DataResponse { } // Process file unlinking - if (key_exists('fileId', $keyValuePairs) && key_exists('fileFormat', $keyValuePairs) && !isset($keyValuePairs['fileFormat'])) { + if (array_key_exists('fileId', $keyValuePairs) && array_key_exists('fileFormat', $keyValuePairs) && !isset($keyValuePairs['fileFormat'])) { $form->setFileId(null); $form->setFileFormat(null); } @@ -347,7 +345,7 @@ public function updateForm(int $formId, array $keyValuePairs): DataResponse { if (array_key_exists('confirmationEmailQuestionId', $keyValuePairs)) { try { $this->confirmationEmailService->validateRecipientQuestionId($form, $keyValuePairs['confirmationEmailQuestionId']); - } catch (\InvalidArgumentException $e) { + } catch (\InvalidArgumentException) { throw new OCSBadRequestException('Invalid confirmationEmailQuestionId, will not update.'); } } @@ -414,7 +412,7 @@ public function deleteForm(int $formId): DataResponse { public function getQuestions(int $formId): DataResponse { try { $form = $this->formMapper->findById($formId); - } catch (IMapperException $e) { + } catch (IMapperException) { $this->logger->debug('Could not find form'); throw new OCSNotFoundException('Could not find form'); } @@ -453,7 +451,7 @@ public function getQuestions(int $formId): DataResponse { public function getQuestion(int $formId, int $questionId): DataResponse { try { $form = $this->formMapper->findById($formId); - } catch (IMapperException $e) { + } catch (IMapperException) { $this->logger->debug('Could not find form'); throw new OCSNotFoundException('Could not find form'); } @@ -575,7 +573,7 @@ public function newQuestion(int $formId, ?string $type = null, ?string $subtype throw new OCSBadRequestException('Question doesn\'t belong to given form'); } $sourceOptions = $this->optionMapper->findByQuestion($fromId); - } catch (IMapperException $e) { + } catch (IMapperException) { $this->logger->debug('Could not find question'); throw new OCSNotFoundException('Could not find question'); } @@ -663,7 +661,7 @@ public function updateQuestion(int $formId, int $questionId, array $keyValuePair try { $question = $this->questionMapper->findById($questionId); - } catch (IMapperException $e) { + } catch (IMapperException) { $this->logger->debug('Could not find question'); throw new OCSNotFoundException('Could not find question'); } @@ -673,24 +671,24 @@ public function updateQuestion(int $formId, int $questionId, array $keyValuePair } // Don't allow empty array - if (sizeof($keyValuePairs) === 0) { + if (count($keyValuePairs) === 0) { $this->logger->info('Empty keyValuePairs, will not update.'); throw new OCSBadRequestException('This form is archived and can not be modified'); } //Don't allow to change id or formId - if (key_exists('id', $keyValuePairs) || key_exists('formId', $keyValuePairs)) { + if (array_key_exists('id', $keyValuePairs) || array_key_exists('formId', $keyValuePairs)) { $this->logger->debug('Not allowed to update \'id\' or \'formId\''); throw new OCSForbiddenException('Not allowed to update \'id\' or \'formId\''); } // Don't allow to reorder here - if (key_exists('order', $keyValuePairs)) { + if (array_key_exists('order', $keyValuePairs)) { $this->logger->debug('Key \'order\' is not allowed on updateQuestion. Please use reorderQuestions() to change order.'); throw new OCSForbiddenException('Please use reorderQuestions() to change order'); } - if (key_exists('extraSettings', $keyValuePairs) && !$this->formsService->areExtraSettingsValid($keyValuePairs['extraSettings'], $question->getType())) { + if (array_key_exists('extraSettings', $keyValuePairs) && !$this->formsService->areExtraSettingsValid($keyValuePairs['extraSettings'], $question->getType())) { throw new OCSBadRequestException('Invalid extraSettings, will not update.'); } @@ -743,7 +741,7 @@ public function deleteQuestion(int $formId, int $questionId): DataResponse { try { $question = $this->questionMapper->findById($questionId); - } catch (IMapperException $e) { + } catch (IMapperException) { $this->logger->debug('Could not find question'); throw new OCSNotFoundException('Could not find question'); } @@ -829,7 +827,7 @@ public function reorderQuestions(int $formId, array $newOrder): DataResponse { // Check if all questions are given in Array. $questions = $this->questionMapper->findByForm($formId); - if (sizeof($questions) !== sizeof($newOrder)) { + if (count($questions) !== count($newOrder)) { $this->logger->debug('The length of the given array does not match the number of stored questions'); throw new OCSBadRequestException('The length of the given array does not match the number of stored questions'); } @@ -841,7 +839,7 @@ public function reorderQuestions(int $formId, array $newOrder): DataResponse { foreach ($newOrder as $arrayKey => $questionId) { try { $questions[$arrayKey] = $this->questionMapper->findById($questionId); - } catch (IMapperException $e) { + } catch (IMapperException) { $this->logger->debug('Could not find question {questionId}', [ 'questionId' => $questionId ]); @@ -1012,7 +1010,7 @@ public function updateOption(int $formId, int $questionId, int $optionId, array try { $option = $this->optionMapper->findById($optionId); $question = $this->questionMapper->findById($questionId); - } catch (IMapperException $e) { + } catch (IMapperException) { $this->logger->debug('Could not find option or question'); throw new OCSNotFoundException('Could not find option or question'); } @@ -1023,13 +1021,13 @@ public function updateOption(int $formId, int $questionId, int $optionId, array } // Don't allow empty array - if (sizeof($keyValuePairs) === 0) { + if (count($keyValuePairs) === 0) { $this->logger->info('Empty keyValuePairs, will not update'); throw new OCSForbiddenException('Empty keyValuePairs, will not update'); } //Don't allow to change id or questionId - if (key_exists('id', $keyValuePairs) || key_exists('questionId', $keyValuePairs)) { + if (array_key_exists('id', $keyValuePairs) || array_key_exists('questionId', $keyValuePairs)) { $this->logger->debug('Not allowed to update id or questionId'); throw new OCSForbiddenException('Not allowed to update id or questionId'); } @@ -1081,7 +1079,7 @@ public function deleteOption(int $formId, int $questionId, int $optionId): DataR try { $option = $this->optionMapper->findById($optionId); $question = $this->questionMapper->findById($questionId); - } catch (IMapperException $e) { + } catch (IMapperException) { $this->logger->debug('Could not find option or question'); throw new OCSBadRequestException('Could not find option or question'); } @@ -1139,7 +1137,7 @@ public function reorderOptions(int $formId, int $questionId, array $newOrder, ?s try { $question = $this->questionMapper->findById($questionId); - } catch (IMapperException $e) { + } catch (IMapperException) { $this->logger->debug('Could not find question'); throw new OCSNotFoundException('Could not find question'); } @@ -1157,7 +1155,7 @@ public function reorderOptions(int $formId, int $questionId, array $newOrder, ?s $options = $this->optionMapper->findByQuestion($questionId, $optionType); - if (sizeof($options) !== sizeof($newOrder)) { + if (count($options) !== count($newOrder)) { $this->logger->debug('The length of the given array does not match the number of stored options'); throw new OCSBadRequestException('The length of the given array does not match the number of stored options'); } @@ -1169,7 +1167,7 @@ public function reorderOptions(int $formId, int $questionId, array $newOrder, ?s foreach ($newOrder as $arrayKey => $optionId) { try { $options[$arrayKey] = $this->optionMapper->findById($optionId); - } catch (IMapperException $e) { + } catch (IMapperException) { $this->logger->debug('Could not find option. Id: {optionId}', [ 'optionId' => $optionId ]); @@ -1278,7 +1276,7 @@ public function getSubmissions(int $formId, ?string $query = null, ?int $limit = }, $submission['answers']); } - if (substr($submission['userId'], 0, 10) === 'anon-user-') { + if (str_starts_with($submission['userId'], 'anon-user-')) { // Anonymous User // TRANSLATORS On Results when listing the single Responses to the form, this text is shown as heading of the Response. $submission['userDisplayName'] = $this->l10n->t('Anonymous response'); @@ -1347,7 +1345,7 @@ public function getSubmission(int $formId, int $submissionId): DataResponse|Data } // Append Display Names - if (substr($submission['userId'], 0, 10) === 'anon-user-') { + if (str_starts_with($submission['userId'], 'anon-user-')) { // Anonymous User // TRANSLATORS On Results when listing the single Responses to the form, this text is shown as heading of the Response. $submission['userDisplayName'] = $this->l10n->t('Anonymous response'); @@ -1442,7 +1440,7 @@ public function newSubmission(int $formId, array $answers, string $shareHash = ' // If not logged in, anonymous, or embedded use anonID if (!$this->currentUser || $form->getIsAnonymous()) { - $anonID = 'anon-user-' . hash('md5', strval(time() + rand())); + $anonID = 'anon-user-' . hash('md5', strval(time() + random_int(0, mt_getrandmax()))); $submission->setUserId($anonID); } else { $submission->setUserId($this->currentUser->getUID()); @@ -1534,7 +1532,7 @@ public function updateSubmission(int $formId, int $submissionId, array $answers) // get existing submission of this user try { $submission = $this->submissionMapper->findById($submissionId); - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { throw new OCSBadRequestException('Submission doesn\'t exist'); } @@ -1595,7 +1593,7 @@ public function deleteSubmission(int $formId, int $submissionId): DataResponse { $form = $this->formsService->getFormIfAllowed($formId, Constants::PERMISSION_RESULTS_DELETE); try { $submission = $this->submissionMapper->findById($submissionId); - } catch (IMapperException $e) { + } catch (IMapperException) { $this->logger->debug('Could not find submission'); throw new OCSNotFoundException('Could not find submission'); } @@ -1698,7 +1696,7 @@ public function uploadFiles(int $formId, int $questionId, string $shareHash = '' try { $question = $this->questionMapper->findById($questionId); - } catch (IMapperException $e) { + } catch (IMapperException) { $this->logger->debug('Could not find question with id {questionId}', [ 'questionId' => $questionId ]); @@ -1835,7 +1833,7 @@ private function storeAnswersForQuestion(Form $form, $submissionId, array $quest $optionIndex = array_search($answer, array_column($question['options'], 'id')); if ($optionIndex !== false) { $answerText = $question['options'][$optionIndex]['text']; - } elseif (!empty($question['extraSettings']['allowOtherAnswer']) && strpos($answer, Constants::QUESTION_EXTRASETTINGS_OTHER_PREFIX) === 0) { + } elseif (!empty($question['extraSettings']['allowOtherAnswer']) && str_starts_with($answer, Constants::QUESTION_EXTRASETTINGS_OTHER_PREFIX)) { $answerText = str_replace(Constants::QUESTION_EXTRASETTINGS_OTHER_PREFIX, '', $answer); } } elseif ($question['type'] === Constants::ANSWER_TYPE_FILE) { @@ -1925,7 +1923,7 @@ private function checkArchivePermission(Form $form, string $currentUserId, array $isOwner = $currentUserId === $form->getOwnerId(); // If the request contains 'state' it must be the only key - if (sizeof($keyValuePairs) !== 1) { + if (count($keyValuePairs) !== 1) { $this->logger->debug('State may only be changed on its own'); throw new OCSForbiddenException('State may only be changed on its own'); } @@ -1944,19 +1942,19 @@ private function checkArchivePermission(Form $form, string $currentUserId, array } private function isLockingRequest(array $keyValuePairs): bool { - return sizeof($keyValuePairs) === 1 + return count($keyValuePairs) === 1 && array_key_exists('lockedUntil', $keyValuePairs) && $keyValuePairs['lockedUntil'] === 0; } private function isUnlockingRequest(array $keyValuePairs): bool { - return sizeof($keyValuePairs) === 1 + return count($keyValuePairs) === 1 && array_key_exists('lockedUntil', $keyValuePairs) && is_null($keyValuePairs['lockedUntil']); } private function isOwnerTransferRequest(array $keyValuePairs): bool { - return sizeof($keyValuePairs) === 1 && key_exists('ownerId', $keyValuePairs); + return count($keyValuePairs) === 1 && array_key_exists('ownerId', $keyValuePairs); } /** diff --git a/lib/Controller/ConfigController.php b/lib/Controller/ConfigController.php index ce53d8018..7eee3e403 100644 --- a/lib/Controller/ConfigController.php +++ b/lib/Controller/ConfigController.php @@ -23,9 +23,9 @@ class ConfigController extends ApiController { public function __construct( protected $appName, - private ConfigService $configService, - private IAppConfig $appConfig, - private LoggerInterface $logger, + private readonly ConfigService $configService, + private readonly IAppConfig $appConfig, + private readonly LoggerInterface $logger, IRequest $request, ) { parent::__construct($appName, $request); diff --git a/lib/Controller/PageController.php b/lib/Controller/PageController.php index 5e5caddb0..64f85f4a9 100644 --- a/lib/Controller/PageController.php +++ b/lib/Controller/PageController.php @@ -44,18 +44,18 @@ class PageController extends Controller { public function __construct( string $appName, IRequest $request, - private FormMapper $formMapper, - private ShareMapper $shareMapper, - private SubmissionMapper $submissionMapper, - private ConfigService $configService, - private FormsService $formsService, - private IAccountManager $accountManager, - private IInitialState $initialState, - private ICommentsManager $commentsManager, - private IL10N $l10n, - private IUrlGenerator $urlGenerator, - private IUserManager $userManager, - private IUserSession $userSession, + private readonly FormMapper $formMapper, + private readonly ShareMapper $shareMapper, + private readonly SubmissionMapper $submissionMapper, + private readonly ConfigService $configService, + private readonly FormsService $formsService, + private readonly IAccountManager $accountManager, + private readonly IInitialState $initialState, + private readonly ICommentsManager $commentsManager, + private readonly IL10N $l10n, + private readonly IUrlGenerator $urlGenerator, + private readonly IUserManager $userManager, + private readonly IUserSession $userSession, ) { parent::__construct($appName, $request); } @@ -80,7 +80,7 @@ public function index(?string $hash = null, ?int $submissionId = null): Template try { $form = $this->formMapper->findByHash($hash); $this->initialState->provideInitialState('formId', $form->id); - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { // Provide null to indicate no form was found $this->initialState->provideInitialState('formId', 'invalid'); } @@ -90,7 +90,7 @@ public function index(?string $hash = null, ?int $submissionId = null): Template try { $submission = $this->submissionMapper->findById($submissionId); $this->initialState->provideInitialState('submissionId', $submission->id); - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { // Ignore exception and just don't set the initialState value } } @@ -153,7 +153,7 @@ public function publicLinkView(string $hash): Response { try { $share = $this->shareMapper->findPublicShareByHash($hash); $form = $this->formMapper->findById($share->getFormId()); - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { return $this->provideEmptyContent(Constants::EMPTY_NOTFOUND); } @@ -177,7 +177,7 @@ public function embeddedFormView(string $hash): Response { } $form = $this->formMapper->findById($share->getFormId()); - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { return $this->provideEmptyContent(Constants::EMPTY_NOTFOUND); // We do not handle the MultipleObjectsReturnedException as this will automatically result in a 500 error as expected } diff --git a/lib/Controller/ShareApiController.php b/lib/Controller/ShareApiController.php index 84954dfb8..544d55fd7 100644 --- a/lib/Controller/ShareApiController.php +++ b/lib/Controller/ShareApiController.php @@ -37,7 +37,6 @@ use OCP\IRequest; use OCP\IUser; use OCP\IUserManager; -use OCP\IUserSession; use OCP\Security\ISecureRandom; use OCP\Share\IManager; use OCP\Share\IShare; @@ -47,27 +46,24 @@ * @psalm-import-type FormsShare from ResponseDefinitions */ class ShareApiController extends OCSController { - private IUser $currentUser; public function __construct( string $appName, IRequest $request, - IUserSession $userSession, - private FormMapper $formMapper, - private ShareMapper $shareMapper, - private ConfigService $configService, - private FormsService $formsService, - private IGroupManager $groupManager, - private LoggerInterface $logger, - private IUserManager $userManager, - private ISecureRandom $secureRandom, - private CirclesService $circlesService, - private IRootFolder $rootFolder, - private FilePathHelper $filePathHelper, - private IManager $shareManager, + private readonly FormMapper $formMapper, + private readonly ShareMapper $shareMapper, + private readonly ConfigService $configService, + private readonly FormsService $formsService, + private readonly IGroupManager $groupManager, + private readonly LoggerInterface $logger, + private readonly IUserManager $userManager, + private readonly ISecureRandom $secureRandom, + private readonly CirclesService $circlesService, + private readonly IRootFolder $rootFolder, + private readonly FilePathHelper $filePathHelper, + private readonly IManager $shareManager, ) { parent::__construct($appName, $request); - $this->currentUser = $userSession->getUser(); } /** @@ -162,7 +158,7 @@ public function newShare(int $formId, int $shareType, string $shareWith = '', ar // If we come here, a share has been found --> The share hash already exists, thus aborting. $this->logger->debug('Share hash already exists.'); throw new OCSBadRequestException('Share hash exists, please retry.'); - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { // Just continue, this is what we expect to happen (share hash not existing yet). } break; @@ -252,7 +248,7 @@ public function updateShare(int $formId, int $shareId, array $keyValuePairs): Da } // Don't allow empty array - if (sizeof($keyValuePairs) === 0) { + if (count($keyValuePairs) === 0) { $this->logger->info('Empty keyValuePairs, will not update.'); throw new OCSForbiddenException('Empty keyValuePairs, will not update'); } @@ -279,7 +275,7 @@ public function updateShare(int $formId, int $shareId, array $keyValuePairs): Da try { /** @var \OCP\Files\Folder $folder */ $folder = $userFolder->get($uploadedFilesFolderPath); - } catch (NotFoundException $e) { + } catch (NotFoundException) { $folder = $userFolder->newFolder($uploadedFilesFolderPath); } @@ -363,7 +359,7 @@ private function removeUploadedFilesShare(Form $form, Share $formShare): void { $uploadedFilesFolderPath = $this->filePathHelper->getFormUploadedFilesFolderPath($form); try { $folder = $userFolder->get($uploadedFilesFolderPath); - } catch (NotFoundException $e) { + } catch (NotFoundException) { return; } $folderShares = $this->shareManager->getSharesBy($form->getOwnerId(), $formShare->getShareType(), $folder, false, -1); diff --git a/lib/Db/FormMapper.php b/lib/Db/FormMapper.php index 5a7289659..adfdbc4c2 100644 --- a/lib/Db/FormMapper.php +++ b/lib/Db/FormMapper.php @@ -31,15 +31,15 @@ class FormMapper extends QBMapper { */ public function __construct( IDBConnection $db, - private QuestionMapper $questionMapper, - private ShareMapper $shareMapper, - private SubmissionMapper $submissionMapper, - private ConfigService $configService, - private ICommentsManager $commentsManager, - private FilePathHelper $filePathHelper, - private UploadedFileMapper $uploadedFileMapper, - private IRootFolder $rootFolder, - private LoggerInterface $logger, + private readonly QuestionMapper $questionMapper, + private readonly ShareMapper $shareMapper, + private readonly SubmissionMapper $submissionMapper, + private readonly ConfigService $configService, + private readonly ICommentsManager $commentsManager, + private readonly FilePathHelper $filePathHelper, + private readonly UploadedFileMapper $uploadedFileMapper, + private readonly IRootFolder $rootFolder, + private readonly LoggerInterface $logger, ) { parent::__construct($db, 'forms_v2_forms', Form::class); } @@ -252,7 +252,7 @@ private function deleteFormFolder(Form $form): void { // Iterate through form folders and delete matching folders foreach ($formsFolder->getDirectoryListing() as $node) { - if (str_starts_with($node->getName(), $formFolderPrefix)) { + if (str_starts_with((string)$node->getName(), $formFolderPrefix)) { $node->delete(); } } diff --git a/lib/Db/QuestionMapper.php b/lib/Db/QuestionMapper.php index fefd9fd25..c705ac3c1 100644 --- a/lib/Db/QuestionMapper.php +++ b/lib/Db/QuestionMapper.php @@ -18,7 +18,7 @@ class QuestionMapper extends QBMapper { public function __construct( IDBConnection $db, - private OptionMapper $optionMapper, + private readonly OptionMapper $optionMapper, ) { parent::__construct($db, 'forms_v2_questions', Question::class); } diff --git a/lib/Db/SubmissionMapper.php b/lib/Db/SubmissionMapper.php index 6f5a836ae..ab6273e44 100644 --- a/lib/Db/SubmissionMapper.php +++ b/lib/Db/SubmissionMapper.php @@ -28,9 +28,9 @@ class SubmissionMapper extends QBMapper { */ public function __construct( IDBConnection $db, - private AnswerMapper $answerMapper, - private FilePathHelper $filePathHelper, - private LoggerInterface $logger, + private readonly AnswerMapper $answerMapper, + private readonly FilePathHelper $filePathHelper, + private readonly LoggerInterface $logger, ) { parent::__construct($db, 'forms_v2_submissions', Submission::class); } diff --git a/lib/Events/FormSubmittedEvent.php b/lib/Events/FormSubmittedEvent.php index dde7ec158..da6dbba6a 100644 --- a/lib/Events/FormSubmittedEvent.php +++ b/lib/Events/FormSubmittedEvent.php @@ -13,7 +13,7 @@ class FormSubmittedEvent extends AbstractFormEvent { public function __construct( Form $form, - private Submission $submission, + private readonly Submission $submission, ) { parent::__construct($form); } diff --git a/lib/FormsMigrator.php b/lib/FormsMigrator.php index 3b8f78f19..91b4ad64b 100644 --- a/lib/FormsMigrator.php +++ b/lib/FormsMigrator.php @@ -94,8 +94,8 @@ public function export(IUser $user, IExportDestination $exportDestination, Outpu // Mark userIds with instance. foreach ($formData['submissions'] as $sKey => $submission) { // Anonymous submission or already migrated, just keep it. - if (substr($submission['userId'], 0, 10) === 'anon-user-' - || substr($submission['userId'], 0, 8) === 'unknown~') { + if (str_starts_with($submission['userId'], 'anon-user-') + || str_starts_with($submission['userId'], 'unknown~')) { continue; } diff --git a/lib/Helper/FilePathHelper.php b/lib/Helper/FilePathHelper.php index 4a611de7b..2da421bab 100644 --- a/lib/Helper/FilePathHelper.php +++ b/lib/Helper/FilePathHelper.php @@ -15,7 +15,7 @@ class FilePathHelper { public function __construct( - private IRootFolder $rootFolder, + private readonly IRootFolder $rootFolder, ) { } @@ -65,7 +65,7 @@ public function getAllFormFoldersById(int $formId, string $ownerId): array { // Collect all folders matching the form ID prefix foreach ($formsFolder->getDirectoryListing() as $node) { - if (str_starts_with($node->getName(), $formFolderPrefix) && $node instanceof Folder) { + if (str_starts_with((string)$node->getName(), $formFolderPrefix) && $node instanceof Folder) { $matchingFolders[] = $node; } } diff --git a/lib/Listener/CommentsEntityListener.php b/lib/Listener/CommentsEntityListener.php index 633d2085d..2b6912f8e 100644 --- a/lib/Listener/CommentsEntityListener.php +++ b/lib/Listener/CommentsEntityListener.php @@ -36,7 +36,7 @@ public function handle(Event $event): void { $event->addEntityCollection('forms', function ($formId) { try { $form = $this->formMapper->findById((int)$formId); - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { return false; } return $this->formService->hasUserAccess($form) && $form->getAllowComments(); diff --git a/lib/Listener/UserDeletedListener.php b/lib/Listener/UserDeletedListener.php index de4179ffc..e177f2baa 100644 --- a/lib/Listener/UserDeletedListener.php +++ b/lib/Listener/UserDeletedListener.php @@ -18,7 +18,7 @@ */ class UserDeletedListener implements IEventListener { public function __construct( - private IJobList $jobList, + private readonly IJobList $jobList, ) { } diff --git a/lib/Migration/Version010200Date20200323141300.php b/lib/Migration/Version010200Date20200323141300.php index 54f4a7439..221edc44d 100644 --- a/lib/Migration/Version010200Date20200323141300.php +++ b/lib/Migration/Version010200Date20200323141300.php @@ -235,9 +235,9 @@ public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $cursor = $qb_fetch->executeQuery(); while ($question = $cursor->fetch()) { //In case the old Question would have been longer than current possible length, create a warning and shorten text to avoid Error on upgrade. - if (strlen($question['form_question_text']) > 2048) { + if (strlen((string)$question['form_question_text']) > 2048) { $output->warning("Question-text is too long for new Database: '" . $question['form_question_text'] . "'"); - $question['form_question_text'] = mb_substr($question['form_question_text'], 0, 2048); + $question['form_question_text'] = mb_substr((string)$question['form_question_text'], 0, 2048); } $qb_restore->insert('forms_v2_questions') @@ -261,9 +261,9 @@ public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $cursor = $qb_fetch->executeQuery(); while ($answer = $cursor->fetch()) { //In case the old Answer would have been longer than current possible length, create a warning and shorten text to avoid Error on upgrade. - if (strlen($answer['text']) > 1024) { + if (strlen((string)$answer['text']) > 1024) { $output->warning("Option-text is too long for new Database: '" . $answer['text'] . "'"); - $answer['text'] = mb_substr($answer['text'], 0, 1024); + $answer['text'] = mb_substr((string)$answer['text'], 0, 1024); } $qb_restore->insert('forms_v2_options') @@ -328,9 +328,9 @@ public function postSchemaChange(IOutput $output, \Closure $schemaClosure, array $last_vote = $vote; //In case the old Answer would have been longer than current possible length, create a warning and shorten text to avoid Error on upgrade. - if (strlen($vote['vote_answer']) > 4096) { + if (strlen((string)$vote['vote_answer']) > 4096) { $output->warning("Answer-text is too long for new Database: '" . $vote['vote_answer'] . "'"); - $vote['vote_answer'] = mb_substr($vote['vote_answer'], 0, 4096); + $vote['vote_answer'] = mb_substr((string)$vote['vote_answer'], 0, 4096); } /* Due to the unconventional storing fo vote_option_ids, the vote_option_id needs to get mapped onto old question-id and from there to new question-id. @@ -371,11 +371,11 @@ private function convertAccessList($accessString) : string { $accessArray['users'] = []; $accessArray['groups'] = []; - $stringExplode = explode(';', $accessString); + $stringExplode = explode(';', (string)$accessString); foreach ($stringExplode as $string) { - if (strpos($string, 'user_') === 0) { + if (str_starts_with($string, 'user_')) { $accessArray['users'][] = substr($string, 5); - } elseif (strpos($string, 'group_') === 0) { + } elseif (str_starts_with($string, 'group_')) { $accessArray['groups'][] = substr($string, 6); } } diff --git a/lib/Migration/Version020202Date20210311150843.php b/lib/Migration/Version020202Date20210311150843.php index 6bb8d6874..886cd7f9d 100644 --- a/lib/Migration/Version020202Date20210311150843.php +++ b/lib/Migration/Version020202Date20210311150843.php @@ -49,7 +49,7 @@ public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $ while ($row = $cursor->fetch()) { // Decode access to array (param assoc=true) - $access = json_decode($row['access_json'], true); + $access = json_decode((string)$row['access_json'], true); $update_necessary = false; // Add empty Arrays, if they do not exist diff --git a/lib/Migration/Version030000Date20211206213004.php b/lib/Migration/Version030000Date20211206213004.php index bff258793..281c1de4c 100644 --- a/lib/Migration/Version030000Date20211206213004.php +++ b/lib/Migration/Version030000Date20211206213004.php @@ -104,7 +104,7 @@ public function postSchemaChange(IOutput $output, Closure $schemaClosure, array // ... then handle each existing form and translate its sharing settings. while ($row = $cursor->fetch()) { // Decode access to array (param assoc=true) - $access = json_decode($row['access_json'], true); + $access = json_decode((string)$row['access_json'], true); // In case there are already migrated forms, just skip. if (array_key_exists('permitAllUsers', $access)) { diff --git a/lib/Migration/Version040200Date20240402200139.php b/lib/Migration/Version040200Date20240402200139.php index fc85d9d18..c9924de85 100644 --- a/lib/Migration/Version040200Date20240402200139.php +++ b/lib/Migration/Version040200Date20240402200139.php @@ -77,7 +77,7 @@ public function postSchemaChange(IOutput $output, Closure $schemaClosure, array // ... then handle each existing form and translate its sharing settings. while ($row = $cursor->fetch()) { // Decode access to array (param assoc=true) - $access = json_decode($row['access_json'], true); + $access = json_decode((string)$row['access_json'], true); $value = Constants::FORM_ACCESS_NOPUBLICSHARE; diff --git a/lib/Search/SearchProvider.php b/lib/Search/SearchProvider.php index 4b0c2e61b..e851501b8 100644 --- a/lib/Search/SearchProvider.php +++ b/lib/Search/SearchProvider.php @@ -23,9 +23,9 @@ class SearchProvider implements IProvider { * @psalm-suppress PossiblyUnusedMethod */ public function __construct( - private IL10N $l10n, - private IURLGenerator $urlGenerator, - private FormsService $formsService, + private readonly IL10N $l10n, + private readonly IURLGenerator $urlGenerator, + private readonly FormsService $formsService, ) { } @@ -40,16 +40,12 @@ public function getName(): string { public function search(IUser $user, ISearchQuery $query): SearchResult { $forms = $this->formsService->search($query); - $results = array_map(function (Form $form) { - return [ - 'object' => $form, - 'entry' => new FormsSearchResultEntry($form, $this->urlGenerator) - ]; - }, $forms); + $results = array_map(fn (Form $form) => [ + 'object' => $form, + 'entry' => new FormsSearchResultEntry($form, $this->urlGenerator) + ], $forms); - $resultEntries = array_map(function (array $result) { - return $result['entry']; - }, $results); + $resultEntries = array_map(fn (array $result) => $result['entry'], $results); return SearchResult::complete( $this->l10n->t('Forms'), diff --git a/lib/Service/CirclesService.php b/lib/Service/CirclesService.php index 2ef1e1cb5..c9156d143 100644 --- a/lib/Service/CirclesService.php +++ b/lib/Service/CirclesService.php @@ -22,14 +22,14 @@ * having the app disabled is properly handled */ class CirclesService { - private bool $circlesEnabled; + private readonly bool $circlesEnabled; private $userCircleCache = []; public function __construct( IAppManager $appManager, - private ContainerInterface $container, - private LoggerInterface $logger, + private readonly ContainerInterface $container, + private readonly LoggerInterface $logger, ) { $this->circlesEnabled = $appManager->isEnabledForUser('circles'); } @@ -48,7 +48,7 @@ public function getCircle(string $circleId): ?Circle { // Enforce current user condition since we always want the full list of members $circlesManager->startSuperSession(); return $circlesManager->getCircle($circleId); - } catch (Throwable $e) { + } catch (Throwable) { } return null; } @@ -76,7 +76,7 @@ public function isUserInCircle(string $circleId, string $userId): bool { $this->userCircleCache[$circleId][$userId] = $isUserInCircle; return $isUserInCircle; - } catch (Throwable $e) { + } catch (Throwable) { } return false; } diff --git a/lib/Service/ConfigService.php b/lib/Service/ConfigService.php index bd335c637..ad73d953e 100644 --- a/lib/Service/ConfigService.php +++ b/lib/Service/ConfigService.php @@ -17,13 +17,13 @@ use OCP\IUserSession; class ConfigService { - private ?IUser $currentUser; + private readonly ?IUser $currentUser; public function __construct( protected string $appName, - private IConfig $config, - private IAppConfig $appConfig, - private IGroupManager $groupManager, + private readonly IConfig $config, + private readonly IAppConfig $appConfig, + private readonly IGroupManager $groupManager, IUserSession $userSession, ) { $this->currentUser = $userSession->getUser(); @@ -123,7 +123,7 @@ public function canCreateForms(): bool { $userGroups = $this->groupManager->getUserGroupIds($this->currentUser); // If array intersection is not empty, user is member of any allowed group. - if (sizeof(array_intersect($userGroups, $this->getUnformattedCreationAllowedGroups()))) { + if (count(array_intersect($userGroups, $this->getUnformattedCreationAllowedGroups()))) { return true; } diff --git a/lib/Service/ConfirmationEmailService.php b/lib/Service/ConfirmationEmailService.php index 3032a23dd..dcdb85b3c 100644 --- a/lib/Service/ConfirmationEmailService.php +++ b/lib/Service/ConfirmationEmailService.php @@ -26,17 +26,17 @@ class ConfirmationEmailService { private const RATE_LIMIT_TTL = 86400; // 24 hours - private ICache $rateLimitCache; + private readonly ICache $rateLimitCache; public function __construct( - private ConfigService $configService, - private AnswerMapper $answerMapper, - private QuestionMapper $questionMapper, - private IEmailValidator $emailValidator, - private IJobList $jobList, + private readonly ConfigService $configService, + private readonly AnswerMapper $answerMapper, + private readonly QuestionMapper $questionMapper, + private readonly IEmailValidator $emailValidator, + private readonly IJobList $jobList, ICacheFactory $cacheFactory, - private IL10N $l10n, - private LoggerInterface $logger, + private readonly IL10N $l10n, + private readonly LoggerInterface $logger, ) { $this->rateLimitCache = $cacheFactory->createDistributed('forms_confirmation_email'); } diff --git a/lib/Service/FormsService.php b/lib/Service/FormsService.php index 454135faa..ee3dc7434 100644 --- a/lib/Service/FormsService.php +++ b/lib/Service/FormsService.php @@ -49,27 +49,27 @@ * @psalm-import-type FormsShare from ResponseDefinitions */ class FormsService { - private ?IUser $currentUser; + private readonly ?IUser $currentUser; public function __construct( IUserSession $userSession, - private ActivityManager $activityManager, - private FormMapper $formMapper, - private OptionMapper $optionMapper, - private QuestionMapper $questionMapper, - private ShareMapper $shareMapper, - private SubmissionMapper $submissionMapper, - private ConfigService $configService, - private IGroupManager $groupManager, - private IUserManager $userManager, - private ISecureRandom $secureRandom, - private CirclesService $circlesService, - private FilePathHelper $filePathHelper, - private IRootFolder $rootFolder, - private IL10N $l10n, - private LoggerInterface $logger, - private IEventDispatcher $eventDispatcher, - private ConfirmationEmailService $confirmationEmailService, + private readonly ActivityManager $activityManager, + private readonly FormMapper $formMapper, + private readonly OptionMapper $optionMapper, + private readonly QuestionMapper $questionMapper, + private readonly ShareMapper $shareMapper, + private readonly SubmissionMapper $submissionMapper, + private readonly ConfigService $configService, + private readonly IGroupManager $groupManager, + private readonly IUserManager $userManager, + private readonly ISecureRandom $secureRandom, + private readonly CirclesService $circlesService, + private readonly FilePathHelper $filePathHelper, + private readonly IRootFolder $rootFolder, + private readonly IL10N $l10n, + private readonly LoggerInterface $logger, + private readonly IEventDispatcher $eventDispatcher, + private readonly ConfirmationEmailService $confirmationEmailService, ) { $this->currentUser = $userSession->getUser(); } @@ -97,7 +97,7 @@ private function getOptions(int $questionId): array { foreach ($optionEntities as $optionEntity) { $optionList[] = $optionEntity->read(); } - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { //handle silently } finally { return $optionList; @@ -120,9 +120,7 @@ public function getQuestions(int $formId): array { $question['accept'] = []; if ($question['type'] === Constants::ANSWER_TYPE_FILE) { if ($question['extraSettings']['allowedFileTypes'] ?? null) { - $question['accept'] = array_map(function (string $fileType) { - return str_contains($fileType, '/') ? $fileType : $fileType . '/*'; - }, $question['extraSettings']['allowedFileTypes']); + $question['accept'] = array_map(fn (string $fileType) => str_contains($fileType, '/') ? $fileType : $fileType . '/*', $question['extraSettings']['allowedFileTypes']); } if ($question['extraSettings']['allowedFileExtensions'] ?? null) { @@ -139,7 +137,7 @@ public function getQuestions(int $formId): array { $questionList[] = $question; } - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { //handle silently } finally { return $questionList; @@ -160,9 +158,7 @@ public function getQuestion(int $questionId): ?array { $question['accept'] = []; if ($question['type'] === Constants::ANSWER_TYPE_FILE) { if ($question['extraSettings']['allowedFileTypes'] ?? null) { - $question['accept'] = array_map(function (string $fileType) { - return str_contains($fileType, '/') ? $fileType : $fileType . '/*'; - }, $question['extraSettings']['allowedFileTypes']); + $question['accept'] = array_map(fn (string $fileType) => str_contains($fileType, '/') ? $fileType : $fileType . '/*', $question['extraSettings']['allowedFileTypes']); } if ($question['extraSettings']['allowedFileExtensions'] ?? null) { @@ -172,7 +168,7 @@ public function getQuestion(int $questionId): ?array { } } return $question; - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { return null; } } @@ -231,7 +227,7 @@ public function getForm(Form $form): array { try { $result['filePath'] = $this->getFilePath($form); // If file was deleted, set filePath to null - } catch (NotFoundException $e) { + } catch (NotFoundException) { $result['filePath'] = null; } } @@ -305,7 +301,7 @@ public function getPublicForm(Form $form): array { public function getFormIfAllowed(int $formId, string $permissions = 'all'): Form { try { $form = $this->formMapper->findById($formId); - } catch (IMapperException $e) { + } catch (IMapperException) { $this->logger->debug('Could not find form'); throw new NoSuchFormException('Could not find form'); } @@ -349,7 +345,7 @@ public function getFormIfAllowed(int $formId, string $permissions = 'all'): Form public function loadFormForSubmission(int $formId, string $shareHash): Form { try { $form = $this->formMapper->findById($formId); - } catch (IMapperException $e) { + } catch (IMapperException) { $this->logger->debug('Could not find form'); throw new NoSuchFormException('Could not find form'); } @@ -366,7 +362,7 @@ public function loadFormForSubmission(int $formId, string $shareHash): Form { $isPublicShare = true; } } - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { // $isPublicShare already false. } finally { // Now forbid, if no public share and no direct share. @@ -584,7 +580,7 @@ public function getSharedForms(IUser $user, bool $filterShown = true): array { ); // filter expired forms - $forms = array_filter($forms, fn (Form $form): bool => $this->isSharedFormShown($form)); + $forms = array_filter($forms, $this->isSharedFormShown(...)); return $forms; } @@ -768,9 +764,7 @@ public function notifyNewSubmission(Form $form, Submission $submission): void { } // Deduplicate and exclude form owner to avoid duplicates - $sharedUserIds = array_unique(array_filter($sharedUserIds, function (string $userId) use ($form) { - return $userId !== $form->getOwnerId(); - })); + $sharedUserIds = array_unique(array_filter($sharedUserIds, fn (string $userId) => $userId !== $form->getOwnerId())); foreach ($sharedUserIds as $userId) { try { @@ -839,38 +833,18 @@ public function areExtraSettingsValid(array $extraSettings, string $questionType } // Ensure only allowed keys are set - switch ($questionType) { - case Constants::ANSWER_TYPE_DROPDOWN: - $allowed = Constants::EXTRA_SETTINGS_DROPDOWN; - break; - case Constants::ANSWER_TYPE_MULTIPLE: - case Constants::ANSWER_TYPE_MULTIPLEUNIQUE: - $allowed = Constants::EXTRA_SETTINGS_MULTIPLE; - break; - case Constants::ANSWER_TYPE_SHORT: - $allowed = Constants::EXTRA_SETTINGS_SHORT; - break; - case Constants::ANSWER_TYPE_FILE: - $allowed = Constants::EXTRA_SETTINGS_FILE; - break; - case Constants::ANSWER_TYPE_DATE: - $allowed = Constants::EXTRA_SETTINGS_DATE; - break; - case Constants::ANSWER_TYPE_GRID: - $allowed = Constants::EXTRA_SETTINGS_GRID; - break; - case Constants::ANSWER_TYPE_RANKING: - $allowed = Constants::EXTRA_SETTINGS_RANKING; - break; - case Constants::ANSWER_TYPE_TIME: - $allowed = Constants::EXTRA_SETTINGS_TIME; - break; - case Constants::ANSWER_TYPE_LINEARSCALE: - $allowed = Constants::EXTRA_SETTINGS_LINEARSCALE; - break; - default: - $allowed = []; - } + $allowed = match ($questionType) { + Constants::ANSWER_TYPE_DROPDOWN => Constants::EXTRA_SETTINGS_DROPDOWN, + Constants::ANSWER_TYPE_MULTIPLE, Constants::ANSWER_TYPE_MULTIPLEUNIQUE => Constants::EXTRA_SETTINGS_MULTIPLE, + Constants::ANSWER_TYPE_SHORT => Constants::EXTRA_SETTINGS_SHORT, + Constants::ANSWER_TYPE_FILE => Constants::EXTRA_SETTINGS_FILE, + Constants::ANSWER_TYPE_DATE => Constants::EXTRA_SETTINGS_DATE, + Constants::ANSWER_TYPE_GRID => Constants::EXTRA_SETTINGS_GRID, + Constants::ANSWER_TYPE_RANKING => Constants::EXTRA_SETTINGS_RANKING, + Constants::ANSWER_TYPE_TIME => Constants::EXTRA_SETTINGS_TIME, + Constants::ANSWER_TYPE_LINEARSCALE => Constants::EXTRA_SETTINGS_LINEARSCALE, + default => [], + }; // Number of keys in extraSettings but not in allowed (but not the other way round) $diff = array_diff(array_keys($extraSettings), array_keys($allowed)); if (count($diff) > 0) { @@ -1003,7 +977,7 @@ public function search(ISearchQuery $query): array { $query->getTerm() ); $formsList = array_merge($ownedForms, $sharedForms); - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { // silent catch } return $formsList; diff --git a/lib/Service/SubmissionService.php b/lib/Service/SubmissionService.php index b35605be3..21b524b75 100644 --- a/lib/Service/SubmissionService.php +++ b/lib/Service/SubmissionService.php @@ -32,7 +32,7 @@ use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; -use OCP\Mail\IMailer; +use OCP\Mail\IEmailValidator; use PhpOffice\PhpSpreadsheet\Cell\DataType; use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\Spreadsheet; @@ -45,24 +45,24 @@ * @psalm-import-type FormsAnswer from ResponseDefinitions */ class SubmissionService { - private ?IUser $currentUser; + private readonly ?IUser $currentUser; public function __construct( - private QuestionMapper $questionMapper, - private SubmissionMapper $submissionMapper, - private AnswerMapper $answerMapper, - private UploadedFileMapper $uploadedFileMapper, - private IRootFolder $rootFolder, - private IConfig $config, - private IL10N $l10n, - private LoggerInterface $logger, - private IUserManager $userManager, + private readonly QuestionMapper $questionMapper, + private readonly SubmissionMapper $submissionMapper, + private readonly AnswerMapper $answerMapper, + private readonly UploadedFileMapper $uploadedFileMapper, + private readonly IRootFolder $rootFolder, + private readonly IConfig $config, + private readonly IL10N $l10n, + private readonly LoggerInterface $logger, + private readonly IUserManager $userManager, IUserSession $userSession, - private IMailer $mailer, - private ITempManager $tempManager, - private FormsService $formsService, - private IUrlGenerator $urlGenerator, - private OptionMapper $optionMapper, + private readonly ITempManager $tempManager, + private readonly FormsService $formsService, + private readonly IUrlGenerator $urlGenerator, + private readonly OptionMapper $optionMapper, + private readonly IEmailValidator $emailValidator, ) { $this->currentUser = $userSession->getUser(); } @@ -80,7 +80,7 @@ private function getAnswers(int $submissionId): array { foreach ($answerEntities as $answerEntity) { $answerList[] = $answerEntity->read(); } - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { //Just ignore, if no Data. Returns empty Answers-Array } finally { return $answerList; @@ -113,7 +113,7 @@ public function getSubmissions(int $formId, ?string $userId = null, ?string $que $submission['answers'] = $this->getAnswers($submission['id']); $submissionList[] = $submission; } - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { // Just ignore, if no Data. Returns empty Submissions-Array } finally { return $submissionList; @@ -138,7 +138,7 @@ public function getSubmission(int $submissionId): ?array { $submission = $submissionEntity->read(); $submission['answers'] = $this->getAnswers($submission['id']); return $submission; - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { return null; } } @@ -221,7 +221,7 @@ public function getSubmissionsData(Form $form, string $fileFormat, ?File $file = try { $submissionEntities = $this->submissionMapper->findByForm($form->getId()); - } catch (DoesNotExistException $e) { + } catch (DoesNotExistException) { // Just ignore, if no Data. Returns empty Submissions-Array } @@ -344,10 +344,7 @@ function (array $carry, Answer $answer) use ($questionPerQuestionId, $gridRowsPe if ($gridCellType === Constants::ANSWER_GRID_TYPE_RADIO) { $columns[] = $optionPerOptionId[$answerText[$row]]->getText(); } elseif ($gridCellType === Constants::ANSWER_GRID_TYPE_CHECKBOX) { - $columns[] = implode('; ', array_map(function ($optionId) use ($optionPerOptionId) { - ; - return $optionPerOptionId[$optionId]->getText(); - }, $answerText[$row])); + $columns[] = implode('; ', array_map(fn ($optionId) => $optionPerOptionId[$optionId]->getText(), $answerText[$row])); } elseif ($gridCellType === Constants::ANSWER_GRID_TYPE_NUMBER) { // For number grids, we need to create a header for each cell in the grid foreach ($gridColumnsPerQuestionId[$questionId] as $column) { @@ -492,9 +489,7 @@ public function validateSubmission(array $questions, array $answers, string $for } // Grid questions - return !empty(array_filter($value, static function ($subValue): bool { - return is_array($subValue) ? !empty(array_filter($subValue)) : $subValue !== ''; - })); + return !empty(array_filter($value, static fn ($subValue): bool => is_array($subValue) ? !empty(array_filter($subValue)) : $subValue !== '')); } return $value !== ''; @@ -558,7 +553,7 @@ public function validateSubmission(array $questions, array $answers, string $for if ($question['type'] === Constants::ANSWER_TYPE_LINEARSCALE) { $optionsLowest = $question['extraSettings']['optionsLowest'] ?? 1; $optionsHighest = $question['extraSettings']['optionsHighest'] ?? 5; - if (!ctype_digit($answer) || intval($answer) < $optionsLowest || intval($answer) > $optionsHighest) { + if (!ctype_digit((string)$answer) || intval($answer) < $optionsLowest || intval($answer) > $optionsHighest) { throw new \InvalidArgumentException(sprintf('The answer for question "%s" must be an integer between %d and %d.', $question['text'], $optionsLowest, $optionsHighest)); } } @@ -590,8 +585,8 @@ public function validateSubmission(array $questions, array $answers, string $for // Handle ranking questions: answers must be a permutation of all option IDs if ($question['type'] === Constants::ANSWER_TYPE_RANKING) { - $optionIds = array_map('intval', array_column($question['options'] ?? [], 'id')); - $rankedIds = array_map('intval', $answers[$questionId]); + $optionIds = array_map(intval(...), array_column($question['options'] ?? [], 'id')); + $rankedIds = array_map(intval(...), $answers[$questionId]); sort($optionIds); sort($rankedIds); @@ -605,7 +600,7 @@ public function validateSubmission(array $questions, array $answers, string $for if ( $question['type'] === Constants::ANSWER_TYPE_COLOR && $answers[$questionId][0] !== '' - && !preg_match('/^#[a-f0-9]{6}$/i', $answers[$questionId][0]) + && !preg_match('/^#[a-f0-9]{6}$/i', (string)$answers[$questionId][0]) ) { throw new \InvalidArgumentException(sprintf('Invalid color string for question "%s".', $question['text'])); } @@ -684,7 +679,7 @@ private function validateShortQuestion(array $question, string $data): bool { switch ($question['extraSettings']['validationType']) { case 'email': - return $this->mailer->validateMailAddress($data); + return $this->emailValidator->isValid($data); case 'number': return is_numeric($data); case 'phone': diff --git a/lib/Settings/Settings.php b/lib/Settings/Settings.php index 5c2e26cda..d92d49c9f 100644 --- a/lib/Settings/Settings.php +++ b/lib/Settings/Settings.php @@ -17,10 +17,10 @@ class Settings implements ISettings { public function __construct( - private string $appName, - private ConfigService $configService, - private IGroupManager $groupManager, - private IInitialState $initialState, + private readonly string $appName, + private readonly ConfigService $configService, + private readonly IGroupManager $groupManager, + private readonly IInitialState $initialState, ) { } diff --git a/lib/Settings/SettingsSection.php b/lib/Settings/SettingsSection.php index a868c0e99..298cc1090 100644 --- a/lib/Settings/SettingsSection.php +++ b/lib/Settings/SettingsSection.php @@ -14,8 +14,8 @@ class SettingsSection implements IIconSection { public function __construct( - private IL10N $l10n, - private IURLGenerator $urlGenerator, + private readonly IL10N $l10n, + private readonly IURLGenerator $urlGenerator, ) { } diff --git a/rector.php b/rector.php new file mode 100644 index 000000000..bc086761a --- /dev/null +++ b/rector.php @@ -0,0 +1,26 @@ +withPaths([ + __DIR__ . '/appinfo', + __DIR__ . '/lib', + __DIR__ . '/tests', + ]) + // uncomment to reach your current PHP version + ->withPhpSets(php81: true) + ->withTypeCoverageLevel(0) + ->withDeadCodeLevel(0) + ->withCodeQualityLevel(0) + ->withSets([ + NextcloudSets::NEXTCLOUD_32, + ]); diff --git a/tests/Integration/Api/ApiV3Test.php b/tests/Integration/Api/ApiV3Test.php index 6f8f2bb9c..c90ef7bb0 100644 --- a/tests/Integration/Api/ApiV3Test.php +++ b/tests/Integration/Api/ApiV3Test.php @@ -272,7 +272,7 @@ public function tearDown(): void { // Small Wrapper for OCS-Response private function OcsResponse2Data($resp) { - $arr = json_decode($resp->getBody()->getContents(), true); + $arr = json_decode((string)$resp->getBody()->getContents(), true); return $arr['ocs']['data']; } @@ -827,7 +827,7 @@ public function testCreateNewQuestion(array $expected): void { // Check formId & order $this->assertEquals($this->testForms[0]['id'], $data['formId']); unset($data['formId']); - $this->assertEquals(sizeof($this->testForms[0]['questions']), $data['order']); + $this->assertEquals(count($this->testForms[0]['questions']), $data['order']); unset($data['order']); unset($data['id']); @@ -1321,7 +1321,7 @@ public static function dataExportSubmissions() { */ public function testExportSubmissions(string $expected) { $resp = $this->http->request('GET', "api/v3/forms/{$this->testForms[0]['id']}/submissions?fileFormat=csv"); - $data = substr($resp->getBody()->getContents(), 3); // Some strange Character removed at the beginning + $data = substr((string)$resp->getBody()->getContents(), 3); // Some strange Character removed at the beginning $this->assertEquals(200, $resp->getStatusCode()); $this->assertEquals('attachment; filename="Title of a Form (responses).csv"', $resp->getHeaders()['Content-Disposition'][0]); @@ -1567,7 +1567,7 @@ public static function dataDeleteSingleSubmission() { * @param array $submissionsExpected */ public function testDeleteSingleSubmission(array $submissionsExpected) { - $submissionsExpected['filteredSubmissionsCount'] = $submissionsExpected['filteredSubmissionsCount'] - 1; + $submissionsExpected['filteredSubmissionsCount'] -= 1; $resp = $this->http->request('DELETE', "api/v3/forms/{$this->testForms[0]['id']}/submissions/{$this->testForms[0]['submissions'][0]['id']}"); $data = $this->OcsResponse2Data($resp); diff --git a/tests/Integration/Api/RespectAdminSettingsTest.php b/tests/Integration/Api/RespectAdminSettingsTest.php index c616b3cc1..3d18e532a 100644 --- a/tests/Integration/Api/RespectAdminSettingsTest.php +++ b/tests/Integration/Api/RespectAdminSettingsTest.php @@ -187,7 +187,7 @@ public function tearDown(): void { // Small Wrapper for OCS-Response private function OcsResponse2Data($resp) { - $arr = json_decode($resp->getBody()->getContents(), true); + $arr = json_decode((string)$resp->getBody()->getContents(), true); return $arr['ocs']['data']; } diff --git a/tests/Integration/BackgroundJob/DeleteQuestionFoldersJobTest.php b/tests/Integration/BackgroundJob/DeleteQuestionFoldersJobTest.php index 061af3d9c..13bcae510 100644 --- a/tests/Integration/BackgroundJob/DeleteQuestionFoldersJobTest.php +++ b/tests/Integration/BackgroundJob/DeleteQuestionFoldersJobTest.php @@ -55,7 +55,7 @@ private function cleanupTestFolders(): void { if ($formsFolder instanceof \OCP\Files\Folder) { $formsFolder->delete(); } - } catch (NotFoundException $e) { + } catch (NotFoundException) { // Folder doesn't exist, nothing to clean up } } diff --git a/tests/Unit/Activity/FilterTest.php b/tests/Unit/Activity/FilterTest.php index ce9a1fba4..5514b859f 100644 --- a/tests/Unit/Activity/FilterTest.php +++ b/tests/Unit/Activity/FilterTest.php @@ -46,9 +46,7 @@ public function testGetIcon() { ->willReturn('apps/forms/img/forms-dark.svg'); $this->urlGenerator->expects($this->once()) ->method('getAbsoluteUrl') - ->will($this->returnCallback(function ($path) { - return 'http://localhost/' . $path; - })); + ->will($this->returnCallback(fn ($path) => 'http://localhost/' . $path)); $this->assertEquals('http://localhost/apps/forms/img/forms-dark.svg', $this->filter->getIcon()); } diff --git a/tests/Unit/Activity/ProviderTest.php b/tests/Unit/Activity/ProviderTest.php index 31323208b..f672062f7 100644 --- a/tests/Unit/Activity/ProviderTest.php +++ b/tests/Unit/Activity/ProviderTest.php @@ -35,12 +35,11 @@ class ProviderTest extends TestCase { private FormMapper|MockObject $formMapper; private IEventMerger|MockObject $eventMerger; private IGroupManager|MockObject $groupManager; - private IL10N|MockObject $l10n; private LoggerInterface|MockObject $logger; private IURLGenerator|MockObject $urlGenerator; private IUserManager|MockObject $userManager; private IFactory|MockObject $l10nFactory; - private IValidator|MockObject $validator; + private readonly IValidator|MockObject $validator; private CirclesService|MockObject $circlesService; public function setUp(): void { @@ -61,9 +60,7 @@ public function setUp(): void { ->willReturn('http://localhost/apps/forms/'); $this->urlGenerator->expects($this->any()) ->method('getAbsoluteUrl') - ->will($this->returnCallback(function (string $path) { - return 'http://localhost' . $path; - })); + ->will($this->returnCallback(fn (string $path) => 'http://localhost' . $path)); $this->urlGenerator->expects($this->any()) ->method('imagePath') ->willReturnMap([ @@ -80,11 +77,7 @@ public function setUp(): void { $this->urlGenerator, $this->userManager, $this->l10nFactory, - $this->validator, $this->circlesService); - - // Only for the test, Provider creates it from Factory - $this->l10n = $this->createMock(IL10N::class); } // Wrong app-name should be blocked @@ -103,9 +96,7 @@ public function testFullParse() { $l10n = $this->createMock(IL10N::class); $l10n->expects($this->once()) ->method('t') - ->will($this->returnCallback(function (string $identity) { - return $identity; - })); + ->will($this->returnCallback(fn (string $identity) => $identity)); $this->l10nFactory->expects($this->once()) ->method('get') ->willReturn($l10n); @@ -188,9 +179,7 @@ public function testGetSubjectString(string $subject, string $expected) { $l10n = $this->createMock(IL10N::class); $l10n->expects($this->once()) ->method('t') - ->will($this->returnCallback(function (string $identity) { - return $identity; - })); + ->will($this->returnCallback(fn (string $identity) => $identity)); $this->assertEquals($expected, $this->provider->getSubjectString($l10n, $subject)); } @@ -353,9 +342,7 @@ public function testGetAnonymousRichUser() { $l10n = $this->createMock(IL10N::class); $l10n->expects($this->any()) ->method('t') - ->will($this->returnCallback(function (string $identity) { - return $identity; - })); + ->will($this->returnCallback(fn (string $identity) => $identity)); $this->assertEquals([ 'type' => 'highlight', diff --git a/tests/Unit/Activity/Settings/FormsActivitySettingsTest.php b/tests/Unit/Activity/Settings/FormsActivitySettingsTest.php index 73022a4a2..eb6ab06e9 100644 --- a/tests/Unit/Activity/Settings/FormsActivitySettingsTest.php +++ b/tests/Unit/Activity/Settings/FormsActivitySettingsTest.php @@ -37,9 +37,7 @@ public function testGetGroupIdentifier() { public function testGetGroupName() { $this->l10n->expects($this->once()) ->method('t') - ->will($this->returnCallback(function ($identity) { - return $identity; - })); + ->will($this->returnCallback(fn ($identity) => $identity)); $this->assertEquals('Forms', $this->activitySettings->getGroupName()); } diff --git a/tests/Unit/Activity/Settings/NewShareTest.php b/tests/Unit/Activity/Settings/NewShareTest.php index 7a05c9e84..0d3053547 100644 --- a/tests/Unit/Activity/Settings/NewShareTest.php +++ b/tests/Unit/Activity/Settings/NewShareTest.php @@ -29,9 +29,7 @@ public function testGetGroupIdentifier() { public function testGetGroupName() { $this->l10n->expects($this->once()) ->method('t') - ->will($this->returnCallback(function ($identity) { - return $identity; - })); + ->will($this->returnCallback(fn ($identity) => $identity)); $this->assertEquals('Forms', $this->newShare->getGroupName()); } @@ -42,9 +40,7 @@ public function testGetIdentifier() { public function testGetName() { $this->l10n->expects($this->once()) ->method('t') - ->will($this->returnCallback(function ($identity) { - return $identity; - })); + ->will($this->returnCallback(fn ($identity) => $identity)); $this->assertEquals('A form has been shared with you', $this->newShare->getName()); } diff --git a/tests/Unit/Activity/Settings/NewSharedSubmissionTest.php b/tests/Unit/Activity/Settings/NewSharedSubmissionTest.php index 1e31db0a6..5a5500842 100644 --- a/tests/Unit/Activity/Settings/NewSharedSubmissionTest.php +++ b/tests/Unit/Activity/Settings/NewSharedSubmissionTest.php @@ -29,9 +29,7 @@ public function testGetGroupIdentifier() { public function testGetGroupName() { $this->l10n->expects($this->once()) ->method('t') - ->will($this->returnCallback(function ($identity) { - return $identity; - })); + ->will($this->returnCallback(fn ($identity) => $identity)); $this->assertEquals('Forms', $this->newShare->getGroupName()); } @@ -42,9 +40,7 @@ public function testGetIdentifier() { public function testGetName() { $this->l10n->expects($this->once()) ->method('t') - ->will($this->returnCallback(function ($identity) { - return $identity; - })); + ->will($this->returnCallback(fn ($identity) => $identity)); $this->assertEquals('Someone answered a shared form', $this->newShare->getName()); } diff --git a/tests/Unit/Activity/Settings/NewSubmissionTest.php b/tests/Unit/Activity/Settings/NewSubmissionTest.php index 5a9c2c557..e3f7f229a 100644 --- a/tests/Unit/Activity/Settings/NewSubmissionTest.php +++ b/tests/Unit/Activity/Settings/NewSubmissionTest.php @@ -29,9 +29,7 @@ public function testGetGroupIdentifier() { public function testGetGroupName() { $this->l10n->expects($this->once()) ->method('t') - ->will($this->returnCallback(function ($identity) { - return $identity; - })); + ->will($this->returnCallback(fn ($identity) => $identity)); $this->assertEquals('Forms', $this->newShare->getGroupName()); } @@ -42,9 +40,7 @@ public function testGetIdentifier() { public function testGetName() { $this->l10n->expects($this->once()) ->method('t') - ->will($this->returnCallback(function ($identity) { - return $identity; - })); + ->will($this->returnCallback(fn ($identity) => $identity)); $this->assertEquals('Someone answered a form', $this->newShare->getName()); } diff --git a/tests/Unit/Controller/ApiControllerTest.php b/tests/Unit/Controller/ApiControllerTest.php index a846facf2..49f0d2ad3 100644 --- a/tests/Unit/Controller/ApiControllerTest.php +++ b/tests/Unit/Controller/ApiControllerTest.php @@ -38,7 +38,6 @@ function is_uploaded_file(string|bool|null $filename) { use OCA\Forms\Db\OptionMapper; use OCA\Forms\Db\Question; use OCA\Forms\Db\QuestionMapper; -use OCA\Forms\Db\ShareMapper; use OCA\Forms\Db\Submission; use OCA\Forms\Db\SubmissionMapper; use OCA\Forms\Db\UploadedFileMapper; @@ -75,7 +74,6 @@ class ApiControllerTest extends TestCase { private FormMapper|MockObject $formMapper; private OptionMapper|MockObject $optionMapper; private QuestionMapper|MockObject $questionMapper; - private ShareMapper|MockObject $shareMapper; private SubmissionMapper|MockObject $submissionMapper; private ConfirmationEmailService|MockObject $confirmationEmailService; private ConfigService|MockObject $configService; @@ -95,7 +93,6 @@ public function setUp(): void { $this->formMapper = $this->createMock(FormMapper::class); $this->optionMapper = $this->createMock(OptionMapper::class); $this->questionMapper = $this->createMock(QuestionMapper::class); - $this->shareMapper = $this->createMock(ShareMapper::class); $this->submissionMapper = $this->createMock(SubmissionMapper::class); $this->confirmationEmailService = $this->createMock(ConfirmationEmailService::class); $this->configService = $this->createMock(ConfigService::class); @@ -107,9 +104,7 @@ public function setUp(): void { $this->l10n = $this->createMock(IL10N::class); $this->l10n->expects($this->any()) ->method('t') - ->willReturnCallback(function ($v) { - return $v; - }); + ->willReturnCallback(fn ($v) => $v); $this->storage = $this->createMock(IRootFolder::class); $this->uploadedFileMapper = $this->createMock(UploadedFileMapper::class); $this->mimeTypeDetector = $this->createMock(IMimeTypeDetector::class); @@ -123,7 +118,6 @@ public function setUp(): void { $this->formMapper, $this->optionMapper, $this->questionMapper, - $this->shareMapper, $this->submissionMapper, $this->confirmationEmailService, $this->configService, @@ -1243,9 +1237,7 @@ public function testUpdateQuestionClearsConfirmationEmailQuestionIdWhenQuestionS ->willReturn($question); $this->questionMapper->expects($this->once()) ->method('update') - ->with($this->callback(function (Question $updatedQuestion): bool { - return $updatedQuestion->getId() === 7; - })); + ->with($this->callback(fn (Question $updatedQuestion): bool => $updatedQuestion->getId() === 7)); $this->formMapper->expects($this->once()) ->method('update') @@ -1287,9 +1279,7 @@ public function testDeleteQuestionClearsConfirmationEmailQuestionIdWhenDeletingS ->willReturn([]); $this->questionMapper->expects($this->once()) ->method('update') - ->with($this->callback(function (Question $updatedQuestion): bool { - return $updatedQuestion->getId() === 7 && $updatedQuestion->getOrder() === 0; - })); + ->with($this->callback(fn (Question $updatedQuestion): bool => $updatedQuestion->getId() === 7 && $updatedQuestion->getOrder() === 0)); $this->formMapper->expects($this->once()) ->method('update') @@ -1334,9 +1324,7 @@ public function testCloneFormWithConfirmationEmailQuestionId(): void { $this->formMapper->expects($this->once()) ->method('update') - ->with($this->callback(function (Form $form) { - return $form->getId() === 14 && $form->getConfirmationEmailQuestionId() === 11; - })); + ->with($this->callback(fn (Form $form) => $form->getId() === 14 && $form->getConfirmationEmailQuestionId() === 11)); $this->apiController->newForm(7); $this->assertEquals(11, $clonedForm->getConfirmationEmailQuestionId()); diff --git a/tests/Unit/Controller/ShareApiControllerTest.php b/tests/Unit/Controller/ShareApiControllerTest.php index 6ba55602b..500dc3de2 100644 --- a/tests/Unit/Controller/ShareApiControllerTest.php +++ b/tests/Unit/Controller/ShareApiControllerTest.php @@ -35,7 +35,6 @@ use OCP\IRequest; use OCP\IUser; use OCP\IUserManager; -use OCP\IUserSession; use OCP\Security\ISecureRandom; use OCP\Share\IManager; use OCP\Share\IShare; @@ -73,18 +72,9 @@ public function setUp(): void { $this->logger = $this->createMock(LoggerInterface::class); $this->request = $this->createMock(IRequest::class); $this->userManager = $this->createMock(IUserManager::class); - $userSession = $this->createMock(IUserSession::class); $this->secureRandom = $this->createMock(ISecureRandom::class); $this->circlesService = $this->createMock(CirclesService::class); - $user = $this->createMock(IUser::class); - $user->expects($this->any()) - ->method('getUID') - ->willReturn('currentUser'); - $userSession->expects($this->once()) - ->method('getUser') - ->willReturn($user); - $this->rootFolder = $this->createMock(IRootFolder::class); $this->filePathHelper = new FilePathHelper($this->rootFolder); $this->shareManager = $this->createMock(IManager::class); @@ -92,7 +82,6 @@ public function setUp(): void { $this->shareApiController = new ShareApiController( 'forms', $this->request, - $userSession, $this->formMapper, $this->shareMapper, $this->configService, @@ -876,9 +865,7 @@ public function testUpdateShare(array $share, string $formOwner, array $keyValue $this->shareMapper->expects($exception === null ? $this->once() : $this->any()) ->method('update') ->with($shareEntity) - ->willReturnCallback(function ($arg) { - return $arg; - }); + ->willReturnCallback(fn ($arg) => $arg); if ($exception === null) { $expectedResponse = new DataResponse($expected); diff --git a/tests/Unit/FormsMigratorTest.php b/tests/Unit/FormsMigratorTest.php index 54219901a..a380cc464 100644 --- a/tests/Unit/FormsMigratorTest.php +++ b/tests/Unit/FormsMigratorTest.php @@ -235,7 +235,7 @@ public function testExport(string $expectedJson) { $exportDestination->expects($this->once()) ->method('addFileContents') - ->will($this->returnCallback(function ($path, $jsonData) use ($expectedJson) { + ->will($this->returnCallback(function ($path, $jsonData) use ($expectedJson): void { $this->assertJsonStringEqualsJsonString($expectedJson, $jsonData); })); $this->formsMigrator->export($user, $exportDestination, $output); diff --git a/tests/Unit/Service/ConfigServiceTest.php b/tests/Unit/Service/ConfigServiceTest.php index 66f3b1ca0..5f058bfbc 100644 --- a/tests/Unit/Service/ConfigServiceTest.php +++ b/tests/Unit/Service/ConfigServiceTest.php @@ -116,7 +116,7 @@ public function testGetAppConfig(array $strConfig, array $groupDisplayNames, arr if (!array_key_exists($configKey, $strConfig)) { return $defaultVal; } - return json_decode($strConfig[$configKey], true); + return json_decode((string)$strConfig[$configKey], true); })); $this->config->expects($this->any()) @@ -181,15 +181,11 @@ public function testGetAppConfig_Default(array $expected) { // Default Values are set within getAppValue, thus returning this one. $this->appConfig->expects($this->any()) ->method('getAppValueBool') - ->will($this->returnCallback(function ($configKey, $defaultVal) { - return $defaultVal; - })); + ->will($this->returnCallback(fn ($configKey, $defaultVal) => $defaultVal)); $this->appConfig->expects($this->any()) ->method('getAppValueArray') - ->will($this->returnCallback(function ($configKey, $defaultVal) { - return $defaultVal; - })); + ->will($this->returnCallback(fn ($configKey, $defaultVal) => $defaultVal)); $this->config->expects($this->any()) ->method('getSystemValue') @@ -240,15 +236,11 @@ public static function dataCanCreateForms() { public function testCanCreateForms(array $config, bool $expected) { $this->appConfig->expects($this->any()) ->method('getAppValueBool') - ->will($this->returnCallback(function ($configKey, $defaultVal) use ($config) { - return $config[$configKey]; - })); + ->will($this->returnCallback(fn ($configKey, $defaultVal) => $config[$configKey])); $this->appConfig->expects($this->any()) ->method('getAppValueArray') - ->will($this->returnCallback(function ($configKey, $defaultVal) use ($config) { - return isset($config[$configKey]) ? json_decode($config[$configKey], true) : $defaultVal; - })); + ->will($this->returnCallback(fn ($configKey, $defaultVal) => isset($config[$configKey]) ? json_decode($config[$configKey], true) : $defaultVal)); $this->groupManager->expects($this->any()) ->method('getUserGroupIds') diff --git a/tests/Unit/Service/SubmissionServiceTest.php b/tests/Unit/Service/SubmissionServiceTest.php index fc6c89d6b..08266087b 100644 --- a/tests/Unit/Service/SubmissionServiceTest.php +++ b/tests/Unit/Service/SubmissionServiceTest.php @@ -34,7 +34,7 @@ use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; -use OCP\Mail\IMailer; +use OCP\Mail\IEmailValidator; use PhpOffice\PhpSpreadsheet\Cell\DataType; use PhpOffice\PhpSpreadsheet\Spreadsheet; use PHPUnit\Framework\MockObject\MockObject; @@ -53,7 +53,7 @@ class SubmissionServiceTest extends TestCase { private IL10N|MockObject $l10n; private LoggerInterface|MockObject $logger; private IUserManager|MockObject $userManager; - private IMailer|MockObject $mailer; + private IEmailValidator|MockObject $emailValidator; private ITempManager|MockObject $tempManager; private FormsService|MockObject $formsService; private IURLGenerator|MockObject $urlGenerator; @@ -70,7 +70,7 @@ public function setUp(): void { $this->config = $this->createMock(IConfig::class); $this->l10n = $this->createMock(IL10N::class); $this->logger = $this->createMock(LoggerInterface::class); - $this->mailer = $this->getMockBuilder(IMailer::class)->getMock(); + $this->emailValidator = $this->getMockBuilder(IEmailValidator::class)->getMock(); $this->userManager = $this->createMock(IUserManager::class); $userSession = $this->createMock(IUserSession::class); $this->tempManager = $this->createMock(ITempManager::class); @@ -85,9 +85,7 @@ public function setUp(): void { $this->l10n->expects($this->any()) ->method('t') - ->will($this->returnCallback(function (string $identity) { - return $identity; - })); + ->will($this->returnCallback(fn (string $identity) => $identity)); $this->formsService = $this->createMock(FormsService::class); $this->urlGenerator = $this->createMock(IURLGenerator::class); @@ -106,11 +104,11 @@ public function setUp(): void { $this->logger, $this->userManager, $userSession, - $this->mailer, $this->tempManager, $this->formsService, $this->urlGenerator, $this->optionMapper, + $this->emailValidator, ); } @@ -741,9 +739,7 @@ private function setUpCsvTest(array $questions, array $submissions, string $csvT ->method('findByQuestion') ->with($questions[0]['id']) ->willReturnCallback(function (int $questionId) use ($questions) { - $optionsEntities = array_map(function ($option) { - return Option::fromParams($option); - }, $questions[0]['options']); + $optionsEntities = array_map(fn ($option) => Option::fromParams($option), $questions[0]['options']); return $optionsEntities; }); @@ -778,19 +774,15 @@ private function setUpCsvTest(array $questions, array $submissions, string $csvT ->method('findBySubmission') // Return AnswerObjects for corresponding submission ->will($this->returnCallback(function (int $submissionId) use ($submissions) { - $matchingSubmission = array_filter($submissions, function ($submission) use ($submissionId) { - return $submission['id'] === $submissionId; - }); + $matchingSubmission = array_filter($submissions, fn ($submission) => $submission['id'] === $submissionId); - $answerEntities = array_map(function ($answer) { - return Answer::fromParams($answer); - }, current($matchingSubmission)['answers']); + $answerEntities = array_map(fn ($answer) => Answer::fromParams($answer), current($matchingSubmission)['answers']); return $answerEntities; })); // Prepend BOM-Sequence as Writer does and remove formatting-artefacts of dataProvider. - $dataExpectation = chr(239) . chr(187) . chr(191) . ltrim(preg_replace('/\t+/', '', $csvText)); + $dataExpectation = chr(239) . chr(187) . chr(191) . ltrim((string)preg_replace('/\t+/', '', $csvText)); return $dataExpectation; } @@ -1362,9 +1354,7 @@ public static function dataValidateSubmission() { * @param null|string $expected */ public function testValidateSubmission(array $questions, array $answers, ?string $expected) { - $this->mailer->method('validateMailAddress')->willReturnCallback(function ($mail) { - return $mail === 'some.name+context@example.com'; - }); + $this->emailValidator->method('isValid')->willReturnCallback(fn ($mail) => $mail === 'some.name+context@example.com'); if ($expected !== null) { $this->expectException(\InvalidArgumentException::class); diff --git a/vendor-bin/rector/composer.json b/vendor-bin/rector/composer.json new file mode 100644 index 000000000..26ec3b866 --- /dev/null +++ b/vendor-bin/rector/composer.json @@ -0,0 +1,6 @@ +{ + "require-dev": { + "rector/rector": "^2.4", + "nextcloud/rector": "^0.5.1" + } +} diff --git a/vendor-bin/rector/composer.lock b/vendor-bin/rector/composer.lock new file mode 100644 index 000000000..dcb3ad235 --- /dev/null +++ b/vendor-bin/rector/composer.lock @@ -0,0 +1,621 @@ +{ + "_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": "a161b87444bbfb4eb08901e001a473bb", + "packages": [], + "packages-dev": [ + { + "name": "nextcloud/ocp", + "version": "v34.0.0", + "source": { + "type": "git", + "url": "https://github.com/nextcloud-deps/ocp.git", + "reference": "1ce31d2ac587e22269fedd9d5b231c4380d8c5af" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nextcloud-deps/ocp/zipball/1ce31d2ac587e22269fedd9d5b231c4380d8c5af", + "reference": "1ce31d2ac587e22269fedd9d5b231c4380d8c5af", + "shasum": "" + }, + "require": { + "php": "~8.1 || ~8.2 || ~8.3 || ~8.4 || ~8.5", + "psr/clock": "^1.0", + "psr/container": "^2.0.2", + "psr/event-dispatcher": "^1.0", + "psr/http-client": "^1.0.3", + "psr/log": "^3.0.2" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-stable34": "34.0.0-dev" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "AGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Christoph Wurst", + "email": "christoph@winzerhof-wurst.at" + }, + { + "name": "Joas Schilling", + "email": "coding@schilljs.com" + } + ], + "description": "Composer package containing Nextcloud's public OCP API and the unstable NCU API", + "support": { + "issues": "https://github.com/nextcloud-deps/ocp/issues", + "source": "https://github.com/nextcloud-deps/ocp/tree/v34.0.0" + }, + "time": "2026-06-04T02:37:14+00:00" + }, + { + "name": "nextcloud/rector", + "version": "v0.5.1", + "source": { + "type": "git", + "url": "https://github.com/nextcloud-libraries/rector.git", + "reference": "d9c4cf53d9bce0fa95edc87cb093307958317e28" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/nextcloud-libraries/rector/zipball/d9c4cf53d9bce0fa95edc87cb093307958317e28", + "reference": "d9c4cf53d9bce0fa95edc87cb093307958317e28", + "shasum": "" + }, + "require": { + "nextcloud/ocp": ">=27", + "php": "^8.1", + "rector/rector": "^2.0.4", + "webmozart/assert": "^1.11" + }, + "require-dev": { + "phpunit/phpunit": "^10.5", + "ramsey/devtools": "^2.0" + }, + "type": "library", + "extra": { + "captainhook": { + "force-install": true + }, + "ramsey/devtools": { + "memory-limit": "-1", + "command-prefix": "dev" + }, + "ramsey/conventional-commits": { + "configFile": "conventional-commits.json" + } + }, + "autoload": { + "psr-4": { + "OCP\\": "vendor/nextcloud/ocp/OCP", + "Nextcloud\\Rector\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "AGPL-3.0-or-later" + ], + "authors": [ + { + "name": "Christoph Wurst", + "email": "christoph@winzerhof-wurst.at", + "homepage": "https://wuc.me" + } + ], + "description": "Rector upgrade rules for Nextcloud", + "keywords": [ + "nextcloud", + "refactoring" + ], + "support": { + "issues": "https://github.com/nextcloud-libraries/rector/issues", + "source": "https://github.com/nextcloud-libraries/rector/tree/v0.5.1" + }, + "time": "2026-05-08T07:32:27+00:00" + }, + { + "name": "phpstan/phpstan", + "version": "2.2.2", + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/e5cc34d491a90e79c216d824f60fe21fd4d93bd6", + "reference": "e5cc34d491a90e79c216d824f60fe21fd4d93bd6", + "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-06-05T09:00:01+00:00" + }, + { + "name": "psr/clock", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/clock.git", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/clock/zipball/e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "reference": "e41a24703d4560fd0acb709162f73b8adfc3aa0d", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Psr\\Clock\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for reading the clock.", + "homepage": "https://github.com/php-fig/clock", + "keywords": [ + "clock", + "now", + "psr", + "psr-20", + "time" + ], + "support": { + "issues": "https://github.com/php-fig/clock/issues", + "source": "https://github.com/php-fig/clock/tree/1.0.0" + }, + "time": "2022-11-25T14:36:26+00:00" + }, + { + "name": "psr/container", + "version": "2.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/container.git", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/container/zipball/c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "reference": "c71ecc56dfe541dbd90c5360474fbc405f8d5963", + "shasum": "" + }, + "require": { + "php": ">=7.4.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Container\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common Container Interface (PHP FIG PSR-11)", + "homepage": "https://github.com/php-fig/container", + "keywords": [ + "PSR-11", + "container", + "container-interface", + "container-interop", + "psr" + ], + "support": { + "issues": "https://github.com/php-fig/container/issues", + "source": "https://github.com/php-fig/container/tree/2.0.2" + }, + "time": "2021-11-05T16:47:00+00:00" + }, + { + "name": "psr/event-dispatcher", + "version": "1.0.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/event-dispatcher.git", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/event-dispatcher/zipball/dbefd12671e8a14ec7f180cab83036ed26714bb0", + "reference": "dbefd12671e8a14ec7f180cab83036ed26714bb0", + "shasum": "" + }, + "require": { + "php": ">=7.2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\EventDispatcher\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" + } + ], + "description": "Standard interfaces for event handling.", + "keywords": [ + "events", + "psr", + "psr-14" + ], + "support": { + "issues": "https://github.com/php-fig/event-dispatcher/issues", + "source": "https://github.com/php-fig/event-dispatcher/tree/1.0.0" + }, + "time": "2019-01-08T18:20:26+00:00" + }, + { + "name": "psr/http-client", + "version": "1.0.3", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-client.git", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-client/zipball/bb5906edc1c324c9a05aa0873d40117941e5fa90", + "reference": "bb5906edc1c324c9a05aa0873d40117941e5fa90", + "shasum": "" + }, + "require": { + "php": "^7.0 || ^8.0", + "psr/http-message": "^1.0 || ^2.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP clients", + "homepage": "https://github.com/php-fig/http-client", + "keywords": [ + "http", + "http-client", + "psr", + "psr-18" + ], + "support": { + "source": "https://github.com/php-fig/http-client" + }, + "time": "2023-09-23T14:17:50+00:00" + }, + { + "name": "psr/http-message", + "version": "2.0", + "source": { + "type": "git", + "url": "https://github.com/php-fig/http-message.git", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "reference": "402d35bcb92c70c026d1a6a9883f06b2ead23d71", + "shasum": "" + }, + "require": { + "php": "^7.2 || ^8.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Http\\Message\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", + "keywords": [ + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" + ], + "support": { + "source": "https://github.com/php-fig/http-message/tree/2.0" + }, + "time": "2023-04-04T09:54:51+00:00" + }, + { + "name": "psr/log", + "version": "3.0.2", + "source": { + "type": "git", + "url": "https://github.com/php-fig/log.git", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/php-fig/log/zipball/f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "reference": "f16e1d5863e37f8d8c2a01719f5b34baa2b714d3", + "shasum": "" + }, + "require": { + "php": ">=8.0.0" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, + "autoload": { + "psr-4": { + "Psr\\Log\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "PHP-FIG", + "homepage": "https://www.php-fig.org/" + } + ], + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", + "keywords": [ + "log", + "psr", + "psr-3" + ], + "support": { + "source": "https://github.com/php-fig/log/tree/3.0.2" + }, + "time": "2024-09-11T13:17:53+00:00" + }, + { + "name": "rector/rector", + "version": "2.4.5", + "source": { + "type": "git", + "url": "https://github.com/rectorphp/rector.git", + "reference": "cbd86024be5014d3c14d9f0b3f7aae8ecbffd62c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/rectorphp/rector/zipball/cbd86024be5014d3c14d9f0b3f7aae8ecbffd62c", + "reference": "cbd86024be5014d3c14d9f0b3f7aae8ecbffd62c", + "shasum": "" + }, + "require": { + "php": "^7.4|^8.0", + "phpstan/phpstan": "^2.1.56" + }, + "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.4.5" + }, + "funding": [ + { + "url": "https://github.com/tomasvotruba", + "type": "github" + } + ], + "time": "2026-05-26T21:03:22+00:00" + }, + { + "name": "webmozart/assert", + "version": "1.12.1", + "source": { + "type": "git", + "url": "https://github.com/webmozarts/assert.git", + "reference": "9be6926d8b485f55b9229203f962b51ed377ba68" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/webmozarts/assert/zipball/9be6926d8b485f55b9229203f962b51ed377ba68", + "reference": "9be6926d8b485f55b9229203f962b51ed377ba68", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-date": "*", + "ext-filter": "*", + "php": "^7.2 || ^8.0" + }, + "suggest": { + "ext-intl": "", + "ext-simplexml": "", + "ext-spl": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.10-dev" + } + }, + "autoload": { + "psr-4": { + "Webmozart\\Assert\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Bernhard Schussek", + "email": "bschussek@gmail.com" + } + ], + "description": "Assertions to validate method input/output with nice error messages.", + "keywords": [ + "assert", + "check", + "validate" + ], + "support": { + "issues": "https://github.com/webmozarts/assert/issues", + "source": "https://github.com/webmozarts/assert/tree/1.12.1" + }, + "time": "2025-10-29T15:56:20+00:00" + } + ], + "aliases": [], + "minimum-stability": "stable", + "stability-flags": {}, + "prefer-stable": false, + "prefer-lowest": false, + "platform": {}, + "platform-dev": {}, + "plugin-api-version": "2.9.0" +}