Subversion-Projekte lars-tiefland.php_share

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
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('&amp;', '&', $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
}