155 lines
3.9 KiB
PHP
155 lines
3.9 KiB
PHP
![]() |
<?php
|
||
|
|
||
|
/*
|
||
|
* This file is part of the Symfony CMF package.
|
||
|
*
|
||
|
* (c) 2011-2014 Symfony CMF
|
||
|
*
|
||
|
* For the full copyright and license information, please view the LICENSE
|
||
|
* file that was distributed with this source code.
|
||
|
*/
|
||
|
|
||
|
namespace Symfony\Cmf\Component\Routing\Candidates;
|
||
|
|
||
|
use Symfony\Component\HttpFoundation\Request;
|
||
|
|
||
|
/**
|
||
|
* A straightforward strategy that splits the URL on "/".
|
||
|
*
|
||
|
* If locales is set, additionally generates candidates removing the locale if
|
||
|
* it is one of the configured locales, for non-locale specific URLs.
|
||
|
*
|
||
|
* @author David Buchmann <mail@davidbu.ch>
|
||
|
*/
|
||
|
class Candidates implements CandidatesInterface
|
||
|
{
|
||
|
/**
|
||
|
* @var array
|
||
|
*/
|
||
|
protected $locales;
|
||
|
|
||
|
/**
|
||
|
* A limit to apply to the number of candidates generated.
|
||
|
*
|
||
|
* This is to prevent abusive requests with a lot of "/". The limit is per
|
||
|
* batch, that is if a locale matches you could get as many as 2 * $limit
|
||
|
* candidates if the URL has that many slashes.
|
||
|
*
|
||
|
* @var int
|
||
|
*/
|
||
|
protected $limit;
|
||
|
|
||
|
/**
|
||
|
* @param array $locales The locales to support.
|
||
|
* @param int $limit A limit to apply to the candidates generated.
|
||
|
*/
|
||
|
public function __construct(array $locales = array(), $limit = 20)
|
||
|
{
|
||
|
$this->setLocales($locales);
|
||
|
$this->limit = $limit;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Set the locales to support by this strategy.
|
||
|
*
|
||
|
* @param array $locales The locales to support.
|
||
|
*/
|
||
|
public function setLocales(array $locales)
|
||
|
{
|
||
|
$this->locales = $locales;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* {@inheritDoc}
|
||
|
*
|
||
|
* Always returns true.
|
||
|
*/
|
||
|
public function isCandidate($name)
|
||
|
{
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* {@inheritDoc}
|
||
|
*
|
||
|
* Does nothing.
|
||
|
*/
|
||
|
public function restrictQuery($queryBuilder)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* {@inheritDoc}
|
||
|
*/
|
||
|
public function getCandidates(Request $request)
|
||
|
{
|
||
|
$url = $request->getPathInfo();
|
||
|
$candidates = $this->getCandidatesFor($url);
|
||
|
|
||
|
$locale = $this->determineLocale($url);
|
||
|
if ($locale) {
|
||
|
$candidates = array_unique(array_merge($candidates, $this->getCandidatesFor(substr($url, strlen($locale) + 1))));
|
||
|
}
|
||
|
|
||
|
return $candidates;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Determine the locale of this URL.
|
||
|
*
|
||
|
* @param string $url The url to determine the locale from.
|
||
|
*
|
||
|
* @return string|boolean The locale if $url starts with one of the allowed locales.
|
||
|
*/
|
||
|
protected function determineLocale($url)
|
||
|
{
|
||
|
if (!count($this->locales)) {
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
$matches = array();
|
||
|
if (preg_match('#(' . implode('|', $this->locales) . ')(/|$)#', $url, $matches)) {
|
||
|
return $matches[1];
|
||
|
}
|
||
|
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Handle a possible format extension and split the $url on "/".
|
||
|
*
|
||
|
* $prefix is prepended to every candidate generated.
|
||
|
*
|
||
|
* @param string $url The URL to split.
|
||
|
* @param string $prefix A prefix to prepend to every pattern.
|
||
|
*
|
||
|
* @return array Paths that could represent routes that match $url and are
|
||
|
* child of $prefix.
|
||
|
*/
|
||
|
protected function getCandidatesFor($url, $prefix = '')
|
||
|
{
|
||
|
$candidates = array();
|
||
|
if ('/' !== $url) {
|
||
|
// handle format extension, like .html or .json
|
||
|
if (preg_match('/(.+)\.[a-z]+$/i', $url, $matches)) {
|
||
|
$candidates[] = $prefix . $url;
|
||
|
$url = $matches[1];
|
||
|
}
|
||
|
|
||
|
$part = $url;
|
||
|
$count = 0;
|
||
|
while (false !== ($pos = strrpos($part, '/'))) {
|
||
|
if (++$count > $this->limit) {
|
||
|
return $candidates;
|
||
|
}
|
||
|
$candidates[] = $prefix . $part;
|
||
|
$part = substr($url, 0, $pos);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$candidates[] = $prefix ?: '/';
|
||
|
|
||
|
return $candidates;
|
||
|
}
|
||
|
}
|