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

Debug toolbar