|
0
|
1 |
<?php |
|
|
2 |
|
|
|
3 |
/* |
|
|
4 |
* This file is part of the Symfony framework. |
|
|
5 |
* |
|
|
6 |
* (c) Fabien Potencier <fabien@symfony.com> |
|
|
7 |
* |
|
|
8 |
* This source file is subject to the MIT license that is bundled |
|
|
9 |
* with this source code in the file LICENSE. |
|
|
10 |
*/ |
|
|
11 |
|
|
|
12 |
namespace Symfony\Bundle\FrameworkBundle; |
|
|
13 |
|
|
|
14 |
use Symfony\Component\HttpFoundation\Request; |
|
|
15 |
use Symfony\Component\HttpKernel\HttpKernelInterface; |
|
|
16 |
use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; |
|
|
17 |
use Symfony\Component\DependencyInjection\ContainerInterface; |
|
|
18 |
use Symfony\Component\HttpKernel\HttpKernel as BaseHttpKernel; |
|
|
19 |
use Symfony\Component\EventDispatcher\EventDispatcherInterface; |
|
|
20 |
|
|
|
21 |
/** |
|
|
22 |
* This HttpKernel is used to manage scope changes of the DI container. |
|
|
23 |
* |
|
|
24 |
* @author Johannes M. Schmitt <schmittjoh@gmail.com> |
|
|
25 |
*/ |
|
|
26 |
class HttpKernel extends BaseHttpKernel |
|
|
27 |
{ |
|
|
28 |
private $container; |
|
|
29 |
private $esiSupport; |
|
|
30 |
|
|
|
31 |
public function __construct(EventDispatcherInterface $dispatcher, ContainerInterface $container, ControllerResolverInterface $controllerResolver) |
|
|
32 |
{ |
|
|
33 |
parent::__construct($dispatcher, $controllerResolver); |
|
|
34 |
|
|
|
35 |
$this->container = $container; |
|
|
36 |
} |
|
|
37 |
|
|
|
38 |
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) |
|
|
39 |
{ |
|
|
40 |
$this->container->enterScope('request'); |
|
|
41 |
$this->container->set('request', $request, 'request'); |
|
|
42 |
|
|
|
43 |
try { |
|
|
44 |
$response = parent::handle($request, $type, $catch); |
|
|
45 |
} catch (\Exception $e) { |
|
|
46 |
$this->container->leaveScope('request'); |
|
|
47 |
|
|
|
48 |
throw $e; |
|
|
49 |
} |
|
|
50 |
|
|
|
51 |
$this->container->leaveScope('request'); |
|
|
52 |
|
|
|
53 |
return $response; |
|
|
54 |
} |
|
|
55 |
|
|
|
56 |
/** |
|
|
57 |
* Forwards the request to another controller. |
|
|
58 |
* |
|
|
59 |
* @param string $controller The controller name (a string like BlogBundle:Post:index) |
|
|
60 |
* @param array $attributes An array of request attributes |
|
|
61 |
* @param array $query An array of request query parameters |
|
|
62 |
* |
|
|
63 |
* @return Response A Response instance |
|
|
64 |
*/ |
|
|
65 |
public function forward($controller, array $attributes = array(), array $query = array()) |
|
|
66 |
{ |
|
|
67 |
$attributes['_controller'] = $controller; |
|
|
68 |
$subRequest = $this->container->get('request')->duplicate($query, null, $attributes); |
|
|
69 |
|
|
|
70 |
return $this->handle($subRequest, HttpKernelInterface::SUB_REQUEST); |
|
|
71 |
} |
|
|
72 |
|
|
|
73 |
/** |
|
|
74 |
* Renders a Controller and returns the Response content. |
|
|
75 |
* |
|
|
76 |
* Note that this method generates an esi:include tag only when both the standalone |
|
|
77 |
* option is set to true and the request has ESI capability (@see Symfony\Component\HttpKernel\HttpCache\ESI). |
|
|
78 |
* |
|
|
79 |
* Available options: |
|
|
80 |
* |
|
|
81 |
* * attributes: An array of request attributes (only when the first argument is a controller) |
|
|
82 |
* * query: An array of request query parameters (only when the first argument is a controller) |
|
|
83 |
* * ignore_errors: true to return an empty string in case of an error |
|
|
84 |
* * alt: an alternative controller to execute in case of an error (can be a controller, a URI, or an array with the controller, the attributes, and the query arguments) |
|
|
85 |
* * standalone: whether to generate an esi:include tag or not when ESI is supported |
|
|
86 |
* * comment: a comment to add when returning an esi:include tag |
|
|
87 |
* |
|
|
88 |
* @param string $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI |
|
|
89 |
* @param array $options An array of options |
|
|
90 |
* |
|
|
91 |
* @return string The Response content |
|
|
92 |
*/ |
|
|
93 |
public function render($controller, array $options = array()) |
|
|
94 |
{ |
|
|
95 |
$options = array_merge(array( |
|
|
96 |
'attributes' => array(), |
|
|
97 |
'query' => array(), |
|
|
98 |
'ignore_errors' => !$this->container->getParameter('kernel.debug'), |
|
|
99 |
'alt' => array(), |
|
|
100 |
'standalone' => false, |
|
|
101 |
'comment' => '', |
|
|
102 |
), $options); |
|
|
103 |
|
|
|
104 |
if (!is_array($options['alt'])) { |
|
|
105 |
$options['alt'] = array($options['alt']); |
|
|
106 |
} |
|
|
107 |
|
|
|
108 |
if (null === $this->esiSupport) { |
|
|
109 |
$this->esiSupport = $this->container->has('esi') && $this->container->get('esi')->hasSurrogateEsiCapability($this->container->get('request')); |
|
|
110 |
} |
|
|
111 |
|
|
|
112 |
if ($this->esiSupport && $options['standalone']) { |
|
|
113 |
$uri = $this->generateInternalUri($controller, $options['attributes'], $options['query']); |
|
|
114 |
|
|
|
115 |
$alt = ''; |
|
|
116 |
if ($options['alt']) { |
|
|
117 |
$alt = $this->generateInternalUri($options['alt'][0], isset($options['alt'][1]) ? $options['alt'][1] : array(), isset($options['alt'][2]) ? $options['alt'][2] : array()); |
|
|
118 |
} |
|
|
119 |
|
|
|
120 |
return $this->container->get('esi')->renderIncludeTag($uri, $alt, $options['ignore_errors'], $options['comment']); |
|
|
121 |
} |
|
|
122 |
|
|
|
123 |
$request = $this->container->get('request'); |
|
|
124 |
|
|
|
125 |
// controller or URI? |
|
|
126 |
if (0 === strpos($controller, '/')) { |
|
|
127 |
$subRequest = Request::create($controller, 'get', array(), $request->cookies->all(), array(), $request->server->all()); |
|
|
128 |
$subRequest->setSession($request->getSession()); |
|
|
129 |
} else { |
|
|
130 |
$options['attributes']['_controller'] = $controller; |
|
|
131 |
$options['attributes']['_format'] = $request->getRequestFormat(); |
|
|
132 |
$options['attributes']['_route'] = '_internal'; |
|
|
133 |
$subRequest = $request->duplicate($options['query'], null, $options['attributes']); |
|
|
134 |
} |
|
|
135 |
|
|
|
136 |
try { |
|
|
137 |
$response = $this->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false); |
|
|
138 |
|
|
|
139 |
if (!$response->isSuccessful()) { |
|
|
140 |
throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $request->getUri(), $response->getStatusCode())); |
|
|
141 |
} |
|
|
142 |
|
|
|
143 |
return $response->getContent(); |
|
|
144 |
} catch (\Exception $e) { |
|
|
145 |
if ($options['alt']) { |
|
|
146 |
$alt = $options['alt']; |
|
|
147 |
unset($options['alt']); |
|
|
148 |
$options['attributes'] = isset($alt[1]) ? $alt[1] : array(); |
|
|
149 |
$options['query'] = isset($alt[2]) ? $alt[2] : array(); |
|
|
150 |
|
|
|
151 |
return $this->render($alt[0], $options); |
|
|
152 |
} |
|
|
153 |
|
|
|
154 |
if (!$options['ignore_errors']) { |
|
|
155 |
throw $e; |
|
|
156 |
} |
|
|
157 |
} |
|
|
158 |
} |
|
|
159 |
|
|
|
160 |
/** |
|
|
161 |
* Generates an internal URI for a given controller. |
|
|
162 |
* |
|
|
163 |
* This method uses the "_internal" route, which should be available. |
|
|
164 |
* |
|
|
165 |
* @param string $controller A controller name to execute (a string like BlogBundle:Post:index), or a relative URI |
|
|
166 |
* @param array $attributes An array of request attributes |
|
|
167 |
* @param array $query An array of request query parameters |
|
|
168 |
* |
|
|
169 |
* @return string An internal URI |
|
|
170 |
*/ |
|
|
171 |
public function generateInternalUri($controller, array $attributes = array(), array $query = array()) |
|
|
172 |
{ |
|
|
173 |
if (0 === strpos($controller, '/')) { |
|
|
174 |
return $controller; |
|
|
175 |
} |
|
|
176 |
|
|
|
177 |
$path = http_build_query($attributes); |
|
|
178 |
$uri = $this->container->get('router')->generate('_internal', array( |
|
|
179 |
'controller' => $controller, |
|
|
180 |
'path' => $path ?: 'none', |
|
|
181 |
'_format' => $this->container->get('request')->getRequestFormat(), |
|
|
182 |
)); |
|
|
183 |
|
|
|
184 |
if ($queryString = http_build_query($query)) { |
|
|
185 |
$uri .= '?'.$queryString; |
|
|
186 |
} |
|
|
187 |
|
|
|
188 |
return $uri; |
|
|
189 |
} |
|
|
190 |
} |