Skip to content

Commit a19b8ef

Browse files
committed
- updated GitHub workflow to support PHP 8.4 and the latest nightly,
- fixed workflow issue to correctly install Psalm 5.x, - adjusted PHPUnit XML file with the latest version structure, - hardened lots of places with old PHP conditions reported with RiskyTruthyFalsyComparison, - hardened lots of places with string docblocks using non-empty-string, - adjusted dataProviders methods to be static.
1 parent 65d8b29 commit a19b8ef

22 files changed

+95
-86
lines changed

.github/workflows/test-old.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
os: ['ubuntu-latest']
1616
steps:
1717
- name: 'Checkout'
18-
uses: 'actions/checkout@v2'
18+
uses: 'actions/checkout@v4'
1919
- name: 'Install PHP'
2020
uses: 'shivammathur/setup-php@v2'
2121
with:

.github/workflows/test.yaml

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ jobs:
1111
runs-on: '${{ matrix.os }}'
1212
strategy:
1313
matrix:
14-
php: ['7.4', '8.0', '8.1', '8.2']
14+
php: ['7.4', '8.0', '8.1', '8.2', '8.3']
1515
os: ['ubuntu-latest']
1616
failure: [false]
1717
include:
18-
- { php: '8.3', os: 'ubuntu-latest', failure: true } # '8.3' means 'nightly'
18+
- { php: '8.4', os: 'ubuntu-latest', failure: true } # Psalm does not support PHP 8.4 yet
19+
- { php: '8.5', os: 'ubuntu-latest', failure: true } # '8.5' means 'nightly'
1920
steps:
2021
- name: 'Checkout'
21-
uses: 'actions/checkout@v2'
22+
uses: 'actions/checkout@v4'
2223
- name: 'Install PHP'
2324
uses: 'shivammathur/setup-php@v2'
2425
with:
@@ -36,11 +37,13 @@ jobs:
3637
continue-on-error: '${{ matrix.failure }}'
3738
- name: 'Psalm'
3839
run: |
39-
composer require --dev vimeo/psalm
40+
composer remove --dev -W 'phpunit/phpunit'
41+
composer require --dev -W 'vimeo/psalm=^5.0' 'nikic/php-parser=^4.0'
4042
php vendor/bin/psalm --shepherd --php-version=${{ matrix.php }}
4143
continue-on-error: '${{ matrix.failure }}'
4244
- name: 'Infection'
4345
run: |
44-
composer require --dev --with-all-dependencies infection/infection
46+
composer remove --dev -W 'vimeo/psalm'
47+
composer require --dev -W phpunit/phpunit infection/infection
4548
php vendor/bin/infection
4649
continue-on-error: '${{ matrix.failure }}'

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2015-2023 Tomasz Kowalczyk
1+
Copyright (c) 2015-2025 Tomasz Kowalczyk
22

33
Permission is hereby granted, free of charge, to any person obtaining a copy
44
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Each part is described in the dedicated section in this document.
3131

3232
## Installation
3333

