8000 feature #10702 [HttpKernel][FrameworkBundle] SSI support (KingCrunch) · symfony/symfony@bf140a8 · GitHub
[go: up one dir, main page]

Skip to content

Commit bf140a8

Browse files
committed
feature #10702 [HttpKernel][FrameworkBundle] SSI support (KingCrunch)
This PR was merged into the 2.6-dev branch. Discussion ---------- [HttpKernel][FrameworkBundle] SSI support | Q | A | ------------- | --- | Bug fix? | No | New feature? | Yes | BC breaks? | No | Deprecations? | No | Tests pass? | Yes | Fixed tickets | #9419 (, #10684) | License | MIT It does not support comments, or alternative URIs, or "continue" in case of errors. Maybe I can workaround that, but I've decided to left it out for this PR. Especially as far as I can see a "alternative URIs"-hack would _always_ lead to two requests, even if it's not needed. Commits ------- 06cea08 SSI support
2 parents fb9dc6a + 06cea08 commit bf140a8

22 files changed

+1019
-207
lines changed

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Configuration.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public function getConfigTreeBuilder()
8181
$this->addCsrfSection($rootNode);
8282
$this->addFormSection($rootNode);
8383
$this->addEsiSection($rootNode);
84+
$this->addSsiSection($rootNode);
8485
$this->addFragmentsSection($rootNode);
8586
$this->addProfilerSection($rootNode);
8687
$this->addRouterSection($rootNode);
@@ -148,6 +149,17 @@ private function addEsiSection(ArrayNodeDefinition $rootNode)
148149
;
149150
}
150151

