Skip to content

Conversation

mnocon
Copy link
Contributor

@mnocon mnocon commented Jun 3, 2025

Target: 5.0

PHPStan is failing on 5.0:

~/Desktop/repos/ibexa/documentation-developer fix-5.0-samples *1 ❯ composer phpstan                                                                                                                        10:48:44
> phpstan analyse
Note: Using configuration file /Users/marek/Desktop/repos/ibexa/documentation-developer/phpstan.neon.
 223/223 [▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓] 100%

 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  Line   back_office/limitation/src/Security/Limitation/CustomLimitationType.php
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  79     Return type mixed of method App\Security\Limitation\CustomLimitationType::valueSchema() is not covariant with return type array|int of method Ibexa\Contracts\Core\Limitation\Type::valueSchema().
 ------ ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 [ERROR] Found 1 error

Script phpstan analyse handling the phpstan event returned with error code 1

I feel never is the right keyword to use here: https://www.php.net/manual/en/language.types.never.php

@mnocon mnocon marked this pull request as ready for review June 3, 2025 08:51
@mnocon mnocon requested a review from a team June 3, 2025 08:51
@ezrobot ezrobot requested review from Steveb-p, ViniTou, adamwojs, alongosz, barw4, ciastektk, konradoboza, mikadamczyk, tbialcz and wiewiurdp and removed request for a team June 3, 2025 08:52
@mnocon mnocon changed the title Added missing return type [5.0] Added missing return type Jun 3, 2025
Copy link

github-actions bot commented Jun 3, 2025

Preview of modified files: no change to preview.

Copy link

github-actions bot commented Jun 3, 2025

code_samples/ change report

Before (on target branch)After (in current PR)

code_samples/back_office/limitation/src/Security/Limitation/CustomLimitationType.php

docs/permissions/custom_policies.md@161:```php
docs/permissions/custom_policies.md@162:[[= include_file('code_samples/back_office/limitation/src/Security/Limitation/CustomLimitationType.php') =]]
docs/permissions/custom_policies.md@163:```

