Version 1
[yaffs-website] / vendor / symfony / http-kernel / Fragment / HIncludeFragmentRenderer.php
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\Templating\EngineInterface;
17 use Symfony\Component\HttpKernel\Controller\ControllerReference;
18 use Symfony\Component\HttpKernel\UriSigner;
19
20 /**
21  * Implements the Hinclude rendering strategy.
22  *
23  * @author Fabien Potencier <fabien@symfony.com>
24  */
25 class HIncludeFragmentRenderer extends RoutableFragmentRenderer
26 {
27     private $globalDefaultTemplate;
28     private $signer;
29     private $templating;
30     private $charset;
31
32     /**
33      * Constructor.
34      *
35      * @param EngineInterface|\Twig_Environment $templating            An EngineInterface or a \Twig_Environment instance
36      * @param UriSigner                         $signer                A UriSigner instance
37      * @param string                            $globalDefaultTemplate The global default content (it can be a template name or the content)
38      * @param string                            $charset
39      */
40     public function __construct($templating = null, UriSigner $signer = null, $globalDefaultTemplate = null, $charset = 'utf-8')
41     {
42         $this->setTemplating($templating);
43         $this->globalDefaultTemplate = $globalDefaultTemplate;
44         $this->signer = $signer;
45         $this->charset = $charset;
46     }
47
48     /**
49      * Sets the templating engine to use to render the default content.
50      *
51      * @param EngineInterface|\Twig_Environment|null $templating An EngineInterface or a \Twig_Environment instance
52      *
53      * @throws \InvalidArgumentException
54      */
55     public function setTemplating($templating)
56     {
57         if (null !== $templating && !$templating instanceof EngineInterface && !$templating instanceof \Twig_Environment) {
58             throw new \InvalidArgumentException('The hinclude rendering strategy needs an instance of \Twig_Environment or Symfony\Component\Templating\EngineInterface');
59         }
60
61         $this->templating = $templating;
62     }
63
64     /**
65      * Checks if a templating engine has been set.
66      *
67      * @return bool true if the templating engine has been set, false otherwise
68      */
69     public function hasTemplating()
70     {
71         return null !== $this->templating;
72     }
73
74     /**
75      * {@inheritdoc}
76      *
77      * Additional available options:
78      *
79      *  * default:    The default content (it can be a template name or the content)
80      *  * id:         An optional hx:include tag id attribute
81      *  * attributes: An optional array of hx:include tag attributes
82      */
83     public function render($uri, Request $request, array $options = array())
84     {
85         if ($uri instanceof ControllerReference) {
86             if (null === $this->signer) {
87                 throw new \LogicException('You must use a proper URI when using the Hinclude rendering strategy or set a URL signer.');
88             }
89
90             // we need to sign the absolute URI, but want to return the path only.
91             $uri = substr($this->signer->sign($this->generateFragmentUri($uri, $request, true)), strlen($request->getSchemeAndHttpHost()));
92         }
93
94         // We need to replace ampersands in the URI with the encoded form in order to return valid html/xml content.
95         $uri = str_replace('&', '&amp;', $uri);
96
97         $template = isset($options['default']) ? $options['default'] : $this->globalDefaultTemplate;
98         if (null !== $this->templating && $template && $this->templateExists($template)) {
99             $content = $this->templating->render($template);
100         } else {
101             $content = $template;
102         }
103
104         $attributes = isset($options['attributes']) && is_array($options['attributes']) ? $options['attributes'] : array();
105         if (isset($options['id']) && $options['id']) {
106             $attributes['id'] = $options['id'];
107         }
108         $renderedAttributes = '';
109         if (count($attributes) > 0) {
110             if (PHP_VERSION_ID >= 50400) {
111                 $flags = ENT_QUOTES | ENT_SUBSTITUTE;
112             } else {
113                 $flags = ENT_QUOTES;
114             }
115             foreach ($attributes as $attribute => $value) {
116                 $renderedAttributes .= sprintf(
117                     ' %s="%s"',
118                     htmlspecialchars($attribute, $flags, $this->charset, false),
119                     htmlspecialchars($value, $flags, $this->charset, false)
120                 );
121             }
122         }
123
124         return new Response(sprintf('<hx:include src="%s"%s>%s</hx:include>', $uri, $renderedAttributes, $content));
125     }
126
127     /**
128      * @param string $template
129      *
130      * @return bool
131      */
132     private function templateExists($template)
133     {
134         if ($this->templating instanceof EngineInterface) {
135             try {
136                 return $this->templating->exists($template);
137             } catch (\InvalidArgumentException $e) {
138                 return false;
139             }
140         }
141
142         $loader = $this->templating->getLoader();
143         if ($loader instanceof \Twig_ExistsLoaderInterface || method_exists($loader, 'exists')) {
144             return $loader->exists($template);
145         }
146
147         try {
148             if (method_exists($loader, 'getSourceContext')) {
149                 $loader->getSourceContext($template);
150             } else {
151                 $loader->getSource($template);
152             }
153
154             return true;
155         } catch (\Twig_Error_Loader $e) {
156         }
157
158         return false;
159     }
160
161     /**
162      * {@inheritdoc}
163      */
164     public function getName()
165     {
166         return 'hinclude';
167     }
168 }