Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/10.6' into 11.x
Browse files Browse the repository at this point in the history
# Conflicts:
#	bundles/CoreBundle/src/Request/ParamConverter/DataObjectParamConverter.php
#	bundles/CoreBundle/src/Request/ParamConverter/DataObjectParamResolver.php
#	doc/Development_Documentation/02_MVC/00_Controller.md
#	doc/Development_Documentation/02_MVC/04_Routing_and_URLs/02_Custom_Routes.md
#	doc/Development_Documentation/23_Installation_and_Upgrade/09_Upgrade_Notes/README.md
#	lib/Controller/Configuration/ResponseHeader.php
#	phpstan-baseline.neon
  • Loading branch information
kingjia90 committed Feb 7, 2023
2 parents 98a5bf1 + 2c5dd1c commit 31f572e
Show file tree
Hide file tree
Showing 14 changed files with 231 additions and 127 deletions.
4 changes: 2 additions & 2 deletions bundles/CoreBundle/config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,9 @@ services:
public: true
class: Pimcore\Model\DataObject\QuantityValue\DefaultConverter

Pimcore\Bundle\CoreBundle\Request\ParamConverter\DataObjectParamConverter:
Pimcore\Bundle\CoreBundle\Request\ParamConverter\DataObjectParamResolver:
tags:
- { name: request.param_converter, priority: -2, converter: data_object_converter }
- { name: controller.argument_value_resolver, priority: 101}

Symfony\Component\Lock\PersistingStoreInterface:
class: Symfony\Component\Lock\Store\DoctrineDbalStore
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

namespace Pimcore\Bundle\CoreBundle\EventListener;

use Pimcore\Controller\Attribute\ResponseHeader;
use Pimcore\Http\Request\Resolver\ResponseHeaderResolver;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
Expand Down Expand Up @@ -51,6 +52,13 @@ 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.'
);
}
$response->headers->set($header->getKey(), $header->getValues(), $header->getReplace());
}
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php
declare(strict_types=1);

/**
* Pimcore
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license http://www.pimcore.org/license GPLv3 and PCL
*/

namespace Pimcore\Bundle\CoreBundle\Request\ParamConverter;

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\ControllerMetadata\ArgumentMetadata;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;

/**
* @internal
*/
class DataObjectParamResolver implements ArgumentValueResolverInterface
{
/**
* {@inheritdoc}
*
* @throws NotFoundHttpException When invalid data object ID given
*/
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 [];
}

$param = $argument->getName();
if (!$request->attributes->has($param)) {
return [];
}

$value = $request->attributes->get($param);

if (!$value && $argument->isNullable()) {
$request->attributes->set($param, null);
return [];
}

/** @var Concrete|null $object */
$object = $class::getById($value);
if (!$object) {
throw new NotFoundHttpException(sprintf('Invalid data object ID given for parameter "%s".', $param));
} elseif (
!$object->isPublished()
&& !Tool::isElementRequestByAdmin($request, $object)
&& (!isset($options[0]) || !$options[0]->unpublished)
) {
throw new NotFoundHttpException(sprintf('Data object for parameter "%s" is not published.', $param));
}

$request->attributes->set($param, $object);

return [$object];
}