001⫶<?php
002⫶
003⫶declare(strict_types=1);
004⫶
005⫶namespace App\Security\Limitation;
006⫶
007⫶use Ibexa\Contracts\Core\Limitation\Type;
008⫶use Ibexa\Contracts\Core\Repository\Exceptions\NotImplementedException;
009⫶use Ibexa\Contracts\Core\Repository\Values\Content\Query\CriterionInterface;
010⫶use Ibexa\Contracts\Core\Repository\Values\User\Limitation;
011⫶use Ibexa\Contracts\Core\Repository\Values\User\UserReference;
012⫶use Ibexa\Contracts\Core\Repository\Values\ValueObject;
013⫶use Ibexa\Core\Base\Exceptions\InvalidArgumentException;
014⫶use Ibexa\Core\Base\Exceptions\InvalidArgumentType;
015⫶use Ibexa\Core\FieldType\ValidationError;
016⫶
017⫶class CustomLimitationType implements Type
018⫶{
019⫶ public function acceptValue(Limitation $limitationValue): void
020⫶ {
021⫶ if (!$limitationValue instanceof CustomLimitationValue) {
022⫶ throw new InvalidArgumentType(
023⫶ '$limitationValue',
024⫶ CustomLimitationValue::class,
025⫶ $limitationValue
026⫶ );
027⫶ }
028⫶ }
029⫶
030⫶ /** @return \Ibexa\Core\FieldType\ValidationError[] */
031⫶ public function validate(Limitation $limitationValue): array
032⫶ {
033⫶ $validationErrors = [];
034⫶ if (!array_key_exists('value', $limitationValue->limitationValues)) {
035⫶ $validationErrors[] = new ValidationError("limitationValues['value'] is missing.");
036⫶ } elseif (!is_bool($limitationValue->limitationValues['value'])) {
037⫶ $validationErrors[] = new ValidationError("limitationValues['value'] is not a boolean.");
038⫶ }
039⫶
040⫶ return $validationErrors;
041⫶ }
042⫶
043⫶ public function buildValue(array $limitationValues): CustomLimitationValue
044⫶ {
045⫶ $value = false;
046⫶ if (array_key_exists('value', $limitationValues)) {
047⫶ $value = $limitationValues['value'];
048⫶ } elseif (count($limitationValues)) {
049⫶ $value = (bool)$limitationValues[0];
050⫶ }
051⫶
052⫶ return new CustomLimitationValue(['limitationValues' => ['value' => $value]]);
053⫶ }
054⫶
055⫶ /**
056⫶ * @param \Ibexa\Contracts\Core\Repository\Values\ValueObject[]|null $targets
057⫶ *
058⫶ * @return bool|null
059⫶ */
060⫶ public function evaluate(Limitation $value, UserReference $currentUser, ValueObject $object, array $targets = null): ?bool
061⫶ {
062⫶ if (!$value instanceof CustomLimitationValue) {
063⫶ throw new InvalidArgumentException('$value', 'Must be of type: CustomLimitationValue');
064⫶ }
065⫶
066⫶ if ($value->limitationValues['value']) {
067⫶ return Type::ACCESS_GRANTED;
068⫶ }
069⫶
070⫶ // If the limitation value is not set to `true`, then $currentUser, $object and/or $targets could be challenged to determine if the access is granted or not; Here or elsewhere. When passing the baton, a limitation can return Type::ACCESS_ABSTAIN
071⫶ return Type::ACCESS_DENIED;
072⫶ }
073⫶
074⫶ public function getCriterion(Limitation $value, UserReference $currentUser): CriterionInterface
075⫶ {
076⫶ throw new NotImplementedException(__METHOD__);
077⫶ }
078⫶

code_samples/back_office/limitation/src/Security/Limitation/CustomLimitationType.php

docs/permissions/custom_policies.md@161:```php
docs/permissions/custom_policies.md@162:[[= include_file('code_samples/back_office/limitation/src/Security/Limitation/CustomLimitationType.php') =]]
docs/permissions/custom_policies.md@163:```

001⫶<?php
002⫶
003⫶declare(strict_types=1);
004⫶
005⫶namespace App\Security\Limitation;
006⫶
007⫶use Ibexa\Contracts\Core\Limitation\Type;
008⫶use Ibexa\Contracts\Core\Repository\Exceptions\NotImplementedException;
009⫶use Ibexa\Contracts\Core\Repository\Values\Content\Query\CriterionInterface;
010⫶use Ibexa\Contracts\Core\Repository\Values\User\Limitation;
011⫶use Ibexa\Contracts\Core\Repository\Values\User\UserReference;
012⫶use Ibexa\Contracts\Core\Repository\Values\ValueObject;
013⫶use Ibexa\Core\Base\Exceptions\InvalidArgumentException;
014⫶use Ibexa\Core\Base\Exceptions\InvalidArgumentType;
015⫶use Ibexa\Core\FieldType\ValidationError;
016⫶
017⫶class CustomLimitationType implements Type
018⫶{
019⫶ public function acceptValue(Limitation $limitationValue): void
020⫶ {
021⫶ if (!$limitationValue instanceof CustomLimitationValue) {
022⫶ throw new InvalidArgumentType(
023⫶ '$limitationValue',
024⫶ CustomLimitationValue::class,
025⫶ $limitationValue
026⫶ );
027⫶ }
028⫶ }
029⫶
030⫶ /** @return \Ibexa\Core\FieldType\ValidationError[] */
031⫶ public function validate(Limitation $limitationValue): array
032⫶ {
033⫶ $validationErrors = [];
034⫶ if (!array_key_exists('value', $limitationValue->limitationValues)) {
035⫶ $validationErrors[] = new ValidationError("limitationValues['value'] is missing.");
036⫶ } elseif (!is_bool($limitationValue->limitationValues['value'])) {
037⫶ $validationErrors[] = new ValidationError("limitationValues['value'] is not a boolean.");
038⫶ }
039⫶
040⫶ return $validationErrors;
041⫶ }
042⫶
043⫶ public function buildValue(array $limitationValues): CustomLimitationValue
044⫶ {
045⫶ $value = false;
046⫶ if (array_key_exists('value', $limitationValues)) {
047⫶ $value = $limitationValues['value'];
048⫶ } elseif (count($limitationValues)) {
049⫶ $value = (bool)$limitationValues[0];
050⫶ }
051⫶
052⫶ return new CustomLimitationValue(['limitationValues' => ['value' => $value]]);
053⫶ }
054⫶
055⫶ /**
056⫶ * @param \Ibexa\Contracts\Core\Repository\Values\ValueObject[]|null $targets
057⫶ *
058⫶ * @return bool|null
059⫶ */
060⫶ public function evaluate(Limitation $value, UserReference $currentUser, ValueObject $object, array $targets = null): ?bool
061⫶ {
062⫶ if (!$value instanceof CustomLimitationValue) {
063⫶ throw new InvalidArgumentException('$value', 'Must be of type: CustomLimitationValue');
064⫶ }
065⫶
066⫶ if ($value->limitationValues['value']) {
067⫶ return Type::ACCESS_GRANTED;
068⫶ }
069⫶
070⫶ // If the limitation value is not set to `true`, then $currentUser, $object and/or $targets could be challenged to determine if the access is granted or not; Here or elsewhere. When passing the baton, a limitation can return Type::ACCESS_ABSTAIN
071⫶ return Type::ACCESS_DENIED;
072⫶ }
073⫶
074⫶ public function getCriterion(Limitation $value, UserReference $currentUser): CriterionInterface
075⫶ {
076⫶ throw new NotImplementedException(__METHOD__);
077⫶ }
078⫶
079⫶    public function valueSchema()
079⫶    public function valueSchema(): never
080⫶    {
081⫶ throw new NotImplementedException(__METHOD__);
082⫶ }
083⫶}

080⫶    {
081⫶ throw new NotImplementedException(__METHOD__);
082⫶ }
083⫶}

Download colorized diff

@mnocon mnocon requested a review from a team June 3, 2025 09:18
@ezrobot ezrobot requested review from adriendupuis, dabrt and julitafalcondusza and removed request for a team June 3, 2025 09:18
}

public function valueSchema()
public function valueSchema(): never
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel never is the right keyword to use here: https://www.php.net/manual/en/language.types.never.php

I would stick to interface here but I guess never will also work in this particular example.

Copy link
Contributor

@adriendupuis adriendupuis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

never makes more sens than array<string|int, mixed>|int in this case.

@mnocon mnocon merged commit df99c4c into 5.0 Jun 5, 2025
22 checks passed
@mnocon mnocon deleted the fix-5.0-samples branch June 5, 2025 08:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants