Skip to content

Commit 41b6821

Browse files
Add AjaxTemplate attribute + listener and listener for setting custom response object
1 parent d2e8b6e commit 41b6821

File tree

3 files changed

+92
-0
lines changed

3 files changed

+92
-0
lines changed
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace App\Twig\Attribute;
4+
5+
use Attribute;
6+
use Symfony\Bridge\Twig\Attribute\Template;
7+
8+
/**
9+
* This attribute can be used to render a different template when the request is an AJAX request.
10+
*/
11+
#[Attribute(Attribute::TARGET_CLASS | Attribute::TARGET_METHOD | Attribute::TARGET_FUNCTION)]
12+
class AjaxTemplate extends Template
13+
{
14+
/**
15+
* @param array<mixed, mixed>|null $vars
16+
*/
17+
public function __construct(
18+
string $normalTemplate,
19+
public string $ajaxTemplate,
20+
?array $vars = null,
21+
bool $stream = false,
22+
) {
23+
parent::__construct($normalTemplate, $vars, $stream);
24+
}
25+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace App\Twig\EventListener;
4+
5+
use App\Twig\Attribute\AjaxTemplate;
6+
use Symfony\Bridge\Twig\Attribute\Template;
7+
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
8+
use Symfony\Component\HttpKernel\Event\ViewEvent;
9+
10+
class AjaxTemplateAttributeListener
11+
{
12+
// Priority needs to be > -128 to come before TemplateAttributeListener
13+
#[AsEventListener]
14+
public function onKernelView(ViewEvent $event): void
15+
{
16+
// Based on Symfony's TemplateAttributeListener
17+
18+
/** @var AjaxTemplate|null $ajaxTemplateAttribute */
19+
$ajaxTemplateAttribute = $event->controllerArgumentsEvent?->getAttributes(AjaxTemplate::class)[0] ?? null;
20+
if (!$ajaxTemplateAttribute) {
21+
return;
22+
}
23+
24+
// Create the template attribute that Symfony can use
25+
$template = new Template(
26+
template: $event->getRequest()->isXmlHttpRequest() ? $ajaxTemplateAttribute->ajaxTemplate : $ajaxTemplateAttribute->template,
27+
vars: $ajaxTemplateAttribute->vars,
28+
stream: $ajaxTemplateAttribute->stream,
29+
);
30+
$attributes = $event->controllerArgumentsEvent?->getAttributes();
31+
$attributes[Template::class] = [$template];
32+
$event->controllerArgumentsEvent?->setController($event->controllerArgumentsEvent->getController(), $attributes);
33+
}
34+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace App\Twig\EventListener;
4+
5+
use Symfony\Component\EventDispatcher\Attribute\AsEventListener;
6+
use Symfony\Component\HttpFoundation\Response;
7+
use Symfony\Component\HttpKernel\Event\ResponseEvent;
8+
9+
/**
10+
* This listener allows one to set a custom response object in a controller.
11+
* It will then use that response, but use the content of the original controller response.
12+
*/
13+
class CustomResponseListener
14+
{
15+
protected ?Response $response = null;
16+
17+
public function setCustomResponse(Response $response): void
18+
{
19+
$this->response = $response;
20+
}
21+
22+
#[AsEventListener]
23+
public function onKernelResponse(ResponseEvent $event): void
24+
{
25+
if ($this->response) {
26+
$this->response->setContent($event->getResponse()->getContent());
27+
$event->setResponse($this->response);
28+
29+
// Make sure to clear the response if we have more requests after this one.
30+
$this->response = null;
31+
}
32+
}
33+
}

0 commit comments

Comments
 (0)