Skip to content

Commit

Permalink
Prepare PHP8.4 compatible release (#359)
Browse files Browse the repository at this point in the history
Add support for PHP8.3+ and clean up documentation
  • Loading branch information
nyamsprod authored Nov 10, 2024
1 parent 34c7177 commit aa1f9bf
Show file tree
Hide file tree
Showing 17 changed files with 208 additions and 112 deletions.
16 changes: 13 additions & 3 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@ jobs:
runs-on: ubuntu-20.04
strategy:
matrix:
php: ['8.1', '8.2']
php: ['8.1', '8.2', '8.3']
stability: [prefer-lowest, prefer-stable]
include:
- php: '8.4'
flags: "--ignore-platform-req=php"
phpunit-flags: '--no-coverage'
stability: prefer-stable
steps:
- name: Checkout code
uses: actions/checkout@v3
Expand Down Expand Up @@ -45,11 +50,16 @@ jobs:

- name: Run Unit tests with coverage
run: composer phpunit -- ${{ matrix.phpunit-flags }}
if: ${{ matrix.php == '8.3' || matrix.php == '8.2' || matrix.php == '8.1'}}

- name: Run Unit tests without coverage
run: composer phpunit:min
if: ${{ matrix.php == '8.4'}}

- name: Run static analysis
run: composer phpstan
if: ${{ matrix.php == '8.2' && matrix.stability == 'prefer-stable'}}
if: ${{ matrix.php == '8.3' && matrix.stability == 'prefer-stable'}}

- name: Run Coding style rules
run: composer phpcs:fix
if: ${{ matrix.php == '8.1' && matrix.stability == 'prefer-stable'}}
if: ${{ matrix.php == '8.3' && matrix.stability == 'prefer-stable'}}
5 changes: 3 additions & 2 deletions .php-cs-fixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
'import_functions' => true,
],
'list_syntax' => ['syntax' => 'short'],
'new_with_braces' => true,
'new_with_parentheses' => true,
'no_blank_lines_after_phpdoc' => true,
'no_empty_phpdoc' => true,
'no_empty_comment' => true,
Expand All @@ -29,6 +29,7 @@
],
'no_trailing_comma_in_singleline' => true,
'no_unused_imports' => true,
'nullable_type_declaration_for_default_null_value' => true,
'ordered_imports' => ['imports_order' => ['class', 'function', 'const'], 'sort_algorithm' => 'alpha'],
'phpdoc_add_missing_param_annotation' => ['only_untyped' => true],
'phpdoc_align' => true,
Expand All @@ -39,7 +40,7 @@
'phpdoc_summary' => true,
'psr_autoloading' => true,
'return_type_declaration' => ['space_before' => 'none'],
'single_blank_line_before_namespace' => true,
'blank_lines_before_namespace' => true,
'single_quote' => true,
'space_after_semicolon' => true,
'ternary_operator_spaces' => true,
Expand Down
70 changes: 37 additions & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,12 @@ You need:

