<?php
namespace Symfony\Cmf\Component\Routing;
use Symfony\Component\Routing\Route as SymfonyRoute;
use Symfony\Component\Routing\Exception\RouteNotFoundException;
use Symfony\Component\Routing\RouteCollection;
class ContentAwareGenerator extends ProviderBasedGenerator {
protected $contentRepository;
public function setContentRepository(ContentRepositoryInterface $contentRepository) {
$this->contentRepository = $contentRepository;
}
public function generate($name, $parameters = array(), $absolute = false) {
if ($name instanceof SymfonyRoute) {
$route = $this
->getBestLocaleRoute($name, $parameters);
}
elseif (is_string($name) && $name) {
$route = $this
->getRouteByName($name, $parameters);
}
else {
$route = $this
->getRouteByContent($name, $parameters);
}
if (!$route instanceof SymfonyRoute) {
$hint = is_object($route) ? get_class($route) : gettype($route);
throw new RouteNotFoundException('Route of this document is not an instance of Symfony\\Component\\Routing\\Route but: ' . $hint);
}
$this
->unsetLocaleIfNotNeeded($route, $parameters);
return parent::generate($route, $parameters, $absolute);
}
protected function getRouteByName($name, array $parameters) {
$route = $this->provider
->getRouteByName($name, $parameters);
if (empty($route)) {
throw new RouteNotFoundException('No route found for name: ' . $name);
}
return $this
->getBestLocaleRoute($route, $parameters);
}
protected function getBestLocaleRoute(SymfonyRoute $route, $parameters) {
if (!$route instanceof RouteObjectInterface) {
return $route;
}
$locale = $this
->getLocale($parameters);
if (!$this
->checkLocaleRequirement($route, $locale)) {
$content = $route
->getRouteContent();
if ($content instanceof RouteAwareInterface) {
$routes = $content
->getRoutes();
$contentRoute = $this
->getRouteByLocale($routes, $locale);
if ($contentRoute) {
return $contentRoute;
}
}
}
return $route;
}
protected function getRouteByContent($name, &$parameters) {
if ($name instanceof RouteAwareInterface) {
$content = $name;
}
elseif (isset($parameters['content_id']) && null !== $this->contentRepository) {
$content = $this->contentRepository
->findById($parameters['content_id']);
if (empty($content)) {
throw new RouteNotFoundException('The content repository found nothing at id ' . $parameters['content_id']);
}
if (!$content instanceof RouteAwareInterface) {
throw new RouteNotFoundException('Content repository did not return a RouteAwareInterface for id ' . $parameters['content_id']);
}
}
else {
$hint = is_object($name) ? get_class($name) : gettype($name);
throw new RouteNotFoundException("The route name argument '{$hint}' is not RouteAwareInterface and there is no 'content_id' parameter");
}
$routes = $content
->getRoutes();
if (empty($routes)) {
$hint = $this->contentRepository && $this->contentRepository
->getContentId($content) ? $this->contentRepository
->getContentId($content) : get_class($content);
throw new RouteNotFoundException('Content document has no route: ' . $hint);
}
unset($parameters['content_id']);
$route = $this
->getRouteByLocale($routes, $this
->getLocale($parameters));
if ($route) {
return $route;
}
return reset($routes);
}
protected function getRouteByLocale($routes, $locale) {
foreach ($routes as $route) {
if (!$route instanceof SymfonyRoute) {
continue;
}
if ($this
->checkLocaleRequirement($route, $locale)) {
return $route;
}
}
return false;
}
private function checkLocaleRequirement(SymfonyRoute $route, $locale) {
return empty($locale) || !$route
->getRequirement('_locale') || preg_match('/' . $route
->getRequirement('_locale') . '/', $locale);
}
protected function getLocale($parameters) {
if (isset($parameters['_locale'])) {
return $parameters['_locale'];
}
return null;
}
public function supports($name) {
return !$name || parent::supports($name) || $name instanceof RouteAwareInterface;
}
public function getRouteDebugMessage($name, array $parameters = array()) {
if (empty($name) && isset($parameters['content_id'])) {
return 'Content id ' . $parameters['content_id'];
}
if ($name instanceof RouteAwareInterface) {
return 'Route aware content ' . $name;
}
return parent::getRouteDebugMessage($name, $parameters);
}
protected function unsetLocaleIfNotNeeded(SymfonyRoute $route, array &$parameters) {
$locale = $this
->getLocale($parameters);
if (null !== $locale) {
if (preg_match('/' . $route
->getRequirement('_locale') . '/', $locale) && $locale == $route
->getDefault('_locale')) {
$compiledRoute = $route
->compile();
if (!in_array('_locale', $compiledRoute
->getVariables())) {
unset($parameters['_locale']);
}
}
}
}
}