From a0555c75d49a2e8790ef7c2067d99efc52260a58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Mon, 22 Sep 2025 14:13:15 +0200 Subject: [PATCH 01/10] Adjusted code samples for Notifications --- .../notifications/src/Notification/ListRenderer.php | 6 +++++- .../notifications/src/Notification/MyRenderer.php | 8 ++++---- code_samples/notifications/Src/Query/search.php | 8 +++++--- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/code_samples/back_office/notifications/src/Notification/ListRenderer.php b/code_samples/back_office/notifications/src/Notification/ListRenderer.php index ced5b5dd1d..1c4eb18d20 100644 --- a/code_samples/back_office/notifications/src/Notification/ListRenderer.php +++ b/code_samples/back_office/notifications/src/Notification/ListRenderer.php @@ -9,6 +9,7 @@ use Ibexa\Core\Notification\Renderer\TypedNotificationRendererInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Routing\RouterInterface; +use Symfony\Contracts\Translation\TranslatorInterface; use Twig\Environment; class ListRenderer implements NotificationRenderer, TypedNotificationRendererInterface @@ -19,11 +20,14 @@ class ListRenderer implements NotificationRenderer, TypedNotificationRendererInt protected RequestStack $requestStack; - public function __construct(Environment $twig, RouterInterface $router, RequestStack $requestStack) + protected TranslatorInterface $translator; + + public function __construct(Environment $twig, RouterInterface $router, RequestStack $requestStack, TranslatorInterface $translator) { $this->twig = $twig; $this->router = $router; $this->requestStack = $requestStack; + $this->translator = $translator; } public function render(Notification $notification): string diff --git a/code_samples/back_office/notifications/src/Notification/MyRenderer.php b/code_samples/back_office/notifications/src/Notification/MyRenderer.php index c79a26f0a1..e0bbd56e02 100644 --- a/code_samples/back_office/notifications/src/Notification/MyRenderer.php +++ b/code_samples/back_office/notifications/src/Notification/MyRenderer.php @@ -8,13 +8,15 @@ use Ibexa\Core\Notification\Renderer\NotificationRenderer; use Ibexa\Core\Notification\Renderer\TypedNotificationRendererInterface; use Symfony\Component\Routing\RouterInterface; +use Symfony\Contracts\Translation\TranslatorInterface; use Twig\Environment; class MyRenderer implements NotificationRenderer, TypedNotificationRendererInterface { public function __construct( protected Environment $twig, - protected RouterInterface $router + protected RouterInterface $router, + protected TranslatorInterface $translator ) { } @@ -22,7 +24,7 @@ public function render(Notification $notification): string { return $this->twig->render('@ibexadesign/notification.html.twig', [ 'notification' => $notification, - 'template_to_extend' => $templateToExtend, + 'template_to_extend' => '@ibexadesign/account/notifications/list_item.html.twig', ]); } @@ -35,8 +37,6 @@ public function generateUrl(Notification $notification): ?string return null; } - } - public function getTypeLabel(): string { return /** @Desc("Workflow stage changed") */ diff --git a/code_samples/notifications/Src/Query/search.php b/code_samples/notifications/Src/Query/search.php index d771b8b343..f7f0e4e2d2 100644 --- a/code_samples/notifications/Src/Query/search.php +++ b/code_samples/notifications/Src/Query/search.php @@ -2,10 +2,12 @@ declare(strict_types=1); -use Ibexa\Contracts\Core\Repository\Values\NotificationQuery; +use Ibexa\Contracts\Core\Repository\Values\Notification\Query\Criterion\DateCreated; +use Ibexa\Contracts\Core\Repository\Values\Notification\Query\Criterion\Status; +use Ibexa\Contracts\Core\Repository\Values\Notification\Query\Criterion\Type; +use Ibexa\Contracts\Core\Repository\Values\Notification\Query\NotificationQuery; -$repository = $this->getRepository(); -$notificationService = $repository->getNotificationService(); +/** @var \Ibexa\Contracts\Core\Repository\NotificationService $notificationService */ $query = new NotificationQuery([], 0, 25); $query->addCriterion(new Type('Workflow:Review')); From 2633acc08c6e0efc086c154a1cbcc7507abcfe6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Mon, 22 Sep 2025 15:47:19 +0200 Subject: [PATCH 02/10] Extracted code sample --- .../src/Controller/CustomController.php | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 code_samples/back_office/limitation/src/Controller/CustomController.php diff --git a/code_samples/back_office/limitation/src/Controller/CustomController.php b/code_samples/back_office/limitation/src/Controller/CustomController.php new file mode 100644 index 0000000000..06535092c4 --- /dev/null +++ b/code_samples/back_office/limitation/src/Controller/CustomController.php @@ -0,0 +1,51 @@ +permissionResolver = $permissionResolver; + $this->permissionChecker = $permissionChecker; + } + + // Controller actions... + public function customAction(Request $request): Response + { + // ... + if ($this->getCustomLimitationValue()) { + // Action only for user having the custom limitation checked + } + } + + private function getCustomLimitationValue(): bool + { + $customLimitationValues = $this->permissionChecker->getRestrictions($this->permissionResolver->hasAccess('custom_module', 'custom_function_2'), CustomLimitationValue::class); + + return $customLimitationValues['value'] ?? false; + } + + public function performAccessCheck() + { + parent::performAccessCheck(); + $this->denyAccessUnlessGranted(new Attribute('custom_module', 'custom_function_2')); + } +} From b3d83c18e7769a71d9eda1816d2c68fdbce3bfab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Mon, 22 Sep 2025 18:29:40 +0200 Subject: [PATCH 03/10] Adjusted custom limitation example --- .../src/Controller/CustomController.php | 6 +- .../Mapper/CustomLimitationValueMapper.php | 5 +- .../custom_limitation_value.html.twig | 5 +- composer.json | 3 +- docs/permissions/custom_policies.md | 63 +++---------------- phpstan-baseline.neon | 12 +--- 6 files changed, 23 insertions(+), 71 deletions(-) diff --git a/code_samples/back_office/limitation/src/Controller/CustomController.php b/code_samples/back_office/limitation/src/Controller/CustomController.php index 06535092c4..e5a17a2244 100644 --- a/code_samples/back_office/limitation/src/Controller/CustomController.php +++ b/code_samples/back_office/limitation/src/Controller/CustomController.php @@ -2,9 +2,11 @@ namespace App\Controller; +use App\Security\Limitation\CustomLimitationValue; use Ibexa\Contracts\AdminUi\Controller\Controller; use Ibexa\Contracts\AdminUi\Permission\PermissionCheckerInterface; use Ibexa\Contracts\Core\Repository\PermissionResolver; +use Ibexa\Core\MVC\Symfony\Security\Authorization\Attribute; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -34,6 +36,8 @@ public function customAction(Request $request): Response if ($this->getCustomLimitationValue()) { // Action only for user having the custom limitation checked } + + return new Response('...'); } private function getCustomLimitationValue(): bool @@ -43,7 +47,7 @@ private function getCustomLimitationValue(): bool return $customLimitationValues['value'] ?? false; } - public function performAccessCheck() + public function performAccessCheck(): void { parent::performAccessCheck(); $this->denyAccessUnlessGranted(new Attribute('custom_module', 'custom_function_2')); diff --git a/code_samples/back_office/limitation/src/Security/Limitation/Mapper/CustomLimitationValueMapper.php b/code_samples/back_office/limitation/src/Security/Limitation/Mapper/CustomLimitationValueMapper.php index 83d6d0c415..41d24ea10e 100644 --- a/code_samples/back_office/limitation/src/Security/Limitation/Mapper/CustomLimitationValueMapper.php +++ b/code_samples/back_office/limitation/src/Security/Limitation/Mapper/CustomLimitationValueMapper.php @@ -9,8 +9,9 @@ class CustomLimitationValueMapper implements LimitationValueMapperInterface { - public function mapLimitationValue(Limitation $limitation): bool + /** return array */ + public function mapLimitationValue(Limitation $limitation): array { - return $limitation->limitationValues['value']; + return [$limitation->limitationValues['value']]; } } diff --git a/code_samples/back_office/limitation/templates/themes/standard/limitation/custom_limitation_value.html.twig b/code_samples/back_office/limitation/templates/themes/standard/limitation/custom_limitation_value.html.twig index 8a4663e9ae..ebb49637d8 100644 --- a/code_samples/back_office/limitation/templates/themes/standard/limitation/custom_limitation_value.html.twig +++ b/code_samples/back_office/limitation/templates/themes/standard/limitation/custom_limitation_value.html.twig @@ -1,4 +1,5 @@ {# templates/themes/standard/limitation/custom_limitation_value.html.twig #} -{% block ez_limitation_customlimitation_value %} - {{ values ? 'Yes' : 'No' }} +{% block ibexa_limitation_customlimitation_value %} + {% set isSet = values | first %} + {{ isSet ? 'Yes' : 'No' }} {% endblock %} diff --git a/composer.json b/composer.json index f4f318a534..b21f1dc068 100644 --- a/composer.json +++ b/composer.json @@ -74,7 +74,8 @@ "ibexa/discounts": "~5.0.x-dev", "ibexa/discounts-codes": "~5.0.x-dev", "ibexa/core-search": "~5.0.x-dev", - "ibexa/product-catalog-symbol-attribute": "~5.0.x-dev" + "ibexa/product-catalog-symbol-attribute": "~5.0.x-dev", + "ibexa/messenger": "~5.0.x-dev" }, "scripts": { "fix-cs": "php-cs-fixer fix --config=.php-cs-fixer.php -v --show-progress=dots", diff --git a/docs/permissions/custom_policies.md b/docs/permissions/custom_policies.md index 25481d977b..75bb09e30f 100644 --- a/docs/permissions/custom_policies.md +++ b/docs/permissions/custom_policies.md @@ -174,7 +174,7 @@ services: #### Form mapper -To provide support for editing custom policies in the back office, you need to implement [`Ibexa\AdminUi\Limitation\LimitationFormMapperInterface`](https://github.com/ibexa/admin-ui/blob/4.5/src/lib/Limitation/LimitationFormMapperInterface.php). +To provide support for editing custom policies in the back office, you need to implement [`Ibexa\AdminUi\Limitation\LimitationFormMapperInterface`](https://github.com/ibexa/admin-ui/blob/5.0/src/lib/Limitation/LimitationFormMapperInterface.php). - `mapLimitationForm` adds the limitation field as a child to a provided Symfony form. - `getFormTemplate` returns the path to the template to use for rendering the limitation form. Here it use [`form_label`]([[= symfony_doc =]]/form/form_customization.html#reference-forms-twig-label) and [`form_widget`]([[= symfony_doc =]]/form/form_customization.html#reference-forms-twig-widget) to do so. @@ -205,7 +205,7 @@ Some abstract limitation type form mapper classes are provided to help implement #### Value mapper -By default, without a value mapper, the limitation value is rendered by using the block `ez_limitation_value_fallback` of the template [`vendor/ibexa/admin-ui/src/bundle/Resources/views/themes/admin/limitation/limitation_values.html.twig`](https://github.com/ibexa/admin-ui/blob/4.5/src/bundle/Resources/views/themes/admin/limitation/limitation_values.html.twig#L1-L6). +By default, without a value mapper, the limitation value is rendered by using the block `ibexa_limitation_value_fallback` of the template [`vendor/ibexa/admin-ui/src/bundle/Resources/views/themes/admin/limitation/limitation_values.html.twig`](https://github.com/ibexa/admin-ui/blob/[[= latest_tag_5_0 =]]/src/bundle/Resources/views/themes/admin/limitation/limitation_values.html.twig). To customize the rendering, a value mapper eventually transforms the limitation value and sends it to a custom template. @@ -223,17 +223,17 @@ Then register the service with the `ibexa.admin_ui.limitation.mapper.value` tag [[= include_file('code_samples/back_office/limitation/config/append_to_services.yaml', 9, 12) =]] ``` -When a value mapper exists for a limitation, the rendering uses a Twig block named `ez_limitation__value` where `` is the limitation identifier in lower case. -In this example, block name is `ez_limitation_customlimitation_value` as the identifier is `CustomLimitation`. +When a value mapper exists for a limitation, the rendering uses a Twig block named `ibexa_limitation__value` where `` is the limitation identifier in lower case. +In this example, block name is `ibexa_limitation_customlimitation_value` as the identifier is `CustomLimitation`. -This template receives a `values` variable which is the return of the `mapLimitationValue` function from the corresponding value mapper. +This template receives a `values` variable which is the return value of the `mapLimitationValue` function from the corresponding value mapper. ``` html+twig [[= include_file('code_samples/back_office/limitation/templates/themes/standard/limitation/custom_limitation_value.html.twig') =]] ``` To have your block found, you have to register its template. -Add the template to the configuration under `ezplatform.system..limitation_value_templates`: +Add the template to the configuration under `ibexa.system..limitation_value_templates`: ``` yaml [[= include_file('code_samples/back_office/limitation/config/packages/ibexa_security.yaml') =]] @@ -251,54 +251,5 @@ For example, `translations/ibexa_content_forms_policies.en.yaml`: Check if current user has this custom limitation set to true from a custom controller: ```php -permissionResolver = $permissionResolver; - $this->permissionChecker = $permissionChecker; - } - - // Controller actions... - public function customAction(Request $request): Response { - // ... - if ($this->getCustomLimitationValue()) { - // Action only for user having the custom limitation checked - } - } - - private function getCustomLimitationValue(): bool { - $customLimitationValues = $this->permissionChecker->getRestrictions($this->permissionResolver->hasAccess('custom_module', 'custom_function_2'), CustomLimitationValue::class); - - return $customLimitationValues['value'] ?? false; - } - - public function performAccessCheck() - { - parent::performAccessCheck(); - $this->denyAccessUnlessGranted(new Attribute('custom_module', 'custom_function_2')); - } -} +[[= include_file('code_samples/back_office/limitation/src/Controller/CustomController.php') =]] ``` diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 0cac07b456..253fa27ab8 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -241,16 +241,10 @@ parameters: path: code_samples/back_office/images/src/PlaceholderProvider.php - - message: '#^Method App\\Security\\Limitation\\Mapper\\CustomLimitationFormMapper\:\:mapLimitationForm\(\) has parameter \$form with generic interface Symfony\\Component\\Form\\FormInterface but does not specify its types\: TData$#' - identifier: missingType.generics - count: 1 - path: code_samples/back_office/limitation/src/Security/Limitation/Mapper/CustomLimitationFormMapper.php - - - - message: '#^Return type \(bool\) of method App\\Security\\Limitation\\Mapper\\CustomLimitationValueMapper\:\:mapLimitationValue\(\) should be compatible with return type \(array\\) of method Ibexa\\AdminUi\\Limitation\\LimitationValueMapperInterface\:\:mapLimitationValue\(\)$#' - identifier: method.childReturnType + message: '#^Parameter \#1 \$hasAccess of method Ibexa\\Contracts\\AdminUi\\Permission\\PermissionCheckerInterface\:\:getRestrictions\(\) expects array\, array\\|Ibexa\\Contracts\\Core\\Repository\\Values\\User\\Limitation\|null\>\>\|bool given\.$#' + identifier: argument.type count: 1 - path: code_samples/back_office/limitation/src/Security/Limitation/Mapper/CustomLimitationValueMapper.php + path: code_samples/back_office/limitation/src/Controller/CustomController.php - message: '#^Method App\\Security\\MyPolicyProvider\:\:getFiles\(\) return type has no value type specified in iterable type array\.$#' From 695c20582e8a8ec1c0d172e81d8fe576df98917e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Mon, 22 Sep 2025 18:29:43 +0200 Subject: [PATCH 04/10] Revert "Adjusted code samples for Notifications" This reverts commit a0555c75d49a2e8790ef7c2067d99efc52260a58. --- .../notifications/src/Notification/ListRenderer.php | 6 +----- .../notifications/src/Notification/MyRenderer.php | 8 ++++---- code_samples/notifications/Src/Query/search.php | 8 +++----- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/code_samples/back_office/notifications/src/Notification/ListRenderer.php b/code_samples/back_office/notifications/src/Notification/ListRenderer.php index 1c4eb18d20..ced5b5dd1d 100644 --- a/code_samples/back_office/notifications/src/Notification/ListRenderer.php +++ b/code_samples/back_office/notifications/src/Notification/ListRenderer.php @@ -9,7 +9,6 @@ use Ibexa\Core\Notification\Renderer\TypedNotificationRendererInterface; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Routing\RouterInterface; -use Symfony\Contracts\Translation\TranslatorInterface; use Twig\Environment; class ListRenderer implements NotificationRenderer, TypedNotificationRendererInterface @@ -20,14 +19,11 @@ class ListRenderer implements NotificationRenderer, TypedNotificationRendererInt protected RequestStack $requestStack; - protected TranslatorInterface $translator; - - public function __construct(Environment $twig, RouterInterface $router, RequestStack $requestStack, TranslatorInterface $translator) + public function __construct(Environment $twig, RouterInterface $router, RequestStack $requestStack) { $this->twig = $twig; $this->router = $router; $this->requestStack = $requestStack; - $this->translator = $translator; } public function render(Notification $notification): string diff --git a/code_samples/back_office/notifications/src/Notification/MyRenderer.php b/code_samples/back_office/notifications/src/Notification/MyRenderer.php index e0bbd56e02..c79a26f0a1 100644 --- a/code_samples/back_office/notifications/src/Notification/MyRenderer.php +++ b/code_samples/back_office/notifications/src/Notification/MyRenderer.php @@ -8,15 +8,13 @@ use Ibexa\Core\Notification\Renderer\NotificationRenderer; use Ibexa\Core\Notification\Renderer\TypedNotificationRendererInterface; use Symfony\Component\Routing\RouterInterface; -use Symfony\Contracts\Translation\TranslatorInterface; use Twig\Environment; class MyRenderer implements NotificationRenderer, TypedNotificationRendererInterface { public function __construct( protected Environment $twig, - protected RouterInterface $router, - protected TranslatorInterface $translator + protected RouterInterface $router ) { } @@ -24,7 +22,7 @@ public function render(Notification $notification): string { return $this->twig->render('@ibexadesign/notification.html.twig', [ 'notification' => $notification, - 'template_to_extend' => '@ibexadesign/account/notifications/list_item.html.twig', + 'template_to_extend' => $templateToExtend, ]); } @@ -37,6 +35,8 @@ public function generateUrl(Notification $notification): ?string return null; } + } + public function getTypeLabel(): string { return /** @Desc("Workflow stage changed") */ diff --git a/code_samples/notifications/Src/Query/search.php b/code_samples/notifications/Src/Query/search.php index f7f0e4e2d2..d771b8b343 100644 --- a/code_samples/notifications/Src/Query/search.php +++ b/code_samples/notifications/Src/Query/search.php @@ -2,12 +2,10 @@ declare(strict_types=1); -use Ibexa\Contracts\Core\Repository\Values\Notification\Query\Criterion\DateCreated; -use Ibexa\Contracts\Core\Repository\Values\Notification\Query\Criterion\Status; -use Ibexa\Contracts\Core\Repository\Values\Notification\Query\Criterion\Type; -use Ibexa\Contracts\Core\Repository\Values\Notification\Query\NotificationQuery; +use Ibexa\Contracts\Core\Repository\Values\NotificationQuery; -/** @var \Ibexa\Contracts\Core\Repository\NotificationService $notificationService */ +$repository = $this->getRepository(); +$notificationService = $repository->getNotificationService(); $query = new NotificationQuery([], 0, 25); $query->addCriterion(new Type('Workflow:Review')); From 3c5703d1fc862c2c9b88d535fe5224c04f3ec344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Mon, 22 Sep 2025 18:30:25 +0200 Subject: [PATCH 05/10] Put Notification errors into the baseline --- .../src/Notification/MyRenderer.php | 2 - phpstan-baseline.neon | 54 +++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/code_samples/back_office/notifications/src/Notification/MyRenderer.php b/code_samples/back_office/notifications/src/Notification/MyRenderer.php index c79a26f0a1..5c3adade2e 100644 --- a/code_samples/back_office/notifications/src/Notification/MyRenderer.php +++ b/code_samples/back_office/notifications/src/Notification/MyRenderer.php @@ -34,8 +34,6 @@ public function generateUrl(Notification $notification): ?string return null; } - - } public function getTypeLabel(): string { diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 253fa27ab8..c2ffdafe4b 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -264,6 +264,24 @@ parameters: count: 1 path: code_samples/back_office/menu/menu_item/src/EventSubscriber/MyMenuSubscriber.php + - + message: '#^Access to an undefined property App\\Notification\\ListRenderer\:\:\$translator\.$#' + identifier: property.notFound + count: 1 + path: code_samples/back_office/notifications/src/Notification/ListRenderer.php + + - + message: '#^Access to an undefined property App\\Notification\\MyRenderer\:\:\$translator\.$#' + identifier: property.notFound + count: 1 + path: code_samples/back_office/notifications/src/Notification/MyRenderer.php + + - + message: '#^Undefined variable\: \$templateToExtend$#' + identifier: variable.undefined + count: 1 + path: code_samples/back_office/notifications/src/Notification/MyRenderer.php + - message: '#^Cannot call method getValue\(\) on Ibexa\\Contracts\\FieldTypePage\\FieldType\\LandingPage\\Model\\Attribute\|null\.$#' identifier: method.nonObject @@ -534,6 +552,42 @@ parameters: count: 1 path: code_samples/front/shop/storefront/src/EventSubscriber/BreadcrumbsMenuSubscriber.php + - + message: '#^Call to method addCriterion\(\) on an unknown class Ibexa\\Contracts\\Core\\Repository\\Values\\NotificationQuery\.$#' + identifier: class.notFound + count: 3 + path: code_samples/notifications/Src/Query/search.php + + - + message: '#^Instantiated class DateCreated not found\.$#' + identifier: class.notFound + count: 1 + path: code_samples/notifications/Src/Query/search.php + + - + message: '#^Instantiated class Ibexa\\Contracts\\Core\\Repository\\Values\\NotificationQuery not found\.$#' + identifier: class.notFound + count: 1 + path: code_samples/notifications/Src/Query/search.php + + - + message: '#^Instantiated class Status not found\.$#' + identifier: class.notFound + count: 1 + path: code_samples/notifications/Src/Query/search.php + + - + message: '#^Instantiated class Type not found\.$#' + identifier: class.notFound + count: 1 + path: code_samples/notifications/Src/Query/search.php + + - + message: '#^Variable \$this might not be defined\.$#' + identifier: variable.undefined + count: 1 + path: code_samples/notifications/Src/Query/search.php + - message: '#^Method App\\Block\\Attribute\\MyStringAttributeMapper\:\:map\(\) has parameter \$constraints with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue From b11790dafda2532b8bcfdb9647358975278de40b Mon Sep 17 00:00:00 2001 From: mnocon Date: Mon, 22 Sep 2025 16:47:07 +0000 Subject: [PATCH 06/10] PHP & JS CS Fixes --- .../back_office/notifications/src/Notification/MyRenderer.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code_samples/back_office/notifications/src/Notification/MyRenderer.php b/code_samples/back_office/notifications/src/Notification/MyRenderer.php index 5c3adade2e..0c2d38ccd4 100644 --- a/code_samples/back_office/notifications/src/Notification/MyRenderer.php +++ b/code_samples/back_office/notifications/src/Notification/MyRenderer.php @@ -34,7 +34,7 @@ public function generateUrl(Notification $notification): ?string return null; } - + public function getTypeLabel(): string { return /** @Desc("Workflow stage changed") */ From c2ac2fa7f36d9e1a70a574bdadba76f0e650a470 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Mon, 22 Sep 2025 18:53:37 +0200 Subject: [PATCH 07/10] Run Rector on CustomController --- .../src/Controller/CustomController.php | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/code_samples/back_office/limitation/src/Controller/CustomController.php b/code_samples/back_office/limitation/src/Controller/CustomController.php index e5a17a2244..1685635f21 100644 --- a/code_samples/back_office/limitation/src/Controller/CustomController.php +++ b/code_samples/back_office/limitation/src/Controller/CustomController.php @@ -6,27 +6,18 @@ use Ibexa\Contracts\AdminUi\Controller\Controller; use Ibexa\Contracts\AdminUi\Permission\PermissionCheckerInterface; use Ibexa\Contracts\Core\Repository\PermissionResolver; +use Ibexa\Contracts\User\Controller\RestrictedControllerInterface; use Ibexa\Core\MVC\Symfony\Security\Authorization\Attribute; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -class CustomController extends Controller +class CustomController extends Controller implements RestrictedControllerInterface { - // ... - /** @var \Ibexa\Contracts\Core\Repository\PermissionResolver */ - private $permissionResolver; - - /** @var \Ibexa\Contracts\AdminUi\Permission\PermissionCheckerInterface */ - private $permissionChecker; - public function __construct( // ..., - PermissionResolver $permissionResolver, - PermissionCheckerInterface $permissionChecker + private readonly PermissionResolver $permissionResolver, + private readonly PermissionCheckerInterface $permissionChecker ) { - // ... - $this->permissionResolver = $permissionResolver; - $this->permissionChecker = $permissionChecker; } // Controller actions... @@ -49,7 +40,6 @@ private function getCustomLimitationValue(): bool public function performAccessCheck(): void { - parent::performAccessCheck(); $this->denyAccessUnlessGranted(new Attribute('custom_module', 'custom_function_2')); } } From 710c67002c1971d59b553aa2805c5ee770ce373b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Wed, 24 Sep 2025 09:54:56 +0200 Subject: [PATCH 08/10] Added AuthenticatedRememberedCheckTrait --- .../limitation/src/Controller/CustomController.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code_samples/back_office/limitation/src/Controller/CustomController.php b/code_samples/back_office/limitation/src/Controller/CustomController.php index 1685635f21..454c171d7d 100644 --- a/code_samples/back_office/limitation/src/Controller/CustomController.php +++ b/code_samples/back_office/limitation/src/Controller/CustomController.php @@ -6,6 +6,7 @@ use Ibexa\Contracts\AdminUi\Controller\Controller; use Ibexa\Contracts\AdminUi\Permission\PermissionCheckerInterface; use Ibexa\Contracts\Core\Repository\PermissionResolver; +use Ibexa\Contracts\User\Controller\AuthenticatedRememberedCheckTrait; use Ibexa\Contracts\User\Controller\RestrictedControllerInterface; use Ibexa\Core\MVC\Symfony\Security\Authorization\Attribute; use Symfony\Component\HttpFoundation\Request; @@ -13,6 +14,10 @@ class CustomController extends Controller implements RestrictedControllerInterface { + use AuthenticatedRememberedCheckTrait { + AuthenticatedRememberedCheckTrait::performAccessCheck as public traitPerformAccessCheck; + } + public function __construct( // ..., private readonly PermissionResolver $permissionResolver, @@ -40,6 +45,7 @@ private function getCustomLimitationValue(): bool public function performAccessCheck(): void { + $this->traitPerformAccessCheck(); $this->denyAccessUnlessGranted(new Attribute('custom_module', 'custom_function_2')); } } From 92ce90df50a2240040027e790f74c80974225881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Wed, 24 Sep 2025 10:06:08 +0200 Subject: [PATCH 09/10] Fixed link --- docs/permissions/custom_policies.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/permissions/custom_policies.md b/docs/permissions/custom_policies.md index 75bb09e30f..84b65e3866 100644 --- a/docs/permissions/custom_policies.md +++ b/docs/permissions/custom_policies.md @@ -205,7 +205,7 @@ Some abstract limitation type form mapper classes are provided to help implement #### Value mapper -By default, without a value mapper, the limitation value is rendered by using the block `ibexa_limitation_value_fallback` of the template [`vendor/ibexa/admin-ui/src/bundle/Resources/views/themes/admin/limitation/limitation_values.html.twig`](https://github.com/ibexa/admin-ui/blob/[[= latest_tag_5_0 =]]/src/bundle/Resources/views/themes/admin/limitation/limitation_values.html.twig). +By default, without a value mapper, the limitation value is rendered by using the block `ibexa_limitation_value_fallback` of the template [`vendor/ibexa/admin-ui/src/bundle/Resources/views/themes/admin/limitation/limitation_values.html.twig`](https://github.com/ibexa/admin-ui/blob/v[[= latest_tag_5_0 =]]/src/bundle/Resources/views/themes/admin/limitation/limitation_values.html.twig). To customize the rendering, a value mapper eventually transforms the limitation value and sends it to a custom template. From c584cf55a3bb7ac7f1679d2b8a43ffa4e0e29aab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Noco=C5=84?= Date: Wed, 24 Sep 2025 11:39:32 +0200 Subject: [PATCH 10/10] Tested the Controller --- .../limitation/src/Controller/CustomController.php | 8 +++++++- phpstan-baseline.neon | 6 ------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/code_samples/back_office/limitation/src/Controller/CustomController.php b/code_samples/back_office/limitation/src/Controller/CustomController.php index 454c171d7d..4f98c830ce 100644 --- a/code_samples/back_office/limitation/src/Controller/CustomController.php +++ b/code_samples/back_office/limitation/src/Controller/CustomController.php @@ -38,7 +38,13 @@ public function customAction(Request $request): Response private function getCustomLimitationValue(): bool { - $customLimitationValues = $this->permissionChecker->getRestrictions($this->permissionResolver->hasAccess('custom_module', 'custom_function_2'), CustomLimitationValue::class); + $hasAccess = $this->permissionResolver->hasAccess('custom_module', 'custom_function_2'); + + if (is_bool($hasAccess)) { + return $hasAccess; + } + + $customLimitationValues = $this->permissionChecker->getRestrictions($hasAccess, CustomLimitationValue::class); return $customLimitationValues['value'] ?? false; } diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index c2ffdafe4b..d5067dcdcc 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -240,12 +240,6 @@ parameters: count: 1 path: code_samples/back_office/images/src/PlaceholderProvider.php - - - message: '#^Parameter \#1 \$hasAccess of method Ibexa\\Contracts\\AdminUi\\Permission\\PermissionCheckerInterface\:\:getRestrictions\(\) expects array\, array\\|Ibexa\\Contracts\\Core\\Repository\\Values\\User\\Limitation\|null\>\>\|bool given\.$#' - identifier: argument.type - count: 1 - path: code_samples/back_office/limitation/src/Controller/CustomController.php - - message: '#^Method App\\Security\\MyPolicyProvider\:\:getFiles\(\) return type has no value type specified in iterable type array\.$#' identifier: missingType.iterableValue