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