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")); + } +}