Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[HttpKernel][FrameworkBundle] SSI support #10702

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 25, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public function getConfigTreeBuilder()
$this->addCsrfSection($rootNode);
$this->addFormSection($rootNode);
$this->addEsiSection($rootNode);
$this->addSsiSection($rootNode);
$this->addFragmentsSection($rootNode);
$this->addProfilerSection($rootNode);
$this->addRouterSection($rootNode);
Expand Down Expand Up @@ -148,6 +149,17 @@ private function addEsiSection(ArrayNodeDefinition $rootNode)
;
}

private function addSsiSection(ArrayNodeDefinition $rootNode)
{
$rootNode
->children()
->arrayNode('ssi')
->info('ssi configuration')
->canBeEnabled()
->end()
->end();
}

private function addFragmentsSection(ArrayNodeDefinition $rootNode)
{
$rootNode
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ public function load(array $configs, ContainerBuilder $container)

$this->registerValidationConfiguration($config['validation'], $container, $loader);
$this->registerEsiConfiguration($config['esi'], $container, $loader);
$this->registerSsiConfiguration($config['ssi'], $container, $loader);
$this->registerFragmentsConfiguration($config['fragments'], $container, $loader);
$this->registerProfilerConfiguration($config['profiler'], $container, $loader);
$this->registerTranslatorConfiguration($config['translator'], $container);
Expand Down Expand Up @@ -208,6 +209,22 @@ private function registerEsiConfiguration(array $config, ContainerBuilder $conta
$loader->load('esi.xml');
}

/**
* Loads the SSI configuration.
*
* @param array $config An SSI configuration array
* @param ContainerBuilder $container A ContainerBuilder instance
* @param XmlFileLoader $loader An XmlFileLoader instance
*/
private function registerSsiConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
{
if (!$this->isConfigEnabled($container, $config)) {
return;
}

$loader->load('ssi.xml');
}

/**
* Loads the fragments configuration.
*
Expand Down
16 changes: 14 additions & 2 deletions src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public function __construct(HttpKernelInterface $kernel, $cacheDir = null)
$this->kernel = $kernel;
$this->cacheDir = $cacheDir;

parent::__construct($kernel, $this->createStore(), $this->createEsi(), array_merge(array('debug' => $kernel->isDebug()), $this->getOptions()));
parent::__construct($kernel, $this->createStore(), $this->createSurrogate(), array_merge(array('debug' => $kernel->isDebug()), $this->getOptions()));
}

/**
Expand All @@ -55,7 +55,7 @@ protected function forward(Request $request, $raw = false, Response $entry = nul
{
$this->getKernel()->boot();
$this->getKernel()->getContainer()->set('cache', $this);
$this->getKernel()->getContainer()->set('esi', $this->getEsi());
$this->getKernel()->getContainer()->set($this->getSurrogate()->getName(), $this->getSurrogate());

return parent::forward($request, $raw, $entry);
}
Expand All @@ -70,6 +70,18 @@ protected function getOptions()
return array();
}

protected function createSurrogate()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you cannot rename the method. It is a BC break. If a child class is overwriting it (which is allowed as it is protected so it is an extension point), your change means that the override is not taken into account anymore.

If you want to have createSurrogate, you need to keep the createEsi method (but deprecating it) and calling it in the new method, so that BC is preserved

{
return $this->createEsi();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you just use return new ESI() here instead?

}

/**
* Creates new ESI instance
*
* @return Esi
*
* @deprecated Deprecated since version 2.6, to be removed in 3.0. Use createSurrogate() instead
*/
protected function createEsi()
{
return new Esi();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about here ? shouldn't be Esi renamed too ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't decide myself (and later I forgot). Problem is, to what should I rename it? You can overwrite it in your applications AppCache-class with

protected function createSurrogate()
{
    return new Ssi();
}

That's not perfect, but it works and is backward compatible. The other solution is to provide two separate FrameworkBundle:HttpCache\HttpCache-classes...

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
<parameter key="fragment.renderer.hinclude.class">Symfony\Bundle\FrameworkBundle\Fragment\ContainerAwareHIncludeFragmentRenderer</parameter>
<parameter key="fragment.renderer.hinclude.global_template"></parameter>
<parameter key="fragment.renderer.esi.class">Symfony\Component\HttpKernel\Fragment\EsiFragmentRenderer</parameter>
<parameter key="fragment.renderer.ssi.class">Symfony\Component\HttpKernel\Fragment\SsiFragmentRenderer</parameter>
<parameter key="fragment.path">/_fragment</parameter>
</parameters>

Expand Down Expand Up @@ -41,5 +42,17 @@
<argument type="service" id="fragment.renderer.inline" />
<call method="setFragmentPath"><argument>%fragment.path%</argument></call>
</service>

<service id="fragment.renderer.ssi" class="%fragment.renderer.ssi.class%">
<tag name="kernel.fragment_renderer" />
<argument type="service" id="ssi" on-invalid="null" />
<argument type="service" id="fragment.renderer.inline" />
<call method="setFragmentPath">
<argument>%fragment.path%</argument>
</call>
<call method="setUriSigner">
<argument type="service" id="uri_signer" />
</call>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of setUriSigner, make this optional __construct() param & use DI addArgument()?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really care, but the rationale behind that was, that it keeps the constructor signatures in sync and beside that it already uses setter injection for the fragment path. Any other suggestions?

Btw: Why addArgument()? It's in no form somehow dynamic, so it can be defined in the services.xml without any hassle.

</service>
</services>
</container>
20 changes: 20 additions & 0 deletions src/Symfony/Bundle/FrameworkBundle/Resources/config/ssi.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?xml version="1.0" ?>

<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">

<parameters>
<parameter key="ssi.class">Symfony\Component\HttpKernel\HttpCache\Ssi</parameter>
<parameter key="ssi_listener.class">Symfony\Component\HttpKernel\EventListener\SurrogateListener</parameter>
</parameters>

<services>
<service id="ssi" class="%ssi.class%" />

<service id="ssi_listener" class="%ssi_listener.class%">
<tag name="kernel.event_subscriber" />
<argument type="service" id="ssi" on-invalid="ignore" />
</service>
</services>
</container>
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ protected static function getBundleDefaultConfig()
'field_name' => '_token',
),
'esi' => array('enabled' => false),
'ssi' => array('enabled' => false),
'fragments' => array(
'enabled' => false,
'path' => '/_fragment',
Expand Down
41 changes: 3 additions & 38 deletions src/Symfony/Component/HttpKernel/EventListener/EsiListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,48 +11,13 @@

namespace Symfony\Component\HttpKernel\EventListener;

use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpKernel\HttpCache\Esi;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* EsiListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for ESI.
*
* @author Fabien Potencier <[email protected]>
*
* @deprecated Deprecated since version 2.6, to be removed in 3.0. Use SurrogateListener instead
*/
class EsiListener implements EventSubscriberInterface
class EsiListener extends SurrogateListener
{
private $esi;

/**
* Constructor.
*
* @param Esi $esi An ESI instance
*/
public function __construct(Esi $esi = null)
{
$this->esi = $esi;
}

/**
* Filters the Response.
*
* @param FilterResponseEvent $event A FilterResponseEvent instance
*/
public function onKernelResponse(FilterResponseEvent $event)
{
if (!$event->isMasterRequest() || null === $this->esi) {
return;
}

$this->esi->addSurrogateControl($event->getResponse());
}

public static function getSubscribedEvents()
{
return array(
KernelEvents::RESPONSE => 'onKernelResponse',
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\HttpKernel\EventListener;

use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
* SurrogateListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for Surrogates
*
* @author Fabien Potencier <[email protected]>
*/
class SurrogateListener implements EventSubscriberInterface
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

renaming the class is a BC break. You need to keep the old one (marking it as deprecated)

{
private $surrogate;

/**
* Constructor.
*
* @param SurrogateInterface $surrogate An SurrogateInterface instance
*/
public function __construct(SurrogateInterface $surrogate = null)
{
$this->surrogate = $surrogate;
}

/**
* Filters the Response.
*
* @param FilterResponseEvent $event A FilterResponseEvent instance
*/
public function onKernelResponse(FilterResponseEvent $event)
{
if (!$event->isMasterRequest() || null === $this->surrogate) {
return;
}

$this->surrogate->addSurrogateControl($event->getResponse());
}

public static function getSubscribedEvents()
{
return array(
KernelEvents::RESPONSE => 'onKernelResponse',
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\HttpKernel\Fragment;

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface;

/**
* Implements Surrogate rendering strategy.
*
* @author Fabien Potencier <[email protected]>
*/
abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRenderer
{
private $surrogate;
private $inlineStrategy;

/**
* Constructor.
*
* The "fallback" strategy when surrogate is not available should always be an
* instance of InlineFragmentRenderer.
*
* @param SurrogateInterface $surrogate An Surrogate instance
* @param FragmentRendererInterface $inlineStrategy The inline strategy to use when the surrogate is not supported
*/
public function __construct(SurrogateInterface $surrogate = null, FragmentRendererInterface $inlineStrategy)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks wrong, first param shouln't be optional if second is required...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is already the existing signature. = null is not really about making the argument optional, but about making it nullable

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly (I've tried it out...)

{
$this->surrogate = $surrogate;
$this->inlineStrategy = $inlineStrategy;
}

/**
* {@inheritdoc}
*
* Note that if the current Request has no surrogate capability, this method
* falls back to use the inline rendering strategy.
*
* Additional available options:
*
* * alt: an alternative URI to render in case of an error
* * comment: a comment to add when returning the surrogate tag
*
* Note, that not all surrogate strategies support all options. For now
* 'alt' and 'comment' are only supported by ESI.
*
* @see Symfony\Component\HttpKernel\HttpCache\SurrogateInterface
*/
public function render($uri, Request $request, array $options = array())
{
if (!$this->surrogate || !$this->surrogate->hasSurrogateCapability($request)) {
return $this->inlineStrategy->render($uri, $request, $options);
}

if ($uri instanceof ControllerReference) {
$uri = $this->generateFragmentUri($uri, $request);
}

$alt = isset($options['alt']) ? $options['alt'] : null;
if ($alt instanceof ControllerReference) {
$alt = $this->generateFragmentUri($alt, $request);
}

$tag = $this->surrogate->renderIncludeTag($uri, $alt, isset($options['ignore_errors']) ? $options['ignore_errors'] : false, isset($options['comment']) ? $options['comment'] : '');

return new Response($tag);
}
}
Loading