Yaffs site version 1.1
[yaffs-website] / vendor / symfony-cmf / routing / Candidates / Candidates.php
1 <?php
2
3 /*
4  * This file is part of the Symfony CMF package.
5  *
6  * (c) 2011-2015 Symfony CMF
7  *
8  * For the full copyright and license information, please view the LICENSE
9  * file that was distributed with this source code.
10  */
11
12 namespace Symfony\Cmf\Component\Routing\Candidates;
13
14 use Symfony\Component\HttpFoundation\Request;
15
16 /**
17  * A straightforward strategy that splits the URL on "/".
18  *
19  * If locales is set, additionally generates candidates removing the locale if
20  * it is one of the configured locales, for non-locale specific URLs.
21  *
22  * @author David Buchmann <mail@davidbu.ch>
23  */
24 class Candidates implements CandidatesInterface
25 {
26     /**
27      * @var array
28      */
29     protected $locales;
30
31     /**
32      * A limit to apply to the number of candidates generated.
33      *
34      * This is to prevent abusive requests with a lot of "/". The limit is per
35      * batch, that is if a locale matches you could get as many as 2 * $limit
36      * candidates if the URL has that many slashes.
37      *
38      * @var int
39      */
40     protected $limit;
41
42     /**
43      * @param array $locales The locales to support.
44      * @param int   $limit   A limit to apply to the candidates generated.
45      */
46     public function __construct(array $locales = array(), $limit = 20)
47     {
48         $this->setLocales($locales);
49         $this->limit = $limit;
50     }
51
52     /**
53      * Set the locales to support by this strategy.
54      *
55      * @param array $locales The locales to support.
56      */
57     public function setLocales(array $locales)
58     {
59         $this->locales = $locales;
60     }
61
62     /**
63      * {@inheritdoc}
64      *
65      * Always returns true.
66      */
67     public function isCandidate($name)
68     {
69         return true;
70     }
71
72     /**
73      * {@inheritdoc}
74      *
75      * Does nothing.
76      */
77     public function restrictQuery($queryBuilder)
78     {
79     }
80
81     /**
82      * {@inheritdoc}
83      */
84     public function getCandidates(Request $request)
85     {
86         $url = $request->getPathInfo();
87         $candidates = $this->getCandidatesFor($url);
88
89         $locale = $this->determineLocale($url);
90         if ($locale) {
91             $candidates = array_unique(array_merge($candidates, $this->getCandidatesFor(substr($url, strlen($locale) + 1))));
92         }
93
94         return $candidates;
95     }
96
97     /**
98      * Determine the locale of this URL.
99      *
100      * @param string $url The url to determine the locale from.
101      *
102      * @return string|bool The locale if $url starts with one of the allowed locales.
103      */
104     protected function determineLocale($url)
105     {
106         if (!count($this->locales)) {
107             return false;
108         }
109
110         $matches = array();
111         if (preg_match('#^/('.implode('|', $this->locales).')(/|$)#', $url, $matches)) {
112             return $matches[1];
113         }
114
115         return false;
116     }
117
118     /**
119      * Handle a possible format extension and split the $url on "/".
120      *
121      * $prefix is prepended to every candidate generated.
122      *
123      * @param string $url    The URL to split.
124      * @param string $prefix A prefix to prepend to every pattern.
125      *
126      * @return array Paths that could represent routes that match $url and are
127      *               child of $prefix.
128      */
129     protected function getCandidatesFor($url, $prefix = '')
130     {
131         $candidates = array();
132         if ('/' !== $url) {
133             // handle format extension, like .html or .json
134             if (preg_match('/(.+)\.[a-z]+$/i', $url, $matches)) {
135                 $candidates[] = $prefix.$url;
136                 $url = $matches[1];
137             }
138
139             $part = $url;
140             $count = 0;
141             while (false !== ($pos = strrpos($part, '/'))) {
142                 if (++$count > $this->limit) {
143                     return $candidates;
144                 }
145                 $candidates[] = $prefix.$part;
146                 $part = substr($url, 0, $pos);
147             }
148         }
149
150         $candidates[] = $prefix ?: '/';
151
152         return $candidates;
153     }
154 }