diff options
author | Nicolas LÅ“uillet <nicolas.loeuillet@gmail.com> | 2013-08-03 19:26:54 +0200 |
---|---|---|
committer | Nicolas LÅ“uillet <nicolas.loeuillet@gmail.com> | 2013-08-03 19:26:54 +0200 |
commit | 4f5b44bd3bd490309eb2ba7b44df4769816ba729 (patch) | |
tree | 6cefe170dfe0a5a361cb1e2d1fc4d580a3316d02 /vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyPathBuilder.php | |
parent | 2b840e0cfb63a453bea67a98541f3df9c273c5f5 (diff) | |
download | wallabag-4f5b44bd3bd490309eb2ba7b44df4769816ba729.tar.gz wallabag-4f5b44bd3bd490309eb2ba7b44df4769816ba729.tar.zst wallabag-4f5b44bd3bd490309eb2ba7b44df4769816ba729.zip |
twig implementation
Diffstat (limited to 'vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyPathBuilder.php')
-rw-r--r-- | vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyPathBuilder.php | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyPathBuilder.php b/vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyPathBuilder.php new file mode 100644 index 00000000..f4eb0fb9 --- /dev/null +++ b/vendor/symfony/property-access/Symfony/Component/PropertyAccess/PropertyPathBuilder.php | |||
@@ -0,0 +1,306 @@ | |||
1 | <?php | ||
2 | |||
3 | /* | ||
4 | * This file is part of the Symfony package. | ||
5 | * | ||
6 | * (c) Fabien Potencier <fabien@symfony.com> | ||
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\Component\PropertyAccess; | ||
13 | |||
14 | use Symfony\Component\PropertyAccess\Exception\OutOfBoundsException; | ||
15 | |||
16 | /** | ||
17 | * @author Bernhard Schussek <bschussek@gmail.com> | ||
18 | */ | ||
19 | class PropertyPathBuilder | ||
20 | { | ||
21 | /** | ||
22 | * @var array | ||
23 | */ | ||
24 | private $elements = array(); | ||
25 | |||
26 | /** | ||
27 | * @var array | ||
28 | */ | ||
29 | private $isIndex = array(); | ||
30 | |||
31 | /** | ||
32 | * Creates a new property path builder. | ||
33 | * | ||
34 | * @param null|PropertyPathInterface|string $path The path to initially store | ||
35 | * in the builder. Optional. | ||
36 | */ | ||
37 | public function __construct($path = null) | ||
38 | { | ||
39 | if (null !== $path) { | ||
40 | $this->append($path); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | /** | ||
45 | * Appends a (sub-) path to the current path. | ||
46 | * | ||
47 | * @param PropertyPathInterface|string $path The path to append. | ||
48 | * @param integer $offset The offset where the appended | ||
49 | * piece starts in $path. | ||
50 | * @param integer $length The length of the appended piece. | ||
51 | * If 0, the full path is appended. | ||
52 | */ | ||
53 | public function append($path, $offset = 0, $length = 0) | ||
54 | { | ||
55 | if (is_string($path)) { | ||
56 | $path = new PropertyPath($path); | ||
57 | } | ||
58 | |||
59 | if (0 === $length) { | ||
60 | $end = $path->getLength(); | ||
61 | } else { | ||
62 | $end = $offset + $length; | ||
63 | } | ||
64 | |||
65 | for (; $offset < $end; ++$offset) { | ||
66 | $this->elements[] = $path->getElement($offset); | ||
67 | $this->isIndex[] = $path->isIndex($offset); | ||
68 | } | ||
69 | } | ||
70 | |||
71 | /** | ||
72 | * Appends an index element to the current path. | ||
73 | * | ||
74 | * @param string $name The name of the appended index | ||
75 | */ | ||
76 | public function appendIndex($name) | ||
77 | { | ||
78 | $this->elements[] = $name; | ||
79 | $this->isIndex[] = true; | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * Appends a property element to the current path. | ||
84 | * | ||
85 | * @param string $name The name of the appended property | ||
86 | */ | ||
87 | public function appendProperty($name) | ||
88 | { | ||
89 | $this->elements[] = $name; | ||
90 | $this->isIndex[] = false; | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * Removes elements from the current path. | ||
95 | * | ||
96 | * @param integer $offset The offset at which to remove | ||
97 | * @param integer $length The length of the removed piece | ||
98 | * | ||
99 | * @throws OutOfBoundsException if offset is invalid | ||
100 | */ | ||
101 | public function remove($offset, $length = 1) | ||
102 | { | ||
103 | if (!isset($this->elements[$offset])) { | ||
104 | throw new OutOfBoundsException(sprintf('The offset %s is not within the property path', $offset)); | ||
105 | } | ||
106 | |||
107 | $this->resize($offset, $length, 0); | ||
108 | } | ||
109 | |||
110 | /** | ||
111 | * Replaces a sub-path by a different (sub-) path. | ||
112 | * | ||
113 | * @param integer $offset The offset at which to replace. | ||
114 | * @param integer $length The length of the piece to replace. | ||
115 | * @param PropertyPathInterface|string $path The path to insert. | ||
116 | * @param integer $pathOffset The offset where the inserted piece | ||
117 | * starts in $path. | ||
118 | * @param integer $pathLength The length of the inserted piece. | ||
119 | * If 0, the full path is inserted. | ||
120 | * | ||
121 | * @throws OutOfBoundsException If the offset is invalid | ||
122 | */ | ||
123 | public function replace($offset, $length, $path, $pathOffset = 0, $pathLength = 0) | ||
124 | { | ||
125 | if (is_string($path)) { | ||
126 | $path = new PropertyPath($path); | ||
127 | } | ||
128 | |||
129 | if ($offset < 0 && abs($offset) <= $this->getLength()) { | ||
130 | $offset = $this->getLength() + $offset; | ||
131 | } elseif (!isset($this->elements[$offset])) { | ||
132 | throw new OutOfBoundsException('The offset ' . $offset . ' is not within the property path'); | ||
133 | } | ||
134 | |||
135 | if (0 === $pathLength) { | ||
136 | $pathLength = $path->getLength() - $pathOffset; | ||
137 | } | ||
138 | |||
139 | $this->resize($offset, $length, $pathLength); | ||
140 | |||
141 | for ($i = 0; $i < $pathLength; ++$i) { | ||
142 | $this->elements[$offset + $i] = $path->getElement($pathOffset + $i); | ||
143 | $this->isIndex[$offset + $i] = $path->isIndex($pathOffset + $i); | ||
144 | } | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * Replaces a property element by an index element. | ||
149 | * | ||
150 | * @param integer $offset The offset at which to replace | ||
151 | * @param string $name The new name of the element. Optional. | ||
152 | * | ||
153 | * @throws OutOfBoundsException If the offset is invalid | ||
154 | */ | ||
155 | public function replaceByIndex($offset, $name = null) | ||
156 | { | ||
157 | if (!isset($this->elements[$offset])) { | ||
158 | throw new OutOfBoundsException(sprintf('The offset %s is not within the property path', $offset)); | ||
159 | } | ||
160 | |||
161 | if (null !== $name) { | ||
162 | $this->elements[$offset] = $name; | ||
163 | } | ||
164 | |||
165 | $this->isIndex[$offset] = true; | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * Replaces an index element by a property element. | ||
170 | * | ||
171 | * @param integer $offset The offset at which to replace | ||
172 | * @param string $name The new name of the element. Optional. | ||
173 | * | ||
174 | * @throws OutOfBoundsException If the offset is invalid | ||
175 | */ | ||
176 | public function replaceByProperty($offset, $name = null) | ||
177 | { | ||
178 | if (!isset($this->elements[$offset])) { | ||
179 | throw new OutOfBoundsException(sprintf('The offset %s is not within the property path', $offset)); | ||
180 | } | ||
181 | |||
182 | if (null !== $name) { | ||
183 | $this->elements[$offset] = $name; | ||
184 | } | ||
185 | |||
186 | $this->isIndex[$offset] = false; | ||
187 | } | ||
188 | |||
189 | /** | ||
190 | * Returns the length of the current path. | ||
191 | * | ||
192 | * @return integer The path length | ||
193 | */ | ||
194 | public function getLength() | ||
195 | { | ||
196 | return count($this->elements); | ||
197 | } | ||
198 | |||
199 | /** | ||
200 | * Returns the current property path. | ||
201 | * | ||
202 | * @return PropertyPathInterface The constructed property path | ||
203 | */ | ||
204 | public function getPropertyPath() | ||
205 | { | ||
206 | $pathAsString = $this->__toString(); | ||
207 | |||
208 | return '' !== $pathAsString ? new PropertyPath($pathAsString) : null; | ||
209 | } | ||
210 | |||
211 | /** | ||
212 | * Returns the current property path as string. | ||
213 | * | ||
214 | * @return string The property path as string | ||
215 | */ | ||
216 | public function __toString() | ||
217 | { | ||
218 | $string = ''; | ||
219 | |||
220 | foreach ($this->elements as $offset => $element) { | ||
221 | if ($this->isIndex[$offset]) { | ||
222 | $element = '['.$element.']'; | ||
223 | } elseif ('' !== $string) { | ||
224 | $string .= '.'; | ||
225 | } | ||
226 | |||
227 | $string .= $element; | ||
228 | } | ||
229 | |||
230 | return $string; | ||
231 | } | ||
232 | |||
233 | /** | ||
234 | * Resizes the path so that a chunk of length $cutLength is | ||
235 | * removed at $offset and another chunk of length $insertionLength | ||
236 | * can be inserted. | ||
237 | * | ||
238 | * @param integer $offset The offset where the removed chunk starts | ||
239 | * @param integer $cutLength The length of the removed chunk | ||
240 | * @param integer $insertionLength The length of the inserted chunk | ||
241 | */ | ||
242 | private function resize($offset, $cutLength, $insertionLength) | ||
243 | { | ||
244 | // Nothing else to do in this case | ||
245 | if ($insertionLength === $cutLength) { | ||
246 | return; | ||
247 | } | ||
248 | |||
249 | $length = count($this->elements); | ||
250 | |||
251 | if ($cutLength > $insertionLength) { | ||
252 | // More elements should be removed than inserted | ||
253 | $diff = $cutLength - $insertionLength; | ||
254 | $newLength = $length - $diff; | ||
255 | |||
256 | // Shift elements to the left (left-to-right until the new end) | ||
257 | // Max allowed offset to be shifted is such that | ||
258 | // $offset + $diff < $length (otherwise invalid index access) | ||
259 | // i.e. $offset < $length - $diff = $newLength | ||
260 | for ($i = $offset; $i < $newLength; ++$i) { | ||
261 | $this->elements[$i] = $this->elements[$i + $diff]; | ||
262 | $this->isIndex[$i] = $this->isIndex[$i + $diff]; | ||
263 | } | ||
264 | |||
265 | // All remaining elements should be removed | ||
266 | for (; $i < $length; ++$i) { | ||
267 | unset($this->elements[$i]); | ||
268 | unset($this->isIndex[$i]); | ||
269 | } | ||
270 | } else { | ||
271 | $diff = $insertionLength - $cutLength; | ||
272 | |||
273 | $newLength = $length + $diff; | ||
274 | $indexAfterInsertion = $offset + $insertionLength; | ||
275 | |||
276 | // $diff <= $insertionLength | ||
277 | // $indexAfterInsertion >= $insertionLength | ||
278 | // => $diff <= $indexAfterInsertion | ||
279 | |||
280 | // In each of the following loops, $i >= $diff must hold, | ||
281 | // otherwise ($i - $diff) becomes negative. | ||
282 | |||
283 | // Shift old elements to the right to make up space for the | ||
284 | // inserted elements. This needs to be done left-to-right in | ||
285 | // order to preserve an ascending array index order | ||
286 | // Since $i = max($length, $indexAfterInsertion) and $indexAfterInsertion >= $diff, | ||
287 | // $i >= $diff is guaranteed. | ||
288 | for ($i = max($length, $indexAfterInsertion); $i < $newLength; ++$i) { | ||
289 | $this->elements[$i] = $this->elements[$i - $diff]; | ||
290 | $this->isIndex[$i] = $this->isIndex[$i - $diff]; | ||
291 | } | ||
292 | |||
293 | // Shift remaining elements to the right. Do this right-to-left | ||
294 | // so we don't overwrite elements before copying them | ||
295 | // The last written index is the immediate index after the inserted | ||
296 | // string, because the indices before that will be overwritten | ||
297 | // anyway. | ||
298 | // Since $i >= $indexAfterInsertion and $indexAfterInsertion >= $diff, | ||
299 | // $i >= $diff is guaranteed. | ||
300 | for ($i = $length - 1; $i >= $indexAfterInsertion; --$i) { | ||
301 | $this->elements[$i] = $this->elements[$i - $diff]; | ||
302 | $this->isIndex[$i] = $this->isIndex[$i - $diff]; | ||
303 | } | ||
304 | } | ||
305 | } | ||
306 | } | ||