diff --git a/composer.json b/composer.json index bd0b66b4a4..7f116c332d 100644 --- a/composer.json +++ b/composer.json @@ -48,7 +48,7 @@ "psalm": "psalm --no-diff", "test:unit": "phpunit -c tests/phpunit.xml", "test:integration": "phpunit -c tests/phpunit.xml", - "psalm:fix": "psalm --alter --php-version=8.1 --issues=MissingReturnType,InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockParamType,MismatchingDocblockReturnType,MissingParamType,InvalidFalsableReturnType", + "psalm:fix": "psalm --alter --issues=MissingReturnType,InvalidReturnType,InvalidNullableReturnType,MismatchingDocblockParamType,MismatchingDocblockReturnType,MissingParamType,InvalidFalsableReturnType", "psalm:info": "psalm --no-diff --show-info=true", "psalm:baseline": "psalm --set-baseline=psalm-baseline.xml", "psalm:baseline:update": "psalm --update-baseline", diff --git a/lib/Controller/BaseApiV2Controller.php b/lib/Controller/BaseApiV2Controller.php index 7fde8862b5..c81d30fae8 100644 --- a/lib/Controller/BaseApiV2Controller.php +++ b/lib/Controller/BaseApiV2Controller.php @@ -5,7 +5,6 @@ * SPDX-FileCopyrightText: 2024 Nextcloud contributors * SPDX-License-Identifier: AGPL-3.0-or-later */ - namespace OCA\Polls\Controller; use Closure; @@ -21,6 +20,7 @@ /** * @psalm-api + * @psalm-import-type HttpStatusCode from \OCA\Polls\Types */ class BaseApiV2Controller extends OCSController { public function __construct( @@ -36,6 +36,7 @@ public function __construct( /** * response * @param Closure $callback Callback function + * @psalm-param HttpStatusCode $successStatus HTTP status code for success */ #[NoAdminRequired] protected function response(Closure $callback, int $successStatus = Http::STATUS_OK): DataResponse { @@ -48,7 +49,7 @@ protected function response(Closure $callback, int $successStatus = Http::STATUS } catch (Exception $e) { if ($e->getStatus() === Http::STATUS_NOT_MODIFIED) { - return new DataResponse(statusCode: $e->getStatus()); + return new DataResponse(statusCode: Http::STATUS_NOT_MODIFIED); } throw new OCSBadRequestException($e->getMessage()); diff --git a/lib/Controller/BaseController.php b/lib/Controller/BaseController.php index ce281660f3..893992b77d 100644 --- a/lib/Controller/BaseController.php +++ b/lib/Controller/BaseController.php @@ -18,6 +18,7 @@ /** * @psalm-api + * @psalm-import-type HttpStatusCode from \OCA\Polls\Types */ class BaseController extends Controller { public function __construct( @@ -30,7 +31,7 @@ public function __construct( /** * response * @param Closure $callback Callback function - * @param int $successStatus HTTP status code for success + * @psalm-param HttpStatusCode $successStatus HTTP status code for success */ #[NoAdminRequired] protected function response( @@ -42,10 +43,12 @@ protected function response( } catch (Exception $e) { if ($e->getStatus() === Http::STATUS_NOT_MODIFIED) { - return new JSONResponse(statusCode: $e->getStatus()); + return new JSONResponse(statusCode: Http::STATUS_NOT_MODIFIED); } - return new JSONResponse(['message' => $e->getMessage()], $e->getStatus()); + /** @var HttpStatusCode $status */ + $status = $e->getStatus(); + return new JSONResponse(['message' => $e->getMessage()], $status); } } diff --git a/lib/Controller/SystemController.php b/lib/Controller/SystemController.php index bbc011cbc3..6afdc02df0 100644 --- a/lib/Controller/SystemController.php +++ b/lib/Controller/SystemController.php @@ -36,7 +36,8 @@ public function __construct( #[OpenAPI(OpenAPI::SCOPE_IGNORE)] #[FrontpageRoute(verb: 'GET', url: '/search/users/{query}')] public function userSearch(string $query, string $types): JSONResponse { - $types = explode(',', $types); + $types = array_map('intval', explode(',', $types)); + // $types = explode(',', $types); return new JSONResponse([ 'siteusers' => $this->systemService->getSiteUsersAndGroups($query, $types), 'types' => $types diff --git a/lib/Exceptions/DuplicateEntryException.php b/lib/Exceptions/DuplicateEntryException.php deleted file mode 100644 index a62f322303..0000000000 --- a/lib/Exceptions/DuplicateEntryException.php +++ /dev/null @@ -1,19 +0,0 @@ -getCoreLimitSharingGroups(); - if ($groupExceptionMode === 'allowGroup') { - // exception mode is 'Limit sharing to some groups' - // if user is in exception group, allow share creation - return $this->userSession->getCurrentUser()->getIsInGroupArray($exceptionGroups); - } elseif ($groupExceptionMode === 'denyGroup') { + if ($groupExceptionMode === 'denyGroup') { // exception mode is 'Exclude some Groups from sharing' // if user is in exception group, deny share creation return !$this->userSession->getCurrentUser()->getIsInGroupArray($exceptionGroups); } - return true; + // exception mode is 'Limit sharing to some groups' + // if user is in exception group, allow share creation + return $this->userSession->getCurrentUser()->getIsInGroupArray($exceptionGroups); } /** * Get share group exception mode - * @return string + * @return 'open'|'closed'|'archived' * @psalm-return 'denyGroup'|'allowGroup'|'off' * Take value from the core setting 'shareapi_exclude_groups' and translate * 'yes' => 'denyGroup' ('Exclude some groups from sharing') existing groups are handeled as deny groups diff --git a/lib/Service/MailService.php b/lib/Service/MailService.php index c21f0c41a9..4e8d214ae7 100644 --- a/lib/Service/MailService.php +++ b/lib/Service/MailService.php @@ -100,8 +100,7 @@ public static function extractEmailAddressAndName($eMailString): array { preg_match(self::REGEX_PARSE_MAIL_AND_NAME, $eMailString, $matches); // Check if the found element is a valid email address - $emailAddress = !empty($matches[1]) ? trim($matches[1]) : null; - + $emailAddress = (isset($matches[1]) && trim($matches[1]) !== '') ? trim($matches[1]) : null; if ($emailAddress !== null && filter_var($emailAddress, FILTER_VALIDATE_EMAIL)) { // Extract the name based on the input string $displayName = trim(str_replace(['<', '>'], '', str_replace($emailAddress, '', $eMailString))); diff --git a/lib/Service/OptionService.php b/lib/Service/OptionService.php index 3990a989bd..f5031bd9f1 100644 --- a/lib/Service/OptionService.php +++ b/lib/Service/OptionService.php @@ -20,7 +20,6 @@ use OCA\Polls\Event\OptionUnconfirmedEvent; use OCA\Polls\Event\OptionUpdatedEvent; use OCA\Polls\Event\PollOptionReorderedEvent; -use OCA\Polls\Exceptions\DuplicateEntryException; use OCA\Polls\Exceptions\InvalidPollTypeException; use OCA\Polls\Model\Sequence; use OCA\Polls\Model\SimpleOption; @@ -168,11 +167,7 @@ public function addBulk(int $pollId, string $bulkText = ''): array { foreach ($newOptionsTexts as $pollOptionText) { if ($pollOptionText) { - try { - $this->add($pollId, new SimpleOption($pollOptionText, 0)); - } catch (DuplicateEntryException $e) { - continue; - } + $this->add($pollId, new SimpleOption($pollOptionText, 0)); } } diff --git a/lib/Service/PollService.php b/lib/Service/PollService.php index c3ccc09789..0205037946 100644 --- a/lib/Service/PollService.php +++ b/lib/Service/PollService.php @@ -135,9 +135,9 @@ public function takeover(int $pollId, ?UserBase $targetUser = null): Poll { /** * Transfer ownership of a poll * @param int|Poll $poll poll or pollId of poll to transfer ownership - * @param null|string|UserBase $targetUser User to transfer polls to. If null the current user will be used + * @param string|UserBase $targetUser User to transfer polls to. If null the current user will be used */ - public function transferPoll(int|Poll $poll, null|string|UserBase $targetUser): Poll { + public function transferPoll(int|Poll $poll, string|UserBase $targetUser): Poll { if (!($poll instanceof Poll)) { $poll = $this->pollMapper->find($poll); } @@ -145,10 +145,12 @@ public function transferPoll(int|Poll $poll, null|string|UserBase $targetUser): $poll->request(Poll::PERMISSION_POLL_CHANGE_OWNER); if (!($targetUser instanceof UserBase)) { + $userId = $targetUser; try { - $targetUser = $this->userMapper->getUserFromUserBase($targetUser); + $targetUser = $this->userMapper->getUserFromUserBase($userId); } catch (UserNotFoundException $e) { - throw new InvalidUsernameException('The user id "' . $targetUser . '" for the target user is not valid.'); + // to keep psalm quiet + throw new InvalidUsernameException('The user id "' . $userId . '" for the target user is not valid.'); } } diff --git a/lib/Service/SystemService.php b/lib/Service/SystemService.php index 47498c1b3e..d6be7a849a 100644 --- a/lib/Service/SystemService.php +++ b/lib/Service/SystemService.php @@ -70,6 +70,7 @@ public function getGroups(string $query = ''): array { /** * Get a combined list of users, groups, circles, contact groups and contacts * + * @param list $types list of types to search for * @return (Circle|Email|Group|User|Contact|ContactGroup|mixed)[] * * @psalm-return array diff --git a/lib/Types.php b/lib/Types.php new file mode 100644 index 0000000000..ed51861fbf --- /dev/null +++ b/lib/Types.php @@ -0,0 +1,19 @@ + - - - - - - - - circle]]> - - - diff --git a/psalm.xml b/psalm.xml index 4f35d3b71e..1fa846a343 100644 --- a/psalm.xml +++ b/psalm.xml @@ -13,6 +13,7 @@ cacheDirectory=".psalm.cache" findUnusedBaselineEntry="true" findUnusedCode="true" + phpVersion="8.1" > @@ -23,6 +24,9 @@ + + + diff --git a/stubs/circles-stubs.php b/stubs/circles-stubs.php new file mode 100644 index 0000000000..d5cb5457b5 --- /dev/null +++ b/stubs/circles-stubs.php @@ -0,0 +1,16 @@ +