From 38d5e8934f450e5c333fc60f51c10ff3acc5200e Mon Sep 17 00:00:00 2001 From: Divesh Pahuja Date: Tue, 7 Feb 2023 16:44:36 +0100 Subject: [PATCH] [Task]: Replace SensioFrameworkExtraBundle with PHP 8 attribute (#14062) * Replace SensioFrameworkExtraBundle with PHP 8 attribute - resolves #13958 Co-authored-by: JiaJia Ji Co-authored-by: Sebastian Blank --- .github/ci/scripts/symfony-require-dev.sh | 2 +- .github/workflows/codeception.yaml | 2 +- .github/workflows/static-analysis.yaml | 2 +- .../CoreBundle/config/pimcore/default.yaml | 4 - bundles/CoreBundle/config/services.yaml | 2 +- .../Frontend/ContentTemplateListener.php | 47 +++++++- .../EventListener/ResponseHeaderListener.php | 23 ++-- .../DataObjectParamResolver.php | 30 +---- composer.json | 90 +++++++------- .../02_MVC/00_Controller.md | 8 +- .../02_MVC/02_Template/README.md | 2 +- .../04_Routing_and_URLs/02_Custom_Routes.md | 9 +- .../01_Data_Types/65_Others.md | 2 +- .../09_Upgrade_Notes/README.md | 8 +- lib/Controller/Attribute/ResponseHeader.php | 40 ++++++- .../Configuration/ResponseHeader.php | 113 ------------------ .../Resolver/ResponseHeaderResolver.php | 10 +- lib/Kernel.php | 2 - phpstan-baseline.neon | 5 - 19 files changed, 164 insertions(+), 237 deletions(-) rename bundles/CoreBundle/src/Request/{ParamConverter => ParamResolver}/DataObjectParamResolver.php (65%) delete mode 100644 lib/Controller/Configuration/ResponseHeader.php diff --git a/.github/ci/scripts/symfony-require-dev.sh b/.github/ci/scripts/symfony-require-dev.sh index d128360e135..b72d7948daa 100755 --- a/.github/ci/scripts/symfony-require-dev.sh +++ b/.github/ci/scripts/symfony-require-dev.sh @@ -2,4 +2,4 @@ set -eu -composer require --no-update symfony/asset:${SYMFONY_VERSION} symfony/cache:${SYMFONY_VERSION} symfony/doctrine-messenger:${SYMFONY_VERSION} symfony/config:${SYMFONY_VERSION} symfony/console:${SYMFONY_VERSION} symfony/dependency-injection:${SYMFONY_VERSION} symfony/debug-bundle:${SYMFONY_VERSION} symfony/dom-crawler:${SYMFONY_VERSION} symfony/error-handler:${SYMFONY_VERSION} symfony/event-dispatcher:${SYMFONY_VERSION} symfony/expression-language:${SYMFONY_VERSION} symfony/filesystem:${SYMFONY_VERSION} symfony/finder:${SYMFONY_VERSION} symfony/form:${SYMFONY_VERSION} symfony/framework-bundle:${SYMFONY_VERSION} symfony/http-foundation:${SYMFONY_VERSION} symfony/http-kernel:${SYMFONY_VERSION} symfony/lock:${SYMFONY_VERSION} symfony/mailer:${SYMFONY_VERSION} symfony/messenger:${SYMFONY_VERSION} symfony/mime:${SYMFONY_VERSION} symfony/options-resolver:${SYMFONY_VERSION} symfony/password-hasher:${SYMFONY_VERSION} symfony/process:${SYMFONY_VERSION} symfony/property-access:${SYMFONY_VERSION} symfony/rate-limiter:${SYMFONY_VERSION} symfony/routing:${SYMFONY_VERSION} symfony/security-bundle:${SYMFONY_VERSION} symfony/security-core:${SYMFONY_VERSION} symfony/security-http:${SYMFONY_VERSION} symfony/serializer:${SYMFONY_VERSION} symfony/stopwatch:${SYMFONY_VERSION} symfony/templating:${SYMFONY_VERSION} symfony/translation:${SYMFONY_VERSION} symfony/twig-bridge:${SYMFONY_VERSION} symfony/twig-bundle:${SYMFONY_VERSION} symfony/uid:${SYMFONY_VERSION} symfony/validator:${SYMFONY_VERSION} symfony/var-dumper:${SYMFONY_VERSION} symfony/web-link:${SYMFONY_VERSION} symfony/web-profiler-bundle:${SYMFONY_VERSION} symfony/workflow:${SYMFONY_VERSION} symfony/yaml:${SYMFONY_VERSION} +composer require --no-update symfony/asset:${SYMFONY_VERSION} symfony/cache:${SYMFONY_VERSION} symfony/doctrine-messenger:${SYMFONY_VERSION} symfony/config:${SYMFONY_VERSION} symfony/console:${SYMFONY_VERSION} symfony/dependency-injection:${SYMFONY_VERSION} symfony/debug-bundle:${SYMFONY_VERSION} symfony/dom-crawler:${SYMFONY_VERSION} symfony/error-handler:${SYMFONY_VERSION} symfony/event-dispatcher:${SYMFONY_VERSION} symfony/expression-language:${SYMFONY_VERSION} symfony/filesystem:${SYMFONY_VERSION} symfony/finder:${SYMFONY_VERSION} symfony/form:${SYMFONY_VERSION} symfony/framework-bundle:${SYMFONY_VERSION} symfony/http-foundation:${SYMFONY_VERSION} symfony/http-kernel:${SYMFONY_VERSION} symfony/lock:${SYMFONY_VERSION} symfony/mailer:${SYMFONY_VERSION} symfony/messenger:${SYMFONY_VERSION} symfony/mime:${SYMFONY_VERSION} symfony/options-resolver:${SYMFONY_VERSION} symfony/password-hasher:${SYMFONY_VERSION} symfony/process:${SYMFONY_VERSION} symfony/property-access:${SYMFONY_VERSION} symfony/rate-limiter:${SYMFONY_VERSION} symfony/routing:${SYMFONY_VERSION} symfony/security-bundle:${SYMFONY_VERSION} symfony/security-core:${SYMFONY_VERSION} symfony/security-http:${SYMFONY_VERSION} symfony/serializer:${SYMFONY_VERSION} symfony/stopwatch:${SYMFONY_VERSION} symfony/templating:${SYMFONY_VERSION} symfony/translation:${SYMFONY_VERSION} symfony/doctrine-bridge:${SYMFONY_VERSION} symfony/twig-bridge:${SYMFONY_VERSION} symfony/twig-bundle:${SYMFONY_VERSION} symfony/uid:${SYMFONY_VERSION} symfony/validator:${SYMFONY_VERSION} symfony/var-dumper:${SYMFONY_VERSION} symfony/web-link:${SYMFONY_VERSION} symfony/web-profiler-bundle:${SYMFONY_VERSION} symfony/workflow:${SYMFONY_VERSION} symfony/yaml:${SYMFONY_VERSION} diff --git a/.github/workflows/codeception.yaml b/.github/workflows/codeception.yaml index 24c7b15b7cf..502810ab16f 100644 --- a/.github/workflows/codeception.yaml +++ b/.github/workflows/codeception.yaml @@ -40,7 +40,7 @@ jobs: strategy: matrix: include: - - { php-version: 8.1, database: "mariadb:10.6", dependencies: highest, experimental: true, storage: local, symfony: "6.2.x-dev", composer-options: "" } + - { php-version: 8.1, database: "mariadb:10.6", dependencies: highest, experimental: true, storage: local, symfony: "6.3.x-dev", composer-options: "" } - { php-version: 8.1, database: "mariadb:10.7", dependencies: highest, experimental: false, storage: local, symfony: "", composer-options: "" } - { php-version: 8.1, database: "mariadb:10.3", dependencies: lowest, experimental: false, storage: local, symfony: "", composer-options: "" } - { php-version: 8.1, database: "mysql:8.0", dependencies: lowest, experimental: false, storage: local, symfony: "", composer-options: "" } diff --git a/.github/workflows/static-analysis.yaml b/.github/workflows/static-analysis.yaml index 56d613de989..5f0a8ddfc9a 100644 --- a/.github/workflows/static-analysis.yaml +++ b/.github/workflows/static-analysis.yaml @@ -40,7 +40,7 @@ jobs: include: - { php-version: "8.1", dependencies: "lowest", experimental: false, symfony: "", composer-options: "" } - { php-version: "8.1", dependencies: "highest", experimental: false, symfony: "", composer-options: "" } - - { php-version: "8.1", dependencies: "highest", experimental: true, symfony: "6.2.x-dev", composer-options: "" } + - { php-version: "8.1", dependencies: "highest", experimental: true, symfony: "6.3.x-dev", composer-options: "" } steps: - name: "Checkout code" diff --git a/bundles/CoreBundle/config/pimcore/default.yaml b/bundles/CoreBundle/config/pimcore/default.yaml index 8e1a15685f0..97a3504a5a6 100644 --- a/bundles/CoreBundle/config/pimcore/default.yaml +++ b/bundles/CoreBundle/config/pimcore/default.yaml @@ -270,7 +270,3 @@ presta_sitemap: lastmod: ~ priority: ~ changefreq: ~ - -sensio_framework_extra: - router: - annotations: false diff --git a/bundles/CoreBundle/config/services.yaml b/bundles/CoreBundle/config/services.yaml index b7dd2ec4bc8..f9c7abb3eb3 100644 --- a/bundles/CoreBundle/config/services.yaml +++ b/bundles/CoreBundle/config/services.yaml @@ -131,7 +131,7 @@ services: public: true class: Pimcore\Model\DataObject\QuantityValue\DefaultConverter - Pimcore\Bundle\CoreBundle\Request\ParamConverter\DataObjectParamResolver: + Pimcore\Bundle\CoreBundle\Request\ParamResolver\DataObjectParamResolver: tags: - { name: controller.argument_value_resolver, priority: 101} diff --git a/bundles/CoreBundle/src/EventListener/Frontend/ContentTemplateListener.php b/bundles/CoreBundle/src/EventListener/Frontend/ContentTemplateListener.php index c39741aaea3..2f507a0658a 100644 --- a/bundles/CoreBundle/src/EventListener/Frontend/ContentTemplateListener.php +++ b/bundles/CoreBundle/src/EventListener/Frontend/ContentTemplateListener.php @@ -19,10 +19,15 @@ use Pimcore\Bundle\CoreBundle\EventListener\Traits\PimcoreContextAwareTrait; use Pimcore\Http\Request\Resolver\PimcoreContextResolver; use Pimcore\Http\Request\Resolver\TemplateResolver; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; +use Symfony\Bridge\Twig\Attribute\Template; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\Form\FormInterface; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\StreamedResponse; +use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; use Symfony\Component\HttpKernel\Event\ViewEvent; use Symfony\Component\HttpKernel\KernelEvents; +use Twig\Environment; /** * If a contentTemplate attribute was set on the request (done by router when building a document route), extract the @@ -34,7 +39,7 @@ class ContentTemplateListener implements EventSubscriberInterface { use PimcoreContextAwareTrait; - public function __construct(protected TemplateResolver $templateResolver) + public function __construct(protected TemplateResolver $templateResolver, protected Environment $twig) { } @@ -63,10 +68,9 @@ public function onKernelView(ViewEvent $event): void return; } - $template = $request->attributes->get('_template'); + $attribute = $event->controllerArgumentsEvent?->getAttributes()[Template::class][0] ?? null; - // no @Template present -> nothing to do - if (null === $template || !($template instanceof Template)) { + if (!$attribute instanceof Template) { return; } @@ -76,6 +80,37 @@ public function onKernelView(ViewEvent $event): void return; } - $template->setTemplate($resolvedTemplate); + $parameters = $this->resolveParameters($event->controllerArgumentsEvent, $attribute->vars); + $status = 200; + + foreach ($parameters as $k => $v) { + if (!$v instanceof FormInterface) { + continue; + } + if ($v->isSubmitted() && !$v->isValid()) { + $status = 422; + } + $parameters[$k] = $v->createView(); + } + + $event->setResponse($attribute->stream + ? new StreamedResponse(fn () => $this->twig->display($resolvedTemplate, $parameters), $status) + : new Response($this->twig->render($resolvedTemplate, $parameters), $status) + ); + } + + private function resolveParameters(ControllerArgumentsEvent $event, ?array $vars): array + { + if ([] === $vars) { + return []; + } + + $parameters = $event->getNamedArguments(); + + if (null !== $vars) { + $parameters = array_intersect_key($parameters, array_flip($vars)); + } + + return $parameters; } } diff --git a/bundles/CoreBundle/src/EventListener/ResponseHeaderListener.php b/bundles/CoreBundle/src/EventListener/ResponseHeaderListener.php index fd4e21c15e1..5ce13055019 100644 --- a/bundles/CoreBundle/src/EventListener/ResponseHeaderListener.php +++ b/bundles/CoreBundle/src/EventListener/ResponseHeaderListener.php @@ -20,6 +20,7 @@ use Pimcore\Controller\Attribute\ResponseHeader; use Pimcore\Http\Request\Resolver\ResponseHeaderResolver; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; @@ -38,6 +39,7 @@ public function __construct(private ResponseHeaderResolver $responseHeaderResolv public static function getSubscribedEvents(): array { return [ + KernelEvents::CONTROLLER_ARGUMENTS => ['onKernelControllerArguments', 10], KernelEvents::RESPONSE => ['onKernelResponse', 32], ]; } @@ -52,14 +54,21 @@ public function onKernelResponse(ResponseEvent $event): void $response = $event->getResponse(); foreach ($headers as $header) { - if (!$header instanceof ResponseHeader) { - trigger_deprecation( - 'pimcore/pimcore', - '10.6', - 'Usage of @ResponseHeader annotation is deprecated. please use #[ResponseHeader] attribute instead.' - ); + if ($header instanceof ResponseHeader) { + $response->headers->set($header->getKey(), $header->getValues(), $header->getReplace()); } - $response->headers->set($header->getKey(), $header->getValues(), $header->getReplace()); } } + + public function onKernelControllerArguments(ControllerArgumentsEvent $event): void + { + $request = $event->getRequest(); + if (!\is_array($attributes = $event->getAttributes()[ResponseHeader::class] ?? null)) { + return; + } + + $responseHeaders = array_merge($this->responseHeaderResolver->getResponseHeaders($request), $attributes); + + $request->attributes->set($this->responseHeaderResolver::ATTRIBUTE_RESPONSE_HEADER, $responseHeaders); + } } diff --git a/bundles/CoreBundle/src/Request/ParamConverter/DataObjectParamResolver.php b/bundles/CoreBundle/src/Request/ParamResolver/DataObjectParamResolver.php similarity index 65% rename from bundles/CoreBundle/src/Request/ParamConverter/DataObjectParamResolver.php rename to bundles/CoreBundle/src/Request/ParamResolver/DataObjectParamResolver.php index 654b60b0c96..1ecdc41857f 100644 --- a/bundles/CoreBundle/src/Request/ParamConverter/DataObjectParamResolver.php +++ b/bundles/CoreBundle/src/Request/ParamResolver/DataObjectParamResolver.php @@ -14,22 +14,21 @@ * @license http://www.pimcore.org/license GPLv3 and PCL */ -namespace Pimcore\Bundle\CoreBundle\Request\ParamConverter; +namespace Pimcore\Bundle\CoreBundle\Request\ParamResolver; use Pimcore\Model\DataObject\AbstractObject; use Pimcore\Model\DataObject\Concrete; use Pimcore\Request\Attribute\DataObjectParam; use Pimcore\Tool; -use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\Controller\ValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; /** * @internal */ -class DataObjectParamResolver implements ArgumentValueResolverInterface +class DataObjectParamResolver implements ValueResolverInterface { /** * {@inheritdoc} @@ -40,19 +39,6 @@ public function resolve(Request $request, ArgumentMetadata $argument): iterable { $options = $argument->getAttributes(DataObjectParam::class, ArgumentMetadata::IS_INSTANCEOF); - if (!isset($options[0])) { - $converters = $request->attributes->get('_converters'); - $converter = $converters[0] ?? false; - if ($converter instanceof ParamConverter) { - trigger_deprecation( - 'pimcore/pimcore', - '10.6', - 'Usage of @ParamConverter annotation is deprecated. please use #[DataObjectParam] argument attribute instead.' - ); - $options[0] = new DataObjectParam($converter->getClass(), $converter->getOptions()['unpublished'] ?? null, $converter->getOptions()); - } - } - $class = $options[0]->class ?? $argument->getType(); if (null === $class || !is_subclass_of($class, AbstractObject::class)) { return []; @@ -67,7 +53,6 @@ public function resolve(Request $request, ArgumentMetadata $argument): iterable if (!$value && $argument->isNullable()) { $request->attributes->set($param, null); - return []; } @@ -87,13 +72,4 @@ public function resolve(Request $request, ArgumentMetadata $argument): iterable return [$object]; } - - public function supports(Request $request, ArgumentMetadata $argument) - { - if (null === $argument->getType()) { - return false; - } - - return is_subclass_of($argument->getType(), AbstractObject::class); - } } diff --git a/composer.json b/composer.json index 3e55d6d26a8..33dd9426f09 100644 --- a/composer.json +++ b/composer.json @@ -56,7 +56,7 @@ "doctrine/doctrine-bundle": "^2.6.3", "doctrine/doctrine-migrations-bundle": "^3.2.2", "doctrine/inflector": "^2.0.2", - "symfony/doctrine-messenger": "^6.1", + "symfony/doctrine-messenger": "^6.2", "egulias/email-validator": "^3.0.0", "endroid/qr-code": "^4", "friendsofsymfony/jsrouting-bundle": "^3.2.1", @@ -76,53 +76,53 @@ "matomo/device-detector": "^6.0", "presta/sitemap-bundle": "^3.3", "sabre/dav": "^4.1.2", - "sensio/framework-extra-bundle": "^6.2", "sensiolabs/ansi-to-html": "^1.1", "symfony-cmf/routing-bundle": "^3.0", "symfony/contracts": "^3.2", "symfony/monolog-bundle": "^3.8", - "symfony/asset": "^6.1", - "symfony/cache": "^6.1", - "symfony/config": "^6.1", - "symfony/console": "^6.1", - "symfony/dependency-injection": "^6.1", - "symfony/debug-bundle": "^6.1", - "symfony/dom-crawler": "^6.1", - "symfony/error-handler": "^6.1", - "symfony/event-dispatcher": "^6.1", - "symfony/expression-language": "^6.1", - "symfony/filesystem": "^6.1", - "symfony/finder": "^6.1", - "symfony/form": "^6.1", - "symfony/framework-bundle": "^6.1", - "symfony/http-foundation": "^6.1", - "symfony/http-kernel": "^6.1", - "symfony/lock": "^6.1", - "symfony/mailer": "^6.1", - "symfony/messenger": "^6.1", - "symfony/mime": "^6.1", - "symfony/options-resolver": "^6.1", - "symfony/password-hasher": "^6.1", - "symfony/process": "^6.1", - "symfony/property-access": "^6.1", - "symfony/rate-limiter": "^6.1", - "symfony/routing": "^6.1", - "symfony/security-bundle": "^6.1", - "symfony/security-core": "^6.1", - "symfony/security-http": "^6.1", - "symfony/serializer": "^6.1", - "symfony/stopwatch": "^6.1", - "symfony/templating": "^6.1", - "symfony/translation": "^6.1", - "symfony/twig-bridge": "^6.1", - "symfony/twig-bundle": "^6.1", - "symfony/uid": "^6.1", - "symfony/validator": "^6.1", - "symfony/var-dumper": "^6.1", - "symfony/web-link": "^6.1", - "symfony/web-profiler-bundle": "^6.1", - "symfony/workflow": "^6.1", - "symfony/yaml": "^6.1", + "symfony/asset": "^6.2", + "symfony/cache": "^6.2", + "symfony/config": "^6.2", + "symfony/console": "^6.2", + "symfony/dependency-injection": "^6.2", + "symfony/debug-bundle": "^6.2", + "symfony/dom-crawler": "^6.2", + "symfony/error-handler": "^6.2", + "symfony/event-dispatcher": "^6.2", + "symfony/expression-language": "^6.2", + "symfony/filesystem": "^6.2", + "symfony/finder": "^6.2", + "symfony/form": "^6.2", + "symfony/framework-bundle": "^6.2", + "symfony/http-foundation": "^6.2", + "symfony/http-kernel": "^6.2", + "symfony/lock": "^6.2", + "symfony/mailer": "^6.2", + "symfony/messenger": "^6.2", + "symfony/mime": "^6.2", + "symfony/options-resolver": "^6.2", + "symfony/password-hasher": "^6.2", + "symfony/process": "^6.2", + "symfony/property-access": "^6.2", + "symfony/rate-limiter": "^6.2", + "symfony/routing": "^6.2", + "symfony/security-bundle": "^6.2", + "symfony/security-core": "^6.2", + "symfony/security-http": "^6.2", + "symfony/serializer": "^6.2", + "symfony/stopwatch": "^6.2", + "symfony/templating": "^6.2", + "symfony/translation": "^6.2", + "symfony/doctrine-bridge": "^6.2", + "symfony/twig-bridge": "^6.2", + "symfony/twig-bundle": "^6.2", + "symfony/uid": "^6.2", + "symfony/validator": "^6.2", + "symfony/var-dumper": "^6.2", + "symfony/web-link": "^6.2", + "symfony/web-profiler-bundle": "^6.2", + "symfony/workflow": "^6.2", + "symfony/yaml": "^6.2", "tijsverkoyen/css-to-inline-styles": "^2.2.3", "twig/extra-bundle": "^3.4.0", "twig/twig": "^3.3.9", @@ -158,7 +158,7 @@ "composer/composer": "*", "chrome-php/chrome": "^1.4.0", "webmozarts/console-parallelization": "^2.1", - "symfony/dotenv": "^6.1" + "symfony/dotenv": "^6.2" }, "suggest": { "ext-sockets": "*", diff --git a/doc/Development_Documentation/02_MVC/00_Controller.md b/doc/Development_Documentation/02_MVC/00_Controller.md index dbbc5eefe49..32815b5feb8 100644 --- a/doc/Development_Documentation/02_MVC/00_Controller.md +++ b/doc/Development_Documentation/02_MVC/00_Controller.md @@ -23,10 +23,8 @@ In controllers, for every action there exists a separate method ending with the The `DefaultController` comes with Pimcore. When you create an empty page in Pimcore it will call the `defaultAction` in the `DefaultController` which uses the view `/templates/default/default.html.twig`. -You can render templates just the [standard Symfony way](https://symfony.com/doc/current/templates.html#rendering-a-template-in-emails), either by using: -- the render helper eg. `$this->render('foo.html.twig')` -- the `@Template()` [annotation](https://symfony.com/bundles/SensioFrameworkExtraBundle/current/annotations/view.html), altough this is deprecated and will not be supported in Pimcore 11. -- the `#Template[]` [attribute](https://symfony.com/doc/current/templates.html#rendering-a-template-in-controllers). +You can render templates just the [standard Symfony way](https://symfony.com/doc/current/templates.html#rendering-a-template-in-emails), by either using `$this->render('foo.html.twig')` or using the `#Template[]` [attribute](https://symfony.com/doc/current/templates.html#rendering-a-template-in-controllers). + ### Examples @@ -55,8 +53,6 @@ class DefaultController extends FrontendController * The frontend controller also provides methods to add response headers or via attributes without having * access to the final response object (as it is automatically created when rendering the view). * - * @Template - * @ResponseHeader("X-Foo", values={"123456", "98765"}) */ #[Template('/default/header.html.twig')] #[ResponseHeader(key: "X-Foo", values: ["123456", "98765"])] diff --git a/doc/Development_Documentation/02_MVC/02_Template/README.md b/doc/Development_Documentation/02_MVC/02_Template/README.md index 61db5f76c99..86b4f9708db 100644 --- a/doc/Development_Documentation/02_MVC/02_Template/README.md +++ b/doc/Development_Documentation/02_MVC/02_Template/README.md @@ -28,7 +28,7 @@ class MyController extends FrontendController */ #[Template('content/default.html.twig', vars: ['param1' => 'value1'])] public function attributeAction() - { + { } public function directRenderAction() diff --git a/doc/Development_Documentation/02_MVC/04_Routing_and_URLs/02_Custom_Routes.md b/doc/Development_Documentation/02_MVC/04_Routing_and_URLs/02_Custom_Routes.md index 8c2a64953e6..7e20a7bb4ca 100644 --- a/doc/Development_Documentation/02_MVC/04_Routing_and_URLs/02_Custom_Routes.md +++ b/doc/Development_Documentation/02_MVC/04_Routing_and_URLs/02_Custom_Routes.md @@ -11,7 +11,7 @@ All things where Documents are not practical. Here Custom Routes come into actio Custom Routes come fourth in the route processing priority. Custom routes are an alternative to Symfony's routing functionalities and give you a bit more flexibility, but you can -still use [Symfony's routing capabilities](https://symfony.com/doc/current/routing.html) (eg. @Route() annotation, +still use [Symfony's routing capabilities](https://symfony.com/doc/current/routing.html) (eg. #[Route] attribute, `routing.yaml`, ...) in parallel to Pimcore Custom Routes. ## Configuring Custom Routes @@ -63,16 +63,17 @@ class NewsController extends FrontendController The default variables can be accessed the same way. -## Using Param Converter to convert request ID to Data Object -Pimcore has a built-in [param converter](https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html) +## Using Param Resolver to convert request ID to Data Object +Pimcore has a built-in [param resolver](https://symfony.com/doc/current/controller/value_resolver.html#built-in-value-resolvers) for converting data object IDs in the request parameters to actual objects. -To use the param converter, simply type hint the argument (Symfony routing example): +To use the param resolver, simply type hint the argument (Symfony routing example): ```php use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Annotation\Route; .... + #[Template('/news/test')] #[Route('/news/{news}')] public function detailAction(DataObject\News $news) { diff --git a/doc/Development_Documentation/05_Objects/01_Object_Classes/01_Data_Types/65_Others.md b/doc/Development_Documentation/05_Objects/01_Object_Classes/01_Data_Types/65_Others.md index 446d73ab0b4..6fca807c0c5 100644 --- a/doc/Development_Documentation/05_Objects/01_Object_Classes/01_Data_Types/65_Others.md +++ b/doc/Development_Documentation/05_Objects/01_Object_Classes/01_Data_Types/65_Others.md @@ -147,7 +147,7 @@ class ProductController extends FrontendController { public function slugAction(Request $request, DataObject\Foo $object, DataObject\Data\UrlSlug $urlSlug) { - // we use param converters to the the matched data object ($object) + // we use param resolver to the the matched data object ($object) // $urlSlug contains the context information of the slug return [ diff --git a/doc/Development_Documentation/23_Installation_and_Upgrade/09_Upgrade_Notes/README.md b/doc/Development_Documentation/23_Installation_and_Upgrade/09_Upgrade_Notes/README.md index 17193019a1b..84dc8e09662 100644 --- a/doc/Development_Documentation/23_Installation_and_Upgrade/09_Upgrade_Notes/README.md +++ b/doc/Development_Documentation/23_Installation_and_Upgrade/09_Upgrade_Notes/README.md @@ -3,7 +3,7 @@ - [General] **Attention:** Added native php types for argument types, property types, return types and strict type declaration where possible. This results in **various bc breaks**. Please make sure to add the corresponding types to your implementation. - [UrlSlug] Removed `index` column and `index` index from `object_url_slugs` table as it was not being used anywhere. -- Bumped Symfony packages to "^6.1". Pimcore 11 will only support Symfony 6. +- Bumped Symfony packages to "^6.2". Pimcore 11 will only support Symfony 6. - `FrontendController::renderTemplate()`: Changed the visibility to `protected`. - [Elements] Added `setParentId`, `setType` and `setParent` methods to `Pimcore\Model\Element\ElementInterface` - [JSRouting Bundle] Bumped `friendsofsymfony/jsrouting-bundle` to version `^3.2.1` @@ -167,7 +167,11 @@ Please make sure to set your preferred storage location ***before*** migration. Also run command `bin/console messenger:consume pimcore_core` before the upgrade, so that `AssetUpdateTasksMessage` on the queue gets consumed. - [Events] Event `pimcore.element.note.postAdd` has been removed. Use `pimcore.note.postAdd` instead. Note: The event type changed from `ElementEvent` to `ModelEvent`. - [Environment] - Removed `symfony/dotenv` dependency to make loading of `.env` files optional. please add the requirement to your composer.json, if you still want to use `.env` files. - +- Removed deprecated `SensioFrameworkExtraBundle` which affects the following: + - `@Template` annotation must be replaced with `#[Template]` attribute. Template guessing based on controller::action is not supported anymore. + - `@ResponseHeader` annotation must be replaced with `#[ResponseHeader]` attribute. Removed deprecated `Pimcore\Controller\Configuration\ResponseHeader`. + - `@ParamConverter` annotation must be replaced with `#[DataObjectParam]` attribute. + Replace other annotations provided by [SensioFrameworkExtraBundle](https://symfony.com/bundles/SensioFrameworkExtraBundle/current/index.html#annotations-for-controllers) ## 10.6.0 - [Session] The `getHandler`, `setHandler`, `useSession`, `getSessionId`, `getSessionName`, `invalidate`, `regenerateId`, `requestHasSessionId`, `getSessionIdFromRequest`, `get`, `getReadOnly` and `writeClose` methods of `Pimcore\Tool\Session` and class `PreAuthenticatedAdminSessionFactory` are deprecated and get removed with Pimcore 11. Session Management will be handled by Symfony in Pimcore 11. diff --git a/lib/Controller/Attribute/ResponseHeader.php b/lib/Controller/Attribute/ResponseHeader.php index 823399fab1a..aed1a31ceee 100644 --- a/lib/Controller/Attribute/ResponseHeader.php +++ b/lib/Controller/Attribute/ResponseHeader.php @@ -17,8 +17,6 @@ namespace Pimcore\Controller\Attribute; -use Pimcore\Controller\Configuration\ResponseHeader as BaseResponseHeader; - /** * Allows to set HTTP headers on the response via attributes. The attribute will * be processed by ResponseHeaderListener which will set the HTTP headers on the @@ -28,6 +26,42 @@ * */ #[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD | \Attribute::TARGET_FUNCTION)] -final class ResponseHeader extends BaseResponseHeader +final class ResponseHeader { + public function __construct( + protected string $key, + protected string|array $values = '', + protected bool $replace = false + ) + {} + + public function getKey(): string + { + return $this->key; + } + + public function setKey(string $key): void + { + $this->key = $key; + } + + public function getValues(): array|string + { + return $this->values; + } + + public function setValues(array|string $values): void + { + $this->values = $values; + } + + public function getReplace(): bool + { + return $this->replace; + } + + public function setReplace(bool $replace): void + { + $this->replace = $replace; + } } diff --git a/lib/Controller/Configuration/ResponseHeader.php b/lib/Controller/Configuration/ResponseHeader.php deleted file mode 100644 index fdb2fddca6c..00000000000 --- a/lib/Controller/Configuration/ResponseHeader.php +++ /dev/null @@ -1,113 +0,0 @@ -key = $key; - $this->values = $values; - $this->replace = $replace; - } - - if (empty($this->key)) { - throw new \InvalidArgumentException('The ResponseHeader Annotation/Attribute needs at least a key to be set'); - } - } - - /** - * {@inheritdoc} - */ - public function getAliasName(): string - { - return 'response_header'; - } - - /** - * {@inheritdoc} - */ - public function allowArray(): bool - { - return true; - } - - public function getKey(): string - { - return $this->key; - } - - public function setKey(string $key): void - { - $this->key = $key; - } - - public function getValues(): array|string - { - return $this->values; - } - - public function setValues(array|string $values): void - { - $this->values = $values; - } - - public function getReplace(): bool - { - return $this->replace; - } - - public function setReplace(bool $replace): void - { - $this->replace = $replace; - } -} diff --git a/lib/Http/Request/Resolver/ResponseHeaderResolver.php b/lib/Http/Request/Resolver/ResponseHeaderResolver.php index 4549494899a..d4c04fe07c5 100644 --- a/lib/Http/Request/Resolver/ResponseHeaderResolver.php +++ b/lib/Http/Request/Resolver/ResponseHeaderResolver.php @@ -55,15 +55,11 @@ public function getResponseHeaders(Request $request = null): array */ public function addResponseHeader(Request $request, string $key, array|string $values, bool $replace = false): void { - // the array of headers set by the ResponseHeader annotation + // the array of headers set by the ResponseHeader attribute $responseHeaders = $this->getResponseHeaders($request); - // manually add a @ResponseHeader config annotation to the list of headers - $responseHeaders[] = new ResponseHeader([ - 'key' => $key, - 'values' => $values, - 'replace' => $replace, - ]); + // manually add a #[ResponseHeader] attribute to the list of headers + $responseHeaders[] = new ResponseHeader($key, $values, $replace); $request->attributes->set(static::ATTRIBUTE_RESPONSE_HEADER, $responseHeaders); } diff --git a/lib/Kernel.php b/lib/Kernel.php index 162c14c74a6..494022c90ca 100644 --- a/lib/Kernel.php +++ b/lib/Kernel.php @@ -29,7 +29,6 @@ use Pimcore\HttpKernel\BundleCollection\BundleCollection; use Presta\SitemapBundle\PrestaSitemapBundle; use Scheb\TwoFactorBundle\SchebTwoFactorBundle; -use Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle; use Symfony\Bundle\DebugBundle\DebugBundle; use Symfony\Bundle\FrameworkBundle\FrameworkBundle; use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait; @@ -320,7 +319,6 @@ protected function registerCoreBundlesToCollection(BundleCollection $collection) new MonologBundle(), new DoctrineBundle(), new DoctrineMigrationsBundle(), - new SensioFrameworkExtraBundle(), new CmfRoutingBundle(), new PrestaSitemapBundle(), new SchebTwoFactorBundle(), diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index e462178cf53..c88cae0661a 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -5,11 +5,6 @@ parameters: count: 3 path: bundles/CoreBundle/src/DependencyInjection/PimcoreCoreExtension.php - - - message: "#^If condition is always true\\.$#" - count: 1 - path: bundles/EcommerceFrameworkBundle/CartManager/CartPriceModificator/Discount.php - - message: "#^If condition is always true\\.$#" count: 1