From 342d08967cb8fe4794039276858acebaa2ab7cf3 Mon Sep 17 00:00:00 2001 From: Mike Meier Date: Wed, 20 Mar 2013 15:33:28 +0100 Subject: [PATCH 1/2] Allow to set id + custom attributes to hinclude tag Squashed commits: Allow to set an id attribute to hinclude tag Allow custom attributes on hinclude tag --- .../HttpKernel/Fragment/HIncludeFragmentRenderer.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php b/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php index fafa76368c..0aef1d8236 100644 --- a/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php +++ b/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php @@ -93,7 +93,13 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer $content = $template; } - return new Response(sprintf('%s', $uri, $content)); + $attrOptions = isset($options['attr']) && is_array($options['attr']) ? $options['attr'] : array(); + $attributes = array(); + foreach($attrOptions as $attribute => $value) { + $attributes[] = sprintf('%s="%s"', $attribute, $value); + } + + return new Response(sprintf('%s', $uri, implode(" ", $attributes), $content)); } private function templateExists($template) From 670a5028a85c00ea5c5b4a7878907d5a9fb7e1a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jean-Fran=C3=A7ois=20Simon?= Date: Tue, 26 Mar 2013 10:03:20 +0100 Subject: [PATCH 2/2] [HttpKernel] added escaping for hx:include tag attributes --- ...ContainerAwareHIncludeFragmentRenderer.php | 2 +- .../Fragment/HIncludeFragmentRenderer.php | 39 +++++++++++++++---- .../Fragment/HIncludeFragmentRendererTest.php | 15 +++++++ 3 files changed, 48 insertions(+), 8 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Fragment/ContainerAwareHIncludeFragmentRenderer.php b/src/Symfony/Bundle/FrameworkBundle/Fragment/ContainerAwareHIncludeFragmentRenderer.php index 82c6a0b2b7..698d979082 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Fragment/ContainerAwareHIncludeFragmentRenderer.php +++ b/src/Symfony/Bundle/FrameworkBundle/Fragment/ContainerAwareHIncludeFragmentRenderer.php @@ -32,7 +32,7 @@ class ContainerAwareHIncludeFragmentRenderer extends HIncludeFragmentRenderer { $this->container = $container; - parent::__construct(null, $signer, $globalDefaultTemplate); + parent::__construct(null, $signer, $globalDefaultTemplate, $container->getParameter('kernel.charset')); } /** diff --git a/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php b/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php index 0aef1d8236..1f059da94a 100644 --- a/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php +++ b/src/Symfony/Component/HttpKernel/Fragment/HIncludeFragmentRenderer.php @@ -11,6 +11,10 @@ namespace Symfony\Component\HttpKernel\Fragment; +if (!defined('ENT_SUBSTITUTE')) { + define('ENT_SUBSTITUTE', 8); +} + use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Templating\EngineInterface; @@ -27,6 +31,7 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer private $globalDefaultTemplate; private $signer; private $templating; + private $charset; /** * Constructor. @@ -34,18 +39,22 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer * @param EngineInterface|\Twig_Environment $templating An EngineInterface or a \Twig_Environment instance * @param UriSigner $signer A UriSigner instance * @param string $globalDefaultTemplate The global default content (it can be a template name or the content) + * @param string $charset */ - public function __construct($templating = null, UriSigner $signer = null, $globalDefaultTemplate = null) + public function __construct($templating = null, UriSigner $signer = null, $globalDefaultTemplate = null, $charset = 'utf-8') { $this->setTemplating($templating); $this->globalDefaultTemplate = $globalDefaultTemplate; $this->signer = $signer; + $this->charset = $charset; } /** * Sets the templating engine to use to render the default content. * * @param EngineInterface|\Twig_Environment|null $templating An EngineInterface or a \Twig_Environment instance + * + * @throws \InvalidArgumentException */ public function setTemplating($templating) { @@ -71,7 +80,9 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer * * Additional available options: * - * * default: The default content (it can be a template name or the content) + * * default: The default content (it can be a template name or the content) + * * id: An optional hx:include tag id attribute + * * attributes: An optional array of hx:include tag attributes */ public function render($uri, Request $request, array $options = array()) { @@ -93,15 +104,29 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer $content = $template; } - $attrOptions = isset($options['attr']) && is_array($options['attr']) ? $options['attr'] : array(); - $attributes = array(); - foreach($attrOptions as $attribute => $value) { - $attributes[] = sprintf('%s="%s"', $attribute, $value); + $attributes = isset($options['attributes']) && is_array($options['attributes']) ? $options['attributes'] : array(); + if (isset($options['id']) && $options['id']) { + $attributes['id'] = $options['id']; + } + $renderedAttributes = ''; + if (count($attributes) > 0) { + foreach($attributes as $attribute => $value) { + $renderedAttributes .= sprintf( + ' %s="%s"', + htmlspecialchars($attribute, ENT_QUOTES | ENT_SUBSTITUTE, $this->charset, false), + htmlspecialchars($value, ENT_QUOTES | ENT_SUBSTITUTE, $this->charset, false) + ); + } } - return new Response(sprintf('%s', $uri, implode(" ", $attributes), $content)); + return new Response(sprintf('%s', $uri, $renderedAttributes, $content)); } + /** + * @param string $template + * + * @return boolean + */ private function templateExists($template) { if ($this->templating instanceof EngineInterface) { diff --git a/src/Symfony/Component/HttpKernel/Tests/Fragment/HIncludeFragmentRendererTest.php b/src/Symfony/Component/HttpKernel/Tests/Fragment/HIncludeFragmentRendererTest.php index 1e77374901..53baf5ab51 100644 --- a/src/Symfony/Component/HttpKernel/Tests/Fragment/HIncludeFragmentRendererTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/Fragment/HIncludeFragmentRendererTest.php @@ -64,4 +64,19 @@ class HIncludeFragmentRendererTest extends \PHPUnit_Framework_TestCase $strategy = new HIncludeFragmentRenderer(null, null, 'global_default'); $this->assertEquals('default', $strategy->render('/foo', Request::create('/'), array('default' => 'default'))->getContent()); } + + public function testRenderWithAttributesOptions() + { + // with id + $strategy = new HIncludeFragmentRenderer(); + $this->assertEquals('default', $strategy->render('/foo', Request::create('/'), array('default' => 'default', 'id' => 'bar'))->getContent()); + + // with attributes + $strategy = new HIncludeFragmentRenderer(); + $this->assertEquals('default', $strategy->render('/foo', Request::create('/'), array('default' => 'default', 'attributes' => array('p1' => 'v1', 'p2' => 'v2')))->getContent()); + + // with id & attributes + $strategy = new HIncludeFragmentRenderer(); + $this->assertEquals('default', $strategy->render('/foo', Request::create('/'), array('default' => 'default', 'id' => 'bar', 'attributes' => array('p1' => 'v1', 'p2' => 'v2')))->getContent()); + } }