Skip to content

Commit 7c729f5

Browse files
committed
[PropertyAccess] Added negative path replaces and optional string arguments for PropertyPathBuilder.
1 parent 84d759d commit 7c729f5

File tree

2 files changed

+64
-26
lines changed

2 files changed

+64
-26
lines changed

src/Symfony/Component/PropertyAccess/PropertyPathBuilder.php

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ class PropertyPathBuilder
3131
/**
3232
* Creates a new property path builder.
3333
*
34-
* @param null|PropertyPathInterface $path The path to initially store
35-
* in the builder. Optional.
34+
* @param null|PropertyPathInterface|string $path The path to initially store
35+
* in the builder. Optional.
3636
*/
37-
public function __construct(PropertyPathInterface $path = null)
37+
public function __construct($path = null)
3838
{
3939
if (null !== $path) {
4040
$this->append($path);
@@ -44,14 +44,18 @@ public function __construct(PropertyPathInterface $path = null)
4444
/**
4545
* Appends a (sub-) path to the current path.
4646
*
47-
* @param PropertyPathInterface $path The path to append
48-
* @param integer $offset The offset where the appended piece
49-
* starts in $path
50-
* @param integer $length The length of the appended piece.
51-
* If 0, the full path is appended.
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.
5252
*/
53-
public function append(PropertyPathInterface $path, $offset = 0, $length = 0)
53+
public function append($path, $offset = 0, $length = 0)
5454
{
55+
if (is_string($path)) {
56+
$path = new PropertyPath($path);
57+
}
58+
5559
if (0 === $length) {
5660
$end = $path->getLength();
5761
} else {
@@ -106,20 +110,26 @@ public function remove($offset, $length = 1)
106110
/**
107111
* Replaces a sub-path by a different (sub-) path.
108112
*
109-
* @param integer $offset The offset at which to replace
110-
* @param integer $length The length of the piece to replace
111-
* @param PropertyPathInterface $path The path to insert
112-
* @param integer $pathOffset The offset where the inserted piece
113-
* starts in $path
114-
* @param integer $pathLength The length of the inserted piece.
115-
* If 0, the full path is inserted.
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.
116120
*
117121
* @throws OutOfBoundsException If the offset is invalid
118122
*/
119-
public function replace($offset, $length, PropertyPathInterface $path, $pathOffset = 0, $pathLength = 0)
123+
public function replace($offset, $length, $path, $pathOffset = 0, $pathLength = 0)
120124
{
121-
if (!isset($this->elements[$offset])) {
122-
throw new OutOfBoundsException(sprintf('The offset %s is not within the property path', $offset));
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');
123133
}
124134

125135
if (0 === $pathLength) {

src/Symfony/Component/PropertyAccess/Tests/PropertyPathBuilderTest.php

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,15 @@ public function testAppend()
7373
$this->assertEquals($path, $this->builder->getPropertyPath());
7474
}
7575

76+
public function testAppendUsingString()
77+
{
78+
$this->builder->append('new1[new2]');
79+
80+
$path = new PropertyPath(self::PREFIX . '.new1[new2]');
81+
82+
$this->assertEquals($path, $this->builder->getPropertyPath());
83+
}
84+
7685
public function testAppendWithOffset()
7786
{
7887
$this->builder->append(new PropertyPath('new1[new2].new3'), 1);
@@ -168,20 +177,39 @@ public function testReplace()
168177
$this->assertEquals($path, $this->builder->getPropertyPath());
169178
}
170179

171-
/**
172-
* @expectedException \OutOfBoundsException
173-
*/
174-
public function testReplaceDoesNotAllowInvalidOffsets()
180+
public function testReplaceUsingString()
181+
{
182+
$this->builder->replace(1, 1, 'new1[new2].new3');
183+
184+
$path = new PropertyPath('old1.new1[new2].new3.old3[old4][old5].old6');
185+
186+
$this->assertEquals($path, $this->builder->getPropertyPath());
187+
}
188+
189+
public function testReplaceNegative()
175190
{
176-
$this->builder->replace(6, 1, new PropertyPath('new1[new2].new3'));
191+
$this->builder->replace(-1, 1, new PropertyPath('new1[new2].new3'));
192+
193+
$path = new PropertyPath('old1[old2].old3[old4][old5].new1[new2].new3');
194+
195+
$this->assertEquals($path, $this->builder->getPropertyPath());
177196
}
178197

179198
/**
199+
* @dataProvider provideInvalidOffsets
180200
* @expectedException \OutOfBoundsException
181201
*/
182-
public function testReplaceDoesNotAllowNegativeOffsets()
202+
public function testReplaceDoesNotAllowInvalidOffsets($offset)
183203
{
184-
$this->builder->replace(-1, 1, new PropertyPath('new1[new2].new3'));
204+
$this->builder->replace($offset, 1, new PropertyPath('new1[new2].new3'));
205+
}
206+
207+
public function provideInvalidOffsets()
208+
{
209+
return array(
210+
array(6),
211+
array(-7),
212+
);
185213
}
186214

187215
public function testReplaceWithLengthGreaterOne()

0 commit comments

Comments
 (0)