diff --git a/.github/workflows/standards.yml b/.github/workflows/standards.yml index 10f9fc2..576219c 100644 --- a/.github/workflows/standards.yml +++ b/.github/workflows/standards.yml @@ -13,7 +13,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v6 - name: Run env: @@ -30,7 +30,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v6 - name: Setup php uses: shivammathur/setup-php@v2 diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml index fb7682c..e650942 100644 --- a/.github/workflows/static.yml +++ b/.github/workflows/static.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v6 - name: Setup php uses: shivammathur/setup-php@v2 @@ -36,7 +36,7 @@ jobs: steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v6 - name: Run actionlint run: docker run --rm -v "$PWD:/repo" --workdir /repo rhysd/actionlint:latest -color diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b7160da..44c1b04 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,7 +17,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v6 - name: Setup php uses: shivammathur/setup-php@v2 diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 81a0919..c45f398 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -3,8 +3,6 @@ declare(strict_types=1); $finder = (new PhpCsFixer\Finder()) -// ->in(__DIR__ . '/bin')/ -// ->in(__DIR__ . '/public') ->in(__DIR__ . '/src') ->in(__DIR__ . '/tests') ; @@ -21,33 +19,6 @@ 'php_unit_internal_class' => false, 'php_unit_test_class_requires_covers' => false, 'declare_strict_types' => true, -// 'blank_line_before_statement' => [ -// 'statements' => [ -// 'break', -//// 'case', -// 'continue', -// 'declare', -// 'default', -// 'phpdoc', -// 'do', -// 'exit', -// 'for', -//// 'foreach', -// 'goto', -//// 'if', -// 'include', -// 'include_once', -// 'require', -// 'require_once', -// 'return', -// 'switch', -// 'throw', -// 'try', -// 'while', -// 'yield', -// 'yield_from', -// ], -// ], ]) ->setFinder($finder) ; diff --git a/composer.json b/composer.json index b4a12ca..ffe96fa 100644 --- a/composer.json +++ b/composer.json @@ -40,7 +40,7 @@ "php": "^7.4|^8.0|^8.1", "psr/http-message": "^1", "algo26-matthias/idna-convert": "^3.0", - "hookedmedia/ip-utils": "^1.1" + "xrstf/ip-utils": "^1.1" }, "require-dev": { "phpunit/phpunit": "^9.5", diff --git a/src/Normalizer.php b/src/Normalizer.php index 1217b35..34ff5fd 100644 --- a/src/Normalizer.php +++ b/src/Normalizer.php @@ -19,14 +19,14 @@ class Normalizer public const OPTION_REMOVE_PATH_FILES_PATTERNS = 'remove-path-files-patterns'; public const OPTION_REMOVE_QUERY_PARAMETERS_PATTERNS = 'remove-query-parameters-patterns'; - public const PRESERVING_NORMALIZATIONS = - self::CAPITALIZE_PERCENT_ENCODING | - self::DECODE_UNRESERVED_CHARACTERS | - self::CONVERT_EMPTY_HTTP_PATH | - self::REMOVE_DEFAULT_FILE_HOST | - self::REMOVE_DEFAULT_PORT | - self::REMOVE_PATH_DOT_SEGMENTS | - self::CONVERT_HOST_UNICODE_TO_PUNYCODE; + public const PRESERVING_NORMALIZATIONS + = self::CAPITALIZE_PERCENT_ENCODING + | self::DECODE_UNRESERVED_CHARACTERS + | self::CONVERT_EMPTY_HTTP_PATH + | self::REMOVE_DEFAULT_FILE_HOST + | self::REMOVE_DEFAULT_PORT + | self::REMOVE_PATH_DOT_SEGMENTS + | self::CONVERT_HOST_UNICODE_TO_PUNYCODE; // Semantically-lossless normalizations public const CAPITALIZE_PERCENT_ENCODING = 1; diff --git a/src/Uri.php b/src/Uri.php index 8eb457e..7b9da2b 100644 --- a/src/Uri.php +++ b/src/Uri.php @@ -32,7 +32,13 @@ public function __construct(string $url) $userInfo = new UserInfo($user, $pass); - self::applyComponents($this, $scheme, (string) $userInfo, $host, $port, $path, $query, $fragment); + $this->scheme = strtolower($scheme); + $this->userInfo = (string) $userInfo; + $this->host = strtolower($host); + $this->path = Filter::filterPath($path); + $this->query = Filter::filterQueryOrFragment($query); + $this->fragment = Filter::filterQueryOrFragment($fragment); + $this->port = Filter::filterPort($port, $this->getScheme()); } public function __toString(): string @@ -155,16 +161,10 @@ public function withScheme($scheme): self return $this; } - return self::applyComponents( - clone $this, - $scheme, - $this->userInfo, - $this->host, - $this->port, - $this->path, - $this->query, - $this->fragment - ); + $new = clone $this; + $new->scheme = $scheme; + + return $new->withPort($new->getPort()); } public function withUserInfo($user, $password = null): self @@ -175,16 +175,10 @@ public function withUserInfo($user, $password = null): self return $this; } - return self::applyComponents( - clone $this, - $this->scheme, - $userInfo, - $this->host, - $this->port, - $this->path, - $this->query, - $this->fragment - ); + $new = clone $this; + $new->userInfo = $userInfo; + + return $new; } public function withHost($host): self @@ -195,16 +189,10 @@ public function withHost($host): self return $this; } - return self::applyComponents( - clone $this, - $this->scheme, - $this->userInfo, - $host, - $this->port, - $this->path, - $this->query, - $this->fragment - ); + $new = clone $this; + $new->host = $host; + + return $new; } public function withPort($port): self @@ -213,20 +201,10 @@ public function withPort($port): self $port = (int) $port; } - if ($this->port === $port) { - return $this; - } + $new = clone $this; + $new->port = Filter::filterPort($port, $new->getScheme()); - return self::applyComponents( - clone $this, - $this->scheme, - $this->userInfo, - $this->host, - $port, - $this->path, - $this->query, - $this->fragment - ); + return $new; } public function withPath($path): self @@ -237,16 +215,10 @@ public function withPath($path): self return $this; } - return self::applyComponents( - clone $this, - $this->scheme, - $this->userInfo, - $this->host, - $this->port, - $path, - $this->query, - $this->fragment - ); + $new = clone $this; + $new->path = $path; + + return $new; } public function withQuery($query): self @@ -257,16 +229,10 @@ public function withQuery($query): self return $this; } - return self::applyComponents( - clone $this, - $this->scheme, - $this->userInfo, - $this->host, - $this->port, - $this->path, - $query, - $this->fragment - ); + $new = clone $this; + $new->query = $query; + + return $new; } public function withFragment($fragment): self @@ -277,36 +243,9 @@ public function withFragment($fragment): self return $this; } - return self::applyComponents( - clone $this, - $this->scheme, - $this->userInfo, - $this->host, - $this->port, - $this->path, - $this->query, - $fragment - ); - } + $new = clone $this; + $new->fragment = $fragment; - private static function applyComponents( - Uri $url, - string $scheme, - string $userInfo, - string $host, - ?int $port, - string $path, - string $query, - string $fragment - ): self { - $url->scheme = strtolower($scheme); - $url->userInfo = $userInfo; - $url->host = strtolower($host); - $url->path = Filter::filterPath($path); - $url->query = Filter::filterQueryOrFragment($query); - $url->fragment = Filter::filterQueryOrFragment($fragment); - $url->port = Filter::filterPort($port, $url->getScheme()); - - return $url; + return $new; } } diff --git a/tests/DefaultPortIdentifierTest.php b/tests/DefaultPortIdentifierTest.php index a2d2fc2..b25f8c1 100644 --- a/tests/DefaultPortIdentifierTest.php +++ b/tests/DefaultPortIdentifierTest.php @@ -4,9 +4,10 @@ namespace webignition\Uri\Tests; +use PHPUnit\Framework\TestCase; use webignition\Uri\DefaultPortIdentifier; -class DefaultPortIdentifierTest extends \PHPUnit\Framework\TestCase +class DefaultPortIdentifierTest extends TestCase { /** * @dataProvider isDefaultPortDataProvider diff --git a/tests/FilterTest.php b/tests/FilterTest.php index 32ddc92..8753d20 100644 --- a/tests/FilterTest.php +++ b/tests/FilterTest.php @@ -4,9 +4,10 @@ namespace webignition\Uri\Tests; +use PHPUnit\Framework\TestCase; use webignition\Uri\Filter; -class FilterTest extends \PHPUnit\Framework\TestCase +class FilterTest extends TestCase { public const UNRESERVED_CHARACTERS = 'a-zA-Z0-9.-_~!$&\'()*+,;=:@'; diff --git a/tests/HostTest.php b/tests/HostTest.php index 2f17900..9e093ea 100644 --- a/tests/HostTest.php +++ b/tests/HostTest.php @@ -5,9 +5,10 @@ namespace webignition\Uri\Tests; use IpUtils\Exception\InvalidExpressionException; +use PHPUnit\Framework\TestCase; use webignition\Uri\Host; -class HostTest extends \PHPUnit\Framework\TestCase +class HostTest extends TestCase { /** * @dataProvider createDataProvider @@ -225,26 +226,6 @@ public function testIpRangeIsPubliclyRoutable(string $ipRange, bool $expectedIsP } } - /** - * @throws InvalidExpressionException - */ - public function testLoopbackIpIsNotPubliclyRoutable(): void - { - $host = new Host('127.0.0.1'); - - $this->assertFalse($host->isPubliclyRoutable()); - } - - /** - * @throws InvalidExpressionException - */ - public function testDomainNameIsPubliclyRoutable(): void - { - $host = new Host('foo'); - - $this->assertTrue($host->isPubliclyRoutable()); - } - /** * @return array */ @@ -322,6 +303,26 @@ public function ipRangeIsPubliclyRoutableDataProvider(): array ]; } + /** + * @throws InvalidExpressionException + */ + public function testLoopbackIpIsNotPubliclyRoutable(): void + { + $host = new Host('127.0.0.1'); + + $this->assertFalse($host->isPubliclyRoutable()); + } + + /** + * @throws InvalidExpressionException + */ + public function testDomainNameIsPubliclyRoutable(): void + { + $host = new Host('foo'); + + $this->assertTrue($host->isPubliclyRoutable()); + } + /** * @return int[] */ diff --git a/tests/InspectorTest.php b/tests/InspectorTest.php index 653cc01..2853e4a 100644 --- a/tests/InspectorTest.php +++ b/tests/InspectorTest.php @@ -4,11 +4,12 @@ namespace webignition\Uri\Tests; +use PHPUnit\Framework\TestCase; use Psr\Http\Message\UriInterface; use webignition\Uri\Inspector; use webignition\Uri\Uri; -class InspectorTest extends \PHPUnit\Framework\TestCase +class InspectorTest extends TestCase { /** * @dataProvider isNotPubliclyRoutableDataProvider diff --git a/tests/NormalizerTest.php b/tests/NormalizerTest.php index 826e82f..5b4162d 100644 --- a/tests/NormalizerTest.php +++ b/tests/NormalizerTest.php @@ -4,10 +4,11 @@ namespace webignition\Uri\Tests; +use PHPUnit\Framework\TestCase; use webignition\Uri\Normalizer; use webignition\Uri\Uri; -class NormalizerTest extends \PHPUnit\Framework\TestCase +class NormalizerTest extends TestCase { public const ALPHA_CHARACTERS = 'abcdefghijklmnopqrstuvwxyz'; public const NUMERIC_CHARACTERS = '0123456789'; @@ -386,25 +387,6 @@ public function capitalizePercentEncodingDataProvider(): array ]; } - /** - * @return array - */ - public function convertEmptyHttpPathDataProvider(): array - { - return [ - 'convertEmptyHttpPath: http' => [ - 'url' => 'http://example.com', - 'expectedUrl' => 'http://example.com/', - 'flags' => Normalizer::CONVERT_EMPTY_HTTP_PATH, - ], - 'convertEmptyHttpPath: https' => [ - 'url' => 'https://example.com', - 'expectedUrl' => 'https://example.com/', - 'flags' => Normalizer::CONVERT_EMPTY_HTTP_PATH, - ], - ]; - } - /** * @return array */ @@ -556,6 +538,25 @@ public function defaultsDataProvider(): array ]; } + /** + * @return array + */ + public function convertEmptyHttpPathDataProvider(): array + { + return [ + 'convertEmptyHttpPath: http' => [ + 'url' => 'http://example.com', + 'expectedUrl' => 'http://example.com/', + 'flags' => Normalizer::CONVERT_EMPTY_HTTP_PATH, + ], + 'convertEmptyHttpPath: https' => [ + 'url' => 'https://example.com', + 'expectedUrl' => 'https://example.com/', + 'flags' => Normalizer::CONVERT_EMPTY_HTTP_PATH, + ], + ]; + } + private function createUnreservedCharactersString(): string { return strtoupper(self::ALPHA_CHARACTERS) diff --git a/tests/ParserTest.php b/tests/ParserTest.php index 5a6d3eb..8e50939 100644 --- a/tests/ParserTest.php +++ b/tests/ParserTest.php @@ -4,9 +4,10 @@ namespace webignition\Uri\Tests; +use PHPUnit\Framework\TestCase; use webignition\Uri\Parser; -class ParserTest extends \PHPUnit\Framework\TestCase +class ParserTest extends TestCase { /** * @dataProvider parseDataProvider diff --git a/tests/PathTest.php b/tests/PathTest.php index c0cd59f..b66c5cf 100644 --- a/tests/PathTest.php +++ b/tests/PathTest.php @@ -4,9 +4,10 @@ namespace webignition\Uri\Tests; +use PHPUnit\Framework\TestCase; use webignition\Uri\Path; -class PathTest extends \PHPUnit\Framework\TestCase +class PathTest extends TestCase { /** * @dataProvider createDataProvider diff --git a/tests/PunycodeEncoderTest.php b/tests/PunycodeEncoderTest.php index 41fb538..dbf7df0 100644 --- a/tests/PunycodeEncoderTest.php +++ b/tests/PunycodeEncoderTest.php @@ -4,9 +4,10 @@ namespace webignition\Uri\Tests; +use PHPUnit\Framework\TestCase; use webignition\Uri\PunycodeEncoder; -class PunycodeEncoderTest extends \PHPUnit\Framework\TestCase +class PunycodeEncoderTest extends TestCase { /** * @dataProvider encodeDataProvider diff --git a/tests/ScopeComparerTest.php b/tests/ScopeComparerTest.php index 13bca21..2b0ccde 100644 --- a/tests/ScopeComparerTest.php +++ b/tests/ScopeComparerTest.php @@ -4,11 +4,12 @@ namespace webignition\Uri\Tests; +use PHPUnit\Framework\TestCase; use Psr\Http\Message\UriInterface; use webignition\Uri\ScopeComparer; use webignition\Uri\Uri; -class ScopeComparerTest extends \PHPUnit\Framework\TestCase +class ScopeComparerTest extends TestCase { /** * @dataProvider isInScopeDataProvider diff --git a/tests/UriTest.php b/tests/UriTest.php index 5d3e939..48f206a 100644 --- a/tests/UriTest.php +++ b/tests/UriTest.php @@ -4,10 +4,11 @@ namespace webignition\Uri\Tests; +use PHPUnit\Framework\TestCase; use webignition\Uri\Filter; use webignition\Uri\Uri; -class UriTest extends \PHPUnit\Framework\TestCase +class UriTest extends TestCase { public const UNRESERVED_CHARACTERS = 'a-zA-Z0-9.-_~!$&\'()*+,;=:@'; public const GEN_DELIMITERS = ':/?#[]@'; @@ -376,7 +377,7 @@ public function testWithPort(): void $this->assertSame(8080, $httpUriWithNonDefaultPort->getPort()); $httpUriWithSameNonDefaultPort = $httpUriWithNonDefaultPort->withPort(8080); - $this->assertSame($httpUriWithNonDefaultPort, $httpUriWithSameNonDefaultPort); + $this->assertEquals($httpUriWithNonDefaultPort, $httpUriWithSameNonDefaultPort); $httpUriWithPortRemoved = $httpUriWithNonDefaultPort->withPort(null); $this->assertNull($httpUriWithPortRemoved->getPort()); diff --git a/tests/UserInfoTest.php b/tests/UserInfoTest.php index ae35e34..160d786 100644 --- a/tests/UserInfoTest.php +++ b/tests/UserInfoTest.php @@ -4,9 +4,10 @@ namespace webignition\Uri\Tests; +use PHPUnit\Framework\TestCase; use webignition\Uri\UserInfo; -class UserInfoTest extends \PHPUnit\Framework\TestCase +class UserInfoTest extends TestCase { /** * @dataProvider toStringDataProvider