From 3c97f8572c64a1bf103b086d78070ec42d957aac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Je=CC=81ro=CC=82me=20Vieilledent?= Date: Tue, 8 Apr 2014 17:25:59 +0200 Subject: [PATCH] Fix EZP-22597: Use composition on extended FragmentRenderers --- composer.json | 2 +- .../Compiler/FragmentPass.php | 42 +++++---- .../Fragment/DecoratedFragmentRenderer.php | 89 +++++++++++++++++++ .../Fragment/EsiFragmentRenderer.php | 58 ------------ .../Fragment/FragmentUriGenerator.php | 33 ------- .../Fragment/HincludeFragmentRenderer.php | 58 ------------ .../Fragment/InlineFragmentRenderer.php | 56 +++++++++--- .../Resources/config/services.yml | 14 ++- 8 files changed, 170 insertions(+), 182 deletions(-) create mode 100644 eZ/Bundle/EzPublishCoreBundle/Fragment/DecoratedFragmentRenderer.php delete mode 100644 eZ/Bundle/EzPublishCoreBundle/Fragment/EsiFragmentRenderer.php delete mode 100644 eZ/Bundle/EzPublishCoreBundle/Fragment/FragmentUriGenerator.php delete mode 100644 eZ/Bundle/EzPublishCoreBundle/Fragment/HincludeFragmentRenderer.php diff --git a/composer.json b/composer.json index 80f72c48c61..f966d33575e 100644 --- a/composer.json +++ b/composer.json @@ -36,7 +36,7 @@ "zetacomponents/signal-slot": "dev-master#74deb41", "zetacomponents/system-information": "dev-master#6743362", "zetacomponents/webdav": "1.1.*", - "symfony/symfony": "2.3.*", + "symfony/symfony": "~2.3", "symfony-cmf/routing": "1.1.*", "qafoo/rmf": "1.0.*", "kriswallsmith/buzz": ">=0.9", diff --git a/eZ/Bundle/EzPublishCoreBundle/DependencyInjection/Compiler/FragmentPass.php b/eZ/Bundle/EzPublishCoreBundle/DependencyInjection/Compiler/FragmentPass.php index 83e0e2d5c35..8f91265b1db 100644 --- a/eZ/Bundle/EzPublishCoreBundle/DependencyInjection/Compiler/FragmentPass.php +++ b/eZ/Bundle/EzPublishCoreBundle/DependencyInjection/Compiler/FragmentPass.php @@ -11,6 +11,7 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\Reference; /** @@ -20,9 +21,14 @@ class FragmentPass implements CompilerPassInterface { public function process( ContainerBuilder $container ) { - if ( !$container->hasDefinition( 'fragment.listener' ) ) + if ( + !( + $container->hasDefinition( 'fragment.listener' ) + && $container->hasDefinition( 'ezpublish.decorated_fragment_renderer' ) + ) + ) { - return; + return null; } $fragmentListenerDef = $container->findDefinition( 'fragment.listener' ); @@ -31,24 +37,28 @@ public function process( ContainerBuilder $container ) ->setFactoryMethod( 'buildFragmentListener' ) ->addArgument( '%fragment.listener.class%' ); - foreach ( array( 'esi', 'hinclude' ) as $rendererType ) + // Looping over all fragment renderers to decorate them + // This is to make sure they are siteaccess aware (siteaccess is serialized in rendered path). + foreach ( $container->findTaggedServiceIds( 'kernel.fragment_renderer' ) as $id => $attributes ) { - if ( !$container->hasDefinition( "fragment.renderer.$rendererType" ) ) + $renamedId = "$id.inner"; + $definition = $container->getDefinition( $id ); + $public = $definition->isPublic(); + $tags = $definition->getTags(); + $definition->setPublic( false ); + $container->setDefinition( $renamedId, $definition ); + + $decoratedDef = new DefinitionDecorator( 'ezpublish.decorated_fragment_renderer' ); + $decoratedDef->setArguments( array( new Reference( $renamedId ) ) ); + $decoratedDef->setPublic( $public ); + $decoratedDef->setTags( $tags ); + // Special treatment for inline fragment renderer, to fit ESI renderer constructor type hinting (forced to InlineFragmentRenderer) + if ( $id === 'fragment.renderer.inline' ) { - continue; + $decoratedDef->setClass( $container->getParameter( 'ezpublish.decorated_fragment_renderer.inline.class' ) ); } - // SiteAccess injection must be in first position. - $rendererDef = $container->findDefinition( "fragment.renderer.$rendererType" ); - $methodCalls = $rendererDef->getMethodCalls(); - array_unshift( - $methodCalls, - array( - 'setSiteAccess', - array( new Reference( 'ezpublish.siteaccess' ) ) - ) - ); - $rendererDef->setMethodCalls( $methodCalls ); + $container->setDefinition( $id, $decoratedDef ); } } } diff --git a/eZ/Bundle/EzPublishCoreBundle/Fragment/DecoratedFragmentRenderer.php b/eZ/Bundle/EzPublishCoreBundle/Fragment/DecoratedFragmentRenderer.php new file mode 100644 index 00000000000..0ea7bab3c15 --- /dev/null +++ b/eZ/Bundle/EzPublishCoreBundle/Fragment/DecoratedFragmentRenderer.php @@ -0,0 +1,89 @@ +innerRenderer = $innerRenderer; + } + + /** + * @param \eZ\Publish\Core\MVC\Symfony\SiteAccess $siteAccess + */ + public function setSiteAccess( SiteAccess $siteAccess = null ) + { + $this->siteAccess = $siteAccess; + } + + public function setFragmentPath( $path ) + { + if ( !$this->innerRenderer instanceof RoutableFragmentRenderer ) + { + return null; + } + + if ( $this->siteAccess && $this->siteAccess->matcher instanceof SiteAccess\URILexer ) + { + $path = $this->siteAccess->matcher->analyseLink( $path ); + } + + $this->innerRenderer->setFragmentPath( $path ); + } + + /** + * Renders a URI and returns the Response content. + * + * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance + * @param Request $request A Request instance + * @param array $options An array of options + * + * @return Response A Response instance + */ + public function render( $uri, Request $request, array $options = array() ) + { + if ( $uri instanceof ControllerReference && $request->attributes->has( 'siteaccess' ) ) + { + // Serialize the siteaccess to get it back after. + // @see eZ\Publish\Core\MVC\Symfony\EventListener\SiteAccessMatchListener + $uri->attributes['serialized_siteaccess'] = serialize( $request->attributes->get( 'siteaccess' ) ); + } + + return $this->innerRenderer->render( $uri, $request, $options ); + } + + /** + * Gets the name of the strategy. + * + * @return string The strategy name + */ + public function getName() + { + return $this->innerRenderer->getName(); + } +} diff --git a/eZ/Bundle/EzPublishCoreBundle/Fragment/EsiFragmentRenderer.php b/eZ/Bundle/EzPublishCoreBundle/Fragment/EsiFragmentRenderer.php deleted file mode 100644 index df041c93904..00000000000 --- a/eZ/Bundle/EzPublishCoreBundle/Fragment/EsiFragmentRenderer.php +++ /dev/null @@ -1,58 +0,0 @@ -siteAccess = $siteAccess; - } - - public function setFragmentPath( $path ) - { - if ( $this->siteAccess && $this->siteAccess->matcher instanceof SiteAccess\URILexer ) - { - $path = $this->siteAccess->matcher->analyseLink( $path ); - } - - parent::setFragmentPath( $path ); - } - - protected function generateFragmentUri( ControllerReference $reference, Request $request, $absolute = false ) - { - if ( !isset( $this->fragmentUriGenerator ) ) - { - $this->fragmentUriGenerator = new FragmentUriGenerator; - } - - $this->fragmentUriGenerator->generateFragmentUri( $reference, $request, $absolute ); - return parent::generateFragmentUri( $reference, $request, $absolute ); - } -} diff --git a/eZ/Bundle/EzPublishCoreBundle/Fragment/FragmentUriGenerator.php b/eZ/Bundle/EzPublishCoreBundle/Fragment/FragmentUriGenerator.php deleted file mode 100644 index 7ec945bcd1b..00000000000 --- a/eZ/Bundle/EzPublishCoreBundle/Fragment/FragmentUriGenerator.php +++ /dev/null @@ -1,33 +0,0 @@ -attributes->has( 'siteaccess' ) ) - $reference->attributes['serialized_siteaccess'] = serialize( $request->attributes->get( 'siteaccess' ) ); - } -} diff --git a/eZ/Bundle/EzPublishCoreBundle/Fragment/HincludeFragmentRenderer.php b/eZ/Bundle/EzPublishCoreBundle/Fragment/HincludeFragmentRenderer.php deleted file mode 100644 index 4bdffab1947..00000000000 --- a/eZ/Bundle/EzPublishCoreBundle/Fragment/HincludeFragmentRenderer.php +++ /dev/null @@ -1,58 +0,0 @@ -siteAccess = $siteAccess; - } - - public function setFragmentPath( $path ) - { - if ( $this->siteAccess && $this->siteAccess->matcher instanceof SiteAccess\URILexer ) - { - $path = $this->siteAccess->matcher->analyseLink( $path ); - } - - parent::setFragmentPath( $path ); - } - - protected function generateFragmentUri( ControllerReference $reference, Request $request, $absolute = false ) - { - if ( !isset( $this->fragmentUriGenerator ) ) - { - $this->fragmentUriGenerator = new FragmentUriGenerator; - } - - $this->fragmentUriGenerator->generateFragmentUri( $reference, $request, $absolute ); - return parent::generateFragmentUri( $reference, $request, $absolute ); - } -} diff --git a/eZ/Bundle/EzPublishCoreBundle/Fragment/InlineFragmentRenderer.php b/eZ/Bundle/EzPublishCoreBundle/Fragment/InlineFragmentRenderer.php index a6967e2ee0f..72f377bfac2 100644 --- a/eZ/Bundle/EzPublishCoreBundle/Fragment/InlineFragmentRenderer.php +++ b/eZ/Bundle/EzPublishCoreBundle/Fragment/InlineFragmentRenderer.php @@ -9,31 +9,61 @@ namespace eZ\Bundle\EzPublishCoreBundle\Fragment; +use eZ\Publish\Core\MVC\Symfony\SiteAccess\SiteAccessAware; +use eZ\Publish\Core\MVC\Symfony\SiteAccess; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ControllerReference; +use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface; use Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer as BaseRenderer; +use Symfony\Component\HttpKernel\Fragment\RoutableFragmentRenderer; -class InlineFragmentRenderer extends BaseRenderer +class InlineFragmentRenderer extends BaseRenderer implements SiteAccessAware { /** - * @var FragmentUriGenerator + * @var \Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface */ - private $fragmentUriGenerator; + private $innerRenderer; - protected function generateFragmentUri( ControllerReference $reference, Request $request, $absolute = false ) + /** + * @var \eZ\Publish\Core\MVC\Symfony\SiteAccess + */ + private $siteAccess; + + public function __construct( FragmentRendererInterface $innerRenderer ) + { + $this->innerRenderer = $innerRenderer; + } + + public function setFragmentPath( $path ) + { + if ( $this->innerRenderer instanceof RoutableFragmentRenderer ) + { + $this->innerRenderer->setFragmentPath( $path ); + } + } + + public function setSiteAccess( SiteAccess $siteAccess = null ) + { + $this->siteAccess = $siteAccess; + } + + public function render( $uri, Request $request, array $options = array() ) { - if ( !isset( $this->fragmentUriGenerator ) ) + if ( $uri instanceof ControllerReference ) { - $this->fragmentUriGenerator = new FragmentUriGenerator; + if ( $request->attributes->has( 'siteaccess' ) ) + $uri->attributes['serialized_siteaccess'] = serialize( $request->attributes->get( 'siteaccess' ) ); + if ( $request->attributes->has( 'semanticPathinfo' ) ) + $uri->attributes['semanticPathinfo'] = $request->attributes->get( 'semanticPathinfo' ); + if ( $request->attributes->has( 'viewParametersString' ) ) + $uri->attributes['viewParametersString'] = $request->attributes->get( 'viewParametersString' ); } - // Generate base fragment URI and add other needed attributes - $this->fragmentUriGenerator->generateFragmentUri( $reference, $request, $absolute ); - if ( $request->attributes->has( 'semanticPathinfo' ) ) - $reference->attributes['semanticPathinfo'] = $request->attributes->get( 'semanticPathinfo' ); - if ( $request->attributes->has( 'viewParametersString' ) ) - $reference->attributes['viewParametersString'] = $request->attributes->get( 'viewParametersString' ); + return $this->innerRenderer->render( $uri, $request, $options ); + } - return parent::generateFragmentUri( $reference, $request, $absolute ); + public function getName() + { + return $this->innerRenderer->getName(); } } diff --git a/eZ/Bundle/EzPublishCoreBundle/Resources/config/services.yml b/eZ/Bundle/EzPublishCoreBundle/Resources/config/services.yml index 41367b38ad8..eefd60eaf00 100644 --- a/eZ/Bundle/EzPublishCoreBundle/Resources/config/services.yml +++ b/eZ/Bundle/EzPublishCoreBundle/Resources/config/services.yml @@ -10,9 +10,8 @@ parameters: ezpublish.controller.page.view.class: eZ\Bundle\EzPublishCoreBundle\Controller\PageController # FragmentRenderer overrides - fragment.renderer.esi.class: eZ\Bundle\EzPublishCoreBundle\Fragment\EsiFragmentRenderer - fragment.renderer.inline.class: eZ\Bundle\EzPublishCoreBundle\Fragment\InlineFragmentRenderer - fragment.renderer.hinclude.class: eZ\Bundle\EzPublishCoreBundle\Fragment\HincludeFragmentRenderer + ezpublish.decorated_fragment_renderer.inline.class: eZ\Bundle\EzPublishCoreBundle\Fragment\InlineFragmentRenderer + ezpublish.decorated_fragment_renderer.class: eZ\Bundle\EzPublishCoreBundle\Fragment\DecoratedFragmentRenderer ezpublish.fragment_listener.factory.class: eZ\Bundle\EzPublishCoreBundle\Fragment\FragmentListenerFactory ezpublish.controller_manager.class: eZ\Publish\Core\MVC\Symfony\Controller\Manager @@ -98,3 +97,12 @@ services: arguments: [%fragment.path%] calls: - [setRequest, [@?request=]] + + ezpublish.decorated_fragment_renderer: + class: %ezpublish.decorated_fragment_renderer.class% + # Arguments replaced at compile time + arguments: [] + calls: + - [setFragmentPath, [%fragment.path%]] + - [setSiteAccess, [@ezpublish.siteaccess]] + abstract: true