diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 2a04e16..104bb5f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,19 +1,25 @@
name: CI
-on: [push]
+on:
+ push:
+ pull_request:
+
+permissions:
+ contents: read
+ actions: read
jobs:
composer:
runs-on: ubuntu-latest
strategy:
matrix:
- php: [ 8.1, 8.2, 8.3, 8.4 ]
+ php: [ 8.2, 8.3, 8.4, 8.5 ]
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- name: Cache Composer dependencies
- uses: actions/cache@v4
+ uses: actions/cache@v5
with:
path: /tmp/composer-cache
key: ${{ runner.os }}-${{ matrix.php }}-${{ hashFiles('**/composer.lock') }}
@@ -22,9 +28,10 @@ jobs:
uses: php-actions/composer@v6
with:
php_version: ${{ matrix.php }}
+ php_extensions: pcntl
- name: Archive build
- run: mkdir /tmp/github-actions/ && tar -cvf /tmp/github-actions/build.tar ./
+ run: mkdir /tmp/github-actions/ && tar --exclude=".git" -cvf /tmp/github-actions/build.tar ./
- name: Upload build archive for test runners
uses: actions/upload-artifact@v4
@@ -37,7 +44,7 @@ jobs:
needs: [ composer ]
strategy:
matrix:
- php: [ 8.1, 8.2, 8.3, 8.4 ]
+ php: [ 8.2, 8.3, 8.4, 8.5 ]
outputs:
coverage: ${{ steps.store-coverage.outputs.coverage_text }}
@@ -72,7 +79,7 @@ jobs:
needs: [ phpunit ]
strategy:
matrix:
- php: [ 8.1, 8.2, 8.3, 8.4 ]
+ php: [ 8.2, 8.3, 8.4, 8.5 ]
steps:
- uses: actions/checkout@v4
@@ -87,13 +94,15 @@ jobs:
- name: Upload to Codecov
uses: codecov/codecov-action@v5
+ with:
+ token: ${{ secrets.CODECOV_TOKEN }}
phpstan:
runs-on: ubuntu-latest
needs: [ composer ]
strategy:
matrix:
- php: [ 8.1, 8.2, 8.3, 8.4 ]
+ php: [ 8.2, 8.3, 8.4, 8.5 ]
steps:
- uses: actions/download-artifact@v4
@@ -109,13 +118,15 @@ jobs:
with:
php_version: ${{ matrix.php }}
path: src/
+ level: 6
+ memory_limit: 256M
phpmd:
runs-on: ubuntu-latest
needs: [ composer ]
strategy:
matrix:
- php: [ 8.1, 8.2, 8.3, 8.4 ]
+ php: [ 8.2, 8.3, 8.4, 8.5 ]
steps:
- uses: actions/download-artifact@v4
@@ -139,7 +150,7 @@ jobs:
needs: [ composer ]
strategy:
matrix:
- php: [ 8.1, 8.2, 8.3, 8.4 ]
+ php: [ 8.2, 8.3, 8.4, 8.5 ]
steps:
- uses: actions/download-artifact@v4
@@ -160,12 +171,15 @@ jobs:
remove_old_artifacts:
runs-on: ubuntu-latest
+ permissions:
+ actions: write
+
steps:
- name: Remove old artifacts for prior workflow runs on this repository
env:
GH_TOKEN: ${{ github.token }}
run: |
- gh api "/repos/${{ github.repository }}/actions/artifacts?name=build-artifact" | jq ".artifacts[] | select(.name | startswith(\"build-artifact\")) | .id" > artifact-id-list.txt
+ gh api "/repos/${{ github.repository }}/actions/artifacts" | jq ".artifacts[] | select(.name | startswith(\"build-artifact\")) | .id" > artifact-id-list.txt
while read id
do
echo -n "Deleting artifact ID $id ... "
diff --git a/.gitignore b/.gitignore
index 8d7aea1..84f1c93 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,6 @@
+.idea/
/vendor
/test/phpunit/_coverage
.phpunit.result.cache
-/example.*
\ No newline at end of file
+/example.*
+test/phpunit/.phpunit.cache
diff --git a/composer.json b/composer.json
index 9338355..2cd763f 100644
--- a/composer.json
+++ b/composer.json
@@ -24,5 +24,26 @@
"psr-4": {
"Gt\\Async\\Test\\": "./test/phpunit"
}
- }
+ },
+
+ "scripts": {
+ "phpunit": "vendor/bin/phpunit --configuration phpunit.xml",
+ "phpunit:coverage": "XDEBUG_MODE=coverage vendor/bin/phpunit --configuration phpunit.xml --coverage-text",
+ "phpstan": "vendor/bin/phpstan analyse --level 6 src",
+ "phpcs": "vendor/bin/phpcs src --standard=phpcs.xml",
+ "phpmd": "vendor/bin/phpmd src/ text phpmd.xml",
+ "test": [
+ "@phpunit",
+ "@phpstan",
+ "@phpcs",
+ "@phpmd"
+ ]
+ },
+
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/PhpGt"
+ }
+ ]
}
diff --git a/composer.lock b/composer.lock
index 1fd6a39..7d00186 100644
--- a/composer.lock
+++ b/composer.lock
@@ -8,16 +8,16 @@
"packages": [
{
"name": "phpgt/promise",
- "version": "v2.2.3",
+ "version": "v2.2.4",
"source": {
"type": "git",
- "url": "https://github.com/PhpGt/Promise.git",
- "reference": "907b3a450f3252077f80b50289f73ab930ca2cdc"
+ "url": "https://github.com/phpgt/Promise.git",
+ "reference": "ac75701f90421d922d689038ad3f04028d527372"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PhpGt/Promise/zipball/907b3a450f3252077f80b50289f73ab930ca2cdc",
- "reference": "907b3a450f3252077f80b50289f73ab930ca2cdc",
+ "url": "https://api.github.com/repos/phpgt/Promise/zipball/ac75701f90421d922d689038ad3f04028d527372",
+ "reference": "ac75701f90421d922d689038ad3f04028d527372",
"shasum": ""
},
"require": {
@@ -52,8 +52,8 @@
"then"
],
"support": {
- "issues": "https://github.com/PhpGt/Promise/issues",
- "source": "https://github.com/PhpGt/Promise/tree/v2.2.3"
+ "issues": "https://github.com/phpgt/Promise/issues",
+ "source": "https://github.com/phpgt/Promise/tree/v2.2.4"
},
"funding": [
{
@@ -61,7 +61,7 @@
"type": "github"
}
],
- "time": "2023-07-01T10:59:01+00:00"
+ "time": "2024-05-05T14:21:03+00:00"
}
],
"packages-dev": [
@@ -594,16 +594,11 @@
},
{
"name": "phpstan/phpstan",
- "version": "1.12.20",
- "source": {
- "type": "git",
- "url": "https://github.com/phpstan/phpstan.git",
- "reference": "3240b1972042c7f73cf1045e879ea5bd5f761bb7"
- },
+ "version": "1.12.33",
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/phpstan/phpstan/zipball/3240b1972042c7f73cf1045e879ea5bd5f761bb7",
- "reference": "3240b1972042c7f73cf1045e879ea5bd5f761bb7",
+ "url": "https://api.github.com/repos/phpstan/phpstan/zipball/37982d6fc7cbb746dda7773530cda557cdf119e1",
+ "reference": "37982d6fc7cbb746dda7773530cda557cdf119e1",
"shasum": ""
},
"require": {
@@ -648,7 +643,7 @@
"type": "github"
}
],
- "time": "2025-03-05T13:37:43+00:00"
+ "time": "2026-02-28T20:30:03+00:00"
},
{
"name": "phpunit/php-code-coverage",
@@ -973,16 +968,16 @@
},
{
"name": "phpunit/phpunit",
- "version": "10.5.62",
+ "version": "10.5.63",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
- "reference": "3f7dd5066ebde5809296a81f0b19e8b00e5aab49"
+ "reference": "33198268dad71e926626b618f3ec3966661e4d90"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3f7dd5066ebde5809296a81f0b19e8b00e5aab49",
- "reference": "3f7dd5066ebde5809296a81f0b19e8b00e5aab49",
+ "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/33198268dad71e926626b618f3ec3966661e4d90",
+ "reference": "33198268dad71e926626b618f3ec3966661e4d90",
"shasum": ""
},
"require": {
@@ -1054,7 +1049,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
- "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.62"
+ "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.63"
},
"funding": [
{
@@ -1078,7 +1073,7 @@
"type": "tidelift"
}
],
- "time": "2026-01-27T05:32:38+00:00"
+ "time": "2026-01-27T05:48:37+00:00"
},
{
"name": "psr/container",
@@ -2138,16 +2133,16 @@
},
{
"name": "squizlabs/php_codesniffer",
- "version": "3.11.3",
+ "version": "3.13.5",
"source": {
"type": "git",
"url": "https://github.com/PHPCSStandards/PHP_CodeSniffer.git",
- "reference": "ba05f990e79cbe69b9f35c8c1ac8dca7eecc3a10"
+ "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/ba05f990e79cbe69b9f35c8c1ac8dca7eecc3a10",
- "reference": "ba05f990e79cbe69b9f35c8c1ac8dca7eecc3a10",
+ "url": "https://api.github.com/repos/PHPCSStandards/PHP_CodeSniffer/zipball/0ca86845ce43291e8f5692c7356fccf3bcf02bf4",
+ "reference": "0ca86845ce43291e8f5692c7356fccf3bcf02bf4",
"shasum": ""
},
"require": {
@@ -2164,11 +2159,6 @@
"bin/phpcs"
],
"type": "library",
- "extra": {
- "branch-alias": {
- "dev-master": "3.x-dev"
- }
- },
"notification-url": "https://packagist.org/downloads/",
"license": [
"BSD-3-Clause"
@@ -2214,42 +2204,42 @@
"type": "open_collective"
},
{
- "url": "https://thanks.dev/phpcsstandards",
+ "url": "https://thanks.dev/u/gh/phpcsstandards",
"type": "thanks_dev"
}
],
- "time": "2025-01-23T17:04:15+00:00"
+ "time": "2025-11-04T16:30:35+00:00"
},
{
"name": "symfony/config",
- "version": "v6.4.14",
+ "version": "v7.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/config.git",
- "reference": "4e55e7e4ffddd343671ea972216d4509f46c22ef"
+ "reference": "6c17162555bfb58957a55bb0e43e00035b6ae3d5"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/config/zipball/4e55e7e4ffddd343671ea972216d4509f46c22ef",
- "reference": "4e55e7e4ffddd343671ea972216d4509f46c22ef",
+ "url": "https://api.github.com/repos/symfony/config/zipball/6c17162555bfb58957a55bb0e43e00035b6ae3d5",
+ "reference": "6c17162555bfb58957a55bb0e43e00035b6ae3d5",
"shasum": ""
},
"require": {
- "php": ">=8.1",
+ "php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3",
- "symfony/filesystem": "^5.4|^6.0|^7.0",
+ "symfony/filesystem": "^7.1|^8.0",
"symfony/polyfill-ctype": "~1.8"
},
"conflict": {
- "symfony/finder": "<5.4",
+ "symfony/finder": "<6.4",
"symfony/service-contracts": "<2.5"
},
"require-dev": {
- "symfony/event-dispatcher": "^5.4|^6.0|^7.0",
- "symfony/finder": "^5.4|^6.0|^7.0",
- "symfony/messenger": "^5.4|^6.0|^7.0",
+ "symfony/event-dispatcher": "^6.4|^7.0|^8.0",
+ "symfony/finder": "^6.4|^7.0|^8.0",
+ "symfony/messenger": "^6.4|^7.0|^8.0",
"symfony/service-contracts": "^2.5|^3",
- "symfony/yaml": "^5.4|^6.0|^7.0"
+ "symfony/yaml": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -2277,7 +2267,7 @@
"description": "Helps you find, load, combine, autofill and validate configuration values of any kind",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/config/tree/v6.4.14"
+ "source": "https://github.com/symfony/config/tree/v7.4.7"
},
"funding": [
{
@@ -2288,49 +2278,52 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-11-04T11:33:53+00:00"
+ "time": "2026-03-06T10:41:14+00:00"
},
{
"name": "symfony/dependency-injection",
- "version": "v6.4.19",
+ "version": "v7.4.7",
"source": {
"type": "git",
"url": "https://github.com/symfony/dependency-injection.git",
- "reference": "b343c3b2f1539fe41331657b37d5c96c1d1ea842"
+ "reference": "0f651e58f4917fb0e2cd261ccbfe3d71e6e0f5db"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/b343c3b2f1539fe41331657b37d5c96c1d1ea842",
- "reference": "b343c3b2f1539fe41331657b37d5c96c1d1ea842",
+ "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/0f651e58f4917fb0e2cd261ccbfe3d71e6e0f5db",
+ "reference": "0f651e58f4917fb0e2cd261ccbfe3d71e6e0f5db",
"shasum": ""
},
"require": {
- "php": ">=8.1",
+ "php": ">=8.2",
"psr/container": "^1.1|^2.0",
"symfony/deprecation-contracts": "^2.5|^3",
- "symfony/service-contracts": "^2.5|^3.0",
- "symfony/var-exporter": "^6.2.10|^7.0"
+ "symfony/service-contracts": "^3.6",
+ "symfony/var-exporter": "^6.4.20|^7.2.5|^8.0"
},
"conflict": {
"ext-psr": "<1.1|>=2",
- "symfony/config": "<6.1",
- "symfony/finder": "<5.4",
- "symfony/proxy-manager-bridge": "<6.3",
- "symfony/yaml": "<5.4"
+ "symfony/config": "<6.4",
+ "symfony/finder": "<6.4",
+ "symfony/yaml": "<6.4"
},
"provide": {
"psr/container-implementation": "1.1|2.0",
"symfony/service-implementation": "1.1|2.0|3.0"
},
"require-dev": {
- "symfony/config": "^6.1|^7.0",
- "symfony/expression-language": "^5.4|^6.0|^7.0",
- "symfony/yaml": "^5.4|^6.0|^7.0"
+ "symfony/config": "^6.4|^7.0|^8.0",
+ "symfony/expression-language": "^6.4|^7.0|^8.0",
+ "symfony/yaml": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -2358,7 +2351,7 @@
"description": "Allows you to standardize and centralize the way objects are constructed in your application",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/dependency-injection/tree/v6.4.19"
+ "source": "https://github.com/symfony/dependency-injection/tree/v7.4.7"
},
"funding": [
{
@@ -2369,25 +2362,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2025-02-20T10:02:49+00:00"
+ "time": "2026-03-03T07:48:48+00:00"
},
{
"name": "symfony/deprecation-contracts",
- "version": "v3.5.1",
+ "version": "v3.6.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
- "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6"
+ "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
- "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6",
+ "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62",
+ "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62",
"shasum": ""
},
"require": {
@@ -2400,7 +2397,7 @@
"name": "symfony/contracts"
},
"branch-alias": {
- "dev-main": "3.5-dev"
+ "dev-main": "3.6-dev"
}
},
"autoload": {
@@ -2425,7 +2422,7 @@
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1"
+ "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0"
},
"funding": [
{
@@ -2441,29 +2438,29 @@
"type": "tidelift"
}
],
- "time": "2024-09-25T14:20:29+00:00"
+ "time": "2024-09-25T14:21:43+00:00"
},
{
"name": "symfony/filesystem",
- "version": "v6.4.13",
+ "version": "v7.4.6",
"source": {
"type": "git",
"url": "https://github.com/symfony/filesystem.git",
- "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3"
+ "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/filesystem/zipball/4856c9cf585d5a0313d8d35afd681a526f038dd3",
- "reference": "4856c9cf585d5a0313d8d35afd681a526f038dd3",
+ "url": "https://api.github.com/repos/symfony/filesystem/zipball/3ebc794fa5315e59fd122561623c2e2e4280538e",
+ "reference": "3ebc794fa5315e59fd122561623c2e2e4280538e",
"shasum": ""
},
"require": {
- "php": ">=8.1",
+ "php": ">=8.2",
"symfony/polyfill-ctype": "~1.8",
"symfony/polyfill-mbstring": "~1.8"
},
"require-dev": {
- "symfony/process": "^5.4|^6.4|^7.0"
+ "symfony/process": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -2491,7 +2488,7 @@
"description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com",
"support": {
- "source": "https://github.com/symfony/filesystem/tree/v6.4.13"
+ "source": "https://github.com/symfony/filesystem/tree/v7.4.6"
},
"funding": [
{
@@ -2502,16 +2499,20 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-10-25T15:07:50+00:00"
+ "time": "2026-02-25T16:50:00+00:00"
},
{
"name": "symfony/polyfill-ctype",
- "version": "v1.31.0",
+ "version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-ctype.git",
@@ -2570,7 +2571,7 @@
"portable"
],
"support": {
- "source": "https://github.com/symfony/polyfill-ctype/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-ctype/tree/v1.33.0"
},
"funding": [
{
@@ -2581,6 +2582,10 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
@@ -2590,19 +2595,20 @@
},
{
"name": "symfony/polyfill-mbstring",
- "version": "v1.31.0",
+ "version": "v1.33.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git",
- "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341"
+ "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/85181ba99b2345b0ef10ce42ecac37612d9fd341",
- "reference": "85181ba99b2345b0ef10ce42ecac37612d9fd341",
+ "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6d857f4d76bd4b343eac26d6b539585d2bc56493",
+ "reference": "6d857f4d76bd4b343eac26d6b539585d2bc56493",
"shasum": ""
},
"require": {
+ "ext-iconv": "*",
"php": ">=7.2"
},
"provide": {
@@ -2650,7 +2656,7 @@
"shim"
],
"support": {
- "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.31.0"
+ "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.33.0"
},
"funding": [
{
@@ -2661,25 +2667,29 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-09-09T11:45:10+00:00"
+ "time": "2024-12-23T08:48:59+00:00"
},
{
"name": "symfony/service-contracts",
- "version": "v3.5.1",
+ "version": "v3.6.1",
"source": {
"type": "git",
"url": "https://github.com/symfony/service-contracts.git",
- "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0"
+ "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0",
- "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0",
+ "url": "https://api.github.com/repos/symfony/service-contracts/zipball/45112560a3ba2d715666a509a0bc9521d10b6c43",
+ "reference": "45112560a3ba2d715666a509a0bc9521d10b6c43",
"shasum": ""
},
"require": {
@@ -2697,7 +2707,7 @@
"name": "symfony/contracts"
},
"branch-alias": {
- "dev-main": "3.5-dev"
+ "dev-main": "3.6-dev"
}
},
"autoload": {
@@ -2733,7 +2743,7 @@
"standards"
],
"support": {
- "source": "https://github.com/symfony/service-contracts/tree/v3.5.1"
+ "source": "https://github.com/symfony/service-contracts/tree/v3.6.1"
},
"funding": [
{
@@ -2744,35 +2754,39 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2024-09-25T14:20:29+00:00"
+ "time": "2025-07-15T11:30:57+00:00"
},
{
"name": "symfony/var-exporter",
- "version": "v6.4.19",
+ "version": "v7.4.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-exporter.git",
- "reference": "be6e71b0c257884c1107313de5d247741cfea172"
+ "reference": "03a60f169c79a28513a78c967316fbc8bf17816f"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/symfony/var-exporter/zipball/be6e71b0c257884c1107313de5d247741cfea172",
- "reference": "be6e71b0c257884c1107313de5d247741cfea172",
+ "url": "https://api.github.com/repos/symfony/var-exporter/zipball/03a60f169c79a28513a78c967316fbc8bf17816f",
+ "reference": "03a60f169c79a28513a78c967316fbc8bf17816f",
"shasum": ""
},
"require": {
- "php": ">=8.1",
+ "php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3"
},
"require-dev": {
- "symfony/property-access": "^6.4|^7.0",
- "symfony/serializer": "^6.4|^7.0",
- "symfony/var-dumper": "^5.4|^6.0|^7.0"
+ "symfony/property-access": "^6.4|^7.0|^8.0",
+ "symfony/serializer": "^6.4|^7.0|^8.0",
+ "symfony/var-dumper": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -2810,7 +2824,7 @@
"serialize"
],
"support": {
- "source": "https://github.com/symfony/var-exporter/tree/v6.4.19"
+ "source": "https://github.com/symfony/var-exporter/tree/v7.4.0"
},
"funding": [
{
@@ -2821,12 +2835,16 @@
"url": "https://github.com/fabpot",
"type": "github"
},
+ {
+ "url": "https://github.com/nicolas-grekas",
+ "type": "github"
+ },
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
- "time": "2025-02-13T09:33:32+00:00"
+ "time": "2025-09-11T10:15:23+00:00"
},
{
"name": "theseer/tokenizer",
diff --git a/phpcs.xml b/phpcs.xml
index bff466c..ce2a486 100644
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -30,7 +30,6 @@
-
diff --git a/src/Event/Event.php b/src/Event/Event.php
new file mode 100644
index 0000000..d6709ec
--- /dev/null
+++ b/src/Event/Event.php
@@ -0,0 +1,20 @@
+name = $name;
+ $this->detail = $detail;
+ }
+
+ public function getName():string {
+ return $this->name;
+ }
+
+ public function getDetail():mixed {
+ return $this->detail;
+ }
+}
diff --git a/src/Event/EventDispatcher.php b/src/Event/EventDispatcher.php
new file mode 100644
index 0000000..5b88079
--- /dev/null
+++ b/src/Event/EventDispatcher.php
@@ -0,0 +1,22 @@
+> */
+ private array $subscriberList;
+
+ public function __construct() {
+ $this->subscriberList = [];
+ }
+
+ public function subscribe(string $eventName, callable $callback):void {
+ $this->subscriberList[$eventName] ??= [];
+ $this->subscriberList[$eventName][] = $callback;
+ }
+
+ public function publish(Event $event):void {
+ foreach($this->subscriberList[$event->getName()] ?? [] as $callback) {
+ call_user_func($callback, $event);
+ }
+ }
+}
diff --git a/test/phpunit/Event/EventDispatcherTest.php b/test/phpunit/Event/EventDispatcherTest.php
new file mode 100644
index 0000000..91bcb3c
--- /dev/null
+++ b/test/phpunit/Event/EventDispatcherTest.php
@@ -0,0 +1,76 @@
+subscribe("tick", function(Event $event) use(&$receivedEvent) {
+ $receivedEvent = $event;
+ });
+
+ $event = new Event("tick");
+ $sut->publish($event);
+
+ self::assertSame($event, $receivedEvent);
+ }
+
+ public function testPublishPassesEventDataToSubscriber():void {
+ $receivedDetail = null;
+
+ $sut = new EventDispatcher();
+ $sut->subscribe("message", function(Event $event) use(&$receivedDetail) {
+ $receivedDetail = $event->getDetail();
+ });
+
+ $sut->publish(new Event("message", "hello"));
+
+ self::assertSame("hello", $receivedDetail);
+ }
+
+ public function testPublishInvokesAllSubscribersForMatchingEventInSubscriptionOrder():void {
+ $callOrder = [];
+
+ $sut = new EventDispatcher();
+ $sut->subscribe("tick", function() use(&$callOrder) {
+ $callOrder[] = "first";
+ });
+ $sut->subscribe("tick", function() use(&$callOrder) {
+ $callOrder[] = "second";
+ });
+
+ $sut->publish(new Event("tick"));
+
+ self::assertSame(["first", "second"], $callOrder);
+ }
+
+ public function testPublishOnlyInvokesSubscribersForMatchingEventName():void {
+ $tickCount = 0;
+ $messageCount = 0;
+
+ $sut = new EventDispatcher();
+ $sut->subscribe("tick", function() use(&$tickCount) {
+ $tickCount++;
+ });
+ $sut->subscribe("message", function() use(&$messageCount) {
+ $messageCount++;
+ });
+
+ $sut->publish(new Event("tick"));
+
+ self::assertSame(1, $tickCount);
+ self::assertSame(0, $messageCount);
+ }
+
+ public function testPublishWithNoSubscribersDoesNothing():void {
+ $this->expectNotToPerformAssertions();
+
+ $sut = new EventDispatcher();
+ $sut->publish(new Event("tick"));
+ }
+}