public function supports(Request $request, ArgumentMetadata $argument)
{
if (null === $argument->getType()) {
return false;
}

return is_subclass_of($argument->getType(), AbstractObject::class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -295,14 +295,12 @@ Therefore create another action in the controller (ContentController) called `pr
namespace App\Controller;

use Pimcore\Controller\FrontendController;
use Symfony\Bridge\Twig\Attribute\Template;
use Symfony\Component\HttpFoundation\Request;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;

class ContentController extends FrontendController
{
/**
* @Template
*/
#[Template('content/default.html.twig')]
public function defaultAction (Request $request)
{
return [];
Expand Down
14 changes: 9 additions & 5 deletions doc/Development_Documentation/02_MVC/00_Controller.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ 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), by either using `$this->render('foo.html.twig')` or using the `@Template()` [annotation](https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/view.html).

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).

### Examples

Expand All @@ -36,7 +38,7 @@ namespace App\Controller;
use Pimcore\Controller\FrontendController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Pimcore\Controller\Configuration\ResponseHeader;
use Pimcore\Controller\Attribute\ResponseHeader;

class DefaultController extends FrontendController
{
Expand All @@ -49,13 +51,15 @@ class DefaultController extends FrontendController
}

/**
* Example using the @Template annotation and auto-resolving the template using the controller/action name.
* The frontend controller also provides methods to add response headers via annotation without having
* Example using the #[Template] attribute to resolve the view.
* 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"])]
public function headerAction(Request $request)
{
// schedule a response header via code
Expand Down
13 changes: 6 additions & 7 deletions doc/Development_Documentation/02_MVC/02_Template/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,24 @@ Pimcore uses the Twig templating engine, you can use Twig exactly as documented
* [Symfony Templating Documentation](https://symfony.com/doc/current/templating.html)
* Check also our [Demo](https://github.com/pimcore/demo) as starting point

Just use annotations or render the view directly to use Twig:
Just use attributes or render the view directly to use Twig:

```php
<?php

namespace App\Controller;

use Pimcore\Controller\FrontendController;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bridge\Twig\Attribute\Template;

class MyController extends FrontendController
{
/**
* The annotation will automatically resolve the view to MyController/myAnnotatedAction.html.twig
*
* @Template()
* The attribute will resolve the defined view
*/
public function myAnnotatedAction()
{
#[Template('content/default.html.twig', vars: ['param1' => 'value1'])]
public function attributeAction()
{
}

public function directRenderAction()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,28 +70,26 @@ 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):

```php
/**
* @Template
* @Route("/news/{news}")
*/
public function testAction(DataObject\News $news) {
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Annotation\Route;
....
#[Template('/news/test')]
#[Route('/news/{news}')]
public function detailAction(DataObject\News $news) {
return [
'news' => $news
];
}
```

Param converters work with Pimcore Custom Routes as well as with Symfony Routes.
Of course, you can also configure the param converter using the `@ParamConverter`, for details please have a look at
the official documentation for [param converters](https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/converters.html).
Param resolvers work with Pimcore Custom Routes as well as with Symfony Routes.

By taking advantage of the options that we can pass further on to the object, we can also work with unpublished objects.
By taking advantage of `#[DataObjectParam]` attribute, we can pass further options on to the object, e.g. working with unpublished objects.
````php
/**

@route("/blog/{post}")
@ParamConverter( "post", options={ "unpublished" = true } )
*/
public function detailAction(
#[DataObjectParam(unpublished: true)] DataObject\News $news) {
...
}
````

## Building URLs based on Custom Routes
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,11 @@ Please make sure to set your preferred storage location ***before*** migration.
- [Commands] Calling `configureParallelization` on `Parallelization` trait is deprecated and will be removed in Pimcore 11. Please call `Parallelization::configureCommand` instead.
- [Events] Event `pimcore.element.note.postAdd` has been deprecated. Use `pimcore.note.postAdd` instead. Note: The event type changed from `ElementEvent` to `ModelEvent`.
- [Document] Deprecated loading documents via fixed namespace only. It will be removed in Pimcore 11. Use `pimcore:type_definitions instead`
- [Annotations] Using Annotations `@ResponseHeader` & `@ParamConverter`, `@Template` and
rest from [SensioFrameworkExtraBundle](https://symfony.com/bundles/SensioFrameworkExtraBundle/current/index.html#annotations-for-controllers) is deprecated and will not be supported on Pimcore 11.
Use `#[ResponseHeader]`,`#[DataObjectParam]` argument, `#[Template]` and other attributes instead.
- [Navigation] Changed the navigation building process. It is easier to add main and submenus. For details please see [Adding Custom Main Navigation Items](https://pimcore.com/docs/pimcore/11.0/Development_Documentation/Extending_Pimcore/Bundle_Developers_Guide/Event_Listener_UI.html#page_Adding-Custom-Main-Navigation-Items)

## 10.5.13
- [Web2Print] Print document twig expressions are now executed in a sandbox with restrictive security policies (just like Sending mails and Dataobject Text Layouts introduced in 10.5.9).

Expand Down
33 changes: 33 additions & 0 deletions lib/Controller/Attribute/ResponseHeader.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

/**
* Pimcore
*
* This source file is available under two different licenses:
* - GNU General Public License version 3 (GPLv3)
* - Pimcore Commercial License (PCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (http://www.pimcore.org)
* @license http://www.pimcore.org/license GPLv3 and PCL
*/

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
* response.
*
* See ResponseHeaderBag for documentation on the fields.
*
*/
#[\Attribute(\Attribute::IS_REPEATABLE | \Attribute::TARGET_METHOD | \Attribute::TARGET_FUNCTION)]
final class ResponseHeader extends BaseResponseHeader
{
}
Loading

0 comments on commit 31f572e

Please sign in to comment.