| 1 |
lars |
1 |
<?php
|
|
|
2 |
|
|
|
3 |
/*
|
|
|
4 |
* This file is part of the symfony package.
|
|
|
5 |
* (c) 2004-2006 Fabien Potencier <fabien.potencier@symfony-project.com>
|
|
|
6 |
* (c) 2004-2006 Sean Kerr <sean@code-box.org>
|
|
|
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 |
/**
|
|
|
13 |
* sfWebController provides web specific methods to sfController such as, url redirection.
|
|
|
14 |
*
|
|
|
15 |
* @package symfony
|
|
|
16 |
* @subpackage controller
|
|
|
17 |
* @author Fabien Potencier <fabien.potencier@symfony-project.com>
|
|
|
18 |
* @author Sean Kerr <sean@code-box.org>
|
|
|
19 |
* @version SVN: $Id: sfWebController.class.php 30563 2010-08-06 11:22:44Z fabien $
|
|
|
20 |
*/
|
|
|
21 |
abstract class sfWebController extends sfController
|
|
|
22 |
{
|
|
|
23 |
/**
|
|
|
24 |
* Generates an URL from an array of parameters.
|
|
|
25 |
*
|
|
|
26 |
* @param mixed $parameters An associative array of URL parameters or an internal URI as a string.
|
|
|
27 |
* @param boolean $absolute Whether to generate an absolute URL
|
|
|
28 |
*
|
|
|
29 |
* @return string A URL to a symfony resource
|
|
|
30 |
*/
|
|
|
31 |
public function genUrl($parameters = array(), $absolute = false)
|
|
|
32 |
{
|
|
|
33 |
$route = '';
|
|
|
34 |
$fragment = '';
|
|
|
35 |
|
|
|
36 |
if (is_string($parameters))
|
|
|
37 |
{
|
|
|
38 |
// absolute URL or symfony URL?
|
|
|
39 |
if (preg_match('#^[a-z][a-z0-9\+.\-]*\://#i', $parameters))
|
|
|
40 |
{
|
|
|
41 |
return $parameters;
|
|
|
42 |
}
|
|
|
43 |
|
|
|
44 |
// relative URL?
|
|
|
45 |
if (0 === strpos($parameters, '/'))
|
|
|
46 |
{
|
|
|
47 |
return $parameters;
|
|
|
48 |
}
|
|
|
49 |
|
|
|
50 |
if ($parameters == '#')
|
|
|
51 |
{
|
|
|
52 |
return $parameters;
|
|
|
53 |
}
|
|
|
54 |
|
|
|
55 |
// strip fragment
|
|
|
56 |
if (false !== ($pos = strpos($parameters, '#')))
|
|
|
57 |
{
|
|
|
58 |
$fragment = substr($parameters, $pos + 1);
|
|
|
59 |
$parameters = substr($parameters, 0, $pos);
|
|
|
60 |
}
|
|
|
61 |
|
|
|
62 |
list($route, $parameters) = $this->convertUrlStringToParameters($parameters);
|
|
|
63 |
}
|
|
|
64 |
else if (is_array($parameters))
|
|
|
65 |
{
|
|
|
66 |
if (isset($parameters['sf_route']))
|
|
|
67 |
{
|
|
|
68 |
$route = $parameters['sf_route'];
|
|
|
69 |
unset($parameters['sf_route']);
|
|
|
70 |
}
|
|
|
71 |
}
|
|
|
72 |
|
|
|
73 |
// routing to generate path
|
|
|
74 |
$url = $this->context->getRouting()->generate($route, $parameters, $absolute);
|
|
|
75 |
|
|
|
76 |
if ($fragment)
|
|
|
77 |
{
|
|
|
78 |
$url .= '#'.$fragment;
|
|
|
79 |
}
|
|
|
80 |
|
|
|
81 |
return $url;
|
|
|
82 |
}
|
|
|
83 |
|
|
|
84 |
/**
|
|
|
85 |
* Converts an internal URI string to an array of parameters.
|
|
|
86 |
*
|
|
|
87 |
* @param string $url An internal URI
|
|
|
88 |
*
|
|
|
89 |
* @return array An array of parameters
|
|
|
90 |
*/
|
|
|
91 |
public function convertUrlStringToParameters($url)
|
|
|
92 |
{
|
|
|
93 |
$givenUrl = $url;
|
|
|
94 |
|
|
|
95 |
$params = array();
|
|
|
96 |
$queryString = '';
|
|
|
97 |
$route = '';
|
|
|
98 |
|
|
|
99 |
// empty url?
|
|
|
100 |
if (!$url)
|
|
|
101 |
{
|
|
|
102 |
$url = '/';
|
|
|
103 |
}
|
|
|
104 |
|
|
|
105 |
// we get the query string out of the url
|
|
|
106 |
if ($pos = strpos($url, '?'))
|
|
|
107 |
{
|
|
|
108 |
$queryString = substr($url, $pos + 1);
|
|
|
109 |
$url = substr($url, 0, $pos);
|
|
|
110 |
}
|
|
|
111 |
|
|
|
112 |
// 2 url forms
|
|
|
113 |
// @routeName?key1=value1&key2=value2...
|
|
|
114 |
// module/action?key1=value1&key2=value2...
|
|
|
115 |
|
|
|
116 |
// first slash optional
|
|
|
117 |
if ($url[0] == '/')
|
|
|
118 |
{
|
|
|
119 |
$url = substr($url, 1);
|
|
|
120 |
}
|
|
|
121 |
|
|
|
122 |
// routeName?
|
|
|
123 |
if ($url[0] == '@')
|
|
|
124 |
{
|
|
|
125 |
$route = substr($url, 1);
|
|
|
126 |
}
|
|
|
127 |
else if (false !== strpos($url, '/'))
|
|
|
128 |
{
|
|
|
129 |
list($params['module'], $params['action']) = explode('/', $url);
|
|
|
130 |
}
|
|
|
131 |
else if (!$queryString)
|
|
|
132 |
{
|
|
|
133 |
$route = $givenUrl;
|
|
|
134 |
}
|
|
|
135 |
else
|
|
|
136 |
{
|
|
|
137 |
throw new InvalidArgumentException(sprintf('An internal URI must contain a module and an action (module/action) ("%s" given).', $givenUrl));
|
|
|
138 |
}
|
|
|
139 |
|
|
|
140 |
// split the query string
|
|
|
141 |
if ($queryString)
|
|
|
142 |
{
|
|
|
143 |
$matched = preg_match_all('/
|
|
|
144 |
([^&=]+) # key
|
|
|
145 |
= # =
|
|
|
146 |
(.*?) # value
|
|
|
147 |
(?:
|
|
|
148 |
(?=&[^&=]+=) | $ # followed by another key= or the end of the string
|
|
|
149 |
)
|
|
|
150 |
/x', $queryString, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE);
|
|
|
151 |
foreach ($matches as $match)
|
|
|
152 |
{
|
|
|
153 |
$params[urldecode($match[1][0])] = urldecode($match[2][0]);
|
|
|
154 |
}
|
|
|
155 |
|
|
|
156 |
// check that all string is matched
|
|
|
157 |
if (!$matched)
|
|
|
158 |
{
|
|
|
159 |
throw new sfParseException(sprintf('Unable to parse query string "%s".', $queryString));
|
|
|
160 |
}
|
|
|
161 |
}
|
|
|
162 |
|
|
|
163 |
return array($route, $params);
|
|
|
164 |
}
|
|
|
165 |
|
|
|
166 |
/**
|
|
|
167 |
* Redirects the request to another URL.
|
|
|
168 |
*
|
|
|
169 |
* @param string $url An associative array of URL parameters or an internal URI as a string
|
|
|
170 |
* @param int $delay A delay in seconds before redirecting. This is only needed on
|
|
|
171 |
* browsers that do not support HTTP headers
|
|
|
172 |
* @param int $statusCode The status code
|
|
|
173 |
*
|
|
|
174 |
* @throws InvalidArgumentException If the url argument is null or an empty string
|
|
|
175 |
*/
|
|
|
176 |
public function redirect($url, $delay = 0, $statusCode = 302)
|
|
|
177 |
{
|
|
|
178 |
if (empty($url))
|
|
|
179 |
{
|
|
|
180 |
throw new InvalidArgumentException('Cannot redirect to an empty URL.');
|
|
|
181 |
}
|
|
|
182 |
|
|
|
183 |
$url = $this->genUrl($url, true);
|
|
|
184 |
// see #8083
|
|
|
185 |
$url = str_replace('&', '&', $url);
|
|
|
186 |
|
|
|
187 |
if (sfConfig::get('sf_logging_enabled'))
|
|
|
188 |
{
|
|
|
189 |
$this->dispatcher->notify(new sfEvent($this, 'application.log', array(sprintf('Redirect to "%s"', $url))));
|
|
|
190 |
}
|
|
|
191 |
|
|
|
192 |
// redirect
|
|
|
193 |
$response = $this->context->getResponse();
|
|
|
194 |
$response->clearHttpHeaders();
|
|
|
195 |
$response->setStatusCode($statusCode);
|
|
|
196 |
|
|
|
197 |
// The Location header should only be used for status codes 201 and 3..
|
|
|
198 |
// For other code, only the refresh meta tag is used
|
|
|
199 |
if ($statusCode == 201 || ($statusCode >= 300 && $statusCode < 400))
|
|
|
200 |
{
|
|
|
201 |
$response->setHttpHeader('Location', $url);
|
|
|
202 |
}
|
|
|
203 |
|
|
|
204 |
$response->setContent(sprintf('<html><head><meta http-equiv="refresh" content="%d;url=%s"/></head></html>', $delay, htmlspecialchars($url, ENT_QUOTES, sfConfig::get('sf_charset'))));
|
|
|
205 |
$response->send();
|
|
|
206 |
}
|
|
|
207 |
}
|