diff --git a/system/HTTP/URI.php b/system/HTTP/URI.php index 587e441ffc17..2be84a684a64 100644 --- a/system/HTTP/URI.php +++ b/system/HTTP/URI.php @@ -537,18 +537,22 @@ public function getSegments(): array * @param string $default Default value * * @return string The value of the segment. If no segment is found, - * throws InvalidArgumentError + * throws HTTPException */ public function getSegment(int $number, string $default = ''): string { - // The segment should treat the array as 1-based for the user - // but we still have to deal with a zero-based array. - $number--; + if ($number < 1) { + throw HTTPException::forURISegmentOutOfRange($number); + } if ($number > count($this->segments) && ! $this->silent) { throw HTTPException::forURISegmentOutOfRange($number); } + // The segment should treat the array as 1-based for the user + // but we still have to deal with a zero-based array. + $number--; + return $this->segments[$number] ?? $default; } diff --git a/tests/system/HTTP/URITest.php b/tests/system/HTTP/URITest.php index 14de6e3d587b..5ef3810b2531 100644 --- a/tests/system/HTTP/URITest.php +++ b/tests/system/HTTP/URITest.php @@ -62,7 +62,6 @@ public function testSegmentsIsPopulatedRightForMultipleSegments() $this->assertSame('path', $uri->getSegment(1)); $this->assertSame('to', $uri->getSegment(2)); $this->assertSame('script', $uri->getSegment(3)); - $this->assertSame('', $uri->getSegment(4)); $this->assertSame(3, $uri->getTotalSegments()); } @@ -70,22 +69,43 @@ public function testSegmentsIsPopulatedRightForMultipleSegments() public function testSegmentOutOfRange() { $this->expectException(HTTPException::class); + $uri = new URI('http://hostname/path/to/script'); - $uri->getSegment(5); + $uri->getSegment(4); + } + + public function testSegmentOutOfRangeZero() + { + $this->expectException(HTTPException::class); + + $uri = new URI('http://hostname/path/to/script'); + $uri->getSegment(0); + } + + public function testSegmentOutOfRangeNegative() + { + $this->expectException(HTTPException::class); + + $uri = new URI('http://hostname/path/to/script'); + $uri->getSegment(-1); } public function testSegmentOutOfRangeWithSilent() { $url = 'http://abc.com/a123/b/c'; $uri = new URI($url); + + $this->assertSame('', $uri->setSilent()->getSegment(4)); $this->assertSame('', $uri->setSilent()->getSegment(22)); } public function testSegmentOutOfRangeWithDefaultValue() { $this->expectException(HTTPException::class); + $url = 'http://abc.com/a123/b/c'; $uri = new URI($url); + $uri->getSegment(22, 'something'); } @@ -93,6 +113,7 @@ public function testSegmentOutOfRangeWithSilentAndDefaultValue() { $url = 'http://abc.com/a123/b/c'; $uri = new URI($url); + $this->assertSame('something', $uri->setSilent()->getSegment(22, 'something')); } diff --git a/tests/system/Pager/PagerTest.php b/tests/system/Pager/PagerTest.php index 1c3861748b34..4c151c8ffba8 100644 --- a/tests/system/Pager/PagerTest.php +++ b/tests/system/Pager/PagerTest.php @@ -168,6 +168,8 @@ public function testStoreWithQueries() public function testStoreWithSegments() { + $this->createPager('/3?page=3&foo=bar'); + $_GET['page'] = 3; $_GET['foo'] = 'bar'; diff --git a/user_guide_src/source/changelogs/v4.4.0.rst b/user_guide_src/source/changelogs/v4.4.0.rst index 965a0efbc057..ba962d2e036c 100644 --- a/user_guide_src/source/changelogs/v4.4.0.rst +++ b/user_guide_src/source/changelogs/v4.4.0.rst @@ -20,6 +20,13 @@ BREAKING Behavior Changes ================ +URI::getSegment() and Non-Existent Segment +------------------------------------------ + +An exception is now thrown whenever a non-existent segment number is passed. +In previous versions, an exception was not thrown if the last segment ``+1`` was +specified. + Interface Changes ================= diff --git a/user_guide_src/source/installation/upgrade_440.rst b/user_guide_src/source/installation/upgrade_440.rst index 16995c1d897e..dbf8e6c1a9aa 100644 --- a/user_guide_src/source/installation/upgrade_440.rst +++ b/user_guide_src/source/installation/upgrade_440.rst @@ -15,6 +15,18 @@ Please refer to the upgrade instructions corresponding to your installation meth Breaking Changes **************** +URI::getSegment() Change +======================== + +Dut to a bug, in previous versions an exception was not thrown if the last segment +``+1`` was specified. This bug has been fixed. If the non-existent segment is +specified, an exception is always thrown. + +If your code depends on this bug, add ``->setSilent()`` before the call. + +.. literalinclude:: upgrade_440/001.php + :lines: 2- + Mandatory File Changes ********************** diff --git a/user_guide_src/source/installation/upgrade_440/001.php b/user_guide_src/source/installation/upgrade_440/001.php new file mode 100644 index 000000000000..79167adcabcf --- /dev/null +++ b/user_guide_src/source/installation/upgrade_440/001.php @@ -0,0 +1,5 @@ +getSegment(2); +// ↓ +$uri->setSilent()->getSegment(2); diff --git a/user_guide_src/source/libraries/uri/024.php b/user_guide_src/source/libraries/uri/024.php index 61a951db93c3..3f4bb697d59a 100644 --- a/user_guide_src/source/libraries/uri/024.php +++ b/user_guide_src/source/libraries/uri/024.php @@ -2,13 +2,17 @@ // URI = http://example.com/users/15/profile +echo $uri->getSegment(1, 'foo'); +// will print 'users' + +echo $uri->getSegment(3, 'bar'); // will print 'profile' -echo $uri->getSegment(3, 'foo'); -// will print 'bar' -echo $uri->getSegment(4, 'bar'); + +echo $uri->getSegment(4, 'baz'); // will throw an exception -echo $uri->getSegment(5, 'baz'); + +echo $uri->setSilent()->getSegment(4, 'baz'); // will print 'baz' -echo $uri->setSilent()->getSegment(5, 'baz'); + +echo $uri->setSilent()->getSegment(4); // will print '' (empty string) -echo $uri->setSilent()->getSegment(5);