Skip to content

Commit de59724

Browse files
committed
Adding Psalm as complementary static code analyzer
1 parent 36b27ff commit de59724

19 files changed

+149
-114
lines changed

.github/workflows/quality-assurance.yaml renamed to .github/workflows/build.yaml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
name: Quality Assurance
2+
name: Build
33
on:
44
push: ~
55
pull_request: ~
@@ -21,8 +21,10 @@ jobs:
2121
coverage: pcov
2222
tools: composer:v2
2323
- run: composer update --no-progress ${{ matrix.composer-flags }}
24-
- run: vendor/bin/php-cs-fixer fix -vvv --diff --dry-run --allow-risky=yes --ansi
24+
- run: composer phpunit
25+
- run: composer phpstan
2526
if: ${{ matrix.php == '7.4' }}
26-
- run: vendor/bin/phpstan analyse -l max -c phpstan.neon src --ansi
27+
- run: composer psalm
28+
if: ${{ matrix.php == '7.4' }}
29+
- run: composer phpcs
2730
if: ${{ matrix.php == '7.4' }}
28-
- run: vendor/bin/phpunit ${{ matrix.phpunit-flags }}

README.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
# PHP Domain Parser
22

3-
**PHP Domain Parser** is domain parser implemented in PHP.
3+
**PHP Domain Parser** is a resource based domain parser implemented in PHP.
44