34-
There are no required dependencies and all PHP versions from 5.3 up to latest 8.1 [are tested](https://github.com/thunderer/Shortcode/actions/workflows/test.yaml) and supported. This library is available on Composer/Packagist as `thunderer/shortcode`, to install it execute:
34+
There are no required dependencies and all PHP versions from 5.3 up to latest 8.x [are tested](https://github.com/thunderer/Shortcode/actions/workflows/test.yaml) and supported. This library is available on Composer/Packagist as `thunderer/shortcode`, to install it execute:
3535

3636
```
3737
composer require thunderer/shortcode=^0.7

phpunit.xml.dist

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
<?xml version="1.0" encoding="UTF-8" ?>
22
<phpunit
3-
backupGlobals = "false"
4-
backupStaticAttributes = "false"
53
colors = "true"
6-
convertErrorsToExceptions = "true"
7-
convertNoticesToExceptions = "true"
8-
convertWarningsToExceptions = "true"
4+
backupGlobals = "false"
95
processIsolation = "false"
106
stopOnFailure = "false"
117
bootstrap = "vendor/autoload.php"
128
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
13-
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
9+
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.3/phpunit.xsd">
10+
11+
<source>
12+
<include>
13+
<directory>src</directory>
14+
</include>
15+
</source>
1416

1517
<testsuites>
1618
<testsuite name="Shortcode">
@@ -19,9 +21,6 @@
1921
</testsuites>
2022

2123
<coverage>
22-
<include>
23-
<directory>src</directory>
24-
</include>
2524
<report>
2625
<html outputDirectory="coverage/html" lowUpperBound="50" highLowerBound="90" />
2726
</report>

src/Handler/EmailHandler.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ final class EmailHandler
1919
*/
2020
public function __invoke(ShortcodeInterface $shortcode)
2121
{
22-
$email = $shortcode->getBbCode() ?: $shortcode->getContent();
22+
$email = null !== $shortcode->getBbCode() ? $shortcode->getBbCode() : $shortcode->getContent();
2323
$content = $shortcode->getContent() === null ? $email : $shortcode->getContent();
2424

2525
return '<a href="mailto:'.(string)$email.'">'.(string)$content.'</a>';

src/Handler/UrlHandler.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ final class UrlHandler
1919
*/
2020
public function __invoke(ShortcodeInterface $shortcode)
2121
{
22-
$url = $shortcode->getBbCode() ?: $shortcode->getContent();
22+
$url = null !== $shortcode->getBbCode() ? $shortcode->getBbCode() : $shortcode->getContent();
2323

2424
return '<a href="'.(string)$url.'">'.(string)$shortcode->getContent().'</a>';
2525
}

src/Parser/RegexParser.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@ final class RegexParser implements ParserInterface
1414
{
1515
/** @var SyntaxInterface */
1616
private $syntax;
17-
/** @var string */
17+
/** @var non-empty-string */
1818
private $shortcodeRegex;
19-
/** @var string */
19+
/** @var non-empty-string */
2020
private $singleShortcodeRegex;
21-
/** @var string */
21+
/** @var non-empty-string */
2222
private $parametersRegex;
2323

2424
public function __construct(SyntaxInterface $syntax = null)

src/Parser/RegularParser.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
*/
1313
final class RegularParser implements ParserInterface
1414
{
15-
/** @var string */
15+
/** @var non-empty-string */
1616
private $lexerRegex;
17-
/** @var string */
17+
/** @var non-empty-string */
1818
private $nameRegex;
1919
/** @psalm-var list<array{0:int,1:string,2:int}> */
2020
private $tokens = array();
@@ -184,6 +184,7 @@ private function shortcode(array &$names)
184184
return array_merge(array($this->getObject($name, $parameters, $bbCode, $offset, null, $text)), $shortcodes);
185185
}
186186
$content = $this->getBacktrack();
187+
/** @psalm-suppress RiskyTruthyFalsyComparison */
187188
if(!$this->close($names)) { return false; }
188189
array_pop($names);
189190

@@ -314,6 +315,7 @@ private function match($type, $ws)
314315
}
315316

316317
$token = $this->tokens[$this->position];
318+
/** @psalm-suppress RiskyTruthyFalsyComparison */
317319
if(!empty($type) && $token[0] !== $type) {
318320
return '';
319321
}
@@ -352,7 +354,7 @@ private function tokenize($text)
352354
case -1 !== $match['separator'][1]: { $token = $match['separator'][0]; $type = self::TOKEN_SEPARATOR; break; }
353355
case -1 !== $match['open'][1]: { $token = $match['open'][0]; $type = self::TOKEN_OPEN; break; }
354356
case -1 !== $match['close'][1]: { $token = $match['close'][0]; $type = self::TOKEN_CLOSE; break; }
355-
default: { throw new \RuntimeException(sprintf('Invalid token.')); }
357+
default: { throw new \RuntimeException('Invalid token.'); }
356358
}
357359
$tokens[] = array($type, $token, $position);
358360
$position += mb_strlen($token, 'utf-8');
@@ -361,7 +363,7 @@ private function tokenize($text)
361363
return $tokens;
362364
}
363365

364-
/** @return string */
366+
/** @return non-empty-string */
365367
private function prepareLexer(SyntaxInterface $syntax)
366368
{
367369
// FIXME: for some reason Psalm does not understand the `@psalm-var callable() $var` annotation

src/Parser/WordpressParser.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,15 @@
2121
*
2222
* @see https://core.trac.wordpress.org/browser/tags/4.3.1/src/wp-includes/shortcodes.php#L239
2323
* @see https://core.trac.wordpress.org/browser/tags/4.3.1/src/wp-includes/shortcodes.php#L448
24+
* @psalm-suppress RiskyTruthyFalsyComparison
2425
*
2526
* @author Tomasz Kowalczyk <tomasz@kowalczyk.cc>
2627
*/
2728
final class WordpressParser implements ParserInterface
2829
{
29-
/** @var string */
30+
/** @var non-empty-string */
3031
private static $shortcodeRegex = '/\\[(\\[?)(<NAMES>)(?![\\w-])([^\\]\\/]*(?:\\/(?!\\])[^\\]\\/]*)*?)(?:(\\/)\\]|\\](?:([^\\[]*+(?:\\[(?!\\/\\2\\])[^\\[]*+)*+)\\[\\/\\2\\])?)(\\]?)/s';
31-
/** @var string */
32+
/** @var non-empty-string */
3233
private static $argumentsRegex = '/([\w-]+)\s*=\s*"([^"]*)"(?:\s|$)|([\w-]+)\s*=\s*\'([^\']*)\'(?:\s|$)|([\w-]+)\s*=\s*([^\s\'"]+)(?:\s|$)|"([^"]*)"(?:\s|$)|(\S+)(?:\s|$)/';
3334

3435
/** @var string[] */
@@ -74,6 +75,7 @@ public function parse($text)
7475
$names = $this->names
7576
? implode('|', array_map(function($name) { return preg_quote($name, '/'); }, $this->names))
7677
: RegexBuilderUtility::buildNameRegex();
78+
/** @var non-empty-string $regex */
7779
$regex = str_replace('<NAMES>', $names, static::$shortcodeRegex);
7880
preg_match_all($regex, $text, $matches, PREG_OFFSET_CAPTURE);
7981

0 commit comments

Comments
 (0)