Skip to content

Commit

Permalink
Fix EZP-22597: Use composition on extended FragmentRenderers
Browse files Browse the repository at this point in the history
  • Loading branch information
lolautruche committed Apr 8, 2014
1 parent 9a0c628 commit 3c97f85
Show file tree
Hide file tree
Showing 8 changed files with 170 additions and 182 deletions.
2 changes: 1 addition & 1 deletion composer.json
Expand Up @@ -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",
Expand Down
Expand Up @@ -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;

/**
Expand All @@ -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' );
Expand All @@ -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 );
}
}
}
@@ -0,0 +1,89 @@
<?php
/**
* File containing the DecoratedFragmentRenderer class.
*
* @copyright Copyright (C) 1999-2014 eZ Systems AS. All rights reserved.
* @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2
* @version //autogentag//
*/

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\RoutableFragmentRenderer;

class DecoratedFragmentRenderer implements FragmentRendererInterface, SiteAccessAware
{
/**
* @var \Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface
*/
private $innerRenderer;

/**
* @var \eZ\Publish\Core\MVC\Symfony\SiteAccess
*/
private $siteAccess;

public function __construct( FragmentRendererInterface $innerRenderer )
{
$this->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();
}
}
58 changes: 0 additions & 58 deletions eZ/Bundle/EzPublishCoreBundle/Fragment/EsiFragmentRenderer.php

This file was deleted.

33 changes: 0 additions & 33 deletions eZ/Bundle/EzPublishCoreBundle/Fragment/FragmentUriGenerator.php

This file was deleted.

This file was deleted.

56 changes: 43 additions & 13 deletions eZ/Bundle/EzPublishCoreBundle/Fragment/InlineFragmentRenderer.php
Expand Up @@ -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();
}
}

0 comments on commit 3c97f85

Please sign in to comment.