5-
![Quality Assurance](https://github.com/jeremykendall/php-domain-parser/workflows/Quality%20Assurance/badge.svg)
5+
[![Build Status][ico-github-actions-build]][link-github-actions-build]
66
[![Total Downloads][ico-packagist]][link-packagist]
77
[![Latest Stable Version][ico-release]][link-release]
88
[![Software License][ico-license]][link-license]
@@ -579,10 +579,12 @@ Portions of the `Pdp\Converter` and `Pdp\Rules` are derivative works of the PHP
579579
Those parts of this codebase are heavily commented, and I've included a copy of
580580
the Apache Software Foundation License 2.0 in this project.
581581

582+
[ico-github-actions-build]: https://img.shields.io/github/workflow/status/jeremykendall/php-domain-parser/Build?style=flat-square
582583
[ico-packagist]: https://img.shields.io/packagist/dt/jeremykendall/php-domain-parser.svg?style=flat-square
583584
[ico-release]: https://img.shields.io/github/release/jeremykendall/php-domain-parser.svg?style=flat-square
584585
[ico-license]: https://img.shields.io/badge/license-MIT-brightgreen.svg?style=flat-square
585586

587+
[link-github-actions-build]: https://github.com/jeremykendall/php-domain-parser/actions?query=workflow%3ABuild
586588
[link-packagist]: https://packagist.org/packages/jeremykendall/php-domain-parser
587589
[link-release]: https://github.com/jeremykendall/php-domain-parser/releases
588590
[link-license]: https://github.com/jeremykendall/php-domain-parser/blob/master/LICENSE

composer.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,11 @@
5252
"phpstan/phpstan-phpunit": "^0.12",
5353
"phpstan/phpstan-strict-rules": "^0.12",
5454
"phpunit/phpunit": "^9.3",
55+
"psalm/plugin-phpunit": "^0.15.0",
5556
"psr/http-factory": "^1.0",
5657
"psr/simple-cache": "^1.0",
57-
"symfony/cache": "^v5.0"
58+
"symfony/cache": "^v5.0",
59+
"vimeo/psalm": "^4.3"
5860
},
5961
"suggest": {
6062
"psr/http-client-implementation": "To use the storage functionnality which depends on PSR-18",
@@ -70,16 +72,19 @@
7072
"scripts": {
7173
"phpcs": "php-cs-fixer fix -vvv --diff --dry-run --allow-risky=yes --ansi",
7274
"phpstan": "phpstan analyse -l max -c phpstan.neon src --ansi",
75+
"psalm": "psalm --show-info=true",
7376
"phpunit": "phpunit --coverage-text",
7477
"test": [
75-
"@phpcs",
78+
"@phpunit",
7679
"@phpstan",
77-
"@phpunit"
80+
"@psalm",
81+
"@phpcs"
7882
]
7983
},
8084
"scripts-descriptions": {
8185
"phpcs": "Runs coding style test suite",
8286
"phpstan": "Runs complete codebase static analysis",
87+
"psalm": "Runs complete codebase static analysis",
8388
"phpunit": "Runs unit and functional testing",
8489
"test": "Runs the complete test suite"
8590
},

psalm.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0"?>
2+
<psalm
3+
errorLevel="3"
4+
resolveFromConfigFile="true"
5+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6+
xmlns="https://getpsalm.org/schema/config"
7+
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"
8+
>
9+
<projectFiles>
10+
<directory name="src"/>
11+
<ignoreFiles>
12+
<directory name="vendor"/>
13+
</ignoreFiles>
14+
</projectFiles>
15+
<plugins>
16+
<pluginClass class="Psalm\PhpUnitPlugin\Plugin"/>
17+
</plugins>
18+
</psalm>

src/DomainNameResolver.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
interface DomainNameResolver
88
{
99
/**
10-
* Returns the effective TLD info for a given domain against an external data source.
10+
* Returns the effective TLD info for a given domain against an data source.
1111
*
12-
* If the effective TLD can not be resolved it returns a ResolvedDomainName with a null public suffix
12+
* If the effective TLD can not be resolved it returns a ResolvedDomainName with a null suffix
1313
* If the host is not a valid domain it returns a ResolvedDomainName with a null Domain name
1414
*/
1515
public function resolve(Host $host): ResolvedDomainName;

src/DomainTest.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public function testToAsciiThrowsException(string $domain): void
2424
}
2525

2626
/**
27-
* @return iterable<string,array>
27+
* @return iterable<string,array{0:string}>
2828
*/
2929
public function invalidDomainProvider(): iterable
3030
{
@@ -66,7 +66,7 @@ public function testCountable(?string $domain, int $nbLabels, array $labels): vo
6666
}
6767

6868
/**
69-
* @return iterable<string,array>
69+
* @return iterable<string,array{0:string|null, 1:int, 2:array<string>}>
7070
*/
7171
public function countableProvider(): iterable
7272
{
@@ -131,7 +131,7 @@ public function testToIDN(
131131
}
132132

133133
/**
134-
* @return iterable<string,array>
134+
* @return iterable<string,array{domain:string|null, expectedDomain:string|null, expectedIDNDomain:string|null}>
135135
*/
136136
public function toUnicodeProvider(): iterable
137137
{
@@ -194,7 +194,7 @@ public function testToAscii(
194194
}
195195

196196
/**
197-
* @return iterable<string,array>
197+
* @return iterable<string,array{domain:string|null, expectedDomain:string|null, expectedIDNDomain:string|null}>
198198
*/
199199
public function toAsciiProvider(): iterable
200200
{
@@ -232,14 +232,14 @@ public function toAsciiProvider(): iterable
232232
*
233233
* @param ?string $expected
234234
*/
235-
public function testWithLabelWorks(Domain $domain, int $key, string $label, ?string $expected): void
235+
public function testWithLabelWorks(DomainName $domain, int $key, string $label, ?string $expected): void
236236
{
237237
$result = $domain->withLabel($key, $label);
238238
self::assertSame($expected, $result->value());
239239
}
240240

241241
/**
242-
* @return iterable<string,array>
242+
* @return iterable<string,array{domain:DomainName, key:int, label:string, expected:string}>
243243
*/
244244
public function withLabelWorksProvider(): iterable
245245
{
@@ -337,7 +337,7 @@ public function testAppend(string $raw, string $append, string $expected): void
337337
}
338338

339339
/**
340-
* @return iterable<array>
340+
* @return iterable<array{0:string, 1:string, 2:string}>
341341
*/
342342
public function validAppend(): iterable
343343
{
@@ -358,7 +358,7 @@ public function testPrepend(string $raw, string $prepend, string $expected): voi
358358
}
359359

360360
/**
361-
* @return iterable<array>
361+
* @return iterable<array{0:string, 1:string, 2:string}>
362362
*/
363363
public function validPrepend(): iterable
364364
{
@@ -373,14 +373,14 @@ public function validPrepend(): iterable
373373
* @dataProvider withoutLabelWorksProvider
374374
* @param ?string $expected
375375
*/
376-
public function testwithoutLabelWorks(Domain $domain, int $key, ?string $expected): void
376+
public function testwithoutLabelWorks(DomainName $domain, int $key, ?string $expected): void
377377
{
378378
$result = $domain->withoutLabel($key);
379379
self::assertSame($expected, $result->value());
380380
}
381381

382382
/**
383-
* @return iterable<string,array>
383+
* @return iterable<string,array{domain:DomainName, key:int, expected:string}>
384384
*/
385385
public function withoutLabelWorksProvider(): iterable
386386
{
@@ -444,7 +444,7 @@ public function testResolveWorksWithCustomIDNAOptions(
444444
}
445445

446446
/**
447-
* @return iterable<string,array>
447+
* @return iterable<string,array<string>>
448448
*/
449449
public function resolveCustomIDNAOptionsProvider(): iterable
450450
{

src/IdnaInfoTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public function testInvalidSyntaxAfterIDNConversion(): void
3535
try {
3636
Idna::toAscii('%00.com', Idna::IDNA2008_ASCII);
3737
} catch (SyntaxError $exception) {
38-
$result = $exception->fetchIdnaResult();
38+
$result = $exception->idnaInfo();
3939
self::assertInstanceOf(IdnaInfo::class, $result);
4040
self::assertSame(Idna::ERROR_DISALLOWED, $result->errors());
4141
self::assertIsString($result->error(Idna::ERROR_DISALLOWED));

src/ResolvedDomainTest.php

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public function testItThrowsExceptionMisMatchPublicSuffixDomain(?string $domain,
4343
}
4444

4545
/**
46-
* @return iterable<string,array>
46+
* @return iterable<string,array{domain:string, length:int}>
4747
*/
4848
public function provideWrongConstructor(): iterable
4949
{
@@ -78,7 +78,7 @@ public function testItImplementsCountable(?string $domain, int $nbLabels): void
7878
}
7979

8080
/**
81-
* @return iterable<string,array>
81+
* @return iterable<string,array{0:string|null, 1:int}>
8282
*/
8383
public function countableProvider(): iterable
8484
{
@@ -118,7 +118,7 @@ public function testItCanBeConvertedToUnicode(
118118
}
119119

120120
/**
121-
* @return iterable<string,array>
121+
* @return iterable<string,array{domain:string|null, publicSuffix:string|null, expectedDomain:string|null, expectedSuffix:string|null, expectedIDNDomain:string|null, expectedIDNSuffix:string|null}>
122122
*/
123123
public function toUnicodeProvider(): iterable
124124
{
@@ -210,7 +210,7 @@ public function testItCanBeConvertedToAscii(
210210
}
211211

212212
/**
213-
* @return iterable<string,array>
213+
* @return iterable<string,array{domain:string|null, publicSuffix:string|null, expectedDomain:string|null, expectedSuffix:string|null, expectedIDNDomain:string|null, expectedIDNSuffix:string|null}>
214214
*/
215215
public function toAsciiProvider(): iterable
216216
{
@@ -261,10 +261,9 @@ public function toAsciiProvider(): iterable
261261
/**
262262
* @dataProvider withSubDomainWorksProvider
263263
*
264-
* @param mixed $subdomain the subdomain to add
265-
* @param ?string $expected
264+
* @param DomainName|string|null $subdomain the subdomain to add
266265
*/
267-
public function testItCanHaveItsSubDomainChanged(ResolvedDomain $domain, $subdomain, ?string $expected): void
266+
public function testItCanHaveItsSubDomainChanged(ResolvedDomain $domain, $subdomain, string $expected = null): void
268267
{
269268
$result = $domain->withSubDomain($subdomain);
270269

@@ -274,7 +273,7 @@ public function testItCanHaveItsSubDomainChanged(ResolvedDomain $domain, $subdom
274273
}
275274

276275
/**
277-
* @return iterable<string,array>
276+
* @return iterable<string,array{domain:ResolvedDomain, subdomain:DomainName|string|null, expected:string|null}>
278277
*/
279278
public function withSubDomainWorksProvider(): iterable
280279
{
@@ -359,7 +358,7 @@ public function testItCanChangeItsSuffix(
359358
}
360359

361360
/**
362-
* @return iterable<string,array>
361+
* @return iterable<string, array{domain:ResolvedDomain, publicSuffix:EffectiveTopLevelDomain|string|null, expected:string|null, isKnown:bool,isICANN:bool, isPrivate:bool}>
363362
*/
364363
public function withPublicSuffixWorksProvider(): iterable
365364
{
@@ -450,19 +449,15 @@ public function testItCanThrowsDuringSuffixChangesIfTheDomainHasNotSuffix(): voi
450449

451450
/**
452451
* @dataProvider resolveCustomIDNAOptionsProvider
453-
* @param ?string $expectedContent
454-
* @param ?string $expectedAscii
455-
* @param ?string $expectedUnicode
456-
* @param ?string $expectedRegistrable
457452
* @param ?string $expectedSubDomain
458453
*/
459454
public function testItCanWorksWithIDNAOptions(
460455
string $domainName,
461456
string $publicSuffix,
462-
?string $expectedContent,
463-
?string $expectedAscii,
464-
?string $expectedUnicode,
465-
?string $expectedRegistrable,
457+
string $expectedContent,
458+
string $expectedAscii,
459+
string $expectedUnicode,
460+
string $expectedRegistrable,
466461
?string $expectedSubDomain
467462
): void {
468463
$resolvedDomain = ResolvedDomain::fromICANN($domainName, count(Domain::fromIDNA2008($publicSuffix)));
@@ -475,7 +470,7 @@ public function testItCanWorksWithIDNAOptions(
475470
}
476471

477472
/**
478-
* @return iterable<string,array>
473+
* @return iterable<string,array{0:string, 1:string, 2:string, 3:string, 4:string, 5:string, 6:string|null}>
479474
*/
480475
public function resolveCustomIDNAOptionsProvider(): iterable
481476
{
@@ -544,7 +539,7 @@ public function testWithSecondLevelDomain(
544539
}
545540

546541
/**
547-
* @return iterable<array>
542+
* @return iterable<array{host:string|null, publicSuffix:string|null, sld:string|null, expectedSld:string|null, expectedHost:string|null}>
548543
*/
549544
public function withSldWorksProvider(): iterable
550545
{

src/Rules.php

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,7 @@ private function __construct(array $rules)
6565
*/
6666
public static function fromPath(string $path, $context = null): self
6767
{
68-
$args = [$path, 'r', false];
69-
if (null !== $context) {
70-
$args[] = $context;
71-
}
72-
73-
$resource = @fopen(...$args);
68+
$resource = self::getResource($path, $context);
7469
if (false === $resource) {
7570
throw UnableToLoadPublicSuffixList::dueToInvalidPath($path);
7671
}
@@ -82,6 +77,20 @@ public static function fromPath(string $path, $context = null): self
8277
return self::fromString($content);
8378
}
8479

80+
/**
81+
* @param null|resource $context
82+
*
83+
* @return false|resource
84+
*/
85+
private static function getResource(string $path, $context = null)
86+
{
87+
if (null === $context) {
88+
return @fopen($path, 'r');
89+
}
90+
91+
return @fopen($path, 'r', false, $context);
92+
}
93+
8594
/**
8695
* Returns a new instance from a string.
8796
*
@@ -220,7 +229,7 @@ public function resolve($host): ResolvedDomainName
220229
try {
221230
return $this->getCookieDomain($host);
222231
} catch (UnableToResolveDomain $exception) {
223-
return ResolvedDomain::fromUnknown($exception->getDomain());
232+
return ResolvedDomain::fromUnknown($exception->domain());
224233
} catch (SyntaxError $exception) {
225234
return ResolvedDomain::fromUnknown(Domain::fromIDNA2008(null));
226235
}

0 commit comments

Comments
 (0)