2021-07-27 14:46:32 +02:00
< ? php
/*
* This file is part of the Symfony package .
*
* ( c ) Fabien Potencier < fabien @ symfony . com >
*
* 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 ;
use Symfony\Component\HttpKernel\UriSigner ;
/**
* Implements Surrogate rendering strategy .
*
* @ author Fabien Potencier < fabien @ symfony . com >
*/
abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRenderer
{
private $surrogate ;
private $inlineStrategy ;
private $signer ;
/**
* The " fallback " strategy when surrogate is not available should always be an
* instance of InlineFragmentRenderer .
*
* @ param FragmentRendererInterface $inlineStrategy The inline strategy to use when the surrogate is not supported
*/
public function __construct ( SurrogateInterface $surrogate = null , FragmentRendererInterface $inlineStrategy , UriSigner $signer = null )
{
$this -> surrogate = $surrogate ;
$this -> inlineStrategy = $inlineStrategy ;
$this -> signer = $signer ;
}
/**
* { @ 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 = [])
{
if ( ! $this -> surrogate || ! $this -> surrogate -> hasSurrogateCapability ( $request )) {
if ( $uri instanceof ControllerReference && $this -> containsNonScalars ( $uri -> attributes )) {
throw new \InvalidArgumentException ( 'Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is not supported. Use a different rendering strategy or pass scalar values.' );
}
return $this -> inlineStrategy -> render ( $uri , $request , $options );
}
if ( $uri instanceof ControllerReference ) {
$uri = $this -> generateSignedFragmentUri ( $uri , $request );
}
$alt = $options [ 'alt' ] ? ? null ;
if ( $alt instanceof ControllerReference ) {
$alt = $this -> generateSignedFragmentUri ( $alt , $request );
}
$tag = $this -> surrogate -> renderIncludeTag ( $uri , $alt , $options [ 'ignore_errors' ] ? ? false , $options [ 'comment' ] ? ? '' );
return new Response ( $tag );
}
private function generateSignedFragmentUri ( ControllerReference $uri , Request $request ) : string
{
if ( null === $this -> signer ) {
throw new \LogicException ( 'You must use a URI when using the ESI rendering strategy or set a URL signer.' );
}
// we need to sign the absolute URI, but want to return the path only.
$fragmentUri = $this -> signer -> sign ( $this -> generateFragmentUri ( $uri , $request , true ));
return substr ( $fragmentUri , \strlen ( $request -> getSchemeAndHttpHost ()));
}
private function containsNonScalars ( array $values ) : bool
{
foreach ( $values as $value ) {
2022-10-07 15:20:07 +02:00
if ( \is_scalar ( $value ) || null === $value ) {
continue ;
}
if ( ! \is_array ( $value ) || $this -> containsNonScalars ( $value )) {
2021-07-27 14:46:32 +02:00
return true ;
}
}
return false ;
}
}