Skip to content

Commit

Permalink
[UI] Force no-store cache directives for admin and customer account s…
Browse files Browse the repository at this point in the history
…ection
  • Loading branch information
lchrusciel authored and GSadee committed Mar 7, 2022
1 parent 67de9e8 commit 4b6a77a
Show file tree
Hide file tree
Showing 10 changed files with 358 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Sylius\Bundle\AdminBundle\EventListener;

use Sylius\Bundle\AdminBundle\SectionResolver\AdminSection;
use Sylius\Bundle\CoreBundle\SectionResolver\SectionProviderInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

final class AdminSectionCacheControlSubscriber implements EventSubscriberInterface
{
private SectionProviderInterface $sectionProvider;

public function __construct(SectionProviderInterface $sectionProvider)
{
$this->sectionProvider = $sectionProvider;
}

public static function getSubscribedEvents(): array
{
return [
KernelEvents::RESPONSE => 'setCacheControlDirectives',
];
}

public function setCacheControlDirectives(ResponseEvent $event): void
{
if (!$this->sectionProvider->getSection() instanceof AdminSection) {
return;
}

$response = $event->getResponse();

$response->headers->addCacheControlDirective('no-cache', true);
$response->headers->addCacheControlDirective('max-age', '0');
$response->headers->addCacheControlDirective('must-revalidate', true);
$response->headers->addCacheControlDirective('no-store', true);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,10 @@
<argument type="service" id="session" />
<tag name="kernel.event_subscriber" event="kernel.exception" />
</service>

<service id="sylius.event_subscriber.admin_cache_control_subscriber" class="Sylius\Bundle\AdminBundle\EventListener\AdminSectionCacheControlSubscriber">
<argument type="service" id="sylius.section_resolver.uri_based_section_resolver" />
<tag name="kernel.event_subscriber" event="kernel.response" />
</service>
</services>
</container>
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace spec\Sylius\Bundle\AdminBundle\EventListener;

use PhpSpec\ObjectBehavior;
use Sylius\Bundle\AdminBundle\EmailManager\ShipmentEmailManagerInterface;
use Sylius\Bundle\AdminBundle\SectionResolver\AdminSection;
use Sylius\Bundle\CoreBundle\SectionResolver\SectionInterface;
use Sylius\Bundle\CoreBundle\SectionResolver\SectionProviderInterface;
use Sylius\Component\Core\Model\ShipmentInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\KernelInterface;

final class AdminSectionCacheControlSubscriberSpec extends ObjectBehavior
{
function let(SectionProviderInterface $sectionProvider): void
{
$this->beConstructedWith($sectionProvider);
}

function it_subscribes_to_kernel_response_event()
{
$this::getSubscribedEvents()->shouldReturn([KernelEvents::RESPONSE => 'setCacheControlDirectives']);
}

function it_adds_cache_control_directives_to_admin_requests(
SectionProviderInterface $sectionProvider,
HttpKernelInterface $kernel,
Request $request,
Response $response,
ResponseHeaderBag $responseHeaderBag,
AdminSection $adminSection
): void {
$sectionProvider->getSection()->willReturn($adminSection);

$response->headers = $responseHeaderBag->getWrappedObject();

$event = new ResponseEvent(
$kernel->getWrappedObject(),
$request->getWrappedObject(),
KernelInterface::MASTER_REQUEST,
$response->getWrappedObject()
);

$responseHeaderBag->addCacheControlDirective('no-cache', true)->shouldBeCalled();
$responseHeaderBag->addCacheControlDirective('max-age', '0')->shouldBeCalled();
$responseHeaderBag->addCacheControlDirective('must-revalidate', true)->shouldBeCalled();
$responseHeaderBag->addCacheControlDirective('no-store', true)->shouldBeCalled();

$this->setCacheControlDirectives($event);
}

function it_does_nothing_if_section_is_different_then_admin(
SectionProviderInterface $sectionProvider,
HttpKernelInterface $kernel,
Request $request,
Response $response,
ResponseHeaderBag $responseHeaderBag,
SectionInterface $section
): void {
$sectionProvider->getSection()->willReturn($section);

$response->headers = $responseHeaderBag->getWrappedObject();

$event = new ResponseEvent(
$kernel->getWrappedObject(),
$request->getWrappedObject(),
KernelInterface::MASTER_REQUEST,
$response->getWrappedObject()
);

$responseHeaderBag->addCacheControlDirective('no-cache', true)->shouldNotBeCalled();
$responseHeaderBag->addCacheControlDirective('max-age', '0')->shouldNotBeCalled();
$responseHeaderBag->addCacheControlDirective('must-revalidate', true)->shouldNotBeCalled();
$responseHeaderBag->addCacheControlDirective('no-store', true)->shouldNotBeCalled();

$this->setCacheControlDirectives($event);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Sylius\Bundle\ShopBundle\EventListener;

use Sylius\Bundle\CoreBundle\SectionResolver\SectionProviderInterface;
use Sylius\Bundle\ShopBundle\SectionResolver\ShopCustomerAccountSubSection;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;

final class ShopCustomerAccountSubSectionCacheControlSubscriber implements EventSubscriberInterface
{
private SectionProviderInterface $sectionProvider;

public function __construct(SectionProviderInterface $sectionProvider)
{
$this->sectionProvider = $sectionProvider;
}

public static function getSubscribedEvents(): array
{
return [
KernelEvents::RESPONSE => 'setCacheControlDirectives',
];
}

public function setCacheControlDirectives(ResponseEvent $event): void
{
if (!$this->sectionProvider->getSection() instanceof ShopCustomerAccountSubSection) {
return;
}

$response = $event->getResponse();

$response->headers->addCacheControlDirective('no-cache', true);
$response->headers->addCacheControlDirective('max-age', '0');
$response->headers->addCacheControlDirective('must-revalidate', true);
$response->headers->addCacheControlDirective('no-store', true);
}
}
1 change: 1 addition & 0 deletions src/Sylius/Bundle/ShopBundle/Resources/config/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
</service>

<service id="sylius.section_resolver.shop_uri_based_section_resolver" class="Sylius\Bundle\ShopBundle\SectionResolver\ShopUriBasedSectionResolver">
<argument>account</argument>
<tag name="sylius.uri_based_section_resolver" priority="-10" />
</service>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
<tag name="kernel.event_listener" event="sylius.customer.post_update" method="sendVerificationEmail" />
</service>

<service id="sylius.listener.shop_customer_account_sub_section_cache_control_subscriber" class="Sylius\Bundle\ShopBundle\EventListener\ShopCustomerAccountSubSectionCacheControlSubscriber">
<argument type="service" id="sylius.section_resolver.uri_based_section_resolver" />
<tag name="kernel.event_subscriber" event="kernel.response" />
</service>

<service id="sylius.listener.order_customer_ip" class="Sylius\Bundle\ShopBundle\EventListener\OrderCustomerIpListener">
<argument type="service" id="sylius.customer_ip_assigner" />
<argument type="service" id="request_stack" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace Sylius\Bundle\ShopBundle\SectionResolver;

class ShopCustomerAccountSubSection extends ShopSection
{
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,19 @@

final class ShopUriBasedSectionResolver implements UriBasedSectionResolverInterface
{
private string $shopCustomerAccountResourceUri;

public function __construct(string $shopCustomerAccountResourceUri = 'account')
{
$this->shopCustomerAccountResourceUri = $shopCustomerAccountResourceUri;
}

public function getSection(string $uri): SectionInterface
{
if (str_contains($uri, $this->shopCustomerAccountResourceUri)) {
return new ShopCustomerAccountSubSection();
}

return new ShopSection();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace spec\Sylius\Bundle\ShopBundle\EventListener;

use PhpSpec\ObjectBehavior;
use Sylius\Bundle\CoreBundle\SectionResolver\SectionInterface;
use Sylius\Bundle\CoreBundle\SectionResolver\SectionProviderInterface;
use Sylius\Bundle\ShopBundle\SectionResolver\ShopCustomerAccountSubSection;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpKernel\Event\ResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\KernelInterface;

final class ShopCustomerAccountSubSectionCacheControlSubscriberSpec extends ObjectBehavior
{
function let(SectionProviderInterface $sectionProvider): void
{
$this->beConstructedWith($sectionProvider);
}

function it_subscribes_to_kernel_response_event()
{
$this::getSubscribedEvents()->shouldReturn([KernelEvents::RESPONSE => 'setCacheControlDirectives']);
}

function it_adds_cache_control_directives_to_customer_account_requests(
SectionProviderInterface $sectionProvider,
HttpKernelInterface $kernel,
Request $request,
Response $response,
ResponseHeaderBag $responseHeaderBag,
ShopCustomerAccountSubSection $customerAccountSubSection
): void {
$sectionProvider->getSection()->willReturn($customerAccountSubSection);

$response->headers = $responseHeaderBag->getWrappedObject();

$event = new ResponseEvent(
$kernel->getWrappedObject(),
$request->getWrappedObject(),
KernelInterface::MASTER_REQUEST,
$response->getWrappedObject()
);

$responseHeaderBag->addCacheControlDirective('no-cache', true)->shouldBeCalled();
$responseHeaderBag->addCacheControlDirective('max-age', '0')->shouldBeCalled();
$responseHeaderBag->addCacheControlDirective('must-revalidate', true)->shouldBeCalled();
$responseHeaderBag->addCacheControlDirective('no-store', true)->shouldBeCalled();

$this->setCacheControlDirectives($event);
}

function it_does_nothing_if_section_is_different_then_customer_account(
SectionProviderInterface $sectionProvider,
HttpKernelInterface $kernel,
Request $request,
Response $response,
ResponseHeaderBag $responseHeaderBag,
SectionInterface $section
): void {
$sectionProvider->getSection()->willReturn($section);

$response->headers = $responseHeaderBag->getWrappedObject();

$event = new ResponseEvent(
$kernel->getWrappedObject(),
$request->getWrappedObject(),
KernelInterface::MASTER_REQUEST,
$response->getWrappedObject()
);

$responseHeaderBag->addCacheControlDirective('no-cache', true)->shouldNotBeCalled();
$responseHeaderBag->addCacheControlDirective('max-age', '0')->shouldNotBeCalled();
$responseHeaderBag->addCacheControlDirective('must-revalidate', true)->shouldNotBeCalled();
$responseHeaderBag->addCacheControlDirective('no-store', true)->shouldNotBeCalled();

$this->setCacheControlDirectives($event);
}
}
Loading

0 comments on commit 4b6a77a

Please sign in to comment.