152+
private function addSsiSection(ArrayNodeDefinition $rootNode)
153+
{
154+
$rootNode
155+
->children()
156+
->arrayNode('ssi')
157+
->info('ssi configuration')
158+
->canBeEnabled()
159+
->end()
160+
->end();
161+
}
162+
151163
private function addFragmentsSection(ArrayNodeDefinition $rootNode)
152164
{
153165
$rootNode

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ public function load(array $configs, ContainerBuilder $container)
122122

123123
$this->registerValidationConfiguration($config['validation'], $container, $loader);
124124
$this->registerEsiConfiguration($config['esi'], $container, $loader);
125+
$this->registerSsiConfiguration($config['ssi'], $container, $loader);
125126
$this->registerFragmentsConfiguration($config['fragments'], $container, $loader);
126127
$this->registerProfilerConfiguration($config['profiler'], $container, $loader);
127128
$this->registerTranslatorConfiguration($config['translator'], $container);
@@ -208,6 +209,22 @@ private function registerEsiConfiguration(array $config, ContainerBuilder $conta
208209
$loader->load('esi.xml');
209210
}
210211

212+
/**
213+
* Loads the SSI configuration.
214+
*
215+
* @param array $config An SSI configuration array
216+
* @param ContainerBuilder $container A ContainerBuilder instance
217+
* @param XmlFileLoader $loader An XmlFileLoader instance
218+
*/
219+
private function registerSsiConfiguration(array $config, ContainerBuilder $container, XmlFileLoader $loader)
220+
{
221+
if (!$this->isConfigEnabled($container, $config)) {
222+
return;
223+
}
224+
225+
$loader->load('ssi.xml');
226+
}
227+
211228
/**
212229
* Loads the fragments configuration.
213230
*

src/Symfony/Bundle/FrameworkBundle/HttpCache/HttpCache.php

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public function __construct(HttpKernelInterface $kernel, $cacheDir = null)
3939
$this->kernel = $kernel;
4040
$this->cacheDir = $cacheDir;
4141

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

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

6060
return parent::forward($request, $raw, $entry);
6161
}
@@ -70,6 +70,18 @@ protected function getOptions()
7070
return array();
7171
}
7272

73+
protected function createSurrogate()
74+
{
75+
return $this->createEsi();
76+
}
77+
78+
/**
79+
* Creates new ESI instance
80+
*
81+
* @return Esi
82+
*
83+
* @deprecated Deprecated since version 2.6, to be removed in 3.0. Use createSurrogate() instead
84+
*/
7385
protected function createEsi()
7486
{
7587
return new Esi();

src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<parameter key="fragment.renderer.hinclude.class">Symfony\Bundle\FrameworkBundle\Fragment\ContainerAwareHIncludeFragmentRenderer</parameter>
1111
<parameter key="fragment.renderer.hinclude.global_template"></parameter>
1212
<parameter key="fragment.renderer.esi.class">Symfony\Component\HttpKernel\Fragment\EsiFragmentRenderer</parameter>
13+
<parameter key="fragment.renderer.ssi.class">Symfony\Component\HttpKernel\Fragment\SsiFragmentRenderer</parameter>
1314
<parameter key="fragment.path">/_fragment</parameter>
1415
</parameters>
1516

@@ -41,5 +42,17 @@
4142
<argument type="service" id="fragment.renderer.inline" />
4243
<call method="setFragmentPath"><argument>%fragment.path%</argument></call>
4344
</service>
45+
46+
<service id="fragment.renderer.ssi" class="%fragment.renderer.ssi.class%">
47+
<tag name="kernel.fragment_renderer" />
48+
<argument type="service" id="ssi" on-invalid="null" />
49+
<argument type="service" id="fragment.renderer.inline" />
50+
<call method="setFragmentPath">
51+
<argument>%fragment.path%</argument>
52+
</call>
53+
<call method="setUriSigner">
54+
<argument type="service" id="uri_signer" />
55+
</call>
56+
</service>
4457
</services>
4558
</container>
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?xml version="1.0" ?>
2+
3+
<container xmlns="http://symfony.com/schema/dic/services"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
5+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
6+
7+
<parameters>
8+
<parameter key="ssi.class">Symfony\Component\HttpKernel\HttpCache\Ssi</parameter>
9+
<parameter key="ssi_listener.class">Symfony\Component\HttpKernel\EventListener\SurrogateListener</parameter>
10+
</parameters>
11+
12+
<services>
13+
<service id="ssi" class="%ssi.class%" />
14+
15+
<service id="ssi_listener" class="%ssi_listener.class%">
16+
<tag name="kernel.event_subscriber" />
17+
<argument type="service" id="ssi" on-invalid="ignore" />
18+
</service>
19+
</services>
20+
</container>

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/ConfigurationTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ protected static function getBundleDefaultConfig()
105105
'field_name' => '_token',
106106
),
107107
'esi' => array('enabled' => false),
108+
'ssi' => array('enabled' => false),
108109
'fragments' => array(
109110
'enabled' => false,
110111
'path' => '/_fragment',

src/Symfony/Component/HttpKernel/EventListener/EsiListener.php

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -11,48 +11,13 @@
1111

1212
namespace Symfony\Component\HttpKernel\EventListener;
1313

14-
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
15-
use Symfony\Component\HttpKernel\KernelEvents;
16-
use Symfony\Component\HttpKernel\HttpCache\Esi;
17-
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18-
1914
/**
2015
* EsiListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for ESI.
2116
*
2217
* @author Fabien Potencier <fabien@symfony.com>
18+
*
19+
* @deprecated Deprecated since version 2.6, to be removed in 3.0. Use SurrogateListener instead
2320
*/
24-
class EsiListener implements EventSubscriberInterface
21+
class EsiListener extends SurrogateListener
2522
{
26-
private $esi;
27-
28-
/**
29-
* Constructor.
30-
*
31-
* @param Esi $esi An ESI instance
32-
*/
33-
public function __construct(Esi $esi = null)
34-
{
35-
$this->esi = $esi;
36-
}
37-
38-
/**
39-
* Filters the Response.
40-
*
41-
* @param FilterResponseEvent $event A FilterResponseEvent instance
42-
*/
43-
public function onKernelResponse(FilterResponseEvent $event)
44-
{
45-
if (!$event->isMasterRequest() || null === $this->esi) {
46-
return;
47-
}
48-
49-
$this->esi->addSurrogateControl($event->getResponse());
50-
}
51-
52-
public static function getSubscribedEvents()
53-
{
54-
return array(
55-
KernelEvents::RESPONSE => 'onKernelResponse',
56-
);
57-
}
5823
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpKernel\EventListener;
13+
14+
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
15+
use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface;
16+
use Symfony\Component\HttpKernel\KernelEvents;
17+
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
18+
19+
/**
20+
* SurrogateListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for Surrogates
21+
*
22+
* @author Fabien Potencier <fabien@symfony.com>
23+
*/
24+
class SurrogateListener implements EventSubscriberInterface
25+
{
26+
private $surrogate;
27+
28+
/**
29+
* Constructor.
30+
*
31+
* @param SurrogateInterface $surrogate An SurrogateInterface instance
32+
*/
33+
public function __construct(SurrogateInterface $surrogate = null)
34+
{
35+
$this->surrogate = $surrogate;
36+
}
37+
38+
/**
39+
* Filters the Response.
40+
*
41+
* @param FilterResponseEvent $event A FilterResponseEvent instance
42+
*/
43+
public function onKernelResponse(FilterResponseEvent $event)
44+
{
45+
if (!$event->isMasterRequest() || null === $this->surrogate) {
46+
return;
47+
}
48+
49+
$this->surrogate->addSurrogateControl($event->getResponse());
50+
}
51+
52+
public static function getSubscribedEvents()
53+
{
54+
return array(
55+
KernelEvents::RESPONSE => 'onKernelResponse',
56+
);
57+
}
58+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\HttpKernel\Fragment;
13+
14+
use Symfony\Component\HttpFoundation\Request;
15+
use Symfony\Component\HttpFoundation\Response;
16+
use Symfony\Component\HttpKernel\Controller\ControllerReference;
17+
use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface;
18+
19+
/**
20+
* Implements Surrogate rendering strategy.
21+
*
22+
* @author Fabien Potencier <fabien@symfony.com>
23+
*/
24+
abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRenderer
25+
{
26+
private $surrogate;
27+
private $inlineStrategy;
28+
29+
/**
30+
* Constructor.
31+
*
32+
* The "fallback" strategy when surrogate is not available should always be an
33+
* instance of InlineFragmentRenderer.
34+
*
35+
* @param SurrogateInterface $surrogate An Surrogate instance
36+
* @param FragmentRendererInterface $inlineStrategy The inline strategy to use when the surrogate is not supported
37+
*/
38+
public function __construct(SurrogateInterface $surrogate = null, FragmentRendererInterface $inlineStrategy)
39+
{
40+
$this->surrogate = $surrogate;
41+
$this->inlineStrategy = $inlineStrategy;
42+
}
43+
44+
/**
45+
* {@inheritdoc}
46+
*
47+
* Note that if the current Request has no surrogate capability, this method
48+
* falls back to use the inline rendering strategy.
49+
*
50+
* Additional available options:
51+
*
52+
* * alt: an alternative URI to render in case of an error
53+
* * comment: a comment to add when returning the surrogate tag
54+
*
55+
* Note, that not all surrogate strategies support all options. For now
56+
* 'alt' and 'comment' are only supported by ESI.
57+
*
58+
* @see Symfony\Component\HttpKernel\HttpCache\SurrogateInterface
59+
*/
60+
public function render($uri, Request $request, array $options = array())
61+
{
62+
if (!$this->surrogate || !$this->surrogate->hasSurrogateCapability($request)) {
63+
return $this->inlineStrategy->render($uri, $request, $options);
64+
}
65+
66+
if ($uri instanceof ControllerReference) {
67+
$uri = $this->generateFragmentUri($uri, $request);
68+
}
69+
70+
$alt = isset($options['alt']) ? $options['alt'] : null;
71+
if ($alt instanceof ControllerReference) {
72+
$alt = $this->generateFragmentUri($alt, $request);
73+
}
74+
75+
$tag = $this->surrogate->renderIncludeTag($uri, $alt, isset($options['ignore_errors']) ? $options['ignore_errors'] : false, isset($options['comment']) ? $options['comment'] : '');
76+
77+
return new Response($tag);
78+
}
79+
}

0 commit comments

Comments
 (0)
0