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) Fabien Potencier <fabien.potencier@symfony-project.com>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
 
11
/**
12
 * sfObjectRoute represents a route that is bound to PHP object(s).
13
 *
14
 * An object route can represent a single object or a list of objects.
15
 *
16
 * @package    symfony
17
 * @subpackage routing
18
 * @author     Fabien Potencier <fabien.potencier@symfony-project.com>
19
 * @version    SVN: $Id: sfObjectRoute.class.php 20784 2009-08-04 20:53:57Z Kris.Wallsmith $
20
 */
21
class sfObjectRoute extends sfRequestRoute
22
{
23
  protected
24
    $object  = false,
25
    $objects = false;
26
 
27
  /**
28
   * Constructor.
29
   *
30
   * @param string $pattern       The pattern to match
31
   * @param array  $defaults      An array of default parameter values
32
   * @param array  $requirements  An array of requirements for parameters (regexes)
33
   * @param array  $options       An array of options
34
   *
35
   * @see sfRoute
36
   */
37
  public function __construct($pattern, array $defaults = array(), array $requirements = array(), array $options = array())
38
  {
39
    if (!isset($options['model']))
40
    {
41
      throw new InvalidArgumentException(sprintf('You must pass a "model" option for a %s object (%s).', get_class($this), $pattern));
42
    }
43
 
44
    if (!isset($options['type']))
45
    {
46
      throw new InvalidArgumentException(sprintf('You must pass a "type" option for a %s object (%s).', get_class($this), $pattern));
47
    }
48
 
49
    if (!in_array($options['type'], array('object', 'list')))
50
    {
51
      throw new InvalidArgumentException(sprintf('The "type" option can only be "object" or "list", "%s" given (%s).', $options['type'], $pattern));
52
    }
53
 
54
    parent::__construct($pattern, $defaults, $requirements, $options);
55
  }
56
 
57
  /**
58
   * Returns true if the parameters matches this route, false otherwise.
59
   *
60
   * @param  mixed  $params  The parameters
61
   * @param  array  $context The context
62
   *
63
   * @return Boolean         true if the parameters matches this route, false otherwise.
64
   */
65
  public function matchesParameters($params, $context = array())
66
  {
67
    return parent::matchesParameters('object' == $this->options['type'] ? $this->convertObjectToArray($params) : $params);
68
  }
69
 
70
  /**
71
   * Generates a URL from the given parameters.
72
   *
73
   * @param  mixed   $params    The parameter values
74
   * @param  array   $context   The context
75
   * @param  Boolean $absolute  Whether to generate an absolute URL
76
   *
77
   * @return string The generated URL
78
   */
79
  public function generate($params, $context = array(), $absolute = false)
80
  {
81
    return parent::generate('object' == $this->options['type'] ? $this->convertObjectToArray($params) : $params, $context, $absolute);
82
  }
83
 
84
  /**
85
   * Gets the object related to the current route and parameters.
86
   *
87
   * This method is only accessible if the route is bound and of type "object".
88
   *
89
   * @return Object The related object
90
   */
91
  public function getObject()
92
  {
93
    if (!$this->isBound())
94
    {
95
      throw new LogicException('The route is not bound.');
96
    }
97
 
98
    if ('object' != $this->options['type'])
99
    {
100
      throw new LogicException(sprintf('The route "%s" is not of type "object".', $this->pattern));
101
    }
102
 
103
    if (false !== $this->object)
104
    {
105
      return $this->object;
106
    }
107
 
108
    // check the related object
109
    if (!($this->object = $this->getObjectForParameters($this->parameters)) && (!isset($this->options['allow_empty']) || !$this->options['allow_empty']))
110
    {
111
      throw new sfError404Exception(sprintf('Unable to find the %s object with the following parameters "%s").', $this->options['model'], str_replace("\n", '', var_export($this->filterParameters($this->parameters), true))));
112
    }
113
 
114
    return $this->object;
115
  }
116
 
117
  /**
118
   * Gets the list of objects related to the current route and parameters.
119
   *
120
   * This method is only accessible if the route is bound and of type "list".
121
   *
122
   * @return array And array of related objects
123
   */
124
  public function getObjects()
125
  {
126
    if (!$this->isBound())
127
    {
128
      throw new LogicException('The route is not bound.');
129
    }
130
 
131
    if ('list' != $this->options['type'])
132
    {
133
      throw new LogicException(sprintf('The route "%s" is not of type "list".', $this->pattern));
134
    }
135
 
136
    if (false !== $this->objects)
137
    {
138
      return $this->objects;
139
    }
140
 
141
    $this->objects = $this->getObjectsForParameters($this->parameters);
142
 
143
    if (!count($this->objects) && isset($this->options['allow_empty']) && !$this->options['allow_empty'])
144
    {
145
      throw new sfError404Exception(sprintf('No %s object found for the following parameters "%s").', $this->options['model'], str_replace("\n", '', var_export($this->filterParameters($this->parameters), true))));
146
    }
147
 
148
    return $this->objects;
149
  }
150
 
151
  protected function getObjectForParameters($parameters)
152
  {
153
    $className = $this->options['model'];
154
 
155
    if (!isset($this->options['method']))
156
    {
157
      throw new InvalidArgumentException(sprintf('You must pass a "method" option for a %s object.', get_class($this)));
158
    }
159
 
160
    return call_user_func(array($className, $this->options['method']), $this->filterParameters($parameters));
161
  }
162
 
163
  protected function getObjectsForParameters($parameters)
164
  {
165
    $className = $this->options['model'];
166
 
167
    if (!isset($this->options['method']))
168
    {
169
      throw new InvalidArgumentException(sprintf('You must pass a "method" option for a %s object.', get_class($this)));
170
    }
171
 
172
    return call_user_func(array($className, $this->options['method']), $this->filterParameters($parameters));
173
  }
174
 
175
  protected function filterParameters($parameters)
176
  {
177
    if (!is_array($parameters))
178
    {
179
      return $parameters;
180
    }
181
 
182
    $params = array();
183
    foreach (array_keys($this->variables) as $variable)
184
    {
185
      $params[$variable] = $parameters[$variable];
186
    }
187
 
188
    return $params;
189
  }
190
 
191
  protected function convertObjectToArray($object)
192
  {
193
    if (!$this->compiled)
194
    {
195
      $this->compile();
196
    }
197
 
198
    if (is_array($object))
199
    {
200
      if (!isset($object['sf_subject']))
201
      {
202
        return $object;
203
      }
204
 
205
      $parameters = $object;
206
      $object = $parameters['sf_subject'];
207
      unset($parameters['sf_subject']);
208
    }
209
    else
210
    {
211
      $parameters = array();
212
    }
213
 
214
    return array_merge($parameters, $this->doConvertObjectToArray($object));
215
  }
216
 
217
  protected function doConvertObjectToArray($object)
218
  {
219
    $method = isset($this->options['convert']) ? $this->options['convert'] : 'toParams';
220
 
221
    return $object->$method();
222
  }
223
 
224
  protected function getRealVariables()
225
  {
226
    $variables = array();
227
 
228
    foreach (array_keys($this->variables) as $variable)
229
    {
230
      if (0 === strpos($variable, 'sf_') || in_array($variable, array('module', 'action')))
231
      {
232
        continue;
233
      }
234
 
235
      $variables[] = $variable;
236
    }
237
 
238
    return $variables;
239
  }
240
}