- **PHP >= 7.4** but the latest stable version of PHP is recommended
- the `intl` extension
- a copy of the [Public Suffix List](https://publicsuffix.org/) data and/or a copy of the [IANA Top Level Domain List](https://www.iana.org/domains/root/files). Please refer to the [Managing external data source section](#managing-the-package-external-resources) for more information when using this package in production.

## Usage

**If you are upgrading from version 5 please check the [upgrading guide](UPGRADING.md) for known issues.**
> [!WARNING]
> If you are upgrading from version 5 please check the [upgrading guide](UPGRADING.md) for known issues.
### Resolving Domains

Expand Down Expand Up @@ -115,9 +117,10 @@ These methods resolve the domain against their respective data source using
the same rules as the `resolve` method but will instead throw an exception
if no valid effective TLD is found or if the submitted domain is invalid.

**All these methods expect as their sole argument a `Pdp\Host` implementing
> [!CAUTION]
> All these methods expect as their sole argument a `Pdp\Host` implementing
object, but other types (ie: `string`, `null` and stringable objects) are
supported with predefined conditions as explained in the remaining document.**
supported with predefined conditions as explained in the remaining document.

~~~php
<?php
Expand Down Expand Up @@ -157,23 +160,18 @@ To instantiate each domain resolver you can use the following named constructor:

**If the instantiation does not work an exception will be thrown.**

**WARNING:**

**You should never resolve domain name this way in production, without, at
least, a caching mechanism to reduce PSL downloads.**

**Using the Public Suffix List to determine what is a valid domain name and what
isn't is dangerous, particularly in these days when new gTLDs are arriving at a
rapid pace.**

**If you are looking to know the validity of a Top Level Domain, the
IANA Top Level Domain List is the proper source for this information or
alternatively consider using directly the DNS.**

**If you must use this library for any of the above purposes, please consider
integrating an updating mechanism into your software.**

**For more information go to the [Managing external data source section](#managing-the-package-external-resources)**
> [!WARNING]
> You SHOULD never resolve domain name this way in production, without, at
least, a caching mechanism to reduce external resource downloads.
> Using the Public Suffix List to determine what is a valid domain name and what
isn't is dangerous, and MAY lead to errors because of new gTLDs being registered
on a regular basis.
> If you are looking to know the validity of a Top Level Domain, you MUST use
the IANA Top Level Domain List as the proper source for this information or
alternatively the DNS.
> If you MUST use this library for any of the above purposes, you SHOULD consider
integrating an updating mechanism into your software.
> For more information go to the [Managing external data source section](#managing-the-package-external-resources)**
### Resolved domain information.

Expand Down Expand Up @@ -220,10 +218,11 @@ echo $altResult->domain()->toString(); //display 'foo.bar.test.example';
$altResult->suffix()->isKnown(); //return false;
~~~

**TIP: Always favor submitting a `Pdp\Suffix` object rather that any other
> [!TIP]
> Always favor submitting a `Pdp\Suffix` object rather that any other
supported type to avoid unexpected results. By default, if the input is not a
`Pdp\Suffix` instance, the resulting public suffix will be labelled as
being unknown. For more information go to the [Public Suffix section](#public-suffix)**
being unknown. For more information go to the [Public Suffix section](#public-suffix)

### Domain Suffix

Expand Down Expand Up @@ -339,7 +338,8 @@ $newDomain->clear()->labels(); //return []
echo $domain->slice(2)->toString(); //display 'www'
~~~

**WARNING: Because of its definition, a domain name can be `null` or a string.**
> [!WARNING]
> Because of its definition, a domain name can be `null` or a string.
To distinguish this possibility the object exposes two (2) formatting methods
`Domain::value` which can be `null` or a `string` and `Domain::toString` which
Expand Down Expand Up @@ -396,8 +396,9 @@ is done via two (2) named constructors:
At any given moment the `Pdp\Domain` instance can tell you whether it is in
`ASCII` mode or not.

**Once instantiated there's no way to tell which algorithm is used to convert
the object from ascii to unicode and vice-versa**
> [!WARNING]
> Once instantiated there's no way to tell which algorithm is used to convert
the object from ascii to unicode and vice-versa

~~~php
use Pdp\Domain;
Expand All @@ -419,10 +420,11 @@ echo $asciiDomain->value(); // display 'fass.de'
$asciiDomain->isAscii(); // returns true
~~~

**TIP: Always favor submitting a `Pdp\Domain` object for resolution rather that a
> [!TIP]
> Always favor submitting a `Pdp\Domain` object for resolution rather that a
string or an object that can be cast to a string to avoid unexpected format
conversion errors/results. By default, and with lack of information conversion
is done using IDNA 2008 rules.**
is done using IDNA 2008 rules.

### Managing the package external resources

Expand Down Expand Up @@ -469,7 +471,8 @@ on packagist.

#### Refreshing the resource using the provided factories

**THIS IS THE RECOMMENDED WAY OF USING THE LIBRARY**
> [!NOTE]
> THIS IS THE RECOMMENDED WAY OF USING THE LIBRARY
For the purpose of this example we will use our PSR powered solution with:

Expand Down Expand Up @@ -526,12 +529,14 @@ $publicSuffixList = $pslStorage->get(PsrStorageFactory::PUBLIC_SUFFIX_LIST_URI);
$topLevelDomains = $rzdStorage->get(PsrStorageFactory::TOP_LEVEL_DOMAIN_LIST_URI);
~~~

**Be sure to adapt the following code to your own application.
> [!NOTE]
> Be sure to adapt the following code to your own application.
The following code is an example given without warranty of it working
out of the box.**
out of the box.

**You should use your dependency injection container to avoid repeating this
code in your application.**
> [!WARNING]
> You should use your dependency injection container to avoid repeating this
code in your application.

### Automatic Updates

Expand Down Expand Up @@ -560,7 +565,6 @@ Testing

- a [PHPUnit](https://phpunit.de) test suite
- a code analysis compliance test suite using [PHPStan](https://phpstan.org).
- a code analysis compliance test suite using [Psalm](https://psalm.dev).
- a coding style compliance test suite using [PHP CS Fixer](https://cs.symfony.com).

To run the tests, run the following command from the project folder.
Expand Down
21 changes: 11 additions & 10 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,16 @@
"ext-json": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^v3.13.2",
"guzzlehttp/guzzle": "^7.5",
"guzzlehttp/psr7": "^1.6 || ^2.4.3",
"phpstan/phpstan": "^1.10.3",
"phpstan/phpstan-phpunit": "^1.3.8",
"phpstan/phpstan-strict-rules": "^1.5.0",
"phpunit/phpunit": "^10.0.12",
"psr/http-factory": "^1.0.1",
"friendsofphp/php-cs-fixer": "^3.53.0",
"guzzlehttp/guzzle": "^7.8.1",
"guzzlehttp/psr7": "^1.6 || ^2.6.2",
"phpstan/phpstan": "^1.10.66",
"phpstan/phpstan-phpunit": "^1.3.16",
"phpstan/phpstan-strict-rules": "^1.5.3",
"phpunit/phpunit": "^10.5.15 || ^11.1.1",
"psr/http-factory": "^1.0.2",
"psr/simple-cache": "^1.0.1",
"symfony/cache": "^v5.0.0 || ^v6.0.0"
"symfony/cache": "^v5.0.0 || ^6.4.6"
},
"suggest": {
"psr/http-client-implementation": "To use the storage functionnality which depends on PSR-18",
Expand All @@ -71,8 +71,9 @@
"scripts": {
"phpcs": "PHP_CS_FIXER_IGNORE_ENV=1 php-cs-fixer fix -vvv --diff --dry-run --allow-risky=yes --ansi",
"phpcs:fix": "php-cs-fixer fix -vvv --allow-risky=yes --ansi",
"phpstan": "phpstan analyse -l max -c phpstan.neon src --xdebug --memory-limit=256M --ansi",
"phpstan": "phpstan analyse -c phpstan.neon --ansi --memory-limit=192M",
"phpunit": "XDEBUG_MODE=coverage phpunit --coverage-text",
"phpunit:min": "phpunit --no-coverage",
"test": [
"@phpunit",
"@phpstan",
Expand Down
4 changes: 4 additions & 0 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ includes:
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
parameters:
level: max
paths:
- src
ignoreErrors:
- message: '#has no value type specified in iterable type array.#'
path: src/Rules.php
Expand All @@ -12,4 +15,5 @@ parameters:
path: src/Rules.php
- message: '#Variable \$line on left side of \?\? always exists and is not nullable.#'
path: src/Rules.php
- '#^Parameter \#1 \$callback of function set_error_handler expects#'
reportUnmatchedIgnoredErrors: true
26 changes: 9 additions & 17 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
@@ -1,22 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.0/phpunit.xsd"
bootstrap="vendor/autoload.php"
backupGlobals="false"
colors="true"
processIsolation="false"
stopOnFailure="false"
cacheDirectory=".phpunit.cache"
backupStaticProperties="false"
>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.4/phpunit.xsd" bootstrap="vendor/autoload.php" backupGlobals="false" colors="true" processIsolation="false" stopOnFailure="false" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
<coverage>
<include>
<directory suffix=".php">src</directory>
</include>
<exclude>
<directory suffix="Test.php">src</directory>
</exclude>
<report>
<clover outputFile="build/clover.xml"/>
<html outputDirectory="build/coverage"/>
Expand All @@ -31,4 +15,12 @@
<logging>
<junit outputFile="build/junit.xml"/>
</logging>
<source>
<include>
<directory suffix=".php">src</directory>
</include>
<exclude>
<directory suffix="Test.php">src</directory>
</exclude>
</source>
</phpunit>
4 changes: 2 additions & 2 deletions src/Domain.php
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public function label(int $key): ?string
/**
* @return list<int>
*/
public function keys(string $label = null): array
public function keys(?string $label = null): array
{
return $this->registeredName->keys($label);
}
Expand Down Expand Up @@ -155,7 +155,7 @@ public function clear(): self
/**
* @throws CannotProcessHost
*/
public function slice(int $offset, int $length = null): self
public function slice(int $offset, ?int $length = null): self
{
return $this->newInstance($this->registeredName->slice($offset, $length));
}
Expand Down
4 changes: 2 additions & 2 deletions src/DomainName.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function labels(): array;
*
* @return list<int>
*/
public function keys(string $label = null): array;
public function keys(?string $label = null): array;

/**
* The external iterator iterates over the DomainInterface labels
Expand Down Expand Up @@ -119,5 +119,5 @@ public function clear(): self;
*
* If $length is null it returns all elements from $offset to the end of the Domain.
*/
public function slice(int $offset, int $length = null): self;
public function slice(int $offset, ?int $length = null): self;
}
4 changes: 2 additions & 2 deletions src/DomainTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -168,14 +168,14 @@ public static function toUnicodeProvider(): iterable
public function testToAscii(
?string $domain,
?string $expectedDomain,
?string $expectedAsciiDomain
?string $expectedIDNDomain
): void {
$domain = Domain::fromIDNA2008($domain);
self::assertSame($expectedDomain, $domain->value());

/** @var Domain $domainIDN */
$domainIDN = $domain->toAscii();
self::assertSame($expectedAsciiDomain, $domainIDN->value());
self::assertSame($expectedIDNDomain, $domainIDN->value());
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/RegisteredName.php
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ public function label(int $key): ?string
/**
* @return list<int>
*/
public function keys(string $label = null): array
public function keys(?string $label = null): array
{
if (null === $label) {
return array_keys($this->labels);
Expand Down Expand Up @@ -345,7 +345,7 @@ public function clear(): self
/**
* @throws CannotProcessHost
*/
public function slice(int $offset, int $length = null): self
public function slice(int $offset, ?int $length = null): self
{
$nbLabels = count($this->labels);
if ($offset < - $nbLabels || $offset > $nbLabels) {
Expand Down
10 changes: 5 additions & 5 deletions src/ResolvedDomainTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,17 +173,17 @@ public function testItCanBeConvertedToAscii(
?string $publicSuffix,
?string $expectedDomain,
?string $expectedSuffix,
?string $expectedAsciiDomain,
?string $expectedAsciiSuffix
?string $expectedIDNDomain,
?string $expectedIDNSuffix
): void {
$domain = ResolvedDomain::fromUnknown(Domain::fromIDNA2003($domain), count(Domain::fromIDNA2003($publicSuffix)));
self::assertSame($expectedDomain, $domain->value());
self::assertSame($expectedSuffix, $domain->suffix()->value());

/** @var ResolvedDomain $domainIDN */
$domainIDN = $domain->toAscii();
self::assertSame($expectedAsciiDomain, $domainIDN->value());
self::assertSame($expectedAsciiSuffix, $domainIDN->suffix()->value());
self::assertSame($expectedIDNDomain, $domainIDN->value());
self::assertSame($expectedIDNSuffix, $domainIDN->suffix()->value());
}

/**
Expand Down Expand Up @@ -236,7 +236,7 @@ public static function toAsciiProvider(): iterable
}

#[DataProvider('withSubDomainWorksProvider')]
public function testItCanHaveItsSubDomainChanged(ResolvedDomain $domain, DomainName|string|null $subdomain, string $expected = null): void
public function testItCanHaveItsSubDomainChanged(ResolvedDomain $domain, DomainName|string|null $subdomain, ?string $expected = null): void
{
$result = $domain->withSubDomain($subdomain);

Expand Down
Loading

0 comments on commit aa1f9bf

Please sign in to comment.