Verzeichnisstruktur phpBB-3.3.15
- Veröffentlicht
- 28.08.2024
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
StaticPrefixCollection.php
001 <?php
002
003 /*
004 * This file is part of the Symfony package.
005 *
006 * (c) Fabien Potencier <fabien@symfony.com>
007 *
008 * For the full copyright and license information, please view the LICENSE
009 * file that was distributed with this source code.
010 */
011
012 namespace Symfony\Component\Routing\Matcher\Dumper;
013
014 /**
015 * Prefix tree of routes preserving routes order.
016 *
017 * @author Frank de Jonge <info@frankdejonge.nl>
018 *
019 * @internal
020 */
021 class StaticPrefixCollection
022 {
023 /**
024 * @var string
025 */
026 private $prefix;
027
028 /**
029 * @var array[]|StaticPrefixCollection[]
030 */
031 private $items = [];
032
033 /**
034 * @var int
035 */
036 private $matchStart = 0;
037
038 public function __construct($prefix = '')
039 {
040 $this->prefix = $prefix;
041 }
042
043 public function getPrefix()
044 {
045 return $this->prefix;
046 }
047
048 /**
049 * @return mixed[]|StaticPrefixCollection[]
050 */
051 public function getItems()
052 {
053 return $this->items;
054 }
055
056 /**
057 * Adds a route to a group.
058 *
059 * @param string $prefix
060 * @param mixed $route
061 */
062 public function addRoute($prefix, $route)
063 {
064 $prefix = '/' === $prefix ? $prefix : rtrim($prefix, '/');
065 $this->guardAgainstAddingNotAcceptedRoutes($prefix);
066
067 if ($this->prefix === $prefix) {
068 // When a prefix is exactly the same as the base we move up the match start position.
069 // This is needed because otherwise routes that come afterwards have higher precedence
070 // than a possible regular expression, which goes against the input order sorting.
071 $this->items[] = [$prefix, $route];
072 $this->matchStart = \count($this->items);
073
074 return;
075 }
076
077 foreach ($this->items as $i => $item) {
078 if ($i < $this->matchStart) {
079 continue;
080 }
081
082 if ($item instanceof self && $item->accepts($prefix)) {
083 $item->addRoute($prefix, $route);
084
085 return;
086 }
087
088 $group = $this->groupWithItem($item, $prefix, $route);
089
090 if ($group instanceof self) {
091 $this->items[$i] = $group;
092
093 return;
094 }
095 }
096
097 // No optimised case was found, in this case we simple add the route for possible
098 // grouping when new routes are added.
099 $this->items[] = [$prefix, $route];
100 }
101
102 /**
103 * Tries to combine a route with another route or group.
104 *
105 * @param StaticPrefixCollection|array $item
106 * @param string $prefix
107 * @param mixed $route
108 *
109 * @return StaticPrefixCollection|null
110 */
111 private function groupWithItem($item, $prefix, $route)
112 {
113 $itemPrefix = $item instanceof self ? $item->prefix : $item[0];
114 $commonPrefix = $this->detectCommonPrefix($prefix, $itemPrefix);
115
116 if (!$commonPrefix) {
117 return null;
118 }
119
120 $child = new self($commonPrefix);
121
122 if ($item instanceof self) {
123 $child->items = [$item];
124 } else {
125 $child->addRoute($item[0], $item[1]);
126 }
127
128 $child->addRoute($prefix, $route);
129
130 return $child;
131 }
132
133 /**
134 * Checks whether a prefix can be contained within the group.
135 *
136 * @param string $prefix
137 *
138 * @return bool Whether a prefix could belong in a given group
139 */
140 private function accepts($prefix)
141 {
142 return '' === $this->prefix || 0 === strpos($prefix, $this->prefix);
143 }
144
145 /**
146 * Detects whether there's a common prefix relative to the group prefix and returns it.
147 *
148 * @param string $prefix
149 * @param string $anotherPrefix
150 *
151 * @return false|string A common prefix, longer than the base/group prefix, or false when none available
152 */
153 private function detectCommonPrefix($prefix, $anotherPrefix)
154 {
155 $baseLength = \strlen($this->prefix);
156 $commonLength = $baseLength;
157 $end = min(\strlen($prefix), \strlen($anotherPrefix));
158
159 for ($i = $baseLength; $i <= $end; ++$i) {
160 if (substr($prefix, 0, $i) !== substr($anotherPrefix, 0, $i)) {
161 break;
162 }
163
164 $commonLength = $i;
165 }
166
167 $commonPrefix = rtrim(substr($prefix, 0, $commonLength), '/');
168
169 if (\strlen($commonPrefix) > $baseLength) {
170 return $commonPrefix;
171 }
172
173 return false;
174 }
175
176 /**
177 * Optimizes the tree by inlining items from groups with less than 3 items.
178 */
179 public function optimizeGroups()
180 {
181 $index = -1;
182
183 while (isset($this->items[++$index])) {
184 $item = $this->items[$index];
185
186 if ($item instanceof self) {
187 $item->optimizeGroups();
188
189 // When a group contains only two items there's no reason to optimize because at minimum
190 // the amount of prefix check is 2. In this case inline the group.
191 if ($item->shouldBeInlined()) {
192 array_splice($this->items, $index, 1, $item->items);
193
194 // Lower index to pass through the same index again after optimizing.
195 // The first item of the replacements might be a group needing optimization.
196 --$index;
197 }
198 }
199 }
200 }
201
202 private function shouldBeInlined()
203 {
204 if (\count($this->items) >= 3) {
205 return false;
206 }
207
208 foreach ($this->items as $item) {
209 if ($item instanceof self) {
210 return true;
211 }
212 }
213
214 foreach ($this->items as $item) {
215 if (\is_array($item) && $item[0] === $this->prefix) {
216 return false;
217 }
218 }
219
220 return true;
221 }
222
223 /**
224 * Guards against adding incompatible prefixes in a group.
225 *
226 * @param string $prefix
227 *
228 * @throws \LogicException when a prefix does not belong in a group
229 */
230 private function guardAgainstAddingNotAcceptedRoutes($prefix)
231 {
232 if (!$this->accepts($prefix)) {
233 $message = sprintf('Could not add route with prefix %s to collection with prefix %s', $prefix, $this->prefix);
234
235 throw new \LogicException($message);
236 }
237 }
238 }
239