2015-08-17 17:00:26 -07:00
< ? php
/*
* This file is part of the Symfony CMF package .
*
2016-10-06 15:16:20 -07:00
* ( c ) 2011 - 2015 Symfony CMF
2015-08-17 17:00:26 -07:00
*
* 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 ;
}
/**
2016-10-06 15:16:20 -07:00
* { @ inheritdoc }
2015-08-17 17:00:26 -07:00
*
* Always returns true .
*/
public function isCandidate ( $name )
{
return true ;
}
/**
2016-10-06 15:16:20 -07:00
* { @ inheritdoc }
2015-08-17 17:00:26 -07:00
*
* Does nothing .
*/
public function restrictQuery ( $queryBuilder )
{
}
/**
2016-10-06 15:16:20 -07:00
* { @ inheritdoc }
2015-08-17 17:00:26 -07:00
*/
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 .
*
2016-10-06 15:16:20 -07:00
* @ return string | bool The locale if $url starts with one of the allowed locales .
2015-08-17 17:00:26 -07:00
*/
protected function determineLocale ( $url )
{
if ( ! count ( $this -> locales )) {
return false ;
}
$matches = array ();
2016-10-06 15:16:20 -07:00
if ( preg_match ( '#(' . implode ( '|' , $this -> locales ) . ')(/|$)#' , $url , $matches )) {
2015-08-17 17:00:26 -07:00
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 )) {
2016-10-06 15:16:20 -07:00
$candidates [] = $prefix . $url ;
2015-08-17 17:00:26 -07:00
$url = $matches [ 1 ];
}
$part = $url ;
$count = 0 ;
while ( false !== ( $pos = strrpos ( $part , '/' ))) {
if ( ++ $count > $this -> limit ) {
return $candidates ;
}
2016-10-06 15:16:20 -07:00
$candidates [] = $prefix . $part ;
2015-08-17 17:00:26 -07:00
$part = substr ( $url , 0 , $pos );
}
}
$candidates [] = $prefix ? : '/' ;
return $candidates ;
}
}