mirror of
https://github.com/php-flasher/php-flasher.git
synced 2026-03-31 15:07:47 +01:00
docs: enhance code documentation with comprehensive PHPDoc comments
This commit is contained in:
@@ -1,2 +1 @@
|
|||||||
github: yoeunes
|
github: yoeunes
|
||||||
custom: https://www.paypal.com/paypalme/yoeunes
|
|
||||||
|
|||||||
Vendored
-1
@@ -1,2 +1 @@
|
|||||||
github: yoeunes
|
github: yoeunes
|
||||||
custom: https://www.paypal.com/paypalme/yoeunes
|
|
||||||
|
|||||||
@@ -51,7 +51,6 @@
|
|||||||
"phpunit/phpunit": "^10.5.26",
|
"phpunit/phpunit": "^10.5.26",
|
||||||
"rector/rector": "^1.2.8",
|
"rector/rector": "^1.2.8",
|
||||||
"rector/swiss-knife": "^1.0.0",
|
"rector/swiss-knife": "^1.0.0",
|
||||||
"spatie/ray": "^1.41.2",
|
|
||||||
"symplify/monorepo-builder": "^11.2.22"
|
"symplify/monorepo-builder": "^11.2.22"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
|
|||||||
Generated
+68
-73
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "9847ba2abb14c12d2e0b0d55e8251f79",
|
"content-hash": "d5de08e384654736feea63f1b01ffba1",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "brick/math",
|
"name": "brick/math",
|
||||||
@@ -3162,31 +3162,31 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/cache",
|
"name": "symfony/cache",
|
||||||
"version": "v7.0.0",
|
"version": "v6.4.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/cache.git",
|
"url": "https://github.com/symfony/cache.git",
|
||||||
"reference": "5e2376f726d61541b9617512e374808d12c1dc22"
|
"reference": "ac2d25f97b17eec6e19760b6b9962a4f7c44356a"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/cache/zipball/5e2376f726d61541b9617512e374808d12c1dc22",
|
"url": "https://api.github.com/repos/symfony/cache/zipball/ac2d25f97b17eec6e19760b6b9962a4f7c44356a",
|
||||||
"reference": "5e2376f726d61541b9617512e374808d12c1dc22",
|
"reference": "ac2d25f97b17eec6e19760b6b9962a4f7c44356a",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.2",
|
"php": ">=8.1",
|
||||||
"psr/cache": "^2.0|^3.0",
|
"psr/cache": "^2.0|^3.0",
|
||||||
"psr/log": "^1.1|^2|^3",
|
"psr/log": "^1.1|^2|^3",
|
||||||
"symfony/cache-contracts": "^2.5|^3",
|
"symfony/cache-contracts": "^2.5|^3",
|
||||||
"symfony/service-contracts": "^2.5|^3",
|
"symfony/service-contracts": "^2.5|^3",
|
||||||
"symfony/var-exporter": "^6.4|^7.0"
|
"symfony/var-exporter": "^6.3.6|^7.0"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"doctrine/dbal": "<3.6",
|
"doctrine/dbal": "<2.13.1",
|
||||||
"symfony/dependency-injection": "<6.4",
|
"symfony/dependency-injection": "<5.4",
|
||||||
"symfony/http-kernel": "<6.4",
|
"symfony/http-kernel": "<5.4",
|
||||||
"symfony/var-dumper": "<6.4"
|
"symfony/var-dumper": "<5.4"
|
||||||
},
|
},
|
||||||
"provide": {
|
"provide": {
|
||||||
"psr/cache-implementation": "2.0|3.0",
|
"psr/cache-implementation": "2.0|3.0",
|
||||||
@@ -3195,15 +3195,15 @@
|
|||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"cache/integration-tests": "dev-master",
|
"cache/integration-tests": "dev-master",
|
||||||
"doctrine/dbal": "^3.6|^4",
|
"doctrine/dbal": "^2.13.1|^3|^4",
|
||||||
"predis/predis": "^1.1|^2.0",
|
"predis/predis": "^1.1|^2.0",
|
||||||
"psr/simple-cache": "^1.0|^2.0|^3.0",
|
"psr/simple-cache": "^1.0|^2.0|^3.0",
|
||||||
"symfony/config": "^6.4|^7.0",
|
"symfony/config": "^5.4|^6.0|^7.0",
|
||||||
"symfony/dependency-injection": "^6.4|^7.0",
|
"symfony/dependency-injection": "^5.4|^6.0|^7.0",
|
||||||
"symfony/filesystem": "^6.4|^7.0",
|
"symfony/filesystem": "^5.4|^6.0|^7.0",
|
||||||
"symfony/http-kernel": "^6.4|^7.0",
|
"symfony/http-kernel": "^5.4|^6.0|^7.0",
|
||||||
"symfony/messenger": "^6.4|^7.0",
|
"symfony/messenger": "^5.4|^6.0|^7.0",
|
||||||
"symfony/var-dumper": "^6.4|^7.0"
|
"symfony/var-dumper": "^5.4|^6.0|^7.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -3238,7 +3238,7 @@
|
|||||||
"psr6"
|
"psr6"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/cache/tree/v7.0.0"
|
"source": "https://github.com/symfony/cache/tree/v6.4.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3254,7 +3254,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-11-25T15:40:35+00:00"
|
"time": "2023-11-24T19:28:07+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/cache-contracts",
|
"name": "symfony/cache-contracts",
|
||||||
@@ -3857,24 +3857,24 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/event-dispatcher",
|
"name": "symfony/event-dispatcher",
|
||||||
"version": "v7.0.0",
|
"version": "v6.4.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/event-dispatcher.git",
|
"url": "https://github.com/symfony/event-dispatcher.git",
|
||||||
"reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e"
|
"reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/c459b40ffe67c49af6fd392aac374c9edf8a027e",
|
"url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/d76d2632cfc2206eecb5ad2b26cd5934082941b6",
|
||||||
"reference": "c459b40ffe67c49af6fd392aac374c9edf8a027e",
|
"reference": "d76d2632cfc2206eecb5ad2b26cd5934082941b6",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.2",
|
"php": ">=8.1",
|
||||||
"symfony/event-dispatcher-contracts": "^2.5|^3"
|
"symfony/event-dispatcher-contracts": "^2.5|^3"
|
||||||
},
|
},
|
||||||
"conflict": {
|
"conflict": {
|
||||||
"symfony/dependency-injection": "<6.4",
|
"symfony/dependency-injection": "<5.4",
|
||||||
"symfony/service-contracts": "<2.5"
|
"symfony/service-contracts": "<2.5"
|
||||||
},
|
},
|
||||||
"provide": {
|
"provide": {
|
||||||
@@ -3883,13 +3883,13 @@
|
|||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"psr/log": "^1|^2|^3",
|
"psr/log": "^1|^2|^3",
|
||||||
"symfony/config": "^6.4|^7.0",
|
"symfony/config": "^5.4|^6.0|^7.0",
|
||||||
"symfony/dependency-injection": "^6.4|^7.0",
|
"symfony/dependency-injection": "^5.4|^6.0|^7.0",
|
||||||
"symfony/error-handler": "^6.4|^7.0",
|
"symfony/error-handler": "^5.4|^6.0|^7.0",
|
||||||
"symfony/expression-language": "^6.4|^7.0",
|
"symfony/expression-language": "^5.4|^6.0|^7.0",
|
||||||
"symfony/http-foundation": "^6.4|^7.0",
|
"symfony/http-foundation": "^5.4|^6.0|^7.0",
|
||||||
"symfony/service-contracts": "^2.5|^3",
|
"symfony/service-contracts": "^2.5|^3",
|
||||||
"symfony/stopwatch": "^6.4|^7.0"
|
"symfony/stopwatch": "^5.4|^6.0|^7.0"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"autoload": {
|
"autoload": {
|
||||||
@@ -3917,7 +3917,7 @@
|
|||||||
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
|
"description": "Provides tools that allow your application components to communicate with each other by dispatching events and listening to them",
|
||||||
"homepage": "https://symfony.com",
|
"homepage": "https://symfony.com",
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/event-dispatcher/tree/v7.0.0"
|
"source": "https://github.com/symfony/event-dispatcher/tree/v6.4.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -3933,7 +3933,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-07-27T16:29:09+00:00"
|
"time": "2023-07-27T06:52:43+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/event-dispatcher-contracts",
|
"name": "symfony/event-dispatcher-contracts",
|
||||||
@@ -6454,16 +6454,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/var-dumper",
|
"name": "symfony/var-dumper",
|
||||||
"version": "v7.0.3",
|
"version": "v7.0.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/var-dumper.git",
|
"url": "https://github.com/symfony/var-dumper.git",
|
||||||
"reference": "a7a061abbf6fe3d4a79032cbc5149a4d65a10234"
|
"reference": "cf0220fc7607476fd0d001ab3ed9e830d1fdda56"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/a7a061abbf6fe3d4a79032cbc5149a4d65a10234",
|
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/cf0220fc7607476fd0d001ab3ed9e830d1fdda56",
|
||||||
"reference": "a7a061abbf6fe3d4a79032cbc5149a4d65a10234",
|
"reference": "cf0220fc7607476fd0d001ab3ed9e830d1fdda56",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -6517,7 +6517,7 @@
|
|||||||
"dump"
|
"dump"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/var-dumper/tree/v7.0.3"
|
"source": "https://github.com/symfony/var-dumper/tree/v7.0.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -6533,7 +6533,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-01-23T15:02:46+00:00"
|
"time": "2023-11-27T12:39:18+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/var-exporter",
|
"name": "symfony/var-exporter",
|
||||||
@@ -8028,16 +8028,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "overtrue/phplint",
|
"name": "overtrue/phplint",
|
||||||
"version": "9.5.3",
|
"version": "9.5.6",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/overtrue/phplint.git",
|
"url": "https://github.com/overtrue/phplint.git",
|
||||||
"reference": "584063a687abca041551e0b14c47fe9fc574b193"
|
"reference": "3fdc395a816d1401091062c7a3bfb31252aed6c5"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/overtrue/phplint/zipball/584063a687abca041551e0b14c47fe9fc574b193",
|
"url": "https://api.github.com/repos/overtrue/phplint/zipball/3fdc395a816d1401091062c7a3bfb31252aed6c5",
|
||||||
"reference": "584063a687abca041551e0b14c47fe9fc574b193",
|
"reference": "3fdc395a816d1401091062c7a3bfb31252aed6c5",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -8045,14 +8045,14 @@
|
|||||||
"ext-dom": "*",
|
"ext-dom": "*",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-mbstring": "*",
|
"ext-mbstring": "*",
|
||||||
"php": "^8.2",
|
"php": "^8.1",
|
||||||
"symfony/cache": "^7.0",
|
"symfony/cache": "^6.4 || ^7.0",
|
||||||
"symfony/console": "^7.0",
|
"symfony/console": "^6.4 || ^7.0",
|
||||||
"symfony/event-dispatcher": "^7.0",
|
"symfony/event-dispatcher": "^6.4 || ^7.0",
|
||||||
"symfony/finder": "^7.0",
|
"symfony/finder": "^6.4 || ^7.0",
|
||||||
"symfony/options-resolver": "^7.0",
|
"symfony/options-resolver": "^6.4 || ^7.0",
|
||||||
"symfony/process": "^7.0",
|
"symfony/process": "^6.4 || ^7.0",
|
||||||
"symfony/yaml": "^7.0"
|
"symfony/yaml": "^6.4 || ^7.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"bamarni/composer-bin-plugin": "^1.4",
|
"bamarni/composer-bin-plugin": "^1.4",
|
||||||
@@ -8109,7 +8109,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/overtrue/phplint/issues",
|
"issues": "https://github.com/overtrue/phplint/issues",
|
||||||
"source": "https://github.com/overtrue/phplint/tree/9.5.3"
|
"source": "https://github.com/overtrue/phplint/tree/9.5.6"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -8117,7 +8117,7 @@
|
|||||||
"type": "github"
|
"type": "github"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-10-11T07:13:25+00:00"
|
"time": "2025-01-15T05:41:15+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "phar-io/manifest",
|
"name": "phar-io/manifest",
|
||||||
@@ -10313,16 +10313,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/ray",
|
"name": "spatie/ray",
|
||||||
"version": "1.41.2",
|
"version": "1.41.1",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/spatie/ray.git",
|
"url": "https://github.com/spatie/ray.git",
|
||||||
"reference": "c44f8cfbf82c69909b505de61d8d3f2d324e93fc"
|
"reference": "051a0facb1d2462fafef87ff77eb74d6f2d12944"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/spatie/ray/zipball/c44f8cfbf82c69909b505de61d8d3f2d324e93fc",
|
"url": "https://api.github.com/repos/spatie/ray/zipball/051a0facb1d2462fafef87ff77eb74d6f2d12944",
|
||||||
"reference": "c44f8cfbf82c69909b505de61d8d3f2d324e93fc",
|
"reference": "051a0facb1d2462fafef87ff77eb74d6f2d12944",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
@@ -10333,7 +10333,7 @@
|
|||||||
"spatie/backtrace": "^1.1",
|
"spatie/backtrace": "^1.1",
|
||||||
"spatie/macroable": "^1.0|^2.0",
|
"spatie/macroable": "^1.0|^2.0",
|
||||||
"symfony/stopwatch": "^4.0|^5.1|^6.0|^7.0",
|
"symfony/stopwatch": "^4.0|^5.1|^6.0|^7.0",
|
||||||
"symfony/var-dumper": "^4.2|^5.1|^6.0|^7.0.3"
|
"symfony/var-dumper": "^4.2|^5.1|^6.0|^7.0"
|
||||||
},
|
},
|
||||||
"require-dev": {
|
"require-dev": {
|
||||||
"illuminate/support": "6.x|^8.18|^9.0",
|
"illuminate/support": "6.x|^8.18|^9.0",
|
||||||
@@ -10349,11 +10349,6 @@
|
|||||||
"bin/remove-ray.sh"
|
"bin/remove-ray.sh"
|
||||||
],
|
],
|
||||||
"type": "library",
|
"type": "library",
|
||||||
"extra": {
|
|
||||||
"branch-alias": {
|
|
||||||
"dev-main": "1.x-dev"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"files": [
|
"files": [
|
||||||
"src/helpers.php"
|
"src/helpers.php"
|
||||||
@@ -10382,7 +10377,7 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/spatie/ray/issues",
|
"issues": "https://github.com/spatie/ray/issues",
|
||||||
"source": "https://github.com/spatie/ray/tree/1.41.2"
|
"source": "https://github.com/spatie/ray/tree/1.41.1"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -10394,24 +10389,24 @@
|
|||||||
"type": "other"
|
"type": "other"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2024-04-24T14:21:46+00:00"
|
"time": "2024-01-25T10:15:50+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/options-resolver",
|
"name": "symfony/options-resolver",
|
||||||
"version": "v7.0.0",
|
"version": "v6.4.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/symfony/options-resolver.git",
|
"url": "https://github.com/symfony/options-resolver.git",
|
||||||
"reference": "700ff4096e346f54cb628ea650767c8130f1001f"
|
"reference": "22301f0e7fdeaacc14318928612dee79be99860e"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/700ff4096e346f54cb628ea650767c8130f1001f",
|
"url": "https://api.github.com/repos/symfony/options-resolver/zipball/22301f0e7fdeaacc14318928612dee79be99860e",
|
||||||
"reference": "700ff4096e346f54cb628ea650767c8130f1001f",
|
"reference": "22301f0e7fdeaacc14318928612dee79be99860e",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"php": ">=8.2",
|
"php": ">=8.1",
|
||||||
"symfony/deprecation-contracts": "^2.5|^3"
|
"symfony/deprecation-contracts": "^2.5|^3"
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
@@ -10445,7 +10440,7 @@
|
|||||||
"options"
|
"options"
|
||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/symfony/options-resolver/tree/v7.0.0"
|
"source": "https://github.com/symfony/options-resolver/tree/v6.4.0"
|
||||||
},
|
},
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -10461,7 +10456,7 @@
|
|||||||
"type": "tidelift"
|
"type": "tidelift"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"time": "2023-08-08T10:20:21+00:00"
|
"time": "2023-08-08T10:16:24+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/polyfill-iconv",
|
"name": "symfony/polyfill-iconv",
|
||||||
|
|||||||
+3
-4
@@ -8,16 +8,15 @@ includes:
|
|||||||
- vendor/phpstan/phpstan-phpunit/extension.neon
|
- vendor/phpstan/phpstan-phpunit/extension.neon
|
||||||
- vendor/phpstan/phpstan-phpunit/rules.neon
|
- vendor/phpstan/phpstan-phpunit/rules.neon
|
||||||
|
|
||||||
rules:
|
|
||||||
- Spatie\Ray\PHPStan\RemainingRayCallRule
|
|
||||||
|
|
||||||
parameters:
|
parameters:
|
||||||
level: 9
|
level: max
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
- src/
|
- src/
|
||||||
- tests/
|
- tests/
|
||||||
|
|
||||||
|
editorUrl: 'phpstorm://open?file=%%file%%&line=%%line%%'
|
||||||
|
|
||||||
tmpDir: .cache/phpstan
|
tmpDir: .cache/phpstan
|
||||||
|
|
||||||
ignoreErrors:
|
ignoreErrors:
|
||||||
|
|||||||
@@ -14,7 +14,4 @@ return Rector\Config\RectorConfig::configure()
|
|||||||
Rector\PHPUnit\Set\PHPUnitSetList::PHPUNIT_110,
|
Rector\PHPUnit\Set\PHPUnitSetList::PHPUNIT_110,
|
||||||
Rector\PHPUnit\Set\PHPUnitSetList::ANNOTATIONS_TO_ATTRIBUTES,
|
Rector\PHPUnit\Set\PHPUnitSetList::ANNOTATIONS_TO_ATTRIBUTES,
|
||||||
Rector\PHPUnit\Set\PHPUnitSetList::PHPUNIT_CODE_QUALITY,
|
Rector\PHPUnit\Set\PHPUnitSetList::PHPUNIT_CODE_QUALITY,
|
||||||
])
|
|
||||||
->withRules([
|
|
||||||
Spatie\Ray\Rector\RemoveRayCallRector::class,
|
|
||||||
]);
|
]);
|
||||||
|
|||||||
Vendored
-1
@@ -1,2 +1 @@
|
|||||||
github: yoeunes
|
github: yoeunes
|
||||||
custom: https://www.paypal.com/paypalme/yoeunes
|
|
||||||
|
|||||||
@@ -15,15 +15,41 @@ use Symfony\Component\Console\Input\InputOption;
|
|||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
use Symfony\Component\Finder\Finder;
|
use Symfony\Component\Finder\Finder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* InstallCommand - Artisan command for installing PHPFlasher resources.
|
||||||
|
*
|
||||||
|
* This command provides a CLI interface for installing PHPFlasher resources
|
||||||
|
* including assets (JS and CSS files) and configuration files. It discovers
|
||||||
|
* all registered PHPFlasher plugins and installs their resources.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Command: Implements the command pattern for Artisan CLI integration
|
||||||
|
* - Discovery: Automatically discovers and processes registered plugins
|
||||||
|
*/
|
||||||
final class InstallCommand extends Command
|
final class InstallCommand extends Command
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
protected $description = 'Installs all <fg=blue;options=bold>PHPFlasher</> resources to the <comment>public</comment> and <comment>config</comment> directories.';
|
protected $description = 'Installs all <fg=blue;options=bold>PHPFlasher</> resources to the <comment>public</comment> and <comment>config</comment> directories.';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new InstallCommand instance.
|
||||||
|
*
|
||||||
|
* @param AssetManagerInterface $assetManager Manager for handling PHPFlasher assets
|
||||||
|
*/
|
||||||
public function __construct(private readonly AssetManagerInterface $assetManager)
|
public function __construct(private readonly AssetManagerInterface $assetManager)
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configure the command.
|
||||||
|
*
|
||||||
|
* Sets the command name, description, help text, and options.
|
||||||
|
*/
|
||||||
protected function configure(): void
|
protected function configure(): void
|
||||||
{
|
{
|
||||||
$this
|
$this
|
||||||
@@ -34,6 +60,20 @@ final class InstallCommand extends Command
|
|||||||
->addOption('symlink', 's', InputOption::VALUE_NONE, 'Symlink <fg=blue;options=bold>PHPFlasher</> assets instead of copying them.');
|
->addOption('symlink', 's', InputOption::VALUE_NONE, 'Symlink <fg=blue;options=bold>PHPFlasher</> assets instead of copying them.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the command.
|
||||||
|
*
|
||||||
|
* Installs PHPFlasher resources by:
|
||||||
|
* 1. Displaying a fancy banner
|
||||||
|
* 2. Processing each registered plugin
|
||||||
|
* 3. Publishing assets and config files
|
||||||
|
* 4. Creating a manifest file
|
||||||
|
*
|
||||||
|
* @param InputInterface $input Command input
|
||||||
|
* @param OutputInterface $output Command output
|
||||||
|
*
|
||||||
|
* @return int Command exit code (0 for success, non-zero for failure)
|
||||||
|
*/
|
||||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
$output->writeln('');
|
$output->writeln('');
|
||||||
@@ -122,7 +162,13 @@ final class InstallCommand extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string[]
|
* Publish assets from a plugin to the public directory.
|
||||||
|
*
|
||||||
|
* @param PluginInterface $plugin The plugin to publish assets from
|
||||||
|
* @param string $publicDir The target public directory
|
||||||
|
* @param bool $useSymlinks Whether to symlink or copy assets
|
||||||
|
*
|
||||||
|
* @return string[] Array of published file paths
|
||||||
*/
|
*/
|
||||||
private function publishAssets(PluginInterface $plugin, string $publicDir, bool $useSymlinks): array
|
private function publishAssets(PluginInterface $plugin, string $publicDir, bool $useSymlinks): array
|
||||||
{
|
{
|
||||||
@@ -156,6 +202,12 @@ final class InstallCommand extends Command
|
|||||||
return $files;
|
return $files;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publish a plugin's configuration file.
|
||||||
|
*
|
||||||
|
* @param PluginInterface $plugin The plugin to publish configuration for
|
||||||
|
* @param string $configFile The source configuration file path
|
||||||
|
*/
|
||||||
private function publishConfig(PluginInterface $plugin, string $configFile): void
|
private function publishConfig(PluginInterface $plugin, string $configFile): void
|
||||||
{
|
{
|
||||||
if (!file_exists($configFile)) {
|
if (!file_exists($configFile)) {
|
||||||
|
|||||||
@@ -6,12 +6,39 @@ namespace Flasher\Laravel\Component;
|
|||||||
|
|
||||||
use Illuminate\View\Component;
|
use Illuminate\View\Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FlasherComponent - Blade component for rendering notifications.
|
||||||
|
*
|
||||||
|
* This class provides a Blade component interface for rendering PHPFlasher
|
||||||
|
* notifications in Laravel views. It can be used with Laravel's component syntax:
|
||||||
|
* <x-flasher :criteria="json_encode(['limit' => 5])" :context="json_encode(['foo' => 'bar'])" />
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - View Component: Implements Laravel's view component pattern
|
||||||
|
* - Adapter: Adapts the Flasher render method to Laravel's component interface
|
||||||
|
*/
|
||||||
final class FlasherComponent extends Component
|
final class FlasherComponent extends Component
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new FlasherComponent instance.
|
||||||
|
*
|
||||||
|
* @param string $criteria JSON-encoded filtering criteria for notifications
|
||||||
|
* @param string $context JSON-encoded rendering context
|
||||||
|
*/
|
||||||
public function __construct(public string $criteria = '', public string $context = '')
|
public function __construct(public string $criteria = '', public string $context = '')
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the component.
|
||||||
|
*
|
||||||
|
* This method decodes the JSON criteria and context, then delegates to
|
||||||
|
* the Flasher service to render the notifications as HTML.
|
||||||
|
*
|
||||||
|
* @return string Rendered HTML content
|
||||||
|
*
|
||||||
|
* @throws \JsonException If JSON decoding fails
|
||||||
|
*/
|
||||||
public function render(): string
|
public function render(): string
|
||||||
{
|
{
|
||||||
/** @var array<string, mixed> $criteria */
|
/** @var array<string, mixed> $criteria */
|
||||||
|
|||||||
@@ -13,8 +13,28 @@ use Livewire\Component;
|
|||||||
use Livewire\LivewireManager;
|
use Livewire\LivewireManager;
|
||||||
use Livewire\Mechanisms\HandleComponents\ComponentContext;
|
use Livewire\Mechanisms\HandleComponents\ComponentContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* LivewireListener - Integrates PHPFlasher with Livewire component lifecycle.
|
||||||
|
*
|
||||||
|
* This listener ensures that PHPFlasher notifications can be displayed during
|
||||||
|
* Livewire component updates without requiring a full page load. It dispatches
|
||||||
|
* notifications as Livewire events that are handled by the front-end JavaScript.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Observer: Listens to Livewire component lifecycle events
|
||||||
|
* - Adapter: Adapts PHPFlasher notifications to Livewire's event system
|
||||||
|
* - Security-aware: Ensures CSP compliance with proper nonce handling
|
||||||
|
*/
|
||||||
final readonly class LivewireListener
|
final readonly class LivewireListener
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new LivewireListener instance.
|
||||||
|
*
|
||||||
|
* @param LivewireManager $livewire The Livewire manager
|
||||||
|
* @param FlasherInterface $flasher The PHPFlasher service
|
||||||
|
* @param ContentSecurityPolicyHandlerInterface $cspHandler The CSP handler for security
|
||||||
|
* @param \Closure $request Closure to get the current request
|
||||||
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private LivewireManager $livewire,
|
private LivewireManager $livewire,
|
||||||
private FlasherInterface $flasher,
|
private FlasherInterface $flasher,
|
||||||
@@ -23,6 +43,15 @@ final readonly class LivewireListener
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a Livewire component dehydration event.
|
||||||
|
*
|
||||||
|
* This method is invoked during Livewire's component rendering process
|
||||||
|
* and dispatches any pending notifications as Livewire events.
|
||||||
|
*
|
||||||
|
* @param Component $component The Livewire component being rendered
|
||||||
|
* @param ComponentContext $context The Livewire component context
|
||||||
|
*/
|
||||||
public function __invoke(Component $component, ComponentContext $context): void
|
public function __invoke(Component $component, ComponentContext $context): void
|
||||||
{
|
{
|
||||||
if ($this->shouldSkip($context)) {
|
if ($this->shouldSkip($context)) {
|
||||||
@@ -38,7 +67,14 @@ final readonly class LivewireListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array{envelopes: Envelope[]} $data
|
* Dispatches notifications as Livewire events.
|
||||||
|
*
|
||||||
|
* This method adds the notifications data to the Livewire component's
|
||||||
|
* dispatched events, which will be processed by the front-end.
|
||||||
|
*
|
||||||
|
* @param Component $component The Livewire component
|
||||||
|
* @param ComponentContext $context The Livewire component context
|
||||||
|
* @param array{envelopes: Envelope[]} $data The notification data
|
||||||
*/
|
*/
|
||||||
private function dispatchNotifications(Component $component, ComponentContext $context, array $data): void
|
private function dispatchNotifications(Component $component, ComponentContext $context, array $data): void
|
||||||
{
|
{
|
||||||
@@ -53,13 +89,30 @@ final readonly class LivewireListener
|
|||||||
$context->addEffect('dispatches', $dispatches);
|
$context->addEffect('dispatches', $dispatches);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if notification processing should be skipped.
|
||||||
|
*
|
||||||
|
* Skips processing in the following cases:
|
||||||
|
* - Not a Livewire request
|
||||||
|
* - During component mounting (initial render)
|
||||||
|
* - When a redirect is in progress
|
||||||
|
*
|
||||||
|
* @param ComponentContext $context The Livewire component context
|
||||||
|
*
|
||||||
|
* @return bool True if notification processing should be skipped
|
||||||
|
*/
|
||||||
private function shouldSkip(ComponentContext $context): bool
|
private function shouldSkip(ComponentContext $context): bool
|
||||||
{
|
{
|
||||||
return !$this->livewire->isLivewireRequest() || $context->mounting || isset($context->effects['redirect']);
|
return !$this->livewire->isLivewireRequest() || $context->mounting || isset($context->effects['redirect']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string, mixed>
|
* Creates the security context for rendering notifications.
|
||||||
|
*
|
||||||
|
* This method generates CSP nonces to ensure scripts loaded by PHPFlasher
|
||||||
|
* comply with Content Security Policy.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed> The context with CSP nonces
|
||||||
*/
|
*/
|
||||||
private function createContext(): array
|
private function createContext(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,8 +7,26 @@ namespace Flasher\Laravel\EventListener;
|
|||||||
use Flasher\Prime\EventDispatcher\EventListener\NotificationLoggerListener;
|
use Flasher\Prime\EventDispatcher\EventListener\NotificationLoggerListener;
|
||||||
use Laravel\Octane\Events\RequestReceived;
|
use Laravel\Octane\Events\RequestReceived;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OctaneListener - Resets notification logger between Octane requests.
|
||||||
|
*
|
||||||
|
* This listener ensures that notifications from previous requests don't
|
||||||
|
* leak into new requests when running Laravel Octane, which keeps workers
|
||||||
|
* alive between requests.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Observer: Observes Octane request events
|
||||||
|
* - State Reset: Cleans up state between stateful worker requests
|
||||||
|
*/
|
||||||
final readonly class OctaneListener
|
final readonly class OctaneListener
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Handle the Octane RequestReceived event.
|
||||||
|
*
|
||||||
|
* Resets the notification logger to ensure clean state for the new request.
|
||||||
|
*
|
||||||
|
* @param RequestReceived $event The Octane request received event
|
||||||
|
*/
|
||||||
public function handle(RequestReceived $event): void
|
public function handle(RequestReceived $event): void
|
||||||
{
|
{
|
||||||
/** @var NotificationLoggerListener $listener */
|
/** @var NotificationLoggerListener $listener */
|
||||||
|
|||||||
@@ -10,6 +10,29 @@ use Flasher\Prime\Stamp\StampInterface;
|
|||||||
use Illuminate\Support\Facades\Facade;
|
use Illuminate\Support\Facades\Facade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Flasher - Laravel Facade for the PHPFlasher service.
|
||||||
|
*
|
||||||
|
* This facade provides a static interface to PHPFlasher's functionality within Laravel,
|
||||||
|
* following Laravel's facade pattern. It offers comprehensive IDE autocompletion for all
|
||||||
|
* PHPFlasher methods by providing method signatures in PHPDoc comments.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Facade: Provides a simplified, static interface to a complex subsystem
|
||||||
|
* - Proxy: Acts as a proxy to the underlying PHPFlasher service
|
||||||
|
*
|
||||||
|
* Usage examples:
|
||||||
|
* ```php
|
||||||
|
* // Simple notification
|
||||||
|
* Flasher::success('Operation completed successfully');
|
||||||
|
*
|
||||||
|
* // Chained configuration
|
||||||
|
* Flasher::type('success')
|
||||||
|
* ->title('Success')
|
||||||
|
* ->message('Record saved')
|
||||||
|
* ->option('timeout', 5000)
|
||||||
|
* ->push();
|
||||||
|
* ```
|
||||||
|
*
|
||||||
* @method static NotificationBuilder title(string $message)
|
* @method static NotificationBuilder title(string $message)
|
||||||
* @method static NotificationBuilder message(string $message)
|
* @method static NotificationBuilder message(string $message)
|
||||||
* @method static NotificationBuilder type(string $message)
|
* @method static NotificationBuilder type(string $message)
|
||||||
@@ -48,6 +71,11 @@ use Illuminate\Support\Facades\Facade;
|
|||||||
*/
|
*/
|
||||||
final class Flasher extends Facade
|
final class Flasher extends Facade
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Get the registered name of the component.
|
||||||
|
*
|
||||||
|
* @return string The name of the facade's service binding ('flasher')
|
||||||
|
*/
|
||||||
protected static function getFacadeAccessor(): string
|
protected static function getFacadeAccessor(): string
|
||||||
{
|
{
|
||||||
return 'flasher';
|
return 'flasher';
|
||||||
|
|||||||
@@ -42,8 +42,28 @@ use Illuminate\View\Compilers\BladeCompiler;
|
|||||||
use Laravel\Octane\Events\RequestReceived;
|
use Laravel\Octane\Events\RequestReceived;
|
||||||
use Livewire\LivewireManager;
|
use Livewire\LivewireManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FlasherServiceProvider - Main service provider for Laravel integration.
|
||||||
|
*
|
||||||
|
* This class serves as the entry point for integrating PHPFlasher with Laravel.
|
||||||
|
* It registers all necessary services, components, commands, and middleware
|
||||||
|
* to provide a seamless Laravel experience.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Service Provider: Implements Laravel's service provider pattern for registration
|
||||||
|
* - Adapter: Adapts Laravel-specific components to PHPFlasher interfaces
|
||||||
|
* - Bridge: Connects the framework-agnostic PHPFlasher core to Laravel
|
||||||
|
*/
|
||||||
final class FlasherServiceProvider extends PluginServiceProvider
|
final class FlasherServiceProvider extends PluginServiceProvider
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Register PHPFlasher services with the Laravel container.
|
||||||
|
*
|
||||||
|
* This method follows Laravel's service provider registration phase by:
|
||||||
|
* 1. Creating the core plugin
|
||||||
|
* 2. Registering configuration
|
||||||
|
* 3. Registering core services and adapters
|
||||||
|
*/
|
||||||
public function register(): void
|
public function register(): void
|
||||||
{
|
{
|
||||||
$this->plugin = $this->createPlugin();
|
$this->plugin = $this->createPlugin();
|
||||||
@@ -60,6 +80,17 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
$this->registerAssetManager();
|
$this->registerAssetManager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Boot PHPFlasher services after all providers are registered.
|
||||||
|
*
|
||||||
|
* This method follows Laravel's service provider boot phase by:
|
||||||
|
* 1. Setting up the service container bridge
|
||||||
|
* 2. Registering commands
|
||||||
|
* 3. Loading translations
|
||||||
|
* 4. Registering middleware
|
||||||
|
* 5. Registering Blade directives and components
|
||||||
|
* 6. Setting up Livewire integration
|
||||||
|
*/
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
FlasherContainer::from(static fn () => Container::getInstance());
|
FlasherContainer::from(static fn () => Container::getInstance());
|
||||||
@@ -71,11 +102,22 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
$this->registerLivewire();
|
$this->registerLivewire();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the PHPFlasher core plugin instance.
|
||||||
|
*
|
||||||
|
* @return FlasherPlugin The core PHPFlasher plugin
|
||||||
|
*/
|
||||||
public function createPlugin(): FlasherPlugin
|
public function createPlugin(): FlasherPlugin
|
||||||
{
|
{
|
||||||
return new FlasherPlugin();
|
return new FlasherPlugin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the main Flasher service with Laravel's container.
|
||||||
|
*
|
||||||
|
* This service is the main entry point for all PHPFlasher functionality
|
||||||
|
* and is made available via the 'flasher' service binding.
|
||||||
|
*/
|
||||||
private function registerFlasher(): void
|
private function registerFlasher(): void
|
||||||
{
|
{
|
||||||
$this->app->singleton('flasher', static function (Application $app) {
|
$this->app->singleton('flasher', static function (Application $app) {
|
||||||
@@ -93,6 +135,12 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
$this->app->bind(FlasherInterface::class, 'flasher');
|
$this->app->bind(FlasherInterface::class, 'flasher');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the factory locator service.
|
||||||
|
*
|
||||||
|
* The factory locator is responsible for locating and providing
|
||||||
|
* notification factory instances.
|
||||||
|
*/
|
||||||
private function registerFactoryLocator(): void
|
private function registerFactoryLocator(): void
|
||||||
{
|
{
|
||||||
$this->app->singleton('flasher.factory_locator', static function () {
|
$this->app->singleton('flasher.factory_locator', static function () {
|
||||||
@@ -100,6 +148,12 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the response manager service.
|
||||||
|
*
|
||||||
|
* The response manager is responsible for rendering notifications
|
||||||
|
* into different formats (HTML, JSON, etc.).
|
||||||
|
*/
|
||||||
private function registerResponseManager(): void
|
private function registerResponseManager(): void
|
||||||
{
|
{
|
||||||
$this->app->singleton('flasher.response_manager', static function (Application $app) {
|
$this->app->singleton('flasher.response_manager', static function (Application $app) {
|
||||||
@@ -111,6 +165,11 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the template engine adapter for Blade.
|
||||||
|
*
|
||||||
|
* This adapter allows PHPFlasher to render templates using Laravel's Blade engine.
|
||||||
|
*/
|
||||||
private function registerTemplateEngine(): void
|
private function registerTemplateEngine(): void
|
||||||
{
|
{
|
||||||
$this->app->singleton('flasher.template_engine', static function (Application $app) {
|
$this->app->singleton('flasher.template_engine', static function (Application $app) {
|
||||||
@@ -120,6 +179,12 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the resource manager service.
|
||||||
|
*
|
||||||
|
* The resource manager is responsible for managing assets (JS, CSS)
|
||||||
|
* needed by notifications.
|
||||||
|
*/
|
||||||
private function registerResourceManager(): void
|
private function registerResourceManager(): void
|
||||||
{
|
{
|
||||||
$this->app->singleton('flasher.resource_manager', static function (Application $app) {
|
$this->app->singleton('flasher.resource_manager', static function (Application $app) {
|
||||||
@@ -134,6 +199,12 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the storage manager service.
|
||||||
|
*
|
||||||
|
* The storage manager is responsible for storing and retrieving
|
||||||
|
* notifications from storage (session in Laravel's case).
|
||||||
|
*/
|
||||||
private function registerStorageManager(): void
|
private function registerStorageManager(): void
|
||||||
{
|
{
|
||||||
$this->app->singleton('flasher.storage_manager', static function (Application $app) {
|
$this->app->singleton('flasher.storage_manager', static function (Application $app) {
|
||||||
@@ -148,6 +219,12 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the event dispatcher and event listeners.
|
||||||
|
*
|
||||||
|
* The event dispatcher is responsible for dispatching events during
|
||||||
|
* the notification lifecycle.
|
||||||
|
*/
|
||||||
private function registerEventDispatcher(): void
|
private function registerEventDispatcher(): void
|
||||||
{
|
{
|
||||||
$this->app->singleton('flasher.notification_logger_listener', fn () => new NotificationLoggerListener());
|
$this->app->singleton('flasher.notification_logger_listener', fn () => new NotificationLoggerListener());
|
||||||
@@ -173,6 +250,11 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the Artisan commands for PHPFlasher.
|
||||||
|
*
|
||||||
|
* Commands are only registered when running in console mode.
|
||||||
|
*/
|
||||||
private function registerCommands(): void
|
private function registerCommands(): void
|
||||||
{
|
{
|
||||||
if (!$this->app->runningInConsole()) {
|
if (!$this->app->runningInConsole()) {
|
||||||
@@ -190,6 +272,11 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
$this->commands(InstallCommand::class);
|
$this->commands(InstallCommand::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register PHPFlasher information with Laravel's about command.
|
||||||
|
*
|
||||||
|
* This adds PHPFlasher information to the output of the `php artisan about` command.
|
||||||
|
*/
|
||||||
private function registerAboutCommand(): void
|
private function registerAboutCommand(): void
|
||||||
{
|
{
|
||||||
if (!class_exists(AboutCommand::class)) {
|
if (!class_exists(AboutCommand::class)) {
|
||||||
@@ -214,12 +301,22 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register PHPFlasher middleware with Laravel.
|
||||||
|
*
|
||||||
|
* Middleware includes session processing and response modification.
|
||||||
|
*/
|
||||||
private function registerMiddlewares(): void
|
private function registerMiddlewares(): void
|
||||||
{
|
{
|
||||||
$this->registerSessionMiddleware();
|
$this->registerSessionMiddleware();
|
||||||
$this->registerFlasherMiddleware();
|
$this->registerFlasherMiddleware();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the response middleware.
|
||||||
|
*
|
||||||
|
* This middleware injects notification assets into responses.
|
||||||
|
*/
|
||||||
private function registerFlasherMiddleware(): void
|
private function registerFlasherMiddleware(): void
|
||||||
{
|
{
|
||||||
if (!$this->getConfig('inject_assets')) {
|
if (!$this->getConfig('inject_assets')) {
|
||||||
@@ -239,6 +336,11 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
$this->pushMiddlewareToGroup(FlasherMiddleware::class);
|
$this->pushMiddlewareToGroup(FlasherMiddleware::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the session middleware.
|
||||||
|
*
|
||||||
|
* This middleware processes flash messages from the session.
|
||||||
|
*/
|
||||||
private function registerSessionMiddleware(): void
|
private function registerSessionMiddleware(): void
|
||||||
{
|
{
|
||||||
if (!$this->getConfig('flash_bag')) {
|
if (!$this->getConfig('flash_bag')) {
|
||||||
@@ -257,6 +359,11 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
$this->pushMiddlewareToGroup(SessionMiddleware::class);
|
$this->pushMiddlewareToGroup(SessionMiddleware::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push middleware to the web middleware group.
|
||||||
|
*
|
||||||
|
* @param string $middleware The middleware class name
|
||||||
|
*/
|
||||||
private function pushMiddlewareToGroup(string $middleware): void
|
private function pushMiddlewareToGroup(string $middleware): void
|
||||||
{
|
{
|
||||||
$this->callAfterResolving(HttpKernel::class, function (HttpKernel $kernel) use ($middleware) {
|
$this->callAfterResolving(HttpKernel::class, function (HttpKernel $kernel) use ($middleware) {
|
||||||
@@ -264,6 +371,11 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the Content Security Policy handler.
|
||||||
|
*
|
||||||
|
* This service handles CSP headers when injecting assets.
|
||||||
|
*/
|
||||||
private function registerCspHandler(): void
|
private function registerCspHandler(): void
|
||||||
{
|
{
|
||||||
$this->app->singleton('flasher.csp_handler', static function () {
|
$this->app->singleton('flasher.csp_handler', static function () {
|
||||||
@@ -271,6 +383,11 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the asset manager service.
|
||||||
|
*
|
||||||
|
* The asset manager is responsible for managing asset paths and manifests.
|
||||||
|
*/
|
||||||
private function registerAssetManager(): void
|
private function registerAssetManager(): void
|
||||||
{
|
{
|
||||||
$this->app->singleton('flasher.asset_manager', static function () {
|
$this->app->singleton('flasher.asset_manager', static function () {
|
||||||
@@ -281,6 +398,11 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register Blade directives and components.
|
||||||
|
*
|
||||||
|
* @param BladeCompiler $blade The Blade compiler instance
|
||||||
|
*/
|
||||||
private function registerBladeDirectives(BladeCompiler $blade): void
|
private function registerBladeDirectives(BladeCompiler $blade): void
|
||||||
{
|
{
|
||||||
$blade->directive('flasher_render', function (string $expression = '') {
|
$blade->directive('flasher_render', function (string $expression = '') {
|
||||||
@@ -294,6 +416,11 @@ final class FlasherServiceProvider extends PluginServiceProvider
|
|||||||
$blade->component(FlasherComponent::class, 'flasher');
|
$blade->component(FlasherComponent::class, 'flasher');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register Livewire integration.
|
||||||
|
*
|
||||||
|
* This sets up listeners for Livewire component lifecycle events.
|
||||||
|
*/
|
||||||
private function registerLivewire(): void
|
private function registerLivewire(): void
|
||||||
{
|
{
|
||||||
if (class_exists(LivewireManager::class) && !$this->app->bound('livewire')) {
|
if (class_exists(LivewireManager::class) && !$this->app->bound('livewire')) {
|
||||||
|
|||||||
@@ -8,8 +8,25 @@ use Flasher\Prime\Http\RequestInterface;
|
|||||||
use Illuminate\Contracts\Session\Session;
|
use Illuminate\Contracts\Session\Session;
|
||||||
use Illuminate\Http\Request as LaravelRequest;
|
use Illuminate\Http\Request as LaravelRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request - Adapter for Laravel HTTP requests.
|
||||||
|
*
|
||||||
|
* This adapter implements PHPFlasher's RequestInterface for Laravel HTTP requests,
|
||||||
|
* providing a consistent interface for request inspection and session interaction
|
||||||
|
* regardless of the underlying framework.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Adapter: Adapts framework-specific request objects to PHPFlasher's interface
|
||||||
|
* - Decorator: Adds PHPFlasher-specific functionality to request objects
|
||||||
|
* - Composition: Uses composition to delegate to the underlying request object
|
||||||
|
*/
|
||||||
final readonly class Request implements RequestInterface
|
final readonly class Request implements RequestInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new Request adapter.
|
||||||
|
*
|
||||||
|
* @param LaravelRequest $request The underlying Laravel request object
|
||||||
|
*/
|
||||||
public function __construct(private LaravelRequest $request)
|
public function __construct(private LaravelRequest $request)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -73,6 +90,11 @@ final readonly class Request implements RequestInterface
|
|||||||
$session?->forget($type);
|
$session?->forget($type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the session from the request, with graceful handling of missing sessions.
|
||||||
|
*
|
||||||
|
* @return Session|null The session or null if not available
|
||||||
|
*/
|
||||||
private function getSession(): ?Session
|
private function getSession(): ?Session
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -9,8 +9,25 @@ use Illuminate\Http\Response as LaravelResponse;
|
|||||||
use Symfony\Component\HttpFoundation\JsonResponse as SymfonyJsonResponse;
|
use Symfony\Component\HttpFoundation\JsonResponse as SymfonyJsonResponse;
|
||||||
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
|
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response - Adapter for Laravel/Symfony HTTP responses.
|
||||||
|
*
|
||||||
|
* This adapter implements PHPFlasher's ResponseInterface for Laravel and Symfony
|
||||||
|
* HTTP responses, providing a consistent interface for response manipulation
|
||||||
|
* regardless of the underlying framework.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Adapter: Adapts framework-specific response objects to PHPFlasher's interface
|
||||||
|
* - Decorator: Adds PHPFlasher-specific functionality to response objects
|
||||||
|
* - Composition: Uses composition to delegate to the underlying response object
|
||||||
|
*/
|
||||||
final readonly class Response implements ResponseInterface
|
final readonly class Response implements ResponseInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new Response adapter.
|
||||||
|
*
|
||||||
|
* @param SymfonyResponse $response The underlying Symfony/Laravel response object
|
||||||
|
*/
|
||||||
public function __construct(private SymfonyResponse $response)
|
public function __construct(private SymfonyResponse $response)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -57,6 +74,12 @@ final readonly class Response implements ResponseInterface
|
|||||||
return $this->response->getContent() ?: '';
|
return $this->response->getContent() ?: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* This implementation preserves the original content in Laravel responses,
|
||||||
|
* ensuring compatibility with Laravel's view system and JSON responses.
|
||||||
|
*/
|
||||||
public function setContent(string $content): void
|
public function setContent(string $content): void
|
||||||
{
|
{
|
||||||
$original = null;
|
$original = null;
|
||||||
|
|||||||
@@ -10,12 +10,40 @@ use Flasher\Prime\Http\ResponseExtensionInterface;
|
|||||||
use Illuminate\Http\Request as LaravelRequest;
|
use Illuminate\Http\Request as LaravelRequest;
|
||||||
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
|
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FlasherMiddleware - Middleware for injecting PHPFlasher assets into responses.
|
||||||
|
*
|
||||||
|
* This middleware processes outgoing HTTP responses to inject PHPFlasher's
|
||||||
|
* JavaScript and CSS assets when needed. It's typically added to Laravel's
|
||||||
|
* web middleware group.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Pipeline: Participates in Laravel's middleware pipeline
|
||||||
|
* - Decorator: Decorates HTTP responses with PHPFlasher assets
|
||||||
|
* - Adapter: Adapts Laravel requests/responses to PHPFlasher interfaces
|
||||||
|
*/
|
||||||
final readonly class FlasherMiddleware
|
final readonly class FlasherMiddleware
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new FlasherMiddleware instance.
|
||||||
|
*
|
||||||
|
* @param ResponseExtensionInterface $responseExtension Service for extending responses with notifications
|
||||||
|
*/
|
||||||
public function __construct(private ResponseExtensionInterface $responseExtension)
|
public function __construct(private ResponseExtensionInterface $responseExtension)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* Processes the response after the application has generated it,
|
||||||
|
* injecting PHPFlasher assets and notifications as needed.
|
||||||
|
*
|
||||||
|
* @param LaravelRequest $request The incoming request
|
||||||
|
* @param \Closure $next The next middleware handler
|
||||||
|
*
|
||||||
|
* @return mixed The processed response
|
||||||
|
*/
|
||||||
public function handle(LaravelRequest $request, \Closure $next): mixed
|
public function handle(LaravelRequest $request, \Closure $next): mixed
|
||||||
{
|
{
|
||||||
$response = $next($request);
|
$response = $next($request);
|
||||||
|
|||||||
@@ -10,12 +10,40 @@ use Flasher\Prime\Http\RequestExtensionInterface;
|
|||||||
use Illuminate\Http\Request as LaravelRequest;
|
use Illuminate\Http\Request as LaravelRequest;
|
||||||
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
|
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SessionMiddleware - Middleware for processing session flash messages.
|
||||||
|
*
|
||||||
|
* This middleware processes Laravel's session flash messages and converts them
|
||||||
|
* to PHPFlasher notifications, allowing seamless integration with existing code
|
||||||
|
* that uses Laravel's built-in flash messaging.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Pipeline: Participates in Laravel's middleware pipeline
|
||||||
|
* - Adapter: Adapts Laravel flash messages to PHPFlasher notifications
|
||||||
|
* - Transformer: Transforms one message format to another
|
||||||
|
*/
|
||||||
final readonly class SessionMiddleware
|
final readonly class SessionMiddleware
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new SessionMiddleware instance.
|
||||||
|
*
|
||||||
|
* @param RequestExtensionInterface $requestExtension Service for processing request flash messages
|
||||||
|
*/
|
||||||
public function __construct(private RequestExtensionInterface $requestExtension)
|
public function __construct(private RequestExtensionInterface $requestExtension)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle an incoming request.
|
||||||
|
*
|
||||||
|
* Processes the request and response to convert Laravel flash messages
|
||||||
|
* to PHPFlasher notifications.
|
||||||
|
*
|
||||||
|
* @param LaravelRequest $request The incoming request
|
||||||
|
* @param \Closure $next The next middleware handler
|
||||||
|
*
|
||||||
|
* @return mixed The processed response
|
||||||
|
*/
|
||||||
public function handle(LaravelRequest $request, \Closure $next): mixed
|
public function handle(LaravelRequest $request, \Closure $next): mixed
|
||||||
{
|
{
|
||||||
$response = $next($request);
|
$response = $next($request);
|
||||||
|
|||||||
@@ -2,9 +2,19 @@
|
|||||||
|
|
||||||
namespace Orchestra\Testbench\Concerns;
|
namespace Orchestra\Testbench\Concerns;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ApplicationTestingHooks - PHPStan stub for Orchestra Testbench.
|
||||||
|
*
|
||||||
|
* This stub file enhances PHPStan's static analysis for PHPFlasher by
|
||||||
|
* providing type information for Orchestra Testbench's testing hooks.
|
||||||
|
*
|
||||||
|
* Design pattern: Type Annotation - Provides type information for static analysis
|
||||||
|
*/
|
||||||
trait ApplicationTestingHooks
|
trait ApplicationTestingHooks
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* The Laravel application instance for testing.
|
||||||
|
*
|
||||||
* @var \Illuminate\Foundation\Application
|
* @var \Illuminate\Foundation\Application
|
||||||
*/
|
*/
|
||||||
protected $app;
|
protected $app;
|
||||||
|
|||||||
@@ -5,6 +5,14 @@ declare(strict_types=1);
|
|||||||
namespace Illuminate\Contracts\Config;
|
namespace Illuminate\Contracts\Config;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Repository - PHPStan stub for Laravel's Config Repository.
|
||||||
|
*
|
||||||
|
* This stub file enhances PHPStan's static analysis for PHPFlasher by
|
||||||
|
* providing detailed type information for Laravel's configuration repository,
|
||||||
|
* particularly for PHPFlasher's configuration structure.
|
||||||
|
*
|
||||||
|
* Design pattern: Type Annotation - Provides detailed type information for static analysis
|
||||||
|
*
|
||||||
* @phpstan-type ConfigType array{
|
* @phpstan-type ConfigType array{
|
||||||
* default: string,
|
* default: string,
|
||||||
* main_script: string,
|
* main_script: string,
|
||||||
@@ -36,7 +44,15 @@ namespace Illuminate\Contracts\Config;
|
|||||||
interface Repository
|
interface Repository
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param string[]|string $key
|
* Get a configuration value.
|
||||||
|
*
|
||||||
|
* This stub provides detailed return type information for PHPFlasher's
|
||||||
|
* configuration structure, enabling better static analysis.
|
||||||
|
*
|
||||||
|
* @param string[]|string $key The configuration key
|
||||||
|
* @param mixed $default Default value if key doesn't exist
|
||||||
|
*
|
||||||
|
* @return mixed The configuration value with precise type information for PHPFlasher keys
|
||||||
*
|
*
|
||||||
* @phpstan-return ($key is 'flasher' ? ConfigType :
|
* @phpstan-return ($key is 'flasher' ? ConfigType :
|
||||||
* ($key is 'flasher.default' ? string :
|
* ($key is 'flasher.default' ? string :
|
||||||
|
|||||||
@@ -4,6 +4,15 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
use Flasher\Prime\Configuration;
|
use Flasher\Prime\Configuration;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Default PHPFlasher configuration for Laravel.
|
||||||
|
*
|
||||||
|
* This configuration file defines the default settings for PHPFlasher when
|
||||||
|
* used within a Laravel application. It uses the Configuration class from
|
||||||
|
* the core PHPFlasher library to establish type-safe configuration.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed> PHPFlasher configuration
|
||||||
|
*/
|
||||||
return Configuration::from([
|
return Configuration::from([
|
||||||
// Default notification library (e.g., 'flasher', 'toastr', 'noty', 'notyf', 'sweetalert')
|
// Default notification library (e.g., 'flasher', 'toastr', 'noty', 'notyf', 'sweetalert')
|
||||||
'default' => 'flasher',
|
'default' => 'flasher',
|
||||||
|
|||||||
@@ -8,14 +8,39 @@ use Flasher\Prime\Notification\Envelope;
|
|||||||
use Flasher\Prime\Storage\Bag\BagInterface;
|
use Flasher\Prime\Storage\Bag\BagInterface;
|
||||||
use Illuminate\Session\SessionManager;
|
use Illuminate\Session\SessionManager;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SessionBag - Laravel session storage for PHPFlasher notifications.
|
||||||
|
*
|
||||||
|
* This class implements PHPFlasher's storage interface using Laravel's session
|
||||||
|
* system, providing persistence for notifications across requests.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Adapter: Adapts Laravel's session system to PHPFlasher's storage interface
|
||||||
|
* - Repository: Provides CRUD operations for notification storage
|
||||||
|
*/
|
||||||
final readonly class SessionBag implements BagInterface
|
final readonly class SessionBag implements BagInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Session key for storing notification envelopes.
|
||||||
|
*/
|
||||||
public const ENVELOPES_NAMESPACE = 'flasher::envelopes';
|
public const ENVELOPES_NAMESPACE = 'flasher::envelopes';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new SessionBag instance.
|
||||||
|
*
|
||||||
|
* @param SessionManager $session Laravel's session manager
|
||||||
|
*/
|
||||||
public function __construct(private SessionManager $session)
|
public function __construct(private SessionManager $session)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Retrieves all stored notification envelopes from the session.
|
||||||
|
*
|
||||||
|
* @return Envelope[] The stored notification envelopes
|
||||||
|
*/
|
||||||
public function get(): array
|
public function get(): array
|
||||||
{
|
{
|
||||||
/** @var Envelope[] $envelopes */
|
/** @var Envelope[] $envelopes */
|
||||||
@@ -24,6 +49,13 @@ final readonly class SessionBag implements BagInterface
|
|||||||
return $envelopes;
|
return $envelopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Stores notification envelopes in the session.
|
||||||
|
*
|
||||||
|
* @param Envelope[] $envelopes The notification envelopes to store
|
||||||
|
*/
|
||||||
public function set(array $envelopes): void
|
public function set(array $envelopes): void
|
||||||
{
|
{
|
||||||
$this->session->put(self::ENVELOPES_NAMESPACE, $envelopes);
|
$this->session->put(self::ENVELOPES_NAMESPACE, $envelopes);
|
||||||
|
|||||||
@@ -11,12 +11,44 @@ use Illuminate\Contracts\Foundation\Application;
|
|||||||
use Illuminate\Contracts\Foundation\CachesConfiguration;
|
use Illuminate\Contracts\Foundation\CachesConfiguration;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PluginServiceProvider - Base service provider for PHPFlasher plugins.
|
||||||
|
*
|
||||||
|
* This abstract class provides the foundation for all PHPFlasher plugin
|
||||||
|
* service providers in Laravel. It handles the registration of plugin
|
||||||
|
* configuration, factories, and services.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Template Method: Defines the skeleton of registration process with customizable steps
|
||||||
|
* - Factory: Creates plugin instances via createPlugin method
|
||||||
|
* - Service Provider: Implements Laravel's service provider pattern
|
||||||
|
*
|
||||||
|
* Plugin providers should extend this class and implement the createPlugin method.
|
||||||
|
*/
|
||||||
abstract class PluginServiceProvider extends ServiceProvider
|
abstract class PluginServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The plugin instance.
|
||||||
|
*/
|
||||||
protected PluginInterface $plugin;
|
protected PluginInterface $plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the plugin instance.
|
||||||
|
*
|
||||||
|
* Child classes must implement this method to provide their specific plugin.
|
||||||
|
*
|
||||||
|
* @return PluginInterface The plugin instance
|
||||||
|
*/
|
||||||
abstract public function createPlugin(): PluginInterface;
|
abstract public function createPlugin(): PluginInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register services with the Laravel container.
|
||||||
|
*
|
||||||
|
* This method:
|
||||||
|
* 1. Creates the plugin instance
|
||||||
|
* 2. Registers plugin configuration
|
||||||
|
* 3. Calls the afterRegister hook for customization
|
||||||
|
*/
|
||||||
public function register(): void
|
public function register(): void
|
||||||
{
|
{
|
||||||
$this->plugin = $this->createPlugin();
|
$this->plugin = $this->createPlugin();
|
||||||
@@ -25,17 +57,37 @@ abstract class PluginServiceProvider extends ServiceProvider
|
|||||||
$this->afterRegister();
|
$this->afterRegister();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bootstrap services after all providers are registered.
|
||||||
|
*
|
||||||
|
* This method:
|
||||||
|
* 1. Registers the plugin factory
|
||||||
|
* 2. Calls the afterBoot hook for customization
|
||||||
|
*/
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
$this->registerFactory();
|
$this->registerFactory();
|
||||||
$this->afterBoot();
|
$this->afterBoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the plugin's configuration file path.
|
||||||
|
*
|
||||||
|
* @return string The absolute path to the configuration file
|
||||||
|
*/
|
||||||
public function getConfigurationFile(): string
|
public function getConfigurationFile(): string
|
||||||
{
|
{
|
||||||
return rtrim($this->getResourcesDir(), '/').'/config.php';
|
return rtrim($this->getResourcesDir(), '/').'/config.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a configuration value with optional default.
|
||||||
|
*
|
||||||
|
* @param string|null $key The configuration key to retrieve, or null for all config
|
||||||
|
* @param mixed $default The default value to return if the key doesn't exist
|
||||||
|
*
|
||||||
|
* @return mixed The configuration value
|
||||||
|
*/
|
||||||
protected function getConfig(?string $key = null, mixed $default = null): mixed
|
protected function getConfig(?string $key = null, mixed $default = null): mixed
|
||||||
{
|
{
|
||||||
/** @var Repository $config */
|
/** @var Repository $config */
|
||||||
@@ -44,6 +96,11 @@ abstract class PluginServiceProvider extends ServiceProvider
|
|||||||
return $key ? $config->get('flasher.'.$key, $default) : $config->get('flasher');
|
return $key ? $config->get('flasher.'.$key, $default) : $config->get('flasher');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the plugin's resources directory path.
|
||||||
|
*
|
||||||
|
* @return string The absolute path to the resources directory
|
||||||
|
*/
|
||||||
protected function getResourcesDir(): string
|
protected function getResourcesDir(): string
|
||||||
{
|
{
|
||||||
$r = new \ReflectionClass($this);
|
$r = new \ReflectionClass($this);
|
||||||
@@ -51,6 +108,12 @@ abstract class PluginServiceProvider extends ServiceProvider
|
|||||||
return pathinfo($r->getFileName() ?: '', \PATHINFO_DIRNAME).'/Resources/';
|
return pathinfo($r->getFileName() ?: '', \PATHINFO_DIRNAME).'/Resources/';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the plugin's configuration.
|
||||||
|
*
|
||||||
|
* This method merges the plugin's default configuration with any user-defined
|
||||||
|
* configuration and registers it with Laravel's config repository.
|
||||||
|
*/
|
||||||
protected function registerConfiguration(): void
|
protected function registerConfiguration(): void
|
||||||
{
|
{
|
||||||
if ($this->app instanceof CachesConfiguration && $this->app->configurationIsCached()) {
|
if ($this->app instanceof CachesConfiguration && $this->app->configurationIsCached()) {
|
||||||
@@ -73,14 +136,32 @@ abstract class PluginServiceProvider extends ServiceProvider
|
|||||||
$config->set($key, $this->plugin->normalizeConfig($current));
|
$config->set($key, $this->plugin->normalizeConfig($current));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook method executed after registration.
|
||||||
|
*
|
||||||
|
* Child classes can override this method to add custom registration logic.
|
||||||
|
*/
|
||||||
protected function afterRegister(): void
|
protected function afterRegister(): void
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hook method executed after boot.
|
||||||
|
*
|
||||||
|
* Child classes can override this method to add custom boot logic.
|
||||||
|
*/
|
||||||
protected function afterBoot(): void
|
protected function afterBoot(): void
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register the plugin's notification factory.
|
||||||
|
*
|
||||||
|
* This method:
|
||||||
|
* 1. Registers the factory as a singleton
|
||||||
|
* 2. Registers any aliases for the factory
|
||||||
|
* 3. Adds the factory to the factory locator
|
||||||
|
*/
|
||||||
protected function registerFactory(): void
|
protected function registerFactory(): void
|
||||||
{
|
{
|
||||||
$this->app->singleton($this->plugin->getServiceId(), function (Application $app) {
|
$this->app->singleton($this->plugin->getServiceId(), function (Application $app) {
|
||||||
|
|||||||
@@ -7,12 +7,38 @@ namespace Flasher\Laravel\Template;
|
|||||||
use Flasher\Prime\Template\TemplateEngineInterface;
|
use Flasher\Prime\Template\TemplateEngineInterface;
|
||||||
use Illuminate\View\Factory;
|
use Illuminate\View\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* BladeTemplateEngine - Laravel Blade adapter for PHPFlasher templates.
|
||||||
|
*
|
||||||
|
* This class provides an implementation of PHPFlasher's template engine interface
|
||||||
|
* using Laravel's Blade templating system. It allows PHPFlasher to render templates
|
||||||
|
* using all of Blade's features.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Adapter: Adapts Laravel's Blade engine to PHPFlasher's template interface
|
||||||
|
* - Bridge: Connects PHPFlasher's templating needs with Laravel's templating system
|
||||||
|
*/
|
||||||
final readonly class BladeTemplateEngine implements TemplateEngineInterface
|
final readonly class BladeTemplateEngine implements TemplateEngineInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new BladeTemplateEngine instance.
|
||||||
|
*
|
||||||
|
* @param Factory $blade Laravel's view factory
|
||||||
|
*/
|
||||||
public function __construct(private Factory $blade)
|
public function __construct(private Factory $blade)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Renders a template using Laravel's Blade engine.
|
||||||
|
*
|
||||||
|
* @param string $name The template name or path
|
||||||
|
* @param array<string, mixed> $context The template variables
|
||||||
|
*
|
||||||
|
* @return string The rendered template
|
||||||
|
*/
|
||||||
public function render(string $name, array $context = []): string
|
public function render(string $name, array $context = []): string
|
||||||
{
|
{
|
||||||
return $this->blade->make($name, $context)->render();
|
return $this->blade->make($name, $context)->render();
|
||||||
|
|||||||
@@ -7,12 +7,43 @@ namespace Flasher\Laravel\Translation;
|
|||||||
use Flasher\Prime\Translation\TranslatorInterface;
|
use Flasher\Prime\Translation\TranslatorInterface;
|
||||||
use Illuminate\Translation\Translator as LaravelTranslator;
|
use Illuminate\Translation\Translator as LaravelTranslator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translator - Laravel adapter for PHPFlasher translations.
|
||||||
|
*
|
||||||
|
* This class provides an implementation of PHPFlasher's translator interface
|
||||||
|
* using Laravel's translation system. It enables PHPFlasher notifications
|
||||||
|
* to be localized using Laravel's language files and translation workflow.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Adapter: Adapts Laravel's translator to PHPFlasher's interface
|
||||||
|
* - Decorator: Adds PHPFlasher-specific behavior to Laravel's translator
|
||||||
|
*/
|
||||||
final readonly class Translator implements TranslatorInterface
|
final readonly class Translator implements TranslatorInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new Translator instance.
|
||||||
|
*
|
||||||
|
* @param LaravelTranslator $translator Laravel's translator service
|
||||||
|
*/
|
||||||
public function __construct(private LaravelTranslator $translator)
|
public function __construct(private LaravelTranslator $translator)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Translates a message using Laravel's translation system.
|
||||||
|
* Tries multiple namespaces in this order:
|
||||||
|
* 1. flasher::messages.{id}
|
||||||
|
* 2. messages.{id}
|
||||||
|
* 3. {id} directly
|
||||||
|
*
|
||||||
|
* @param string $id The translation key
|
||||||
|
* @param array<string, mixed> $parameters The parameters for variable substitution
|
||||||
|
* @param string|null $locale The locale to use, or null for default
|
||||||
|
*
|
||||||
|
* @return string The translated string
|
||||||
|
*/
|
||||||
public function translate(string $id, array $parameters = [], ?string $locale = null): string
|
public function translate(string $id, array $parameters = [], ?string $locale = null): string
|
||||||
{
|
{
|
||||||
$parameters = $this->formatParameters($parameters);
|
$parameters = $this->formatParameters($parameters);
|
||||||
@@ -30,6 +61,13 @@ final readonly class Translator implements TranslatorInterface
|
|||||||
return $translation;
|
return $translation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Gets the current locale from Laravel's translator.
|
||||||
|
*
|
||||||
|
* @return string The current locale code
|
||||||
|
*/
|
||||||
public function getLocale(): string
|
public function getLocale(): string
|
||||||
{
|
{
|
||||||
return $this->translator->getLocale();
|
return $this->translator->getLocale();
|
||||||
@@ -38,9 +76,12 @@ final readonly class Translator implements TranslatorInterface
|
|||||||
/**
|
/**
|
||||||
* Formats the parameters by stripping the colon prefix from keys for Laravel's translator.
|
* Formats the parameters by stripping the colon prefix from keys for Laravel's translator.
|
||||||
*
|
*
|
||||||
* @param array<string, mixed> $parameters
|
* This ensures compatibility between PHPFlasher's parameter format (:parameter)
|
||||||
|
* and Laravel's parameter format (parameter).
|
||||||
*
|
*
|
||||||
* @return array<string, mixed>
|
* @param array<string, mixed> $parameters The parameters with potential colon prefixes
|
||||||
|
*
|
||||||
|
* @return array<string, mixed> The formatted parameters
|
||||||
*/
|
*/
|
||||||
private function formatParameters(array $parameters): array
|
private function formatParameters(array $parameters): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,4 +2,16 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Arabic translations for PHPFlasher.
|
||||||
|
*
|
||||||
|
* This file serves as a bridge between Laravel's translation system and
|
||||||
|
* PHPFlasher's core translation repository. It simply returns Arabic
|
||||||
|
* translations from the core Messages class.
|
||||||
|
*
|
||||||
|
* Design pattern: Bridge - Connects Laravel's translation system to PHPFlasher's
|
||||||
|
* centralized message store.
|
||||||
|
*
|
||||||
|
* @return array<string, string> Key-value pairs of message identifiers and translations
|
||||||
|
*/
|
||||||
return Flasher\Prime\Translation\Messages::get('ar');
|
return Flasher\Prime\Translation\Messages::get('ar');
|
||||||
|
|||||||
@@ -2,4 +2,16 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* German translations for PHPFlasher.
|
||||||
|
*
|
||||||
|
* This file serves as a bridge between Laravel's translation system and
|
||||||
|
* PHPFlasher's core translation repository. It simply returns German
|
||||||
|
* translations from the core Messages class.
|
||||||
|
*
|
||||||
|
* Design pattern: Bridge - Connects Laravel's translation system to PHPFlasher's
|
||||||
|
* centralized message store.
|
||||||
|
*
|
||||||
|
* @return array<string, string> Key-value pairs of message identifiers and translations
|
||||||
|
*/
|
||||||
return Flasher\Prime\Translation\Messages::get('de');
|
return Flasher\Prime\Translation\Messages::get('de');
|
||||||
|
|||||||
@@ -2,4 +2,16 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* English translations for PHPFlasher.
|
||||||
|
*
|
||||||
|
* This file serves as a bridge between Laravel's translation system and
|
||||||
|
* PHPFlasher's core translation repository. It simply returns English
|
||||||
|
* translations from the core Messages class.
|
||||||
|
*
|
||||||
|
* Design pattern: Bridge - Connects Laravel's translation system to PHPFlasher's
|
||||||
|
* centralized message store.
|
||||||
|
*
|
||||||
|
* @return array<string, string> Key-value pairs of message identifiers and translations
|
||||||
|
*/
|
||||||
return Flasher\Prime\Translation\Messages::get('en');
|
return Flasher\Prime\Translation\Messages::get('en');
|
||||||
|
|||||||
@@ -2,4 +2,16 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spanish translations for PHPFlasher.
|
||||||
|
*
|
||||||
|
* This file serves as a bridge between Laravel's translation system and
|
||||||
|
* PHPFlasher's core translation repository. It simply returns Spanish
|
||||||
|
* translations from the core Messages class.
|
||||||
|
*
|
||||||
|
* Design pattern: Bridge - Connects Laravel's translation system to PHPFlasher's
|
||||||
|
* centralized message store.
|
||||||
|
*
|
||||||
|
* @return array<string, string> Key-value pairs of message identifiers and translations
|
||||||
|
*/
|
||||||
return Flasher\Prime\Translation\Messages::get('es');
|
return Flasher\Prime\Translation\Messages::get('es');
|
||||||
|
|||||||
@@ -2,4 +2,16 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* French translations for PHPFlasher.
|
||||||
|
*
|
||||||
|
* This file serves as a bridge between Laravel's translation system and
|
||||||
|
* PHPFlasher's core translation repository. It simply returns French
|
||||||
|
* translations from the core Messages class.
|
||||||
|
*
|
||||||
|
* Design pattern: Bridge - Connects Laravel's translation system to PHPFlasher's
|
||||||
|
* centralized message store.
|
||||||
|
*
|
||||||
|
* @return array<string, string> Key-value pairs of message identifiers and translations
|
||||||
|
*/
|
||||||
return Flasher\Prime\Translation\Messages::get('fr');
|
return Flasher\Prime\Translation\Messages::get('fr');
|
||||||
|
|||||||
@@ -2,4 +2,16 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Portuguese translations for PHPFlasher.
|
||||||
|
*
|
||||||
|
* This file serves as a bridge between Laravel's translation system and
|
||||||
|
* PHPFlasher's core translation repository. It simply returns Portuguese
|
||||||
|
* translations from the core Messages class.
|
||||||
|
*
|
||||||
|
* Design pattern: Bridge - Connects Laravel's translation system to PHPFlasher's
|
||||||
|
* centralized message store.
|
||||||
|
*
|
||||||
|
* @return array<string, string> Key-value pairs of message identifiers and translations
|
||||||
|
*/
|
||||||
return Flasher\Prime\Translation\Messages::get('pt');
|
return Flasher\Prime\Translation\Messages::get('pt');
|
||||||
|
|||||||
@@ -2,4 +2,16 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Russian translations for PHPFlasher.
|
||||||
|
*
|
||||||
|
* This file serves as a bridge between Laravel's translation system and
|
||||||
|
* PHPFlasher's core translation repository. It simply returns Russian
|
||||||
|
* translations from the core Messages class.
|
||||||
|
*
|
||||||
|
* Design pattern: Bridge - Connects Laravel's translation system to PHPFlasher's
|
||||||
|
* centralized message store.
|
||||||
|
*
|
||||||
|
* @return array<string, string> Key-value pairs of message identifiers and translations
|
||||||
|
*/
|
||||||
return Flasher\Prime\Translation\Messages::get('ru');
|
return Flasher\Prime\Translation\Messages::get('ru');
|
||||||
|
|||||||
@@ -2,4 +2,16 @@
|
|||||||
|
|
||||||
declare(strict_types=1);
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Chinese translations for PHPFlasher.
|
||||||
|
*
|
||||||
|
* This file serves as a bridge between Laravel's translation system and
|
||||||
|
* PHPFlasher's core translation repository. It simply returns Chinese
|
||||||
|
* translations from the core Messages class.
|
||||||
|
*
|
||||||
|
* Design pattern: Bridge - Connects Laravel's translation system to PHPFlasher's
|
||||||
|
* centralized message store.
|
||||||
|
*
|
||||||
|
* @return array<string, string> Key-value pairs of message identifiers and translations
|
||||||
|
*/
|
||||||
return Flasher\Prime\Translation\Messages::get('zh');
|
return Flasher\Prime\Translation\Messages::get('zh');
|
||||||
|
|||||||
Vendored
-1
@@ -1,2 +1 @@
|
|||||||
github: yoeunes
|
github: yoeunes
|
||||||
custom: https://www.paypal.com/paypalme/yoeunes
|
|
||||||
|
|||||||
@@ -10,6 +10,29 @@ use Flasher\Prime\Stamp\StampInterface;
|
|||||||
use Illuminate\Support\Facades\Facade;
|
use Illuminate\Support\Facades\Facade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Noty - Laravel facade for Noty notifications.
|
||||||
|
*
|
||||||
|
* This facade provides a static interface to Noty's functionality within Laravel,
|
||||||
|
* following Laravel's facade pattern. It offers comprehensive IDE autocompletion
|
||||||
|
* for all Noty builder methods.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Facade: Provides a simplified, static interface to a complex subsystem
|
||||||
|
* - Proxy: Acts as a proxy to the underlying Noty service
|
||||||
|
*
|
||||||
|
* Usage examples:
|
||||||
|
* ```php
|
||||||
|
* // Simple notification
|
||||||
|
* Noty::success('Operation completed successfully');
|
||||||
|
*
|
||||||
|
* // Chained configuration
|
||||||
|
* Noty::layout('topRight')
|
||||||
|
* ->theme('mint')
|
||||||
|
* ->timeout(5000)
|
||||||
|
* ->progressBar(true)
|
||||||
|
* ->success('Record saved');
|
||||||
|
* ```
|
||||||
|
*
|
||||||
* @method static NotyBuilder success(string $message, array<string, mixed> $options = array())
|
* @method static NotyBuilder success(string $message, array<string, mixed> $options = array())
|
||||||
* @method static NotyBuilder error(string $message, array<string, mixed> $options = array())
|
* @method static NotyBuilder error(string $message, array<string, mixed> $options = array())
|
||||||
* @method static NotyBuilder warning(string $message, array<string, mixed> $options = array())
|
* @method static NotyBuilder warning(string $message, array<string, mixed> $options = array())
|
||||||
@@ -48,6 +71,11 @@ use Illuminate\Support\Facades\Facade;
|
|||||||
*/
|
*/
|
||||||
final class Noty extends Facade
|
final class Noty extends Facade
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Get the registered name of the component.
|
||||||
|
*
|
||||||
|
* @return string The service container binding key for Noty
|
||||||
|
*/
|
||||||
protected static function getFacadeAccessor(): string
|
protected static function getFacadeAccessor(): string
|
||||||
{
|
{
|
||||||
return 'flasher.noty';
|
return 'flasher.noty';
|
||||||
|
|||||||
@@ -7,8 +7,24 @@ namespace Flasher\Noty\Laravel;
|
|||||||
use Flasher\Laravel\Support\PluginServiceProvider;
|
use Flasher\Laravel\Support\PluginServiceProvider;
|
||||||
use Flasher\Noty\Prime\NotyPlugin;
|
use Flasher\Noty\Prime\NotyPlugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FlasherNotyServiceProvider - Laravel service provider for Noty integration.
|
||||||
|
*
|
||||||
|
* This service provider registers the Noty plugin with Laravel's service container.
|
||||||
|
* It extends the base plugin service provider to inherit common registration logic
|
||||||
|
* while providing the Noty-specific plugin implementation.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Service Provider: Implements Laravel's service provider pattern
|
||||||
|
* - Factory Method: Creates the plugin instance
|
||||||
|
*/
|
||||||
final class FlasherNotyServiceProvider extends PluginServiceProvider
|
final class FlasherNotyServiceProvider extends PluginServiceProvider
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates the Noty plugin instance.
|
||||||
|
*
|
||||||
|
* @return NotyPlugin The Noty plugin instance
|
||||||
|
*/
|
||||||
public function createPlugin(): NotyPlugin
|
public function createPlugin(): NotyPlugin
|
||||||
{
|
{
|
||||||
return new NotyPlugin();
|
return new NotyPlugin();
|
||||||
|
|||||||
Vendored
-1
@@ -1,2 +1 @@
|
|||||||
github: yoeunes
|
github: yoeunes
|
||||||
custom: https://www.paypal.com/paypalme/yoeunes
|
|
||||||
|
|||||||
@@ -1,10 +1,30 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PhpStorm Meta File - IDE Enhancement for Noty.
|
||||||
|
*
|
||||||
|
* This file provides PhpStorm with additional type information and method completion
|
||||||
|
* capabilities for the Noty library. It's not loaded during runtime but is used
|
||||||
|
* exclusively by the IDE to improve developer experience.
|
||||||
|
*
|
||||||
|
* The file enhances code intelligence in several ways:
|
||||||
|
* 1. Adds expected arguments for Noty functions and methods
|
||||||
|
* 2. Maps factory methods to their return types
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Metadata: Provides additional information about code that's only used by tools
|
||||||
|
* - IDE Integration: Bridges the gap between dynamic PHP code and static analysis tools
|
||||||
|
*
|
||||||
|
* Note: This file is part of the development tooling and has no effect on runtime behavior.
|
||||||
|
*/
|
||||||
|
|
||||||
namespace PHPSTORM_META;
|
namespace PHPSTORM_META;
|
||||||
|
|
||||||
|
// Define expected values for noty function's type parameter
|
||||||
expectedArguments(\noty(), 1, 'success', 'error', 'info', 'warning');
|
expectedArguments(\noty(), 1, 'success', 'error', 'info', 'warning');
|
||||||
expectedArguments(\Flasher\Noty\Prime\noty(), 1, 'success', 'error', 'info', 'warning');
|
expectedArguments(\Flasher\Noty\Prime\noty(), 1, 'success', 'error', 'info', 'warning');
|
||||||
|
|
||||||
|
// Define expected values for various builder methods
|
||||||
expectedArguments(\Flasher\Noty\Prime\NotyBuilder::layout(), 0, 'top', 'topLeft', 'topCenter', 'topRight', 'center', 'centerLeft', 'centerRight', 'bottom', 'bottomLeft', 'bottomCenter', 'bottomRight');
|
expectedArguments(\Flasher\Noty\Prime\NotyBuilder::layout(), 0, 'top', 'topLeft', 'topCenter', 'topRight', 'center', 'centerLeft', 'centerRight', 'bottom', 'bottomLeft', 'bottomCenter', 'bottomRight');
|
||||||
expectedArguments(\Flasher\Noty\Prime\NotyBuilder::theme(), 0, 'relax', 'mint', 'metroui');
|
expectedArguments(\Flasher\Noty\Prime\NotyBuilder::theme(), 0, 'relax', 'mint', 'metroui');
|
||||||
expectedArguments(\Flasher\Noty\Prime\NotyBuilder::timeout(), 0, false, 1000, 3000, 3500, 5000);
|
expectedArguments(\Flasher\Noty\Prime\NotyBuilder::timeout(), 0, false, 1000, 3000, 3500, 5000);
|
||||||
@@ -14,6 +34,7 @@ expectedArguments(\Flasher\Noty\Prime\NotyBuilder::sounds(), 0, 'sources', 'volu
|
|||||||
expectedArguments(\Flasher\Noty\Prime\NotyBuilder::docTitle(), 0, 'conditions');
|
expectedArguments(\Flasher\Noty\Prime\NotyBuilder::docTitle(), 0, 'conditions');
|
||||||
expectedArguments(\Flasher\Noty\Prime\NotyBuilder::queue(), 0, 'global');
|
expectedArguments(\Flasher\Noty\Prime\NotyBuilder::queue(), 0, 'global');
|
||||||
|
|
||||||
|
// Map factory methods to their return types
|
||||||
override(\Flasher\Prime\FlasherInterface::use(), map(['noty' => \Flasher\Noty\Prime\NotyInterface::class]));
|
override(\Flasher\Prime\FlasherInterface::use(), map(['noty' => \Flasher\Noty\Prime\NotyInterface::class]));
|
||||||
override(\Flasher\Prime\FlasherInterface::create(), map(['noty' => \Flasher\Noty\Prime\NotyInterface::class]));
|
override(\Flasher\Prime\FlasherInterface::create(), map(['noty' => \Flasher\Noty\Prime\NotyInterface::class]));
|
||||||
override(\Flasher\Prime\Container\FlasherContainer::create(), map(['flasher.noty' => \Flasher\Noty\Prime\NotyInterface::class]));
|
override(\Flasher\Prime\Container\FlasherContainer::create(), map(['flasher.noty' => \Flasher\Noty\Prime\NotyInterface::class]));
|
||||||
|
|||||||
@@ -7,10 +7,28 @@ namespace Flasher\Noty\Prime;
|
|||||||
use Flasher\Prime\Factory\NotificationFactory;
|
use Flasher\Prime\Factory\NotificationFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Noty - Factory implementation for Noty.js notifications.
|
||||||
|
*
|
||||||
|
* This class implements the notification factory for Noty.js, creating
|
||||||
|
* specialized notification builders configured for Noty's specific features.
|
||||||
|
* It serves as the primary entry point for creating Noty notifications.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Factory: Creates specialized notification builders
|
||||||
|
* - Bridge: Connects PHPFlasher's notification system to Noty.js
|
||||||
|
* - Composition: Delegates to NotyBuilder for construction details
|
||||||
|
*
|
||||||
* @mixin \Flasher\Noty\Prime\NotyBuilder
|
* @mixin \Flasher\Noty\Prime\NotyBuilder
|
||||||
*/
|
*/
|
||||||
final class Noty extends NotificationFactory implements NotyInterface
|
final class Noty extends NotificationFactory implements NotyInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Creates a new Noty-specific notification builder.
|
||||||
|
*
|
||||||
|
* @return NotyBuilder A builder configured for Noty.js notifications
|
||||||
|
*/
|
||||||
public function createNotificationBuilder(): NotyBuilder
|
public function createNotificationBuilder(): NotyBuilder
|
||||||
{
|
{
|
||||||
return new NotyBuilder('noty', $this->storageManager);
|
return new NotyBuilder('noty', $this->storageManager);
|
||||||
|
|||||||
+195
-25
@@ -8,6 +8,17 @@ use Flasher\Prime\Notification\Envelope;
|
|||||||
use Flasher\Prime\Notification\NotificationBuilder;
|
use Flasher\Prime\Notification\NotificationBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* NotyBuilder - Builder implementation for Noty.js notifications.
|
||||||
|
*
|
||||||
|
* This class provides a fluent interface for configuring Noty.js notifications.
|
||||||
|
* It extends the core notification builder with Noty-specific options and
|
||||||
|
* features, such as layout, theme, animation, and more.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Builder: Provides a fluent interface for constructing complex objects
|
||||||
|
* - Fluent Interface: Methods return $this for method chaining
|
||||||
|
* - Type Safety: Uses PHPStan annotations for compile-time type checking
|
||||||
|
*
|
||||||
* @phpstan-type NotificationType "success"|"info"|"warning"|"error"|"alert"|"information"
|
* @phpstan-type NotificationType "success"|"info"|"warning"|"error"|"alert"|"information"
|
||||||
* @phpstan-type OptionsType array{
|
* @phpstan-type OptionsType array{
|
||||||
* layout?: "top"|"topLeft"|"topCenter"|"topRight"|"center"|"centerLeft"|"centerRight"|"bottom"|"bottomLeft"|"bottomCenter"|"bottomRight",
|
* layout?: "top"|"topLeft"|"topCenter"|"topRight"|"center"|"centerLeft"|"centerRight"|"bottom"|"bottomLeft"|"bottomCenter"|"bottomRight",
|
||||||
@@ -40,7 +51,11 @@ use Flasher\Prime\Notification\NotificationBuilder;
|
|||||||
final class NotyBuilder extends NotificationBuilder
|
final class NotyBuilder extends NotificationBuilder
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @phpstan-param NotificationType $type
|
* Sets the notification type with Noty-specific type checking.
|
||||||
|
*
|
||||||
|
* @phpstan-param NotificationType $type The notification type
|
||||||
|
*
|
||||||
|
* @return static The builder instance
|
||||||
*/
|
*/
|
||||||
public function type(string $type): static
|
public function type(string $type): static
|
||||||
{
|
{
|
||||||
@@ -48,7 +63,13 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param OptionsType $options
|
* Creates a success notification with Noty-specific options.
|
||||||
|
*
|
||||||
|
* @param string $message The notification message
|
||||||
|
* @param OptionsType $options Noty-specific options
|
||||||
|
* @param string|null $title The notification title
|
||||||
|
*
|
||||||
|
* @return Envelope The notification envelope
|
||||||
*/
|
*/
|
||||||
public function success(string $message, array $options = [], ?string $title = null): Envelope
|
public function success(string $message, array $options = [], ?string $title = null): Envelope
|
||||||
{
|
{
|
||||||
@@ -56,7 +77,13 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param OptionsType $options
|
* Creates an error notification with Noty-specific options.
|
||||||
|
*
|
||||||
|
* @param string $message The notification message
|
||||||
|
* @param OptionsType $options Noty-specific options
|
||||||
|
* @param string|null $title The notification title
|
||||||
|
*
|
||||||
|
* @return Envelope The notification envelope
|
||||||
*/
|
*/
|
||||||
public function error(string $message, array $options = [], ?string $title = null): Envelope
|
public function error(string $message, array $options = [], ?string $title = null): Envelope
|
||||||
{
|
{
|
||||||
@@ -64,7 +91,13 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param OptionsType $options
|
* Creates an info notification with Noty-specific options.
|
||||||
|
*
|
||||||
|
* @param string $message The notification message
|
||||||
|
* @param OptionsType $options Noty-specific options
|
||||||
|
* @param string|null $title The notification title
|
||||||
|
*
|
||||||
|
* @return Envelope The notification envelope
|
||||||
*/
|
*/
|
||||||
public function info(string $message, array $options = [], ?string $title = null): Envelope
|
public function info(string $message, array $options = [], ?string $title = null): Envelope
|
||||||
{
|
{
|
||||||
@@ -72,7 +105,13 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param OptionsType $options
|
* Creates a warning notification with Noty-specific options.
|
||||||
|
*
|
||||||
|
* @param string $message The notification message
|
||||||
|
* @param OptionsType $options Noty-specific options
|
||||||
|
* @param string|null $title The notification title
|
||||||
|
*
|
||||||
|
* @return Envelope The notification envelope
|
||||||
*/
|
*/
|
||||||
public function warning(string $message, array $options = [], ?string $title = null): Envelope
|
public function warning(string $message, array $options = [], ?string $title = null): Envelope
|
||||||
{
|
{
|
||||||
@@ -80,8 +119,17 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @phpstan-param NotificationType $type
|
* Creates a notification of the specified type with Noty-specific options.
|
||||||
* @phpstan-param OptionsType $options
|
*
|
||||||
|
* @phpstan-param NotificationType|null $type The notification type
|
||||||
|
* @phpstan-param OptionsType $options Noty-specific options
|
||||||
|
*
|
||||||
|
* @param string|null $type The notification type
|
||||||
|
* @param string|null $message The notification message
|
||||||
|
* @param array $options Noty-specific options
|
||||||
|
* @param string|null $title The notification title
|
||||||
|
*
|
||||||
|
* @return Envelope The notification envelope
|
||||||
*/
|
*/
|
||||||
public function flash(?string $type = null, ?string $message = null, array $options = [], ?string $title = null): Envelope
|
public function flash(?string $type = null, ?string $message = null, array $options = [], ?string $title = null): Envelope
|
||||||
{
|
{
|
||||||
@@ -89,7 +137,12 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param OptionsType $options
|
* Sets notification options with Noty-specific type checking.
|
||||||
|
*
|
||||||
|
* @param OptionsType $options The notification options
|
||||||
|
* @param bool $append Whether to append or replace existing options
|
||||||
|
*
|
||||||
|
* @return static The builder instance
|
||||||
*/
|
*/
|
||||||
public function options(array $options, bool $append = true): static
|
public function options(array $options, bool $append = true): static
|
||||||
{
|
{
|
||||||
@@ -97,11 +150,18 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets a specific notification option with Noty-specific type checking.
|
||||||
|
*
|
||||||
* @template T of OptionsType
|
* @template T of OptionsType
|
||||||
* @template K of key-of<T>
|
* @template K of key-of<T>
|
||||||
*
|
*
|
||||||
* @phpstan-param K $name
|
* @phpstan-param K $name
|
||||||
* @phpstan-param T[K] $value
|
* @phpstan-param T[K] $value
|
||||||
|
*
|
||||||
|
* @param string $name The option name
|
||||||
|
* @param mixed $value The option value
|
||||||
|
*
|
||||||
|
* @return static The builder instance
|
||||||
*/
|
*/
|
||||||
public function option(string $name, mixed $value): static
|
public function option(string $name, mixed $value): static
|
||||||
{
|
{
|
||||||
@@ -109,7 +169,13 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets the notification text (alias for message).
|
||||||
|
*
|
||||||
* This string can contain HTML too. But be careful and don't pass user inputs to this parameter.
|
* This string can contain HTML too. But be careful and don't pass user inputs to this parameter.
|
||||||
|
*
|
||||||
|
* @param string $text The notification text
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function text(string $text): self
|
public function text(string $text): self
|
||||||
{
|
{
|
||||||
@@ -117,7 +183,13 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param OptionsType $options
|
* Creates an alert notification.
|
||||||
|
*
|
||||||
|
* @param string|null $message The notification message
|
||||||
|
* @param string|null $title The notification title
|
||||||
|
* @param OptionsType $options Noty-specific options
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function alert(?string $message = null, ?string $title = null, array $options = []): self
|
public function alert(?string $message = null, ?string $title = null, array $options = []): self
|
||||||
{
|
{
|
||||||
@@ -139,9 +211,15 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @phpstan-param OptionsType['layout'] $layout
|
* Sets the notification layout.
|
||||||
|
*
|
||||||
|
* @phpstan-param OptionsType['layout'] $layout The layout position
|
||||||
*
|
*
|
||||||
* - ClassName generator uses this value → noty_layout__${layout}
|
* - ClassName generator uses this value → noty_layout__${layout}
|
||||||
|
*
|
||||||
|
* @param string $layout The layout position
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function layout(string $layout): self
|
public function layout(string $layout): self
|
||||||
{
|
{
|
||||||
@@ -151,9 +229,15 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @phpstan-param OptionsType['theme'] $theme
|
* Sets the notification theme.
|
||||||
|
*
|
||||||
|
* @phpstan-param OptionsType['theme'] $theme The theme name
|
||||||
*
|
*
|
||||||
* ClassName generator uses this value → noty_theme__${theme}
|
* ClassName generator uses this value → noty_theme__${theme}
|
||||||
|
*
|
||||||
|
* @param string $theme The theme name
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function theme(string $theme): self
|
public function theme(string $theme): self
|
||||||
{
|
{
|
||||||
@@ -163,7 +247,14 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* false, 1000, 3000, 3500, etc. Delay for closing event in milliseconds (ms). Set 'false' for sticky notifications.
|
* Sets the notification timeout.
|
||||||
|
*
|
||||||
|
* false, 1000, 3000, 3500, etc. Delay for closing event in milliseconds (ms).
|
||||||
|
* Set 'false' for sticky notifications.
|
||||||
|
*
|
||||||
|
* @param false|int $timeout The timeout in milliseconds or false for sticky
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function timeout(false|int $timeout): self
|
public function timeout(false|int $timeout): self
|
||||||
{
|
{
|
||||||
@@ -173,7 +264,13 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets whether to display a progress bar.
|
||||||
|
*
|
||||||
* true, false - Displays a progress bar if timeout is not false.
|
* true, false - Displays a progress bar if timeout is not false.
|
||||||
|
*
|
||||||
|
* @param bool $progressBar Whether to display a progress bar
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function progressBar(bool $progressBar = false): self
|
public function progressBar(bool $progressBar = false): self
|
||||||
{
|
{
|
||||||
@@ -183,9 +280,13 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets how the notification can be closed.
|
||||||
|
*
|
||||||
* click, button.
|
* click, button.
|
||||||
*
|
*
|
||||||
* @param string|string[] $closeWith
|
* @param string|string[] $closeWith Close methods
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function closeWith(string|array $closeWith): self
|
public function closeWith(string|array $closeWith): self
|
||||||
{
|
{
|
||||||
@@ -195,11 +296,16 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param "open"|"close" $option
|
* Sets animation effects for opening or closing.
|
||||||
* @param "noty_effects_open"|"noty_effects_close"|string $effect
|
|
||||||
*
|
*
|
||||||
* If string, assumed to be CSS class name. If null, no animation at all. If function, runs the function. (v3.0.1+)
|
* @param "open"|"close" $option Which animation to set
|
||||||
|
* @param "noty_effects_open"|"noty_effects_close"|string $effect The animation effect
|
||||||
|
*
|
||||||
|
* If string, assumed to be CSS class name. If null, no animation at all.
|
||||||
|
* If function, runs the function. (v3.0.1+)
|
||||||
* You can use animate.css class names or your custom css animations as well.
|
* You can use animate.css class names or your custom css animations as well.
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function animation(string $option, string $effect): self
|
public function animation(string $option, string $effect): self
|
||||||
{
|
{
|
||||||
@@ -213,11 +319,18 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @phpstan-param "sources"|"volume"|"conditions" $option
|
* Sets sound options for the notification.
|
||||||
|
*
|
||||||
|
* @phpstan-param "sources"|"volume"|"conditions" $option The sound option to set
|
||||||
* @phpstan-param ($option is "sources" ? string[] :
|
* @phpstan-param ($option is "sources" ? string[] :
|
||||||
* ($option is "volume" ? int :
|
* ($option is "volume" ? int :
|
||||||
* ($option is "conditions" ? string[] :
|
* ($option is "conditions" ? string[] :
|
||||||
* mixed))) $value
|
* mixed))) $value The option value
|
||||||
|
*
|
||||||
|
* @param string $option The sound option to set
|
||||||
|
* @param mixed $value The option value
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function sounds(string $option, mixed $value): self
|
public function sounds(string $option, mixed $value): self
|
||||||
{
|
{
|
||||||
@@ -231,8 +344,15 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @phpstan-param "conditions"|string $option
|
* Sets document title options for the notification.
|
||||||
* @phpstan-param ($option is "conditions" ? string[] : mixed) $value
|
*
|
||||||
|
* @phpstan-param "conditions"|string $option The document title option
|
||||||
|
* @phpstan-param ($option is "conditions" ? string[] : mixed) $value The option value
|
||||||
|
*
|
||||||
|
* @param string $option The document title option
|
||||||
|
* @param mixed $value The option value
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function docTitle(string $option, mixed $value): self
|
public function docTitle(string $option, mixed $value): self
|
||||||
{
|
{
|
||||||
@@ -245,6 +365,13 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets whether the notification is modal.
|
||||||
|
*
|
||||||
|
* @param bool $modal Whether the notification is modal
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
|
*/
|
||||||
public function modal(bool $modal = true): self
|
public function modal(bool $modal = true): self
|
||||||
{
|
{
|
||||||
$this->option('modal', $modal);
|
$this->option('modal', $modal);
|
||||||
@@ -253,7 +380,13 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets the notification ID.
|
||||||
|
*
|
||||||
* You can use this id with querySelectors. Generated automatically if false.
|
* You can use this id with querySelectors. Generated automatically if false.
|
||||||
|
*
|
||||||
|
* @param bool|string $id The notification ID or false to generate automatically
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function id(bool|string $id): self
|
public function id(bool|string $id): self
|
||||||
{
|
{
|
||||||
@@ -263,7 +396,13 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets whether to force the notification.
|
||||||
|
*
|
||||||
* DOM insert method depends on this parameter. If false uses append, if true uses prepend.
|
* DOM insert method depends on this parameter. If false uses append, if true uses prepend.
|
||||||
|
*
|
||||||
|
* @param bool $force Whether to force the notification
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function force(bool $force = true): self
|
public function force(bool $force = true): self
|
||||||
{
|
{
|
||||||
@@ -272,6 +411,13 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the notification queue.
|
||||||
|
*
|
||||||
|
* @param string $queue The queue name
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
|
*/
|
||||||
public function queue(string $queue): self
|
public function queue(string $queue): self
|
||||||
{
|
{
|
||||||
$this->option('queue', $queue);
|
$this->option('queue', $queue);
|
||||||
@@ -280,8 +426,14 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true closes all visible notifications and shows itself. If string(queueName) closes all visible notification
|
* Sets whether the notification kills other notifications.
|
||||||
* on this queue and shows itself.
|
*
|
||||||
|
* If true closes all visible notifications and shows itself.
|
||||||
|
* If string(queueName) closes all visible notification on this queue and shows itself.
|
||||||
|
*
|
||||||
|
* @param bool|string $killer Whether to kill other notifications
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function killer(bool|string $killer): self
|
public function killer(bool|string $killer): self
|
||||||
{
|
{
|
||||||
@@ -291,7 +443,14 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom container selector string. Like '.my-custom-container'. Layout parameter will be ignored.
|
* Sets the notification container.
|
||||||
|
*
|
||||||
|
* Custom container selector string. Like '.my-custom-container'.
|
||||||
|
* Layout parameter will be ignored.
|
||||||
|
*
|
||||||
|
* @param false|string $container The container selector or false to use default
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function container(false|string $container): self
|
public function container(false|string $container): self
|
||||||
{
|
{
|
||||||
@@ -301,9 +460,13 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets the notification buttons.
|
||||||
|
*
|
||||||
* An array of Noty.button, for creating confirmation dialogs.
|
* An array of Noty.button, for creating confirmation dialogs.
|
||||||
*
|
*
|
||||||
* @param string[] $buttons
|
* @param string[] $buttons The buttons configuration
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function buttons(array $buttons): self
|
public function buttons(array $buttons): self
|
||||||
{
|
{
|
||||||
@@ -313,7 +476,14 @@ final class NotyBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If true Noty uses PageVisibility API to handle timeout. To ensure that users do not miss their notifications.
|
* Sets whether to use visibility control.
|
||||||
|
*
|
||||||
|
* If true Noty uses PageVisibility API to handle timeout.
|
||||||
|
* To ensure that users do not miss their notifications.
|
||||||
|
*
|
||||||
|
* @param bool $visibilityControl Whether to use visibility control
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function visibilityControl(bool $visibilityControl): self
|
public function visibilityControl(bool $visibilityControl): self
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,6 +7,17 @@ namespace Flasher\Noty\Prime;
|
|||||||
use Flasher\Prime\Factory\NotificationFactoryInterface;
|
use Flasher\Prime\Factory\NotificationFactoryInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* NotyInterface - Contract for Noty notification factories.
|
||||||
|
*
|
||||||
|
* This interface defines the contract for Noty notification factories.
|
||||||
|
* It extends the core notification factory interface to ensure compatibility
|
||||||
|
* with PHPFlasher's notification system, while allowing IDE completion for
|
||||||
|
* Noty-specific methods through the mixin annotation.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Interface Segregation: Provides a specific interface for Noty functionality
|
||||||
|
* - Contract: Defines a contract for creating Noty notifications
|
||||||
|
*
|
||||||
* @mixin \Flasher\Noty\Prime\NotyBuilder
|
* @mixin \Flasher\Noty\Prime\NotyBuilder
|
||||||
*/
|
*/
|
||||||
interface NotyInterface extends NotificationFactoryInterface
|
interface NotyInterface extends NotificationFactoryInterface
|
||||||
|
|||||||
@@ -6,25 +6,56 @@ namespace Flasher\Noty\Prime;
|
|||||||
|
|
||||||
use Flasher\Prime\Plugin\Plugin;
|
use Flasher\Prime\Plugin\Plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NotyPlugin - Plugin definition for Noty.js integration with PHPFlasher.
|
||||||
|
*
|
||||||
|
* This class defines the core plugin configuration for the Noty.js notification
|
||||||
|
* library integration. It specifies the required JavaScript and CSS assets,
|
||||||
|
* factory class, and service identifiers for dependency injection containers.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Plugin: Implements the plugin pattern for extending core functionality
|
||||||
|
* - Registry: Registers the plugin's assets and identifiers with the core system
|
||||||
|
* - Metadata: Provides metadata about the plugin's requirements
|
||||||
|
*/
|
||||||
final class NotyPlugin extends Plugin
|
final class NotyPlugin extends Plugin
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Returns the plugin's unique identifier.
|
||||||
|
*/
|
||||||
public function getAlias(): string
|
public function getAlias(): string
|
||||||
{
|
{
|
||||||
return 'noty';
|
return 'noty';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Returns the factory class responsible for creating Noty notifications.
|
||||||
|
*/
|
||||||
public function getFactory(): string
|
public function getFactory(): string
|
||||||
{
|
{
|
||||||
return Noty::class;
|
return Noty::class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Returns the service alias for dependency injection containers.
|
||||||
|
*/
|
||||||
public function getServiceAliases(): string
|
public function getServiceAliases(): string
|
||||||
{
|
{
|
||||||
return NotyInterface::class;
|
return NotyInterface::class;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string[]
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Returns the required JavaScript files for Noty.js integration.
|
||||||
|
*
|
||||||
|
* @return string[] Array of script paths
|
||||||
*/
|
*/
|
||||||
public function getScripts(): array
|
public function getScripts(): array
|
||||||
{
|
{
|
||||||
@@ -35,7 +66,11 @@ final class NotyPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string[]
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Returns the required CSS files for Noty.js styling.
|
||||||
|
*
|
||||||
|
* @return string[] Array of stylesheet paths
|
||||||
*/
|
*/
|
||||||
public function getStyles(): array
|
public function getStyles(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,15 @@ use Flasher\Prime\Container\FlasherContainer;
|
|||||||
use Flasher\Prime\Notification\Envelope;
|
use Flasher\Prime\Notification\Envelope;
|
||||||
use Flasher\Prime\Notification\Type;
|
use Flasher\Prime\Notification\Type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Namespace-specific helper functions for Noty notifications.
|
||||||
|
*
|
||||||
|
* This file provides a namespace-specific helper function that simplifies
|
||||||
|
* the creation of Noty notifications from code that uses imports.
|
||||||
|
*
|
||||||
|
* Design pattern: Facade - Provides a simplified interface to a complex subsystem
|
||||||
|
*/
|
||||||
|
|
||||||
if (!\function_exists('Flasher\Noty\Prime\noty')) {
|
if (!\function_exists('Flasher\Noty\Prime\noty')) {
|
||||||
/**
|
/**
|
||||||
* Creates a Noty notification or returns the Noty factory.
|
* Creates a Noty notification or returns the Noty factory.
|
||||||
|
|||||||
@@ -7,6 +7,15 @@ use Flasher\Prime\Container\FlasherContainer;
|
|||||||
use Flasher\Prime\Notification\Envelope;
|
use Flasher\Prime\Notification\Envelope;
|
||||||
use Flasher\Prime\Notification\Type;
|
use Flasher\Prime\Notification\Type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global helper functions for Noty notifications.
|
||||||
|
*
|
||||||
|
* This file provides a global helper function that simplifies
|
||||||
|
* the creation of Noty notifications from any PHP code.
|
||||||
|
*
|
||||||
|
* Design pattern: Facade - Provides a simplified interface to a complex subsystem
|
||||||
|
*/
|
||||||
|
|
||||||
if (!function_exists('noty')) {
|
if (!function_exists('noty')) {
|
||||||
/**
|
/**
|
||||||
* Creates a Noty notification or returns the Noty factory.
|
* Creates a Noty notification or returns the Noty factory.
|
||||||
|
|||||||
Vendored
-1
@@ -1,2 +1 @@
|
|||||||
github: yoeunes
|
github: yoeunes
|
||||||
custom: https://www.paypal.com/paypalme/yoeunes
|
|
||||||
|
|||||||
@@ -8,8 +8,24 @@ use Flasher\Noty\Prime\NotyPlugin;
|
|||||||
use Flasher\Prime\Plugin\PluginInterface;
|
use Flasher\Prime\Plugin\PluginInterface;
|
||||||
use Flasher\Symfony\Support\PluginBundle;
|
use Flasher\Symfony\Support\PluginBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FlasherNotySymfonyBundle - Symfony bundle for Noty integration.
|
||||||
|
*
|
||||||
|
* This bundle registers the Noty plugin with Symfony's service container.
|
||||||
|
* It extends the base plugin bundle to inherit common registration logic
|
||||||
|
* while providing the Noty-specific plugin implementation.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Bundle: Implements Symfony's bundle pattern for packaging functionality
|
||||||
|
* - Factory Method: Creates the plugin instance
|
||||||
|
*/
|
||||||
final class FlasherNotySymfonyBundle extends PluginBundle // Symfony\Component\HttpKernel\Bundle\Bundle
|
final class FlasherNotySymfonyBundle extends PluginBundle // Symfony\Component\HttpKernel\Bundle\Bundle
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates the Noty plugin instance.
|
||||||
|
*
|
||||||
|
* @return PluginInterface The Noty plugin instance
|
||||||
|
*/
|
||||||
public function createPlugin(): PluginInterface
|
public function createPlugin(): PluginInterface
|
||||||
{
|
{
|
||||||
return new NotyPlugin();
|
return new NotyPlugin();
|
||||||
|
|||||||
-1
@@ -1,2 +1 @@
|
|||||||
github: yoeunes
|
github: yoeunes
|
||||||
custom: https://www.paypal.com/paypalme/yoeunes
|
|
||||||
|
|||||||
@@ -10,6 +10,29 @@ use Flasher\Prime\Stamp\StampInterface;
|
|||||||
use Illuminate\Support\Facades\Facade;
|
use Illuminate\Support\Facades\Facade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Notyf - Laravel facade for Notyf notifications.
|
||||||
|
*
|
||||||
|
* This facade provides a static interface to Notyf's functionality within Laravel,
|
||||||
|
* following Laravel's facade pattern. It offers comprehensive IDE autocompletion
|
||||||
|
* for all Notyf builder methods.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Facade: Provides a simplified, static interface to a complex subsystem
|
||||||
|
* - Proxy: Acts as a proxy to the underlying Notyf service
|
||||||
|
*
|
||||||
|
* Usage examples:
|
||||||
|
* ```php
|
||||||
|
* // Simple notification
|
||||||
|
* Notyf::success('Operation completed successfully');
|
||||||
|
*
|
||||||
|
* // Chained configuration
|
||||||
|
* Notyf::duration(3000)
|
||||||
|
* ->dismissible(true)
|
||||||
|
* ->position('x', 'right')
|
||||||
|
* ->position('y', 'top')
|
||||||
|
* ->success('Record saved');
|
||||||
|
* ```
|
||||||
|
*
|
||||||
* @method static NotyfBuilder success(string $message, array<string, mixed> $options = array())
|
* @method static NotyfBuilder success(string $message, array<string, mixed> $options = array())
|
||||||
* @method static NotyfBuilder error(string $message, array<string, mixed> $options = array())
|
* @method static NotyfBuilder error(string $message, array<string, mixed> $options = array())
|
||||||
* @method static NotyfBuilder warning(string $message, array<string, mixed> $options = array())
|
* @method static NotyfBuilder warning(string $message, array<string, mixed> $options = array())
|
||||||
@@ -34,6 +57,11 @@ use Illuminate\Support\Facades\Facade;
|
|||||||
*/
|
*/
|
||||||
final class Notyf extends Facade
|
final class Notyf extends Facade
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Get the registered name of the component.
|
||||||
|
*
|
||||||
|
* @return string The service container binding key for Notyf
|
||||||
|
*/
|
||||||
protected static function getFacadeAccessor(): string
|
protected static function getFacadeAccessor(): string
|
||||||
{
|
{
|
||||||
return 'flasher.notyf';
|
return 'flasher.notyf';
|
||||||
|
|||||||
@@ -7,8 +7,24 @@ namespace Flasher\Notyf\Laravel;
|
|||||||
use Flasher\Laravel\Support\PluginServiceProvider;
|
use Flasher\Laravel\Support\PluginServiceProvider;
|
||||||
use Flasher\Notyf\Prime\NotyfPlugin;
|
use Flasher\Notyf\Prime\NotyfPlugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FlasherNotyfServiceProvider - Laravel service provider for Notyf integration.
|
||||||
|
*
|
||||||
|
* This service provider registers the Notyf plugin with Laravel's service container.
|
||||||
|
* It extends the base plugin service provider to inherit common registration logic
|
||||||
|
* while providing the Notyf-specific plugin implementation.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Service Provider: Implements Laravel's service provider pattern
|
||||||
|
* - Factory Method: Creates the plugin instance
|
||||||
|
*/
|
||||||
final class FlasherNotyfServiceProvider extends PluginServiceProvider
|
final class FlasherNotyfServiceProvider extends PluginServiceProvider
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates the Notyf plugin instance.
|
||||||
|
*
|
||||||
|
* @return NotyfPlugin The Notyf plugin instance
|
||||||
|
*/
|
||||||
public function createPlugin(): NotyfPlugin
|
public function createPlugin(): NotyfPlugin
|
||||||
{
|
{
|
||||||
return new NotyfPlugin();
|
return new NotyfPlugin();
|
||||||
|
|||||||
Vendored
-1
@@ -1,2 +1 @@
|
|||||||
github: yoeunes
|
github: yoeunes
|
||||||
custom: https://www.paypal.com/paypalme/yoeunes
|
|
||||||
|
|||||||
@@ -1,15 +1,35 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PhpStorm Meta File - IDE Enhancement for Notyf.
|
||||||
|
*
|
||||||
|
* This file provides PhpStorm with additional type information and method completion
|
||||||
|
* capabilities for the Notyf library. It's not loaded during runtime but is used
|
||||||
|
* exclusively by the IDE to improve developer experience.
|
||||||
|
*
|
||||||
|
* The file enhances code intelligence in several ways:
|
||||||
|
* 1. Adds expected arguments for Notyf functions and methods
|
||||||
|
* 2. Maps factory methods to their return types
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Metadata: Provides additional information about code that's only used by tools
|
||||||
|
* - IDE Integration: Bridges the gap between dynamic PHP code and static analysis tools
|
||||||
|
*
|
||||||
|
* Note: This file is part of the development tooling and has no effect on runtime behavior.
|
||||||
|
*/
|
||||||
|
|
||||||
namespace PHPSTORM_META;
|
namespace PHPSTORM_META;
|
||||||
|
|
||||||
|
// Define expected values for notyf function's type parameter
|
||||||
expectedArguments(\notyf(), 1, 'success', 'error', 'info', 'warning');
|
expectedArguments(\notyf(), 1, 'success', 'error', 'info', 'warning');
|
||||||
expectedArguments(\Flasher\Notyf\Prime\notyf(), 1, 'success', 'error', 'info', 'warning');
|
expectedArguments(\Flasher\Notyf\Prime\notyf(), 1, 'success', 'error', 'info', 'warning');
|
||||||
|
|
||||||
|
// Define expected values for various builder methods
|
||||||
expectedArguments(\Flasher\Notyf\Prime\NotyfBuilder::duration(), 0, 1000, 2000, 3000, 4000, 5000);
|
expectedArguments(\Flasher\Notyf\Prime\NotyfBuilder::duration(), 0, 1000, 2000, 3000, 4000, 5000);
|
||||||
expectedArguments(\Flasher\Notyf\Prime\NotyfBuilder::position(), 0, 'x', 'y');
|
expectedArguments(\Flasher\Notyf\Prime\NotyfBuilder::position(), 0, 'x', 'y');
|
||||||
expectedArguments(\Flasher\Notyf\Prime\NotyfBuilder::position(), 1, 'top', 'right', 'bottom', 'left', 'center');
|
expectedArguments(\Flasher\Notyf\Prime\NotyfBuilder::position(), 1, 'top', 'right', 'bottom', 'left', 'center');
|
||||||
|
|
||||||
|
// Map factory methods to their return types
|
||||||
override(\Flasher\Prime\FlasherInterface::use(), map(['notyf' => \Flasher\Notyf\Prime\NotyfInterface::class]));
|
override(\Flasher\Prime\FlasherInterface::use(), map(['notyf' => \Flasher\Notyf\Prime\NotyfInterface::class]));
|
||||||
override(\Flasher\Prime\FlasherInterface::create(), map(['notyf' => \Flasher\Notyf\Prime\NotyfInterface::class]));
|
override(\Flasher\Prime\FlasherInterface::create(), map(['notyf' => \Flasher\Notyf\Prime\NotyfInterface::class]));
|
||||||
override(\Flasher\Prime\Container\FlasherContainer::create(), map(['flasher.notyf' => \Notyf\Notyf\Prime\NotyfInterface::class]));
|
override(\Flasher\Prime\Container\FlasherContainer::create(), map(['flasher.notyf' => \Notyf\Notyf\Prime\NotyfInterface::class]));
|
||||||
|
|
||||||
|
|||||||
@@ -7,10 +7,28 @@ namespace Flasher\Notyf\Prime;
|
|||||||
use Flasher\Prime\Factory\NotificationFactory;
|
use Flasher\Prime\Factory\NotificationFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Notyf - Factory implementation for Notyf.js notifications.
|
||||||
|
*
|
||||||
|
* This class implements the notification factory for Notyf.js, creating
|
||||||
|
* specialized notification builders configured for Notyf's specific features.
|
||||||
|
* It serves as the primary entry point for creating Notyf notifications.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Factory: Creates specialized notification builders
|
||||||
|
* - Bridge: Connects PHPFlasher's notification system to Notyf.js
|
||||||
|
* - Composition: Delegates to NotyfBuilder for construction details
|
||||||
|
*
|
||||||
* @mixin \Flasher\Notyf\Prime\NotyfBuilder
|
* @mixin \Flasher\Notyf\Prime\NotyfBuilder
|
||||||
*/
|
*/
|
||||||
final class Notyf extends NotificationFactory implements NotyfInterface
|
final class Notyf extends NotificationFactory implements NotyfInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Creates a new Notyf-specific notification builder.
|
||||||
|
*
|
||||||
|
* @return NotyfBuilder A builder configured for Notyf.js notifications
|
||||||
|
*/
|
||||||
public function createNotificationBuilder(): NotyfBuilder
|
public function createNotificationBuilder(): NotyfBuilder
|
||||||
{
|
{
|
||||||
return new NotyfBuilder('notyf', $this->storageManager);
|
return new NotyfBuilder('notyf', $this->storageManager);
|
||||||
|
|||||||
@@ -7,6 +7,18 @@ namespace Flasher\Notyf\Prime;
|
|||||||
use Flasher\Prime\Notification\NotificationBuilder;
|
use Flasher\Prime\Notification\NotificationBuilder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* NotyfBuilder - Builder implementation for Notyf.js notifications.
|
||||||
|
*
|
||||||
|
* This class provides a fluent interface for configuring Notyf.js notifications.
|
||||||
|
* It extends the core notification builder with Notyf-specific options and
|
||||||
|
* features, focusing on Notyf's minimalist approach with fewer options than other
|
||||||
|
* notification libraries.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Builder: Provides a fluent interface for constructing complex objects
|
||||||
|
* - Fluent Interface: Methods return $this for method chaining
|
||||||
|
* - Type Safety: Uses PHPStan annotations for compile-time type checking
|
||||||
|
*
|
||||||
* @phpstan-type NotificationType "success"|"info"|"warning"|"error"
|
* @phpstan-type NotificationType "success"|"info"|"warning"|"error"
|
||||||
* @phpstan-type OptionsType array{
|
* @phpstan-type OptionsType array{
|
||||||
* duration?: int,
|
* duration?: int,
|
||||||
@@ -22,7 +34,13 @@ use Flasher\Prime\Notification\NotificationBuilder;
|
|||||||
final class NotyfBuilder extends NotificationBuilder
|
final class NotyfBuilder extends NotificationBuilder
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* Sets the notification display duration.
|
||||||
|
*
|
||||||
* Number of milliseconds before hiding the notification. Use 0 for infinite duration.
|
* Number of milliseconds before hiding the notification. Use 0 for infinite duration.
|
||||||
|
*
|
||||||
|
* @param int $duration Duration in milliseconds
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function duration(int $duration): self
|
public function duration(int $duration): self
|
||||||
{
|
{
|
||||||
@@ -32,7 +50,11 @@ final class NotyfBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether to show the notification with a ripple effect.
|
* Sets whether to show the notification with a ripple effect.
|
||||||
|
*
|
||||||
|
* @param bool $ripple Whether to enable ripple effect
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function ripple(bool $ripple = true): self
|
public function ripple(bool $ripple = true): self
|
||||||
{
|
{
|
||||||
@@ -42,14 +64,18 @@ final class NotyfBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets the notification position in the viewport.
|
||||||
|
*
|
||||||
* Viewport location where notifications are rendered.
|
* Viewport location where notifications are rendered.
|
||||||
*
|
*
|
||||||
* @param "x"|"y" $position specifies the axis: 'x' for horizontal, 'y' for vertical
|
* @param "x"|"y" $position Specifies the axis: 'x' for horizontal, 'y' for vertical
|
||||||
* @param "left"|"center"|"right"|"top"|"bottom" $value Position value, dependent on the axis:
|
* @param "left"|"center"|"right"|"top"|"bottom" $value Position value, dependent on the axis:
|
||||||
* - If $position is 'x', $value must be 'left', 'center' or 'right'.
|
* - If $position is 'x', $value must be 'left', 'center' or 'right'
|
||||||
* - If $position is 'y', $value must be 'top', 'center' or 'bottom'.
|
* - If $position is 'y', $value must be 'top', 'center' or 'bottom'
|
||||||
*
|
*
|
||||||
* @phpstan-param ($position is 'x' ? "left"|"center"|"right" : "top"|"center"|"bottom") $value
|
* @phpstan-param ($position is 'x' ? "left"|"center"|"right" : "top"|"center"|"bottom") $value
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function position(string $position, string $value): self
|
public function position(string $position, string $value): self
|
||||||
{
|
{
|
||||||
@@ -62,7 +88,13 @@ final class NotyfBuilder extends NotificationBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Sets whether to allow users to dismiss the notification.
|
||||||
|
*
|
||||||
* Whether to allow users to dismiss the notification with a button.
|
* Whether to allow users to dismiss the notification with a button.
|
||||||
|
*
|
||||||
|
* @param bool $dismissible Whether to make the notification dismissible
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
*/
|
*/
|
||||||
public function dismissible(bool $dismissible): self
|
public function dismissible(bool $dismissible): self
|
||||||
{
|
{
|
||||||
@@ -71,6 +103,13 @@ final class NotyfBuilder extends NotificationBuilder
|
|||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the background color of the notification.
|
||||||
|
*
|
||||||
|
* @param string $background CSS color value for the notification background
|
||||||
|
*
|
||||||
|
* @return self The builder instance
|
||||||
|
*/
|
||||||
public function background(string $background): self
|
public function background(string $background): self
|
||||||
{
|
{
|
||||||
$this->option('background', $background);
|
$this->option('background', $background);
|
||||||
|
|||||||
@@ -7,6 +7,17 @@ namespace Flasher\Notyf\Prime;
|
|||||||
use Flasher\Prime\Factory\NotificationFactoryInterface;
|
use Flasher\Prime\Factory\NotificationFactoryInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* NotyfInterface - Contract for Notyf notification factories.
|
||||||
|
*
|
||||||
|
* This interface defines the contract for Notyf notification factories.
|
||||||
|
* It extends the core notification factory interface to ensure compatibility
|
||||||
|
* with PHPFlasher's notification system, while allowing IDE completion for
|
||||||
|
* Notyf-specific methods through the mixin annotation.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Interface Segregation: Provides a specific interface for Notyf functionality
|
||||||
|
* - Contract: Defines a contract for creating Notyf notifications
|
||||||
|
*
|
||||||
* @mixin \Flasher\Notyf\Prime\NotyfBuilder
|
* @mixin \Flasher\Notyf\Prime\NotyfBuilder
|
||||||
*/
|
*/
|
||||||
interface NotyfInterface extends NotificationFactoryInterface
|
interface NotyfInterface extends NotificationFactoryInterface
|
||||||
|
|||||||
@@ -6,25 +6,57 @@ namespace Flasher\Notyf\Prime;
|
|||||||
|
|
||||||
use Flasher\Prime\Plugin\Plugin;
|
use Flasher\Prime\Plugin\Plugin;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NotyfPlugin - Plugin definition for Notyf.js integration with PHPFlasher.
|
||||||
|
*
|
||||||
|
* This class defines the core plugin configuration for the Notyf.js notification
|
||||||
|
* library integration. It specifies the required JavaScript and CSS assets,
|
||||||
|
* factory class, and service identifiers for dependency injection containers.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Plugin: Implements the plugin pattern for extending core functionality
|
||||||
|
* - Registry: Registers the plugin's assets and identifiers with the core system
|
||||||
|
* - Metadata: Provides metadata about the plugin's requirements
|
||||||
|
*/
|
||||||
final class NotyfPlugin extends Plugin
|
final class NotyfPlugin extends Plugin
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Returns the plugin's unique identifier.
|
||||||
|
*/
|
||||||
public function getAlias(): string
|
public function getAlias(): string
|
||||||
{
|
{
|
||||||
return 'notyf';
|
return 'notyf';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Returns the factory class responsible for creating Notyf notifications.
|
||||||
|
*/
|
||||||
public function getFactory(): string
|
public function getFactory(): string
|
||||||
{
|
{
|
||||||
return Notyf::class;
|
return Notyf::class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Returns the service alias for dependency injection containers.
|
||||||
|
*/
|
||||||
public function getServiceAliases(): string
|
public function getServiceAliases(): string
|
||||||
{
|
{
|
||||||
return NotyfInterface::class;
|
return NotyfInterface::class;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string[]
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Returns the required JavaScript files for Notyf.js integration.
|
||||||
|
* Compared to other libraries, Notyf has a minimal footprint with just one script.
|
||||||
|
*
|
||||||
|
* @return string[] Array of script paths
|
||||||
*/
|
*/
|
||||||
public function getScripts(): array
|
public function getScripts(): array
|
||||||
{
|
{
|
||||||
@@ -34,7 +66,12 @@ final class NotyfPlugin extends Plugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return string[]
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Returns the required CSS files for Notyf.js styling.
|
||||||
|
* Notyf has a minimal footprint with just one stylesheet.
|
||||||
|
*
|
||||||
|
* @return string[] Array of stylesheet paths
|
||||||
*/
|
*/
|
||||||
public function getStyles(): array
|
public function getStyles(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,15 @@ use Flasher\Prime\Container\FlasherContainer;
|
|||||||
use Flasher\Prime\Notification\Envelope;
|
use Flasher\Prime\Notification\Envelope;
|
||||||
use Flasher\Prime\Notification\Type;
|
use Flasher\Prime\Notification\Type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Namespace-specific helper functions for Notyf notifications.
|
||||||
|
*
|
||||||
|
* This file provides a namespace-specific helper function that simplifies
|
||||||
|
* the creation of Notyf notifications from code that uses imports.
|
||||||
|
*
|
||||||
|
* Design pattern: Facade - Provides a simplified interface to a complex subsystem
|
||||||
|
*/
|
||||||
|
|
||||||
if (!\function_exists('Flasher\Notyf\Prime\notyf')) {
|
if (!\function_exists('Flasher\Notyf\Prime\notyf')) {
|
||||||
/**
|
/**
|
||||||
* Creates a Notyf notification or returns the Notyf factory.
|
* Creates a Notyf notification or returns the Notyf factory.
|
||||||
|
|||||||
@@ -7,6 +7,15 @@ use Flasher\Prime\Container\FlasherContainer;
|
|||||||
use Flasher\Prime\Notification\Envelope;
|
use Flasher\Prime\Notification\Envelope;
|
||||||
use Flasher\Prime\Notification\Type;
|
use Flasher\Prime\Notification\Type;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Global helper functions for Notyf notifications.
|
||||||
|
*
|
||||||
|
* This file provides a global helper function that simplifies
|
||||||
|
* the creation of Notyf notifications from any PHP code.
|
||||||
|
*
|
||||||
|
* Design pattern: Facade - Provides a simplified interface to a complex subsystem
|
||||||
|
*/
|
||||||
|
|
||||||
if (!function_exists('notyf')) {
|
if (!function_exists('notyf')) {
|
||||||
/**
|
/**
|
||||||
* Creates a Notyf notification or returns the Notyf factory.
|
* Creates a Notyf notification or returns the Notyf factory.
|
||||||
|
|||||||
-1
@@ -1,2 +1 @@
|
|||||||
github: yoeunes
|
github: yoeunes
|
||||||
custom: https://www.paypal.com/paypalme/yoeunes
|
|
||||||
|
|||||||
@@ -8,8 +8,24 @@ use Flasher\Notyf\Prime\NotyfPlugin;
|
|||||||
use Flasher\Prime\Plugin\PluginInterface;
|
use Flasher\Prime\Plugin\PluginInterface;
|
||||||
use Flasher\Symfony\Support\PluginBundle;
|
use Flasher\Symfony\Support\PluginBundle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FlasherNotyfSymfonyBundle - Symfony bundle for Notyf integration.
|
||||||
|
*
|
||||||
|
* This bundle registers the Notyf plugin with Symfony's service container.
|
||||||
|
* It extends the base plugin bundle to inherit common registration logic
|
||||||
|
* while providing the Notyf-specific plugin implementation.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Bundle: Implements Symfony's bundle pattern for packaging functionality
|
||||||
|
* - Factory Method: Creates the plugin instance
|
||||||
|
*/
|
||||||
final class FlasherNotyfSymfonyBundle extends PluginBundle // Symfony\Component\HttpKernel\Bundle\Bundle
|
final class FlasherNotyfSymfonyBundle extends PluginBundle // Symfony\Component\HttpKernel\Bundle\Bundle
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates the Notyf plugin instance.
|
||||||
|
*
|
||||||
|
* @return PluginInterface The Notyf plugin instance
|
||||||
|
*/
|
||||||
public function createPlugin(): PluginInterface
|
public function createPlugin(): PluginInterface
|
||||||
{
|
{
|
||||||
return new NotyfPlugin();
|
return new NotyfPlugin();
|
||||||
|
|||||||
Vendored
-1
@@ -1,2 +1 @@
|
|||||||
github: yoeunes
|
github: yoeunes
|
||||||
custom: https://www.paypal.com/paypalme/yoeunes
|
|
||||||
|
|||||||
@@ -1,13 +1,36 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PhpStorm Meta File - IDE Enhancement for PHPFlasher.
|
||||||
|
*
|
||||||
|
* This file provides PhpStorm with additional type information and method completion
|
||||||
|
* capabilities for the PHPFlasher library. It's not loaded during runtime but is used
|
||||||
|
* exclusively by the IDE to improve developer experience.
|
||||||
|
*
|
||||||
|
* The file enhances code intelligence in several ways:
|
||||||
|
* 1. Adds type inference for Envelope::get() method
|
||||||
|
* 2. Provides completion for factory methods in FlasherInterface
|
||||||
|
* 3. Registers expected argument sets for notification types
|
||||||
|
* 4. Defines expected arguments for various builder methods
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Metadata: Provides additional information about code that's only used by tools
|
||||||
|
* - IDE Integration: Bridges the gap between dynamic PHP code and static analysis tools
|
||||||
|
*
|
||||||
|
* Note: This file is part of the development tooling and has no effect on runtime behavior.
|
||||||
|
*/
|
||||||
|
|
||||||
namespace PHPSTORM_META;
|
namespace PHPSTORM_META;
|
||||||
|
|
||||||
|
// Infer the correct type when Envelope::get() is called with a class name
|
||||||
override(Envelope::get(0), type(0));
|
override(Envelope::get(0), type(0));
|
||||||
|
|
||||||
|
// Map factory methods to their return types for better autocompletion
|
||||||
override(\Flasher\Prime\FlasherInterface::create(), map(['flasher' => \Flasher\Prime\Factory\FlasherFactory::class, 'theme.' => \Flasher\Prime\Factory\FlasherFactory::class]));
|
override(\Flasher\Prime\FlasherInterface::create(), map(['flasher' => \Flasher\Prime\Factory\FlasherFactory::class, 'theme.' => \Flasher\Prime\Factory\FlasherFactory::class]));
|
||||||
override(\Flasher\Prime\Container\FlasherContainer::create(), map(['flasher' => \Flasher\Prime\Factory\FlasherFactory::class, 'theme.' => \Flasher\Prime\Factory\FlasherFactory::class]));
|
override(\Flasher\Prime\Container\FlasherContainer::create(), map(['flasher' => \Flasher\Prime\Factory\FlasherFactory::class, 'theme.' => \Flasher\Prime\Factory\FlasherFactory::class]));
|
||||||
override(\Flasher\Prime\FlasherInterface::use(), map(['flasher' => \Flasher\Prime\Factory\FlasherFactory::class, 'theme.' => \Flasher\Prime\Factory\FlasherFactory::class]));
|
override(\Flasher\Prime\FlasherInterface::use(), map(['flasher' => \Flasher\Prime\Factory\FlasherFactory::class, 'theme.' => \Flasher\Prime\Factory\FlasherFactory::class]));
|
||||||
|
|
||||||
|
// Register and utilize notification type constants for better code completion
|
||||||
registerArgumentsSet('types', 'success', 'error', 'warning', 'info');
|
registerArgumentsSet('types', 'success', 'error', 'warning', 'info');
|
||||||
expectedArguments(\Flasher\Prime\Notification\NotificationBuilderInterface::type(), 0, argumentsSet('types'));
|
expectedArguments(\Flasher\Prime\Notification\NotificationBuilderInterface::type(), 0, argumentsSet('types'));
|
||||||
expectedArguments(\Flasher\Prime\Notification\NotificationBuilderInterface::addFlash(), 0, argumentsSet('types'));
|
expectedArguments(\Flasher\Prime\Notification\NotificationBuilderInterface::addFlash(), 0, argumentsSet('types'));
|
||||||
@@ -17,7 +40,11 @@ expectedArguments(flash(), 1, argumentsSet('types'));
|
|||||||
expectedArguments(\Flasher\Prime\flash(), 1, argumentsSet('types'));
|
expectedArguments(\Flasher\Prime\flash(), 1, argumentsSet('types'));
|
||||||
expectedReturnValues(\Flasher\Prime\Notification\NotificationInterface::getType(), argumentsSet('types'));
|
expectedReturnValues(\Flasher\Prime\Notification\NotificationInterface::getType(), argumentsSet('types'));
|
||||||
|
|
||||||
|
// Define expected arguments for handlers
|
||||||
expectedArguments(\Flasher\Prime\Notification\NotificationBuilderInterface::handler(), 0, 'flasher', 'toastr', 'noty', 'notyf', 'sweetalert');
|
expectedArguments(\Flasher\Prime\Notification\NotificationBuilderInterface::handler(), 0, 'flasher', 'toastr', 'noty', 'notyf', 'sweetalert');
|
||||||
|
|
||||||
|
// Define expected arguments for render formats
|
||||||
expectedArguments(\Flasher\Prime\FlasherInterface::render(), 0, 'html', 'json', 'array');
|
expectedArguments(\Flasher\Prime\FlasherInterface::render(), 0, 'html', 'json', 'array');
|
||||||
|
|
||||||
|
// Define expected arguments for common option keys
|
||||||
expectedArguments(\Flasher\Prime\Notification\FlasherBuilder::option(), 0, 'timeout', 'timeouts', 'fps', 'position', 'direction', 'rtl', 'style', 'escapeHtml');
|
expectedArguments(\Flasher\Prime\Notification\FlasherBuilder::option(), 0, 'timeout', 'timeouts', 'fps', 'position', 'direction', 'rtl', 'style', 'escapeHtml');
|
||||||
|
|||||||
@@ -4,17 +4,45 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Flasher\Prime\Asset;
|
namespace Flasher\Prime\Asset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AssetManager - Manages asset files and their versioning via a manifest file.
|
||||||
|
*
|
||||||
|
* This class provides functionality for handling asset versioning through a manifest
|
||||||
|
* file that maps original asset paths to versioned paths with hash parameters.
|
||||||
|
* The asset versioning helps with cache busting by appending a content hash to the URL.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Resource Manager: Centralized management of web asset resources
|
||||||
|
* - Cache Buster: Handles versioning of assets to ensure browser cache invalidation
|
||||||
|
*/
|
||||||
final class AssetManager implements AssetManagerInterface
|
final class AssetManager implements AssetManagerInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* Cached manifest entries mapping original paths to versioned paths.
|
||||||
|
*
|
||||||
* @var array<string, string>
|
* @var array<string, string>
|
||||||
*/
|
*/
|
||||||
private array $entries = [];
|
private array $entries = [];
|
||||||
|
|
||||||
public function __construct(private readonly string $publicDir, private readonly string $manifestPath)
|
/**
|
||||||
{
|
* Creates a new AssetManager instance.
|
||||||
|
*
|
||||||
|
* @param string $publicDir The public directory where assets are located
|
||||||
|
* @param string $manifestPath The path to the manifest file
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
private readonly string $publicDir,
|
||||||
|
private readonly string $manifestPath,
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* This implementation first checks for an exact match in the manifest,
|
||||||
|
* then tries with directory separators normalized, and falls back to the
|
||||||
|
* original path if no match is found.
|
||||||
|
*/
|
||||||
public function getPath(string $path): string
|
public function getPath(string $path): string
|
||||||
{
|
{
|
||||||
$entriesData = $this->getEntriesData();
|
$entriesData = $this->getEntriesData();
|
||||||
@@ -27,6 +55,16 @@ final class AssetManager implements AssetManagerInterface
|
|||||||
return array_map(fn (string $path) => $this->getPath($path), $paths);
|
return array_map(fn (string $path) => $this->getPath($path), $paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* This method:
|
||||||
|
* 1. Processes each file to calculate its content hash
|
||||||
|
* 2. Creates a mapping from relative paths to versioned paths
|
||||||
|
* 3. Writes the mapping to the manifest file as JSON
|
||||||
|
*
|
||||||
|
* @throws \RuntimeException If unable to write to the manifest file
|
||||||
|
*/
|
||||||
public function createManifest(array $files): void
|
public function createManifest(array $files): void
|
||||||
{
|
{
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
@@ -51,7 +89,12 @@ final class AssetManager implements AssetManagerInterface
|
|||||||
/**
|
/**
|
||||||
* Loads and returns the entries from the manifest file.
|
* Loads and returns the entries from the manifest file.
|
||||||
*
|
*
|
||||||
* @return array<string, string> the manifest entries
|
* This method lazily loads the manifest data and caches it for subsequent calls.
|
||||||
|
* If no manifest file exists or it cannot be parsed, an empty array is returned.
|
||||||
|
*
|
||||||
|
* @return array<string, string> The manifest entries mapping original to versioned paths
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException If the manifest file contains invalid JSON
|
||||||
*/
|
*/
|
||||||
private function getEntriesData(): array
|
private function getEntriesData(): array
|
||||||
{
|
{
|
||||||
@@ -73,6 +116,16 @@ final class AssetManager implements AssetManagerInterface
|
|||||||
return $this->entries = $entries; // @phpstan-ignore-line
|
return $this->entries = $entries; // @phpstan-ignore-line
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Computes a hash for a file based on its contents.
|
||||||
|
*
|
||||||
|
* This method normalizes line endings to ensure consistent hashing
|
||||||
|
* across different platforms.
|
||||||
|
*
|
||||||
|
* @param string $path The path to the file
|
||||||
|
*
|
||||||
|
* @return string The MD5 hash of the file contents or empty string if file cannot be read
|
||||||
|
*/
|
||||||
private function computeHash(string $path): string
|
private function computeHash(string $path): string
|
||||||
{
|
{
|
||||||
$contents = file_get_contents($path);
|
$contents = file_get_contents($path);
|
||||||
|
|||||||
@@ -4,28 +4,49 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Flasher\Prime\Asset;
|
namespace Flasher\Prime\Asset;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AssetManagerInterface - Contract for asset management services.
|
||||||
|
*
|
||||||
|
* This interface defines the essential operations for managing web assets,
|
||||||
|
* particularly focusing on path resolution and manifest generation for versioning.
|
||||||
|
*
|
||||||
|
* Design pattern: Strategy - Defines a common interface for different asset
|
||||||
|
* management strategies that can be used interchangeably.
|
||||||
|
*/
|
||||||
interface AssetManagerInterface
|
interface AssetManagerInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Resolves the given path to its hashed version if available in the manifest.
|
* Resolves the given path to its hashed version if available in the manifest.
|
||||||
*
|
*
|
||||||
* @param string $path the original file path
|
* This method should look up the original path in a manifest of versioned assets
|
||||||
|
* and return the versioned path if found. Otherwise, it should return the original path.
|
||||||
*
|
*
|
||||||
* @return string the resolved file path or the original path if not found in the manifest
|
* @param string $path The original file path
|
||||||
|
*
|
||||||
|
* @return string The resolved file path with version hash or the original path if not found
|
||||||
*/
|
*/
|
||||||
public function getPath(string $path): string;
|
public function getPath(string $path): string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string[] $paths
|
* Resolves multiple paths to their hashed versions if available.
|
||||||
*
|
*
|
||||||
* @return string[]
|
* This is a batch version of getPath() that processes multiple paths at once.
|
||||||
|
*
|
||||||
|
* @param string[] $paths Array of original file paths
|
||||||
|
*
|
||||||
|
* @return string[] Array of resolved file paths in the same order
|
||||||
*/
|
*/
|
||||||
public function getPaths(array $paths): array;
|
public function getPaths(array $paths): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a json manifest from given files.
|
* Generates a JSON manifest from given files.
|
||||||
*
|
*
|
||||||
* @param string[] $files array of file paths
|
* This method should create a mapping between original file paths and
|
||||||
|
* versioned paths (typically with content hashes) and save it to a manifest file.
|
||||||
|
*
|
||||||
|
* @param string[] $files Array of file paths to include in the manifest
|
||||||
|
*
|
||||||
|
* @throws \RuntimeException If the manifest cannot be created
|
||||||
*/
|
*/
|
||||||
public function createManifest(array $files): void;
|
public function createManifest(array $files): void;
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-27
@@ -5,6 +5,29 @@ declare(strict_types=1);
|
|||||||
namespace Flasher\Prime;
|
namespace Flasher\Prime;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Configuration for PHPFlasher.
|
||||||
|
*
|
||||||
|
* This class provides type-safe access to PHPFlasher's configuration structure.
|
||||||
|
* It uses PHPStan annotations to define the complex nested configuration schema,
|
||||||
|
* ensuring configuration consistency and enabling IDE autocompletion.
|
||||||
|
*
|
||||||
|
* Design pattern: Type-safe Configuration - Uses PHP's type system to validate
|
||||||
|
* and document complex configuration structures.
|
||||||
|
*
|
||||||
|
* The configuration array structure contains:
|
||||||
|
* - default: The default notification adapter to use
|
||||||
|
* - main_script: Main JavaScript file path
|
||||||
|
* - scripts: Additional JavaScript files to include
|
||||||
|
* - styles: CSS stylesheets to include
|
||||||
|
* - inject_assets: Whether to auto-inject assets in responses
|
||||||
|
* - translate: Whether to translate notifications
|
||||||
|
* - excluded_paths: Paths where notifications shouldn't be displayed
|
||||||
|
* - options: Global notification options
|
||||||
|
* - filter: Default filtering criteria
|
||||||
|
* - flash_bag: Flash bag configuration for framework integration
|
||||||
|
* - presets: Notification templates/presets with type, title, message and options
|
||||||
|
* - plugins: Plugin-specific configuration with scripts, styles and options
|
||||||
|
*
|
||||||
* @phpstan-type ConfigType array{
|
* @phpstan-type ConfigType array{
|
||||||
* default: string,
|
* default: string,
|
||||||
* main_script?: string,
|
* main_script?: string,
|
||||||
@@ -20,45 +43,26 @@ namespace Flasher\Prime;
|
|||||||
* type: string,
|
* type: string,
|
||||||
* title: string,
|
* title: string,
|
||||||
* message: string,
|
* message: string,
|
||||||
* options: array<string, mixed>,
|
* options: array<string, mixed>
|
||||||
* }>,
|
* }>,
|
||||||
* plugins?: array<string, array{
|
* plugins?: array<string, array{
|
||||||
* scripts?: string[],
|
* scripts?: string[],
|
||||||
* styles?: string[],
|
* styles?: string[],
|
||||||
* options?: array<string, mixed>,
|
* options?: array<string, mixed>
|
||||||
* }>,
|
* }>
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
final class Configuration
|
final class Configuration
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param array{
|
* Validates and returns the configuration array.
|
||||||
* default: string,
|
*
|
||||||
* main_script?: string,
|
* This method serves as a type-safe wrapper around configuration arrays,
|
||||||
* scripts?: string[],
|
* ensuring that they match the expected schema defined in the PHPStan annotations.
|
||||||
* styles?: string[],
|
|
||||||
* inject_assets?: bool,
|
|
||||||
* translate?: bool,
|
|
||||||
* excluded_paths?: list<non-empty-string>,
|
|
||||||
* options?: array<string, mixed>,
|
|
||||||
* filter?: array<string, mixed>,
|
|
||||||
* flash_bag?: false|array<string, string[]>,
|
|
||||||
* presets?: array<string, array{
|
|
||||||
* type: string,
|
|
||||||
* title: string,
|
|
||||||
* message: string,
|
|
||||||
* options: array<string, mixed>,
|
|
||||||
* }>,
|
|
||||||
* plugins?: array<string, array{
|
|
||||||
* scripts?: string[],
|
|
||||||
* styles?: string[],
|
|
||||||
* options?: array<string, mixed>,
|
|
||||||
* }>,
|
|
||||||
* } $config
|
|
||||||
*
|
*
|
||||||
* @phpstan-param ConfigType $config
|
* @phpstan-param ConfigType $config
|
||||||
*
|
*
|
||||||
* @return ConfigType
|
* @phpstan-return ConfigType
|
||||||
*/
|
*/
|
||||||
public static function from(array $config): array
|
public static function from(array $config): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,24 +9,43 @@ use Flasher\Prime\FlasherInterface;
|
|||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manages and provides access to Flasher service instances using a PSR-11 compatible container.
|
* FlasherContainer - Service locator for PHPFlasher services using PSR-11 containers.
|
||||||
* Allows initializing the internal container using a direct instance, a Closure, or a callable
|
|
||||||
* that returns a ContainerInterface instance.
|
|
||||||
*
|
*
|
||||||
* @internal
|
* This class provides static access to Flasher services through a PSR-11 compatible
|
||||||
|
* container. It manages a singleton instance that wraps the container and provides
|
||||||
|
* type-safe access to Flasher services.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Service Locator: Provides a centralized registry for accessing services
|
||||||
|
* - Singleton: Maintains a single, global instance of the container wrapper
|
||||||
|
* - Adapter: Adapts a PSR-11 container to provide Flasher-specific service access
|
||||||
|
*
|
||||||
|
* @internal This class is not part of the public API and may change without notice
|
||||||
*/
|
*/
|
||||||
final class FlasherContainer
|
final class FlasherContainer
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The singleton instance of this class.
|
||||||
|
*/
|
||||||
private static ?self $instance = null;
|
private static ?self $instance = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private constructor to prevent direct instantiation.
|
||||||
|
*
|
||||||
|
* @param ContainerInterface|\Closure $container A ContainerInterface instance or factory
|
||||||
|
*/
|
||||||
private function __construct(private readonly ContainerInterface|\Closure $container)
|
private function __construct(private readonly ContainerInterface|\Closure $container)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the container with a direct ContainerInterface or a Closure/callable that resolves to one.
|
* Initializes the container with a PSR-11 container or a factory.
|
||||||
*
|
*
|
||||||
* @param ContainerInterface|\Closure $container a ContainerInterface instance or a resolver that returns one
|
* This method initializes the singleton instance if it doesn't exist yet.
|
||||||
|
* It accepts either a direct ContainerInterface implementation or a closure
|
||||||
|
* that will return one when invoked.
|
||||||
|
*
|
||||||
|
* @param ContainerInterface|\Closure $container A ContainerInterface instance or factory
|
||||||
*/
|
*/
|
||||||
public static function from(ContainerInterface|\Closure $container): void
|
public static function from(ContainerInterface|\Closure $container): void
|
||||||
{
|
{
|
||||||
@@ -34,7 +53,11 @@ final class FlasherContainer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resets the container instance, effectively clearing it.
|
* Resets the container instance.
|
||||||
|
*
|
||||||
|
* This method clears the singleton instance, effectively removing all
|
||||||
|
* service references. Useful for testing or situations that require
|
||||||
|
* container replacement.
|
||||||
*/
|
*/
|
||||||
public static function reset(): void
|
public static function reset(): void
|
||||||
{
|
{
|
||||||
@@ -42,10 +65,17 @@ final class FlasherContainer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and returns an instance of a service identified by $id.
|
* Creates and returns an instance of a Flasher service by ID.
|
||||||
* Throws an exception if the service is not found or does not implement the required interfaces.
|
|
||||||
*
|
*
|
||||||
* @param string $id the service identifier
|
* This method retrieves a service from the container and ensures it
|
||||||
|
* implements the appropriate interface. It provides type-safe access
|
||||||
|
* to various Flasher services with PHPStan return type specifications.
|
||||||
|
*
|
||||||
|
* @param string $id The service identifier (e.g., 'flasher', 'flasher.toastr')
|
||||||
|
*
|
||||||
|
* @return FlasherInterface|NotificationFactoryInterface The requested service
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException If the service doesn't exist or has an invalid type
|
||||||
*
|
*
|
||||||
* @phpstan-return ($id is 'flasher' ? \Flasher\Prime\FlasherInterface :
|
* @phpstan-return ($id is 'flasher' ? \Flasher\Prime\FlasherInterface :
|
||||||
* ($id is 'flasher.noty' ? \Flasher\Noty\Prime\NotyInterface :
|
* ($id is 'flasher.noty' ? \Flasher\Noty\Prime\NotyInterface :
|
||||||
@@ -70,11 +100,11 @@ final class FlasherContainer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the container has a service identified by $id.
|
* Checks if a service exists in the container.
|
||||||
*
|
*
|
||||||
* @param string $id the service identifier
|
* @param string $id The service identifier
|
||||||
*
|
*
|
||||||
* @return bool true if the service exists, false otherwise
|
* @return bool True if the service exists, false otherwise
|
||||||
*/
|
*/
|
||||||
public static function has(string $id): bool
|
public static function has(string $id): bool
|
||||||
{
|
{
|
||||||
@@ -84,7 +114,12 @@ final class FlasherContainer
|
|||||||
/**
|
/**
|
||||||
* Retrieves the container, resolving it if necessary.
|
* Retrieves the container, resolving it if necessary.
|
||||||
*
|
*
|
||||||
* @return ContainerInterface the container instance
|
* If the container was provided as a factory closure, this method
|
||||||
|
* invokes it to get the actual container instance.
|
||||||
|
*
|
||||||
|
* @return ContainerInterface The resolved container instance
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException If the resolved container is not a ContainerInterface
|
||||||
*/
|
*/
|
||||||
public static function getContainer(): ContainerInterface
|
public static function getContainer(): ContainerInterface
|
||||||
{
|
{
|
||||||
@@ -100,9 +135,11 @@ final class FlasherContainer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the singleton instance of FlasherContainer, throws if not initialized.
|
* Retrieves the singleton instance, throws if not initialized.
|
||||||
*
|
*
|
||||||
* @return self the singleton instance
|
* @return self The singleton instance
|
||||||
|
*
|
||||||
|
* @throws \LogicException If the instance hasn't been initialized yet
|
||||||
*/
|
*/
|
||||||
private static function getInstance(): self
|
private static function getInstance(): self
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,11 +8,20 @@ use Flasher\Prime\Notification\Envelope;
|
|||||||
use Flasher\Prime\Storage\Filter\Filter;
|
use Flasher\Prime\Storage\Filter\Filter;
|
||||||
use Flasher\Prime\Storage\Filter\FilterInterface;
|
use Flasher\Prime\Storage\Filter\FilterInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FilterEvent - Event dispatched when notifications are being filtered.
|
||||||
|
*
|
||||||
|
* This event is dispatched during the filtering process, allowing listeners
|
||||||
|
* to modify the filter, the envelopes being filtered, or the filter criteria.
|
||||||
|
*/
|
||||||
final class FilterEvent
|
final class FilterEvent
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param Envelope[] $envelopes
|
* Creates a new FilterEvent instance.
|
||||||
* @param array<string, mixed> $criteria
|
*
|
||||||
|
* @param FilterInterface $filter The filter being applied
|
||||||
|
* @param Envelope[] $envelopes The notification envelopes to filter
|
||||||
|
* @param array<string, mixed> $criteria The filtering criteria
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private FilterInterface $filter,
|
private FilterInterface $filter,
|
||||||
@@ -21,18 +30,32 @@ final class FilterEvent
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the filter being applied.
|
||||||
|
*
|
||||||
|
* @return FilterInterface The filter
|
||||||
|
*/
|
||||||
public function getFilter(): FilterInterface
|
public function getFilter(): FilterInterface
|
||||||
{
|
{
|
||||||
return $this->filter;
|
return $this->filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the filter to be applied.
|
||||||
|
*
|
||||||
|
* This allows listeners to replace the filter with a custom implementation.
|
||||||
|
*
|
||||||
|
* @param Filter $filter The new filter
|
||||||
|
*/
|
||||||
public function setFilter(Filter $filter): void
|
public function setFilter(Filter $filter): void
|
||||||
{
|
{
|
||||||
$this->filter = $filter;
|
$this->filter = $filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Envelope[]
|
* Gets the notification envelopes being filtered.
|
||||||
|
*
|
||||||
|
* @return Envelope[] The notification envelopes
|
||||||
*/
|
*/
|
||||||
public function getEnvelopes(): array
|
public function getEnvelopes(): array
|
||||||
{
|
{
|
||||||
@@ -40,7 +63,11 @@ final class FilterEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Envelope[] $envelopes
|
* Sets the notification envelopes to be filtered.
|
||||||
|
*
|
||||||
|
* This allows listeners to modify the collection of envelopes before filtering.
|
||||||
|
*
|
||||||
|
* @param Envelope[] $envelopes The notification envelopes to filter
|
||||||
*/
|
*/
|
||||||
public function setEnvelopes(array $envelopes): void
|
public function setEnvelopes(array $envelopes): void
|
||||||
{
|
{
|
||||||
@@ -48,7 +75,11 @@ final class FilterEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string, mixed>
|
* Gets the filtering criteria.
|
||||||
|
*
|
||||||
|
* These criteria determine how notifications will be filtered.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed> The filtering criteria
|
||||||
*/
|
*/
|
||||||
public function getCriteria(): array
|
public function getCriteria(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,13 +7,31 @@ namespace Flasher\Prime\EventDispatcher\Event;
|
|||||||
use Flasher\Prime\Notification\Envelope;
|
use Flasher\Prime\Notification\Envelope;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* NotificationEvents - Collector for notification envelopes.
|
||||||
|
*
|
||||||
|
* This class provides a simple container for collecting notification envelopes
|
||||||
|
* during various system processes. It's primarily used by logging and debugging
|
||||||
|
* listeners to track which notifications were dispatched or displayed.
|
||||||
|
*
|
||||||
|
* Design pattern: Collection - Provides a way to collect and access notification
|
||||||
|
* envelopes in a consistent manner.
|
||||||
|
*
|
||||||
|
* @internal This class is not part of the public API and may change without notice
|
||||||
*/
|
*/
|
||||||
final class NotificationEvents
|
final class NotificationEvents
|
||||||
{
|
{
|
||||||
/** @var Envelope[] */
|
/**
|
||||||
|
* The collected notification envelopes.
|
||||||
|
*
|
||||||
|
* @var Envelope[]
|
||||||
|
*/
|
||||||
private array $envelopes = [];
|
private array $envelopes = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds multiple notification envelopes to the collection.
|
||||||
|
*
|
||||||
|
* @param Envelope ...$notifications The notification envelopes to add
|
||||||
|
*/
|
||||||
public function add(Envelope ...$notifications): void
|
public function add(Envelope ...$notifications): void
|
||||||
{
|
{
|
||||||
foreach ($notifications as $notification) {
|
foreach ($notifications as $notification) {
|
||||||
@@ -21,13 +39,20 @@ final class NotificationEvents
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a single notification envelope to the collection.
|
||||||
|
*
|
||||||
|
* @param Envelope $notification The notification envelope to add
|
||||||
|
*/
|
||||||
public function addEnvelope(Envelope $notification): void
|
public function addEnvelope(Envelope $notification): void
|
||||||
{
|
{
|
||||||
$this->envelopes[] = $notification;
|
$this->envelopes[] = $notification;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Envelope[]
|
* Gets all the collected notification envelopes.
|
||||||
|
*
|
||||||
|
* @return Envelope[] The collected notification envelopes
|
||||||
*/
|
*/
|
||||||
public function getEnvelopes(): array
|
public function getEnvelopes(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,17 +6,27 @@ namespace Flasher\Prime\EventDispatcher\Event;
|
|||||||
|
|
||||||
use Flasher\Prime\Notification\Envelope;
|
use Flasher\Prime\Notification\Envelope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PersistEvent - Event dispatched when notifications are being persisted.
|
||||||
|
*
|
||||||
|
* This event is dispatched when notifications are about to be added to storage.
|
||||||
|
* It allows listeners to modify the notifications before they are stored.
|
||||||
|
*/
|
||||||
final class PersistEvent
|
final class PersistEvent
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param Envelope[] $envelopes
|
* Creates a new PersistEvent instance.
|
||||||
|
*
|
||||||
|
* @param Envelope[] $envelopes The notification envelopes to be persisted
|
||||||
*/
|
*/
|
||||||
public function __construct(private array $envelopes)
|
public function __construct(private array $envelopes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Envelope[]
|
* Gets the notification envelopes to be persisted.
|
||||||
|
*
|
||||||
|
* @return Envelope[] The notification envelopes
|
||||||
*/
|
*/
|
||||||
public function getEnvelopes(): array
|
public function getEnvelopes(): array
|
||||||
{
|
{
|
||||||
@@ -24,7 +34,11 @@ final class PersistEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Envelope[] $envelopes
|
* Sets the notification envelopes to be persisted.
|
||||||
|
*
|
||||||
|
* This allows listeners to filter or modify the notifications before storage.
|
||||||
|
*
|
||||||
|
* @param Envelope[] $envelopes The notification envelopes to persist
|
||||||
*/
|
*/
|
||||||
public function setEnvelopes(array $envelopes): void
|
public function setEnvelopes(array $envelopes): void
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,17 +6,27 @@ namespace Flasher\Prime\EventDispatcher\Event;
|
|||||||
|
|
||||||
use Flasher\Prime\Notification\Envelope;
|
use Flasher\Prime\Notification\Envelope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PostPersistEvent - Event dispatched after notifications are persisted.
|
||||||
|
*
|
||||||
|
* This event is dispatched after notification envelopes have been added to storage.
|
||||||
|
* It allows listeners to perform actions after notifications have been successfully stored.
|
||||||
|
*/
|
||||||
final readonly class PostPersistEvent
|
final readonly class PostPersistEvent
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param Envelope[] $envelopes
|
* Creates a new PostPersistEvent instance.
|
||||||
|
*
|
||||||
|
* @param Envelope[] $envelopes The notification envelopes that were persisted
|
||||||
*/
|
*/
|
||||||
public function __construct(private array $envelopes)
|
public function __construct(private array $envelopes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Envelope[]
|
* Gets the notification envelopes that were persisted.
|
||||||
|
*
|
||||||
|
* @return Envelope[] The persisted notification envelopes
|
||||||
*/
|
*/
|
||||||
public function getEnvelopes(): array
|
public function getEnvelopes(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,11 +6,20 @@ namespace Flasher\Prime\EventDispatcher\Event;
|
|||||||
|
|
||||||
use Flasher\Prime\Notification\Envelope;
|
use Flasher\Prime\Notification\Envelope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PostRemoveEvent - Event dispatched after notifications are removed.
|
||||||
|
*
|
||||||
|
* This event is dispatched after notification envelopes have been removed from or
|
||||||
|
* kept in storage. It provides information about which envelopes were removed
|
||||||
|
* and which were kept.
|
||||||
|
*/
|
||||||
final readonly class PostRemoveEvent
|
final readonly class PostRemoveEvent
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param Envelope[] $envelopesToRemove
|
* Creates a new PostRemoveEvent instance.
|
||||||
* @param Envelope[] $envelopesToKeep
|
*
|
||||||
|
* @param Envelope[] $envelopesToRemove The notification envelopes that were removed
|
||||||
|
* @param Envelope[] $envelopesToKeep The notification envelopes that were kept
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private array $envelopesToRemove = [],
|
private array $envelopesToRemove = [],
|
||||||
@@ -19,7 +28,9 @@ final readonly class PostRemoveEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Envelope[]
|
* Gets the notification envelopes that were removed.
|
||||||
|
*
|
||||||
|
* @return Envelope[] The removed notification envelopes
|
||||||
*/
|
*/
|
||||||
public function getEnvelopesToRemove(): array
|
public function getEnvelopesToRemove(): array
|
||||||
{
|
{
|
||||||
@@ -27,7 +38,9 @@ final readonly class PostRemoveEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Envelope[]
|
* Gets the notification envelopes that were kept.
|
||||||
|
*
|
||||||
|
* @return Envelope[] The kept notification envelopes
|
||||||
*/
|
*/
|
||||||
public function getEnvelopesToKeep(): array
|
public function getEnvelopesToKeep(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,17 +6,27 @@ namespace Flasher\Prime\EventDispatcher\Event;
|
|||||||
|
|
||||||
use Flasher\Prime\Notification\Envelope;
|
use Flasher\Prime\Notification\Envelope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PostUpdateEvent - Event dispatched after notification envelopes are updated.
|
||||||
|
*
|
||||||
|
* This event is dispatched after notification envelopes have been updated in storage.
|
||||||
|
* It allows listeners to perform actions based on the updated notifications.
|
||||||
|
*/
|
||||||
final readonly class PostUpdateEvent
|
final readonly class PostUpdateEvent
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param Envelope[] $envelopes
|
* Creates a new PostUpdateEvent instance.
|
||||||
|
*
|
||||||
|
* @param Envelope[] $envelopes The updated notification envelopes
|
||||||
*/
|
*/
|
||||||
public function __construct(private array $envelopes)
|
public function __construct(private array $envelopes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Envelope[]
|
* Gets the updated notification envelopes.
|
||||||
|
*
|
||||||
|
* @return Envelope[] The updated notification envelopes
|
||||||
*/
|
*/
|
||||||
public function getEnvelopes(): array
|
public function getEnvelopes(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,11 +6,20 @@ namespace Flasher\Prime\EventDispatcher\Event;
|
|||||||
|
|
||||||
use Flasher\Prime\Notification\Envelope;
|
use Flasher\Prime\Notification\Envelope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PresentationEvent - Event dispatched when notifications are being prepared for presentation.
|
||||||
|
*
|
||||||
|
* This event is dispatched during the rendering process, before notifications are
|
||||||
|
* converted to their final format. It allows listeners to modify notifications
|
||||||
|
* right before they are presented to the user (e.g., for translation or formatting).
|
||||||
|
*/
|
||||||
final readonly class PresentationEvent
|
final readonly class PresentationEvent
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param Envelope[] $envelopes
|
* Creates a new PresentationEvent instance.
|
||||||
* @param array<string, mixed> $context
|
*
|
||||||
|
* @param Envelope[] $envelopes The notification envelopes being presented
|
||||||
|
* @param array<string, mixed> $context Additional context for presentation
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private array $envelopes,
|
private array $envelopes,
|
||||||
@@ -19,7 +28,9 @@ final readonly class PresentationEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Envelope[]
|
* Gets the notification envelopes being presented.
|
||||||
|
*
|
||||||
|
* @return Envelope[] The notification envelopes
|
||||||
*/
|
*/
|
||||||
public function getEnvelopes(): array
|
public function getEnvelopes(): array
|
||||||
{
|
{
|
||||||
@@ -27,7 +38,12 @@ final readonly class PresentationEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string, mixed>
|
* Gets the presentation context.
|
||||||
|
*
|
||||||
|
* This context provides additional information that may be useful
|
||||||
|
* for listeners during the presentation process.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed> The presentation context
|
||||||
*/
|
*/
|
||||||
public function getContext(): array
|
public function getContext(): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -6,22 +6,36 @@ namespace Flasher\Prime\EventDispatcher\Event;
|
|||||||
|
|
||||||
use Flasher\Prime\Notification\Envelope;
|
use Flasher\Prime\Notification\Envelope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RemoveEvent - Event dispatched when notifications are being removed.
|
||||||
|
*
|
||||||
|
* This event is dispatched when notifications are about to be removed from storage.
|
||||||
|
* It allows listeners to modify which notifications should be removed and which
|
||||||
|
* should be kept. This is used for implementing hopping behavior where notifications
|
||||||
|
* can persist across multiple requests.
|
||||||
|
*/
|
||||||
final class RemoveEvent
|
final class RemoveEvent
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* Notification envelopes that should be kept in storage.
|
||||||
|
*
|
||||||
* @var Envelope[]
|
* @var Envelope[]
|
||||||
*/
|
*/
|
||||||
private array $envelopesToKeep = [];
|
private array $envelopesToKeep = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Envelope[] $envelopesToRemove
|
* Creates a new RemoveEvent instance.
|
||||||
|
*
|
||||||
|
* @param Envelope[] $envelopesToRemove The notification envelopes initially marked for removal
|
||||||
*/
|
*/
|
||||||
public function __construct(private array $envelopesToRemove)
|
public function __construct(private array $envelopesToRemove)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Envelope[]
|
* Gets the notification envelopes marked for removal.
|
||||||
|
*
|
||||||
|
* @return Envelope[] The notification envelopes to remove
|
||||||
*/
|
*/
|
||||||
public function getEnvelopesToRemove(): array
|
public function getEnvelopesToRemove(): array
|
||||||
{
|
{
|
||||||
@@ -29,7 +43,9 @@ final class RemoveEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Envelope[] $envelopesToRemove
|
* Sets the notification envelopes to be removed.
|
||||||
|
*
|
||||||
|
* @param Envelope[] $envelopesToRemove The notification envelopes to remove
|
||||||
*/
|
*/
|
||||||
public function setEnvelopesToRemove(array $envelopesToRemove): void
|
public function setEnvelopesToRemove(array $envelopesToRemove): void
|
||||||
{
|
{
|
||||||
@@ -37,7 +53,9 @@ final class RemoveEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Envelope[]
|
* Gets the notification envelopes that should be kept in storage.
|
||||||
|
*
|
||||||
|
* @return Envelope[] The notification envelopes to keep
|
||||||
*/
|
*/
|
||||||
public function getEnvelopesToKeep(): array
|
public function getEnvelopesToKeep(): array
|
||||||
{
|
{
|
||||||
@@ -45,7 +63,9 @@ final class RemoveEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Envelope[] $envelopesToKeep
|
* Sets the notification envelopes that should be kept in storage.
|
||||||
|
*
|
||||||
|
* @param Envelope[] $envelopesToKeep The notification envelopes to keep
|
||||||
*/
|
*/
|
||||||
public function setEnvelopesToKeep(array $envelopesToKeep): void
|
public function setEnvelopesToKeep(array $envelopesToKeep): void
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,24 +4,55 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Flasher\Prime\EventDispatcher\Event;
|
namespace Flasher\Prime\EventDispatcher\Event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ResponseEvent - Event dispatched when a response is being prepared.
|
||||||
|
*
|
||||||
|
* This event is dispatched during the response rendering process. It allows
|
||||||
|
* listeners to modify the rendered response before it's returned to the client.
|
||||||
|
* This is particularly useful for adapting the response format or adding
|
||||||
|
* additional data.
|
||||||
|
*/
|
||||||
final class ResponseEvent
|
final class ResponseEvent
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new ResponseEvent instance.
|
||||||
|
*
|
||||||
|
* @param mixed $response The response data that has been rendered
|
||||||
|
* @param string $presenter The name of the presenter that rendered the response
|
||||||
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private mixed $response,
|
private mixed $response,
|
||||||
private readonly string $presenter,
|
private readonly string $presenter,
|
||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the current response data.
|
||||||
|
*
|
||||||
|
* @return mixed The response data
|
||||||
|
*/
|
||||||
public function getResponse(): mixed
|
public function getResponse(): mixed
|
||||||
{
|
{
|
||||||
return $this->response;
|
return $this->response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the response data.
|
||||||
|
*
|
||||||
|
* This allows listeners to modify or replace the response content.
|
||||||
|
*
|
||||||
|
* @param mixed $response The new response data
|
||||||
|
*/
|
||||||
public function setResponse(mixed $response): void
|
public function setResponse(mixed $response): void
|
||||||
{
|
{
|
||||||
$this->response = $response;
|
$this->response = $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of the presenter that rendered the response.
|
||||||
|
*
|
||||||
|
* @return string The presenter name (e.g., 'html', 'json')
|
||||||
|
*/
|
||||||
public function getPresenter(): string
|
public function getPresenter(): string
|
||||||
{
|
{
|
||||||
return $this->presenter;
|
return $this->presenter;
|
||||||
|
|||||||
@@ -4,7 +4,25 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Flasher\Prime\EventDispatcher\Event;
|
namespace Flasher\Prime\EventDispatcher\Event;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StoppableEventInterface - Contract for events that can stop propagation.
|
||||||
|
*
|
||||||
|
* This interface marks an event as being able to stop propagation through the
|
||||||
|
* event dispatcher. Once an event's propagation is stopped, no further listeners
|
||||||
|
* will be called for that event.
|
||||||
|
*
|
||||||
|
* Design pattern: Circuit Breaker - Provides a mechanism to halt the normal
|
||||||
|
* flow of execution when certain conditions are met.
|
||||||
|
*/
|
||||||
interface StoppableEventInterface
|
interface StoppableEventInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Checks if event propagation should be stopped.
|
||||||
|
*
|
||||||
|
* This method returns true if event propagation should be stopped,
|
||||||
|
* false otherwise.
|
||||||
|
*
|
||||||
|
* @return bool True if event propagation should stop, false otherwise
|
||||||
|
*/
|
||||||
public function isPropagationStopped(): bool;
|
public function isPropagationStopped(): bool;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,17 +6,27 @@ namespace Flasher\Prime\EventDispatcher\Event;
|
|||||||
|
|
||||||
use Flasher\Prime\Notification\Envelope;
|
use Flasher\Prime\Notification\Envelope;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UpdateEvent - Event dispatched when notifications are being updated.
|
||||||
|
*
|
||||||
|
* This event is dispatched when notifications are about to be updated in storage.
|
||||||
|
* It allows listeners to modify the notifications before they are committed to storage.
|
||||||
|
*/
|
||||||
final class UpdateEvent
|
final class UpdateEvent
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param Envelope[] $envelopes
|
* Creates a new UpdateEvent instance.
|
||||||
|
*
|
||||||
|
* @param Envelope[] $envelopes The notification envelopes to be updated
|
||||||
*/
|
*/
|
||||||
public function __construct(private array $envelopes)
|
public function __construct(private array $envelopes)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Envelope[]
|
* Gets the notification envelopes to be updated.
|
||||||
|
*
|
||||||
|
* @return Envelope[] The notification envelopes
|
||||||
*/
|
*/
|
||||||
public function getEnvelopes(): array
|
public function getEnvelopes(): array
|
||||||
{
|
{
|
||||||
@@ -24,7 +34,11 @@ final class UpdateEvent
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Envelope[] $envelopes
|
* Sets the notification envelopes to be updated.
|
||||||
|
*
|
||||||
|
* This allows listeners to modify which notifications will be updated.
|
||||||
|
*
|
||||||
|
* @param Envelope[] $envelopes The notification envelopes to update
|
||||||
*/
|
*/
|
||||||
public function setEnvelopes(array $envelopes): void
|
public function setEnvelopes(array $envelopes): void
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,13 +10,36 @@ use Flasher\Prime\EventDispatcher\EventListener\AttachDefaultStampsListener;
|
|||||||
use Flasher\Prime\EventDispatcher\EventListener\EnvelopeRemovalListener;
|
use Flasher\Prime\EventDispatcher\EventListener\EnvelopeRemovalListener;
|
||||||
use Flasher\Prime\EventDispatcher\EventListener\EventListenerInterface;
|
use Flasher\Prime\EventDispatcher\EventListener\EventListenerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EventDispatcher - Default implementation of the event dispatcher interface.
|
||||||
|
*
|
||||||
|
* This class provides the core event dispatching functionality for PHPFlasher.
|
||||||
|
* It allows registering listeners for specific events and dispatches events
|
||||||
|
* to all relevant listeners. It also comes pre-configured with the essential
|
||||||
|
* system listeners that implement core notification behaviors.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Observer: Implements the observer pattern for event notification
|
||||||
|
* - Chain of Responsibility: Passes events through a chain of listeners
|
||||||
|
*/
|
||||||
final class EventDispatcher implements EventDispatcherInterface
|
final class EventDispatcher implements EventDispatcherInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* Mapping of event names to their registered listeners.
|
||||||
|
*
|
||||||
* @var array<string, EventListenerInterface[]>
|
* @var array<string, EventListenerInterface[]>
|
||||||
*/
|
*/
|
||||||
private array $listeners = [];
|
private array $listeners = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new EventDispatcher with default system listeners.
|
||||||
|
*
|
||||||
|
* This constructor automatically registers the core system listeners
|
||||||
|
* that are essential for proper notification handling:
|
||||||
|
* - EnvelopeRemovalListener: Manages notification lifetime across requests
|
||||||
|
* - AttachDefaultStampsListener: Adds required stamps to notifications
|
||||||
|
* - AddToStorageListener: Filters notifications before storage
|
||||||
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->addListener(new EnvelopeRemovalListener());
|
$this->addListener(new EnvelopeRemovalListener());
|
||||||
@@ -24,6 +47,15 @@ final class EventDispatcher implements EventDispatcherInterface
|
|||||||
$this->addListener(new AddToStorageListener());
|
$this->addListener(new AddToStorageListener());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* This implementation supports event propagation stopping for events
|
||||||
|
* that implement StoppableEventInterface. It calls each listener in
|
||||||
|
* registration order until all listeners are called or propagation is stopped.
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException If a listener is not callable
|
||||||
|
*/
|
||||||
public function dispatch(object $event): object
|
public function dispatch(object $event): object
|
||||||
{
|
{
|
||||||
$listeners = $this->getListeners($event::class);
|
$listeners = $this->getListeners($event::class);
|
||||||
@@ -43,6 +75,12 @@ final class EventDispatcher implements EventDispatcherInterface
|
|||||||
return $event;
|
return $event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* This implementation registers a listener for all events it declares
|
||||||
|
* interest in through its getSubscribedEvents() method.
|
||||||
|
*/
|
||||||
public function addListener(EventListenerInterface $listener): void
|
public function addListener(EventListenerInterface $listener): void
|
||||||
{
|
{
|
||||||
foreach ((array) $listener->getSubscribedEvents() as $eventName) {
|
foreach ((array) $listener->getSubscribedEvents() as $eventName) {
|
||||||
@@ -50,9 +88,6 @@ final class EventDispatcher implements EventDispatcherInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return EventListenerInterface[]
|
|
||||||
*/
|
|
||||||
public function getListeners(string $eventName): array
|
public function getListeners(string $eventName): array
|
||||||
{
|
{
|
||||||
return $this->listeners[$eventName] ?? [];
|
return $this->listeners[$eventName] ?? [];
|
||||||
|
|||||||
@@ -6,10 +6,30 @@ namespace Flasher\Prime\EventDispatcher;
|
|||||||
|
|
||||||
use Flasher\Prime\EventDispatcher\EventListener\EventListenerInterface;
|
use Flasher\Prime\EventDispatcher\EventListener\EventListenerInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EventDispatcherInterface - Contract for event dispatching services.
|
||||||
|
*
|
||||||
|
* This interface defines the essential operations for dispatching events to
|
||||||
|
* registered listeners. It provides a simple but powerful event system where
|
||||||
|
* listeners can react to various events in the notification lifecycle.
|
||||||
|
*
|
||||||
|
* Design pattern: Observer - Defines a one-to-many dependency between objects
|
||||||
|
* where multiple observers are notified of state changes in the subject.
|
||||||
|
*/
|
||||||
interface EventDispatcherInterface
|
interface EventDispatcherInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @phpstan-template T of object
|
* Dispatches an event to all registered listeners.
|
||||||
|
*
|
||||||
|
* This method notifies all listeners subscribed to the event's class.
|
||||||
|
* It passes the event object to each listener for processing and returns
|
||||||
|
* the potentially modified event object.
|
||||||
|
*
|
||||||
|
* @template T of object
|
||||||
|
*
|
||||||
|
* @param T $event The event to dispatch
|
||||||
|
*
|
||||||
|
* @return T The event after it has been processed by all listeners
|
||||||
*
|
*
|
||||||
* @phpstan-param T $event
|
* @phpstan-param T $event
|
||||||
*
|
*
|
||||||
@@ -17,10 +37,24 @@ interface EventDispatcherInterface
|
|||||||
*/
|
*/
|
||||||
public function dispatch(object $event): object;
|
public function dispatch(object $event): object;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers a listener with the dispatcher.
|
||||||
|
*
|
||||||
|
* This method registers a listener that will be notified when events
|
||||||
|
* it's interested in are dispatched.
|
||||||
|
*
|
||||||
|
* @param EventListenerInterface $listener The listener to register
|
||||||
|
*/
|
||||||
public function addListener(EventListenerInterface $listener): void;
|
public function addListener(EventListenerInterface $listener): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return EventListenerInterface[]
|
* Gets all listeners for a specific event.
|
||||||
|
*
|
||||||
|
* This method retrieves all listeners that are registered for the given event name.
|
||||||
|
*
|
||||||
|
* @param string $eventName The event class name
|
||||||
|
*
|
||||||
|
* @return EventListenerInterface[] Array of listeners for the event
|
||||||
*/
|
*/
|
||||||
public function getListeners(string $eventName): array;
|
public function getListeners(string $eventName): array;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,8 +9,26 @@ use Flasher\Prime\Notification\Envelope;
|
|||||||
use Flasher\Prime\Stamp\UnlessStamp;
|
use Flasher\Prime\Stamp\UnlessStamp;
|
||||||
use Flasher\Prime\Stamp\WhenStamp;
|
use Flasher\Prime\Stamp\WhenStamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AddToStorageListener - Filters notifications before storage based on conditions.
|
||||||
|
*
|
||||||
|
* This listener is responsible for checking whether notifications should be stored
|
||||||
|
* based on their WhenStamp and UnlessStamp conditions. It allows for conditional
|
||||||
|
* notifications that only appear when certain criteria are met.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Filter Chain: Acts as a filter in the notification processing pipeline
|
||||||
|
* - Strategy: Applies different filtering strategies based on stamp conditions
|
||||||
|
*/
|
||||||
final readonly class AddToStorageListener implements EventListenerInterface
|
final readonly class AddToStorageListener implements EventListenerInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Handles persist events by filtering notifications based on conditions.
|
||||||
|
*
|
||||||
|
* This method filters out notifications that don't meet their when/unless conditions.
|
||||||
|
*
|
||||||
|
* @param PersistEvent $event The persist event
|
||||||
|
*/
|
||||||
public function __invoke(PersistEvent $event): void
|
public function __invoke(PersistEvent $event): void
|
||||||
{
|
{
|
||||||
$envelopes = array_filter($event->getEnvelopes(), $this->isEligibleForStorage(...));
|
$envelopes = array_filter($event->getEnvelopes(), $this->isEligibleForStorage(...));
|
||||||
@@ -23,11 +41,33 @@ final readonly class AddToStorageListener implements EventListenerInterface
|
|||||||
return PersistEvent::class;
|
return PersistEvent::class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an envelope is eligible for storage based on its conditions.
|
||||||
|
*
|
||||||
|
* An envelope is eligible if:
|
||||||
|
* - It passes its when condition (if any)
|
||||||
|
* - It passes its unless condition (if any)
|
||||||
|
*
|
||||||
|
* @param Envelope $envelope The envelope to check
|
||||||
|
*
|
||||||
|
* @return bool True if the envelope should be stored, false otherwise
|
||||||
|
*/
|
||||||
private function isEligibleForStorage(Envelope $envelope): bool
|
private function isEligibleForStorage(Envelope $envelope): bool
|
||||||
{
|
{
|
||||||
return $this->whenCondition($envelope) && $this->unlessCondition($envelope);
|
return $this->whenCondition($envelope) && $this->unlessCondition($envelope);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the envelope passes its when condition.
|
||||||
|
*
|
||||||
|
* The envelope passes if:
|
||||||
|
* - It has no WhenStamp, or
|
||||||
|
* - Its WhenStamp condition evaluates to true
|
||||||
|
*
|
||||||
|
* @param Envelope $envelope The envelope to check
|
||||||
|
*
|
||||||
|
* @return bool True if the envelope passes its when condition
|
||||||
|
*/
|
||||||
private function whenCondition(Envelope $envelope): bool
|
private function whenCondition(Envelope $envelope): bool
|
||||||
{
|
{
|
||||||
$whenStamp = $envelope->get(WhenStamp::class);
|
$whenStamp = $envelope->get(WhenStamp::class);
|
||||||
@@ -35,6 +75,17 @@ final readonly class AddToStorageListener implements EventListenerInterface
|
|||||||
return !($whenStamp instanceof WhenStamp && !$whenStamp->getCondition());
|
return !($whenStamp instanceof WhenStamp && !$whenStamp->getCondition());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the envelope passes its unless condition.
|
||||||
|
*
|
||||||
|
* The envelope passes if:
|
||||||
|
* - It has no UnlessStamp, or
|
||||||
|
* - Its UnlessStamp condition evaluates to false
|
||||||
|
*
|
||||||
|
* @param Envelope $envelope The envelope to check
|
||||||
|
*
|
||||||
|
* @return bool True if the envelope passes its unless condition
|
||||||
|
*/
|
||||||
private function unlessCondition(Envelope $envelope): bool
|
private function unlessCondition(Envelope $envelope): bool
|
||||||
{
|
{
|
||||||
$unlessStamp = $envelope->get(UnlessStamp::class);
|
$unlessStamp = $envelope->get(UnlessStamp::class);
|
||||||
|
|||||||
@@ -10,6 +10,16 @@ use Flasher\Prime\Notification\Envelope;
|
|||||||
use Flasher\Prime\Stamp\PresetStamp;
|
use Flasher\Prime\Stamp\PresetStamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* ApplyPresetListener - Applies preset configurations to notifications.
|
||||||
|
*
|
||||||
|
* This listener is responsible for applying predefined notification templates (presets)
|
||||||
|
* to envelopes that contain a PresetStamp. Presets allow defining common notification
|
||||||
|
* patterns that can be reused across an application.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Template Method: Applies predefined templates to notifications
|
||||||
|
* - Strategy: Uses different preset configurations based on the preset name
|
||||||
|
*
|
||||||
* @phpstan-type PresetType array{
|
* @phpstan-type PresetType array{
|
||||||
* type: string,
|
* type: string,
|
||||||
* title: string,
|
* title: string,
|
||||||
@@ -20,14 +30,20 @@ use Flasher\Prime\Stamp\PresetStamp;
|
|||||||
final readonly class ApplyPresetListener implements EventListenerInterface
|
final readonly class ApplyPresetListener implements EventListenerInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @phpstan-param array<string, PresetType> $presets
|
* Creates a new ApplyPresetListener with the specified presets.
|
||||||
|
*
|
||||||
|
* @param array<string, PresetType> $presets Map of preset names to their configurations
|
||||||
*/
|
*/
|
||||||
public function __construct(private array $presets)
|
public function __construct(private array $presets)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws PresetNotFoundException
|
* Handles persist events by applying presets to envelopes with PresetStamps.
|
||||||
|
*
|
||||||
|
* @param PersistEvent $event The persist event
|
||||||
|
*
|
||||||
|
* @throws PresetNotFoundException If a requested preset doesn't exist
|
||||||
*/
|
*/
|
||||||
public function __invoke(PersistEvent $event): void
|
public function __invoke(PersistEvent $event): void
|
||||||
{
|
{
|
||||||
@@ -44,7 +60,12 @@ final readonly class ApplyPresetListener implements EventListenerInterface
|
|||||||
/**
|
/**
|
||||||
* Applies preset settings to an envelope if applicable.
|
* Applies preset settings to an envelope if applicable.
|
||||||
*
|
*
|
||||||
* @throws PresetNotFoundException if the preset is not found
|
* This method checks if the envelope has a PresetStamp and if so, applies
|
||||||
|
* the corresponding preset configuration.
|
||||||
|
*
|
||||||
|
* @param Envelope $envelope The envelope to process
|
||||||
|
*
|
||||||
|
* @throws PresetNotFoundException If the requested preset doesn't exist
|
||||||
*/
|
*/
|
||||||
private function applyPreset(Envelope $envelope): void
|
private function applyPreset(Envelope $envelope): void
|
||||||
{
|
{
|
||||||
@@ -63,11 +84,11 @@ final readonly class ApplyPresetListener implements EventListenerInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves preset data or default values if not set.
|
* Retrieves preset data with default values for missing fields.
|
||||||
*
|
*
|
||||||
* @param string $alias the preset key
|
* @param string $alias The preset key
|
||||||
*
|
*
|
||||||
* @phpstan-return PresetType The preset data.
|
* @return PresetType The preset data with defaults for missing fields
|
||||||
*/
|
*/
|
||||||
private function getPreset(string $alias): array
|
private function getPreset(string $alias): array
|
||||||
{
|
{
|
||||||
@@ -83,9 +104,12 @@ final readonly class ApplyPresetListener implements EventListenerInterface
|
|||||||
/**
|
/**
|
||||||
* Updates the envelope with the provided preset data.
|
* Updates the envelope with the provided preset data.
|
||||||
*
|
*
|
||||||
* @param Envelope $envelope the envelope to be updated
|
* This method applies the preset data to the envelope, but only for fields
|
||||||
|
* that aren't already set. Envelope-specific settings take precedence over
|
||||||
|
* preset defaults.
|
||||||
*
|
*
|
||||||
* @phpstan-param PresetType $preset The preset data to apply.
|
* @param Envelope $envelope The envelope to update
|
||||||
|
* @param PresetType $preset The preset data to apply
|
||||||
*/
|
*/
|
||||||
private function updateEnvelope(Envelope $envelope, array $preset): void
|
private function updateEnvelope(Envelope $envelope, array $preset): void
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,10 +14,23 @@ use Flasher\Prime\Stamp\IdStamp;
|
|||||||
use Flasher\Prime\Stamp\PriorityStamp;
|
use Flasher\Prime\Stamp\PriorityStamp;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener responsible for attaching default stamps to envelopes during persist and update events.
|
* AttachDefaultStampsListener - Ensures notifications have required stamps.
|
||||||
|
*
|
||||||
|
* This listener is responsible for ensuring that all notification envelopes
|
||||||
|
* have the required system stamps. These stamps provide essential functionality
|
||||||
|
* like identification, timing, and lifecycle management.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Decorator: Adds default stamps to notification envelopes
|
||||||
|
* - Template Method: Defines a standard set of stamps for all notifications
|
||||||
*/
|
*/
|
||||||
final readonly class AttachDefaultStampsListener implements EventListenerInterface
|
final readonly class AttachDefaultStampsListener implements EventListenerInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Handles persist and update events by attaching default stamps.
|
||||||
|
*
|
||||||
|
* @param PersistEvent|UpdateEvent $event The event to handle
|
||||||
|
*/
|
||||||
public function __invoke(PersistEvent|UpdateEvent $event): void
|
public function __invoke(PersistEvent|UpdateEvent $event): void
|
||||||
{
|
{
|
||||||
foreach ($event->getEnvelopes() as $envelope) {
|
foreach ($event->getEnvelopes() as $envelope) {
|
||||||
@@ -26,6 +39,11 @@ final readonly class AttachDefaultStampsListener implements EventListenerInterfa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* This listener subscribes to both persist and update events to ensure
|
||||||
|
* that stamps are attached to notifications in both scenarios.
|
||||||
|
*
|
||||||
* @return string[]
|
* @return string[]
|
||||||
*/
|
*/
|
||||||
public function getSubscribedEvents(): array
|
public function getSubscribedEvents(): array
|
||||||
@@ -36,6 +54,18 @@ final readonly class AttachDefaultStampsListener implements EventListenerInterfa
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches default stamps to an envelope if they don't already exist.
|
||||||
|
*
|
||||||
|
* The default stamps are:
|
||||||
|
* - CreatedAtStamp: Records when the notification was created
|
||||||
|
* - IdStamp: Provides a unique identifier
|
||||||
|
* - DelayStamp: Controls display timing (default: immediate)
|
||||||
|
* - HopsStamp: Controls persistence across requests (default: 1 request)
|
||||||
|
* - PriorityStamp: Controls display order (default: normal priority)
|
||||||
|
*
|
||||||
|
* @param Envelope $envelope The envelope to attach stamps to
|
||||||
|
*/
|
||||||
private function attachStamps(Envelope $envelope): void
|
private function attachStamps(Envelope $envelope): void
|
||||||
{
|
{
|
||||||
$envelope->withStamp(new CreatedAtStamp(), false);
|
$envelope->withStamp(new CreatedAtStamp(), false);
|
||||||
|
|||||||
@@ -8,8 +8,28 @@ use Flasher\Prime\EventDispatcher\Event\RemoveEvent;
|
|||||||
use Flasher\Prime\Notification\Envelope;
|
use Flasher\Prime\Notification\Envelope;
|
||||||
use Flasher\Prime\Stamp\HopsStamp;
|
use Flasher\Prime\Stamp\HopsStamp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* EnvelopeRemovalListener - Manages notification lifecycle across requests.
|
||||||
|
*
|
||||||
|
* This listener is responsible for implementing the "hops" feature, which allows
|
||||||
|
* notifications to persist across multiple page loads or redirects. When a notification
|
||||||
|
* is removed, this listener checks if it has remaining hops and if so, decrements
|
||||||
|
* the hop count and keeps the notification in storage.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Chain of Responsibility: Processes each envelope and decides its fate
|
||||||
|
* - State: Manages the state transition of notifications across requests
|
||||||
|
*/
|
||||||
final readonly class EnvelopeRemovalListener implements EventListenerInterface
|
final readonly class EnvelopeRemovalListener implements EventListenerInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Handles remove events by categorizing envelopes into keep and remove groups.
|
||||||
|
*
|
||||||
|
* This method processes the envelopes marked for removal, checking if any should
|
||||||
|
* be kept based on their hop count.
|
||||||
|
*
|
||||||
|
* @param RemoveEvent $event The remove event
|
||||||
|
*/
|
||||||
public function __invoke(RemoveEvent $event): void
|
public function __invoke(RemoveEvent $event): void
|
||||||
{
|
{
|
||||||
[$envelopesToKeep, $envelopesToRemove] = $this->categorizeEnvelopes($event->getEnvelopesToRemove());
|
[$envelopesToKeep, $envelopesToRemove] = $this->categorizeEnvelopes($event->getEnvelopesToRemove());
|
||||||
@@ -24,9 +44,15 @@ final readonly class EnvelopeRemovalListener implements EventListenerInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Envelope[] $envelopes
|
* Categorizes envelopes into those to keep and those to remove.
|
||||||
*
|
*
|
||||||
* @return array<Envelope[]>
|
* For each envelope:
|
||||||
|
* - If it has a HopsStamp with a count > 1, decrement the count and keep it
|
||||||
|
* - Otherwise, mark it for removal
|
||||||
|
*
|
||||||
|
* @param Envelope[] $envelopes The envelopes to categorize
|
||||||
|
*
|
||||||
|
* @return array<Envelope[]> Array with [0] => envelopes to keep, [1] => envelopes to remove
|
||||||
*/
|
*/
|
||||||
private function categorizeEnvelopes(array $envelopes): array
|
private function categorizeEnvelopes(array $envelopes): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,19 +5,44 @@ declare(strict_types=1);
|
|||||||
namespace Flasher\Prime\EventDispatcher\EventListener;
|
namespace Flasher\Prime\EventDispatcher\EventListener;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Event listener interface for handling events.
|
* EventListenerInterface - Contract for event listeners.
|
||||||
* Implementers should define an __invoke method with their specific event type.
|
|
||||||
*
|
*
|
||||||
* Example: function __invoke(MyCustomEvent $event): void
|
* This interface defines the essential operations for event listeners in the
|
||||||
|
* PHPFlasher event system. Implementers should define an __invoke method that
|
||||||
|
* processes events they're interested in and declare which events they listen to.
|
||||||
*
|
*
|
||||||
* @method void __invoke(object $event)
|
* Design patterns:
|
||||||
|
* - Observer: Defines a contract for objects that observe and respond to events
|
||||||
|
* - Visitor: Allows operations to be performed on event objects
|
||||||
|
*
|
||||||
|
* Example implementation:
|
||||||
|
* ```php
|
||||||
|
* class MyListener implements EventListenerInterface
|
||||||
|
* {
|
||||||
|
* public function __invoke(MyEvent $event): void
|
||||||
|
* {
|
||||||
|
* // Handle the event
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* public function getSubscribedEvents(): string
|
||||||
|
* {
|
||||||
|
* return MyEvent::class;
|
||||||
|
* }
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @method void __invoke(object $event) Method that handles the event
|
||||||
*/
|
*/
|
||||||
interface EventListenerInterface
|
interface EventListenerInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Returns a list of event names this listener wants to listen to.
|
* Returns a list of event names this listener wants to listen to.
|
||||||
*
|
*
|
||||||
* @return string|string[]
|
* The returned value can be:
|
||||||
|
* - A string: Single event class name
|
||||||
|
* - An array: Multiple event class names
|
||||||
|
*
|
||||||
|
* @return string|string[] The event class name(s) this listener subscribes to
|
||||||
*/
|
*/
|
||||||
public function getSubscribedEvents(): string|array;
|
public function getSubscribedEvents(): string|array;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,26 +9,56 @@ use Flasher\Prime\EventDispatcher\Event\PersistEvent;
|
|||||||
use Flasher\Prime\EventDispatcher\Event\PresentationEvent;
|
use Flasher\Prime\EventDispatcher\Event\PresentationEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @internal
|
* NotificationLoggerListener - Logs all notifications that are dispatched and displayed.
|
||||||
|
*
|
||||||
|
* This listener keeps track of all notification envelopes that are dispatched to storage
|
||||||
|
* and those that are actually displayed to users. It's useful for debugging and testing
|
||||||
|
* to see which notifications were created vs which were actually shown.
|
||||||
|
*
|
||||||
|
* @internal This class is not part of the public API and may change without notice
|
||||||
*/
|
*/
|
||||||
final class NotificationLoggerListener implements EventListenerInterface
|
final class NotificationLoggerListener implements EventListenerInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Collection of envelopes that were dispatched to storage.
|
||||||
|
*/
|
||||||
private NotificationEvents $dispatchedEnvelopes;
|
private NotificationEvents $dispatchedEnvelopes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Collection of envelopes that were displayed to users.
|
||||||
|
*/
|
||||||
private NotificationEvents $displayedEnvelopes;
|
private NotificationEvents $displayedEnvelopes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new NotificationLoggerListener instance.
|
||||||
|
*
|
||||||
|
* Initializes empty collections for tracking dispatched and displayed notifications.
|
||||||
|
*/
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->dispatchedEnvelopes = new NotificationEvents();
|
$this->dispatchedEnvelopes = new NotificationEvents();
|
||||||
$this->displayedEnvelopes = new NotificationEvents();
|
$this->displayedEnvelopes = new NotificationEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the listener, clearing all tracked notifications.
|
||||||
|
*
|
||||||
|
* This is useful for testing or when you want to start with a clean slate.
|
||||||
|
*/
|
||||||
public function reset(): void
|
public function reset(): void
|
||||||
{
|
{
|
||||||
$this->dispatchedEnvelopes = new NotificationEvents();
|
$this->dispatchedEnvelopes = new NotificationEvents();
|
||||||
$this->displayedEnvelopes = new NotificationEvents();
|
$this->displayedEnvelopes = new NotificationEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles incoming events by delegating to specialized methods.
|
||||||
|
*
|
||||||
|
* This method implements the __invoke method required by the EventListenerInterface.
|
||||||
|
* It routes events to the appropriate handler method based on their type.
|
||||||
|
*
|
||||||
|
* @param object $event The event to handle
|
||||||
|
*/
|
||||||
public function __invoke(object $event): void
|
public function __invoke(object $event): void
|
||||||
{
|
{
|
||||||
if ($event instanceof PersistEvent) {
|
if ($event instanceof PersistEvent) {
|
||||||
@@ -40,21 +70,41 @@ final class NotificationLoggerListener implements EventListenerInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles persist events by logging the notifications being stored.
|
||||||
|
*
|
||||||
|
* @param PersistEvent $event The persist event
|
||||||
|
*/
|
||||||
public function onPersist(PersistEvent $event): void
|
public function onPersist(PersistEvent $event): void
|
||||||
{
|
{
|
||||||
$this->dispatchedEnvelopes->add(...$event->getEnvelopes());
|
$this->dispatchedEnvelopes->add(...$event->getEnvelopes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles presentation events by logging the notifications being displayed.
|
||||||
|
*
|
||||||
|
* @param PresentationEvent $event The presentation event
|
||||||
|
*/
|
||||||
public function onPresentation(PresentationEvent $event): void
|
public function onPresentation(PresentationEvent $event): void
|
||||||
{
|
{
|
||||||
$this->displayedEnvelopes->add(...$event->getEnvelopes());
|
$this->displayedEnvelopes->add(...$event->getEnvelopes());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the collection of envelopes that were dispatched to storage.
|
||||||
|
*
|
||||||
|
* @return NotificationEvents Collection of dispatched notification envelopes
|
||||||
|
*/
|
||||||
public function getDispatchedEnvelopes(): NotificationEvents
|
public function getDispatchedEnvelopes(): NotificationEvents
|
||||||
{
|
{
|
||||||
return $this->dispatchedEnvelopes;
|
return $this->dispatchedEnvelopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the collection of envelopes that were displayed to users.
|
||||||
|
*
|
||||||
|
* @return NotificationEvents Collection of displayed notification envelopes
|
||||||
|
*/
|
||||||
public function getDisplayedEnvelopes(): NotificationEvents
|
public function getDisplayedEnvelopes(): NotificationEvents
|
||||||
{
|
{
|
||||||
return $this->displayedEnvelopes;
|
return $this->displayedEnvelopes;
|
||||||
|
|||||||
@@ -13,17 +13,41 @@ use Flasher\Prime\Translation\Language;
|
|||||||
use Flasher\Prime\Translation\TranslatorInterface;
|
use Flasher\Prime\Translation\TranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Listener responsible for applying translations to envelopes during presentation events based on TranslationStamps and locale settings.
|
* TranslationListener - Applies translations to notifications during presentation.
|
||||||
|
*
|
||||||
|
* This listener is responsible for translating notification titles and messages
|
||||||
|
* before they are displayed to users. It also sets RTL mode for right-to-left
|
||||||
|
* languages and translates preset parameters.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Decorator: Adds translation functionality to notifications
|
||||||
|
* - Strategy: Uses pluggable translation strategies via TranslatorInterface
|
||||||
*/
|
*/
|
||||||
final readonly class TranslationListener implements EventListenerInterface
|
final readonly class TranslationListener implements EventListenerInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* The translator to use for translating notification content.
|
||||||
|
*/
|
||||||
private TranslatorInterface $translator;
|
private TranslatorInterface $translator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new TranslationListener instance.
|
||||||
|
*
|
||||||
|
* If no translator is provided, falls back to the EchoTranslator which simply
|
||||||
|
* returns the input strings unchanged.
|
||||||
|
*
|
||||||
|
* @param TranslatorInterface|null $translator The translator to use
|
||||||
|
*/
|
||||||
public function __construct(?TranslatorInterface $translator = null)
|
public function __construct(?TranslatorInterface $translator = null)
|
||||||
{
|
{
|
||||||
$this->translator = $translator ?: new EchoTranslator();
|
$this->translator = $translator ?: new EchoTranslator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles presentation events by translating all notifications.
|
||||||
|
*
|
||||||
|
* @param PresentationEvent $event The presentation event
|
||||||
|
*/
|
||||||
public function __invoke(PresentationEvent $event): void
|
public function __invoke(PresentationEvent $event): void
|
||||||
{
|
{
|
||||||
foreach ($event->getEnvelopes() as $envelope) {
|
foreach ($event->getEnvelopes() as $envelope) {
|
||||||
@@ -36,6 +60,17 @@ final readonly class TranslationListener implements EventListenerInterface
|
|||||||
return PresentationEvent::class;
|
return PresentationEvent::class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates a notification envelope.
|
||||||
|
*
|
||||||
|
* This method:
|
||||||
|
* 1. Determines the appropriate locale
|
||||||
|
* 2. Gathers translation parameters
|
||||||
|
* 3. Applies translations to title and message
|
||||||
|
* 4. Sets RTL mode if needed
|
||||||
|
*
|
||||||
|
* @param Envelope $envelope The notification envelope to translate
|
||||||
|
*/
|
||||||
private function translateEnvelope(Envelope $envelope): void
|
private function translateEnvelope(Envelope $envelope): void
|
||||||
{
|
{
|
||||||
$translationStamp = $envelope->get(TranslationStamp::class);
|
$translationStamp = $envelope->get(TranslationStamp::class);
|
||||||
@@ -53,7 +88,14 @@ final readonly class TranslationListener implements EventListenerInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string, mixed>
|
* Extracts and translates parameters from preset stamps.
|
||||||
|
*
|
||||||
|
* @param Envelope $envelope The notification envelope
|
||||||
|
* @param string $locale The locale to use
|
||||||
|
*
|
||||||
|
* @return array<string, mixed> The translated parameters
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException If a parameter value is not a string
|
||||||
*/
|
*/
|
||||||
private function getParameters(Envelope $envelope, string $locale): array
|
private function getParameters(Envelope $envelope, string $locale): array
|
||||||
{
|
{
|
||||||
@@ -76,7 +118,13 @@ final readonly class TranslationListener implements EventListenerInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, mixed> $parameters
|
* Applies translations to the notification title and message.
|
||||||
|
*
|
||||||
|
* If the title is empty, the notification type is used as a fallback.
|
||||||
|
*
|
||||||
|
* @param Envelope $envelope The notification envelope
|
||||||
|
* @param string $locale The locale to use
|
||||||
|
* @param array<string, mixed> $parameters The translation parameters
|
||||||
*/
|
*/
|
||||||
private function applyTranslations(Envelope $envelope, string $locale, array $parameters): void
|
private function applyTranslations(Envelope $envelope, string $locale, array $parameters): void
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,10 +4,24 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Flasher\Prime\Exception;
|
namespace Flasher\Prime\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CriteriaNotRegisteredException - Thrown when an unregistered filter criterion is requested.
|
||||||
|
*
|
||||||
|
* This exception is thrown when attempting to use a filter criterion that hasn't been
|
||||||
|
* registered with the FilterFactory. It provides a clear error message that includes
|
||||||
|
* the requested criterion name and available criteria for debugging purposes.
|
||||||
|
*
|
||||||
|
* Design pattern: Domain-specific exception - Provides contextual information about the error.
|
||||||
|
*/
|
||||||
final class CriteriaNotRegisteredException extends \Exception
|
final class CriteriaNotRegisteredException extends \Exception
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param string[] $availableCriteria
|
* Creates a new CriteriaNotRegisteredException with a descriptive message.
|
||||||
|
*
|
||||||
|
* @param string $alias The name of the criterion that was requested
|
||||||
|
* @param string[] $availableCriteria The list of registered criteria names
|
||||||
|
*
|
||||||
|
* @return self The exception instance
|
||||||
*/
|
*/
|
||||||
public static function create(string $alias, array $availableCriteria = []): self
|
public static function create(string $alias, array $availableCriteria = []): self
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,10 +4,24 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Flasher\Prime\Exception;
|
namespace Flasher\Prime\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FactoryNotFoundException - Thrown when an unregistered notification factory is requested.
|
||||||
|
*
|
||||||
|
* This exception is thrown when attempting to use a notification factory that hasn't been
|
||||||
|
* registered with the system. It provides a clear error message that includes the requested
|
||||||
|
* factory name and available factories for debugging purposes.
|
||||||
|
*
|
||||||
|
* Design pattern: Domain-specific exception - Provides contextual information about the error.
|
||||||
|
*/
|
||||||
final class FactoryNotFoundException extends \Exception
|
final class FactoryNotFoundException extends \Exception
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param string[] $availableFactories
|
* Creates a new FactoryNotFoundException with a descriptive message.
|
||||||
|
*
|
||||||
|
* @param string $alias The name of the factory that was requested
|
||||||
|
* @param string[] $availableFactories The list of registered factory names
|
||||||
|
*
|
||||||
|
* @return self The exception instance
|
||||||
*/
|
*/
|
||||||
public static function create(string $alias, array $availableFactories = []): self
|
public static function create(string $alias, array $availableFactories = []): self
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,10 +4,24 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Flasher\Prime\Exception;
|
namespace Flasher\Prime\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PresenterNotFoundException - Thrown when an unregistered presenter is requested.
|
||||||
|
*
|
||||||
|
* This exception is thrown when attempting to use a notification presenter that hasn't been
|
||||||
|
* registered with the system. It provides a clear error message that includes the requested
|
||||||
|
* presenter name and available presenters for debugging purposes.
|
||||||
|
*
|
||||||
|
* Design pattern: Domain-specific exception - Provides contextual information about the error.
|
||||||
|
*/
|
||||||
final class PresenterNotFoundException extends \Exception
|
final class PresenterNotFoundException extends \Exception
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param string[] $availablePresenters
|
* Creates a new PresenterNotFoundException with a descriptive message.
|
||||||
|
*
|
||||||
|
* @param string $alias The name of the presenter that was requested
|
||||||
|
* @param string[] $availablePresenters The list of registered presenter names
|
||||||
|
*
|
||||||
|
* @return self The exception instance
|
||||||
*/
|
*/
|
||||||
public static function create(string $alias, array $availablePresenters = []): self
|
public static function create(string $alias, array $availablePresenters = []): self
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,11 +4,25 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Flasher\Prime\Exception;
|
namespace Flasher\Prime\Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PresetNotFoundException - Thrown when an unregistered notification preset is requested.
|
||||||
|
*
|
||||||
|
* This exception is thrown when attempting to use a notification preset that hasn't been
|
||||||
|
* registered with the system. Presets define reusable notification templates that can be
|
||||||
|
* referenced by name. The exception provides a clear error message that includes the requested
|
||||||
|
* preset name and available presets for debugging purposes.
|
||||||
|
*
|
||||||
|
* Design pattern: Domain-specific exception - Provides contextual information about the error.
|
||||||
|
*/
|
||||||
final class PresetNotFoundException extends \Exception
|
final class PresetNotFoundException extends \Exception
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param string $preset the name of the preset that was not found
|
* Creates a new PresetNotFoundException with a descriptive message.
|
||||||
* @param string[] $availablePresets the list of available presets for reference
|
*
|
||||||
|
* @param string $preset The name of the preset that was not found
|
||||||
|
* @param string[] $availablePresets The list of available presets for reference
|
||||||
|
*
|
||||||
|
* @return self The exception instance
|
||||||
*/
|
*/
|
||||||
public static function create(string $preset, array $availablePresets = []): self
|
public static function create(string $preset, array $availablePresets = []): self
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,10 +8,27 @@ use Flasher\Prime\Notification\FlasherBuilder;
|
|||||||
use Flasher\Prime\Notification\NotificationBuilderInterface;
|
use Flasher\Prime\Notification\NotificationBuilderInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Default implementation of FlasherFactoryInterface.
|
||||||
|
*
|
||||||
|
* This factory creates FlasherBuilder instances for constructing notifications
|
||||||
|
* with the default PHPFlasher implementation. It extends the base NotificationFactory
|
||||||
|
* to inherit common factory functionality.
|
||||||
|
*
|
||||||
|
* Design pattern: Factory Method - Defines an interface for creating objects,
|
||||||
|
* but lets subclasses decide which class to instantiate.
|
||||||
|
*
|
||||||
* @mixin \Flasher\Prime\Notification\FlasherBuilder
|
* @mixin \Flasher\Prime\Notification\FlasherBuilder
|
||||||
*/
|
*/
|
||||||
final class FlasherFactory extends NotificationFactory implements FlasherFactoryInterface
|
final class FlasherFactory extends NotificationFactory implements FlasherFactoryInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates a new FlasherBuilder instance.
|
||||||
|
*
|
||||||
|
* This implementation returns a FlasherBuilder configured with the current plugin name.
|
||||||
|
* The builder provides a fluent API for constructing notifications with type-safe methods.
|
||||||
|
*
|
||||||
|
* @return NotificationBuilderInterface The created notification builder
|
||||||
|
*/
|
||||||
public function createNotificationBuilder(): NotificationBuilderInterface
|
public function createNotificationBuilder(): NotificationBuilderInterface
|
||||||
{
|
{
|
||||||
return new FlasherBuilder($this->plugin ?? 'flasher', $this->storageManager);
|
return new FlasherBuilder($this->plugin ?? 'flasher', $this->storageManager);
|
||||||
|
|||||||
@@ -5,6 +5,13 @@ declare(strict_types=1);
|
|||||||
namespace Flasher\Prime\Factory;
|
namespace Flasher\Prime\Factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Factory interface for creating Flasher-specific notification builders.
|
||||||
|
*
|
||||||
|
* This interface extends the base NotificationFactoryInterface to provide
|
||||||
|
* type safety when working specifically with the default Flasher implementation.
|
||||||
|
* It ensures that methods like createNotificationBuilder() return Flasher-specific
|
||||||
|
* builder instances.
|
||||||
|
*
|
||||||
* @mixin \Flasher\Prime\Notification\FlasherBuilder
|
* @mixin \Flasher\Prime\Notification\FlasherBuilder
|
||||||
*/
|
*/
|
||||||
interface FlasherFactoryInterface extends NotificationFactoryInterface
|
interface FlasherFactoryInterface extends NotificationFactoryInterface
|
||||||
|
|||||||
@@ -8,18 +8,53 @@ use Flasher\Prime\Storage\StorageManagerInterface;
|
|||||||
use Flasher\Prime\Support\Traits\ForwardsCalls;
|
use Flasher\Prime\Support\Traits\ForwardsCalls;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Base abstract class for notification factories.
|
||||||
|
*
|
||||||
|
* This abstract class provides common functionality for all notification factories,
|
||||||
|
* such as storage management and method forwarding to notification builders.
|
||||||
|
* Specific factory implementations should extend this class and implement
|
||||||
|
* the createNotificationBuilder() method.
|
||||||
|
*
|
||||||
|
* Design pattern: Template Method - Defines the skeleton of an algorithm,
|
||||||
|
* deferring some steps to subclasses.
|
||||||
|
*
|
||||||
* @mixin \Flasher\Prime\Notification\NotificationBuilderInterface
|
* @mixin \Flasher\Prime\Notification\NotificationBuilderInterface
|
||||||
*/
|
*/
|
||||||
abstract class NotificationFactory implements NotificationFactoryInterface
|
abstract class NotificationFactory implements NotificationFactoryInterface
|
||||||
{
|
{
|
||||||
use ForwardsCalls;
|
use ForwardsCalls;
|
||||||
|
|
||||||
public function __construct(protected StorageManagerInterface $storageManager, protected ?string $plugin = null)
|
/**
|
||||||
{
|
* Creates a new NotificationFactory instance.
|
||||||
|
*
|
||||||
|
* @param StorageManagerInterface $storageManager The storage manager for persisting notifications
|
||||||
|
* @param string|null $plugin The plugin/adapter name (e.g., 'toastr', 'sweetalert')
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
protected StorageManagerInterface $storageManager,
|
||||||
|
protected ?string $plugin = null,
|
||||||
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param mixed[] $parameters
|
* Dynamically forwards method calls to a notification builder instance.
|
||||||
|
*
|
||||||
|
* This magic method allows calling notification builder methods directly on the factory,
|
||||||
|
* creating a more fluent API for client code.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```php
|
||||||
|
* // Instead of:
|
||||||
|
* $factory->createNotificationBuilder()->success('Message');
|
||||||
|
*
|
||||||
|
* // You can do:
|
||||||
|
* $factory->success('Message');
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param string $method The method name to call
|
||||||
|
* @param mixed[] $parameters The parameters to pass to the method
|
||||||
|
*
|
||||||
|
* @return mixed The result of the method call
|
||||||
*/
|
*/
|
||||||
public function __call(string $method, array $parameters): mixed
|
public function __call(string $method, array $parameters): mixed
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,9 +7,26 @@ namespace Flasher\Prime\Factory;
|
|||||||
use Flasher\Prime\Notification\NotificationBuilderInterface;
|
use Flasher\Prime\Notification\NotificationBuilderInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* NotificationFactoryInterface - Core factory abstraction.
|
||||||
|
*
|
||||||
|
* Defines the contract for all notification factories that can create
|
||||||
|
* notification builders. This interface enables the system to work
|
||||||
|
* with different notification implementations through a common API.
|
||||||
|
*
|
||||||
|
* Design pattern: Abstract Factory - Provides an interface for creating
|
||||||
|
* families of related objects without specifying concrete classes.
|
||||||
|
*
|
||||||
* @mixin \Flasher\Prime\Notification\NotificationBuilderInterface
|
* @mixin \Flasher\Prime\Notification\NotificationBuilderInterface
|
||||||
*/
|
*/
|
||||||
interface NotificationFactoryInterface
|
interface NotificationFactoryInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Creates a notification builder instance.
|
||||||
|
*
|
||||||
|
* Each implementation of this method should return a builder tailored
|
||||||
|
* to the specific notification library or system that the factory supports.
|
||||||
|
*
|
||||||
|
* @return NotificationBuilderInterface A builder for constructing notifications
|
||||||
|
*/
|
||||||
public function createNotificationBuilder(): NotificationBuilderInterface;
|
public function createNotificationBuilder(): NotificationBuilderInterface;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,13 +6,37 @@ namespace Flasher\Prime\Factory;
|
|||||||
|
|
||||||
use Flasher\Prime\Exception\FactoryNotFoundException;
|
use Flasher\Prime\Exception\FactoryNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NotificationFactoryLocator - Registry of available factories.
|
||||||
|
*
|
||||||
|
* Maintains a registry of all available notification factories, allowing
|
||||||
|
* the system to look up the appropriate factory by name at runtime.
|
||||||
|
* Factories can be registered as instances or lazy-loaded through callbacks.
|
||||||
|
*
|
||||||
|
* Design pattern: Service Locator - Centralizes factory discovery and
|
||||||
|
* instantiation, enabling loose coupling between components.
|
||||||
|
*/
|
||||||
final class NotificationFactoryLocator implements NotificationFactoryLocatorInterface
|
final class NotificationFactoryLocator implements NotificationFactoryLocatorInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* Map of factory aliases to instances or factory callbacks.
|
||||||
|
*
|
||||||
* @var array<string, callable|NotificationFactoryInterface>
|
* @var array<string, callable|NotificationFactoryInterface>
|
||||||
*/
|
*/
|
||||||
private array $factories = [];
|
private array $factories = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a notification factory by its identifier.
|
||||||
|
*
|
||||||
|
* If the factory was registered as a callback, it will be invoked to create
|
||||||
|
* the actual factory instance on first access.
|
||||||
|
*
|
||||||
|
* @param string $id The identifier for the factory to retrieve
|
||||||
|
*
|
||||||
|
* @return NotificationFactoryInterface The requested notification factory
|
||||||
|
*
|
||||||
|
* @throws FactoryNotFoundException If no factory is registered with the given identifier
|
||||||
|
*/
|
||||||
public function get(string $id): NotificationFactoryInterface
|
public function get(string $id): NotificationFactoryInterface
|
||||||
{
|
{
|
||||||
if (!$this->has($id)) {
|
if (!$this->has($id)) {
|
||||||
@@ -24,6 +48,13 @@ final class NotificationFactoryLocator implements NotificationFactoryLocatorInte
|
|||||||
return \is_callable($factory) ? $factory() : $factory;
|
return \is_callable($factory) ? $factory() : $factory;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a notification factory exists for the given identifier.
|
||||||
|
*
|
||||||
|
* @param string $id The identifier to check
|
||||||
|
*
|
||||||
|
* @return bool True if a factory exists for the given identifier, false otherwise
|
||||||
|
*/
|
||||||
public function has(string $id): bool
|
public function has(string $id): bool
|
||||||
{
|
{
|
||||||
return \array_key_exists($id, $this->factories);
|
return \array_key_exists($id, $this->factories);
|
||||||
@@ -31,6 +62,23 @@ final class NotificationFactoryLocator implements NotificationFactoryLocatorInte
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Register a custom notification factory.
|
* Register a custom notification factory.
|
||||||
|
*
|
||||||
|
* This method allows registering either a factory instance directly or a callback
|
||||||
|
* that creates the factory when needed (lazy-loading).
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```php
|
||||||
|
* // Register a factory instance
|
||||||
|
* $locator->addFactory('custom', new CustomFactory($storageManager));
|
||||||
|
*
|
||||||
|
* // Register a factory with lazy-loading
|
||||||
|
* $locator->addFactory('custom', function() use ($storageManager) {
|
||||||
|
* return new ExpensiveFactory($storageManager);
|
||||||
|
* });
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param string $alias The identifier for the factory
|
||||||
|
* @param callable|NotificationFactoryInterface $factory The factory instance or a callback that returns one
|
||||||
*/
|
*/
|
||||||
public function addFactory(string $alias, callable|NotificationFactoryInterface $factory): void
|
public function addFactory(string $alias, callable|NotificationFactoryInterface $factory): void
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -4,11 +4,37 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Flasher\Prime\Factory;
|
namespace Flasher\Prime\Factory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface for the notification factory locator service.
|
||||||
|
*
|
||||||
|
* This interface defines the contract for a service that locates and
|
||||||
|
* provides notification factories by their identifiers. It allows the
|
||||||
|
* system to resolve factories at runtime without directly coupling to
|
||||||
|
* specific implementations.
|
||||||
|
*
|
||||||
|
* Design pattern: Service Locator - Provides a centralized registry
|
||||||
|
* for finding and accessing services.
|
||||||
|
*/
|
||||||
interface NotificationFactoryLocatorInterface
|
interface NotificationFactoryLocatorInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Checks if a notification factory exists for the given identifier.
|
||||||
|
*
|
||||||
|
* @param string $id The identifier to check
|
||||||
|
*
|
||||||
|
* @return bool True if a factory exists for the given identifier, false otherwise
|
||||||
|
*/
|
||||||
public function has(string $id): bool;
|
public function has(string $id): bool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Gets a notification factory by its identifier.
|
||||||
|
*
|
||||||
|
* @param string $id The identifier for the factory to retrieve
|
||||||
|
*
|
||||||
|
* @return NotificationFactoryInterface The requested notification factory
|
||||||
|
*
|
||||||
|
* @throws \Flasher\Prime\Exception\FactoryNotFoundException If no factory is registered with the given identifier
|
||||||
|
*
|
||||||
* @phpstan-return ($id is 'flasher' ? \Flasher\Prime\Factory\FlasherFactoryInterface :
|
* @phpstan-return ($id is 'flasher' ? \Flasher\Prime\Factory\FlasherFactoryInterface :
|
||||||
* ($id is 'noty' ? \Flasher\Noty\Prime\NotyInterface :
|
* ($id is 'noty' ? \Flasher\Noty\Prime\NotyInterface :
|
||||||
* ($id is 'notyf' ? \Flasher\Notyf\Prime\NotyfInterface :
|
* ($id is 'notyf' ? \Flasher\Notyf\Prime\NotyfInterface :
|
||||||
|
|||||||
+57
-2
@@ -11,12 +11,34 @@ use Flasher\Prime\Response\ResponseManagerInterface;
|
|||||||
use Flasher\Prime\Storage\StorageManagerInterface;
|
use Flasher\Prime\Storage\StorageManagerInterface;
|
||||||
use Flasher\Prime\Support\Traits\ForwardsCalls;
|
use Flasher\Prime\Support\Traits\ForwardsCalls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Core implementation of the FlasherInterface.
|
||||||
|
*
|
||||||
|
* This class serves as the central hub for the notification system, managing
|
||||||
|
* factories, storage, and response handling. It implements the Façade pattern
|
||||||
|
* to provide a clean, simple API for client code while coordinating complex
|
||||||
|
* subsystems behind the scenes.
|
||||||
|
*
|
||||||
|
* Design pattern: Façade - Provides a simplified interface to a complex system,
|
||||||
|
* delegating to specialized components for specific functionality.
|
||||||
|
*/
|
||||||
final readonly class Flasher implements FlasherInterface
|
final readonly class Flasher implements FlasherInterface
|
||||||
{
|
{
|
||||||
use ForwardsCalls;
|
use ForwardsCalls;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current version of PHPFlasher.
|
||||||
|
*/
|
||||||
public const VERSION = '2.1.6';
|
public const VERSION = '2.1.6';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new Flasher instance.
|
||||||
|
*
|
||||||
|
* @param string $default The default factory to use when none is specified
|
||||||
|
* @param NotificationFactoryLocatorInterface $factoryLocator Service locator for notification factories
|
||||||
|
* @param ResponseManagerInterface $responseManager Manager for rendering notifications
|
||||||
|
* @param StorageManagerInterface $storageManager Manager for storing notifications
|
||||||
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
private string $default,
|
private string $default,
|
||||||
private NotificationFactoryLocatorInterface $factoryLocator,
|
private NotificationFactoryLocatorInterface $factoryLocator,
|
||||||
@@ -25,6 +47,13 @@ final readonly class Flasher implements FlasherInterface
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* This implementation tries to resolve the requested factory from the
|
||||||
|
* factory locator. If not found, it falls back to creating a generic
|
||||||
|
* FlasherFactory with the given alias.
|
||||||
|
*/
|
||||||
public function use(?string $alias): NotificationFactoryInterface
|
public function use(?string $alias): NotificationFactoryInterface
|
||||||
{
|
{
|
||||||
$alias = trim($alias ?: $this->default);
|
$alias = trim($alias ?: $this->default);
|
||||||
@@ -40,20 +69,46 @@ final readonly class Flasher implements FlasherInterface
|
|||||||
return new FlasherFactory($this->storageManager, $alias);
|
return new FlasherFactory($this->storageManager, $alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* This is an alias for the use() method.
|
||||||
|
*/
|
||||||
public function create(?string $alias): NotificationFactoryInterface
|
public function create(?string $alias): NotificationFactoryInterface
|
||||||
{
|
{
|
||||||
return $this->use($alias);
|
return $this->use($alias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* Delegates rendering to the response manager.
|
||||||
|
*/
|
||||||
public function render(string $presenter = 'html', array $criteria = [], array $context = []): mixed
|
public function render(string $presenter = 'html', array $criteria = [], array $context = []): mixed
|
||||||
{
|
{
|
||||||
return $this->responseManager->render($presenter, $criteria, $context);
|
return $this->responseManager->render($presenter, $criteria, $context);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dynamically call the default factory instance.
|
* Dynamically call methods on the default factory instance.
|
||||||
*
|
*
|
||||||
* @param mixed[] $parameters
|
* This magic method enables using the Flasher instance directly with
|
||||||
|
* notification methods like success(), error(), etc., without explicitly
|
||||||
|
* calling use() first.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```php
|
||||||
|
* // Instead of:
|
||||||
|
* $flasher->use('flasher')->success('Message');
|
||||||
|
*
|
||||||
|
* // You can do:
|
||||||
|
* $flasher->success('Message');
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param string $method The method name to call
|
||||||
|
* @param mixed[] $parameters The parameters to pass to the method
|
||||||
|
*
|
||||||
|
* @return mixed The result of the method call
|
||||||
*/
|
*/
|
||||||
public function __call(string $method, array $parameters): mixed
|
public function __call(string $method, array $parameters): mixed
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,6 +8,15 @@ use Flasher\Prime\Factory\NotificationFactoryInterface;
|
|||||||
use Flasher\Prime\Response\Presenter\ArrayPresenter;
|
use Flasher\Prime\Response\Presenter\ArrayPresenter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* FlasherInterface - The primary entry point to the notification system.
|
||||||
|
*
|
||||||
|
* This interface defines the contract for the notification service,
|
||||||
|
* providing methods to access notification factories and render
|
||||||
|
* notifications. It's the main touchpoint for client code.
|
||||||
|
*
|
||||||
|
* Design pattern: Façade Pattern - Provides a simplified interface
|
||||||
|
* to the complex notification subsystems.
|
||||||
|
*
|
||||||
* @mixin \Flasher\Prime\Notification\NotificationBuilder
|
* @mixin \Flasher\Prime\Notification\NotificationBuilder
|
||||||
*
|
*
|
||||||
* @phpstan-import-type ArrayPresenterType from ArrayPresenter
|
* @phpstan-import-type ArrayPresenterType from ArrayPresenter
|
||||||
@@ -15,9 +24,20 @@ use Flasher\Prime\Response\Presenter\ArrayPresenter;
|
|||||||
interface FlasherInterface
|
interface FlasherInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Get a notification factory instance.
|
* Get a notification factory instance by its alias.
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException
|
* This method provides access to specific notification factories (like Toastr, SweetAlert, etc.)
|
||||||
|
* through a unified interface. It allows you to use specialized notification features
|
||||||
|
* while maintaining a consistent API.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```php
|
||||||
|
* $flasher->use('toastr')->success('Message using Toastr library');
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param string $alias The alias of the factory to retrieve (e.g., 'toastr', 'sweetalert')
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException When the requested factory cannot be resolved
|
||||||
*
|
*
|
||||||
* @phpstan-return ($alias is 'flasher' ? \Flasher\Prime\Factory\FlasherFactoryInterface :
|
* @phpstan-return ($alias is 'flasher' ? \Flasher\Prime\Factory\FlasherFactoryInterface :
|
||||||
* ($alias is 'noty' ? \Flasher\Noty\Prime\NotyInterface :
|
* ($alias is 'noty' ? \Flasher\Noty\Prime\NotyInterface :
|
||||||
@@ -29,9 +49,19 @@ interface FlasherInterface
|
|||||||
public function use(string $alias): NotificationFactoryInterface;
|
public function use(string $alias): NotificationFactoryInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a notification factory instance.
|
* Get a notification factory instance by its alias (alias for use()).
|
||||||
*
|
*
|
||||||
* @throws \InvalidArgumentException
|
* This method is identical to use() but provides a more intuitive name
|
||||||
|
* for creating new notification factories.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```php
|
||||||
|
* $flasher->create('sweetalert')->success('Message using SweetAlert library');
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param string $alias The alias of the factory to retrieve (e.g., 'toastr', 'sweetalert')
|
||||||
|
*
|
||||||
|
* @throws \InvalidArgumentException When the requested factory cannot be resolved
|
||||||
*
|
*
|
||||||
* @phpstan-return ($alias is 'flasher' ? \Flasher\Prime\Factory\FlasherFactoryInterface :
|
* @phpstan-return ($alias is 'flasher' ? \Flasher\Prime\Factory\FlasherFactoryInterface :
|
||||||
* ($alias is 'noty' ? \Flasher\Noty\Prime\NotyInterface :
|
* ($alias is 'noty' ? \Flasher\Noty\Prime\NotyInterface :
|
||||||
@@ -45,9 +75,27 @@ interface FlasherInterface
|
|||||||
/**
|
/**
|
||||||
* Renders the flash notifications based on the specified criteria, presenter, and context.
|
* Renders the flash notifications based on the specified criteria, presenter, and context.
|
||||||
*
|
*
|
||||||
* @param array<string, mixed> $criteria the criteria to filter the notifications
|
* This method retrieves notifications from storage and formats them for display.
|
||||||
* @param string|"html"|"json" $presenter The presenter format for rendering the notifications (e.g., 'html', 'json').
|
* Different presenter formats can be specified (html, json, array) to support
|
||||||
* @param array<string, mixed> $context additional context or options for rendering
|
* various output requirements.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* ```php
|
||||||
|
* // Render as HTML
|
||||||
|
* $html = $flasher->render('html');
|
||||||
|
*
|
||||||
|
* // Render as JSON (for API responses)
|
||||||
|
* $json = $flasher->render('json');
|
||||||
|
*
|
||||||
|
* // Render with filtering criteria
|
||||||
|
* $errors = $flasher->render('html', ['type' => 'error']);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @param string $presenter The format to render notifications in ('html', 'json', 'array')
|
||||||
|
* @param array<string, mixed> $criteria Optional filtering criteria for notifications
|
||||||
|
* @param array<string, mixed> $context Additional context or options for rendering
|
||||||
|
*
|
||||||
|
* @return mixed The rendered notifications in the requested format
|
||||||
*
|
*
|
||||||
* @phpstan-return ($presenter is 'html' ? string :
|
* @phpstan-return ($presenter is 'html' ? string :
|
||||||
* ($presenter is 'array' ? ArrayPresenterType :
|
* ($presenter is 'array' ? ArrayPresenterType :
|
||||||
|
|||||||
@@ -7,13 +7,40 @@ namespace Flasher\Prime\Http\Csp;
|
|||||||
use Flasher\Prime\Http\RequestInterface;
|
use Flasher\Prime\Http\RequestInterface;
|
||||||
use Flasher\Prime\Http\ResponseInterface;
|
use Flasher\Prime\Http\ResponseInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ContentSecurityPolicyHandler - Manages Content Security Policy for PHPFlasher.
|
||||||
|
*
|
||||||
|
* This class handles the complex task of managing Content Security Policy (CSP) headers
|
||||||
|
* to allow PHPFlasher's JavaScript and CSS to run securely. It generates nonces for
|
||||||
|
* scripts and styles, modifies CSP headers to include these nonces, and ensures that
|
||||||
|
* inline code can execute without being blocked by CSP.
|
||||||
|
*
|
||||||
|
* Design patterns:
|
||||||
|
* - Strategy: Implements a specific approach to CSP handling
|
||||||
|
* - Adapter: Works with different request and response implementations
|
||||||
|
*/
|
||||||
final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandlerInterface
|
final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandlerInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Header for passing script nonce between components.
|
||||||
|
*/
|
||||||
private const SCRIPT_NONCE_HEADER = 'X-PHPFlasher-Script-Nonce';
|
private const SCRIPT_NONCE_HEADER = 'X-PHPFlasher-Script-Nonce';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Header for passing style nonce between components.
|
||||||
|
*/
|
||||||
private const STYLE_NONCE_HEADER = 'X-PHPFlasher-Style-Nonce';
|
private const STYLE_NONCE_HEADER = 'X-PHPFlasher-Style-Nonce';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether CSP handling is disabled.
|
||||||
|
*/
|
||||||
private bool $cspDisabled = false;
|
private bool $cspDisabled = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new ContentSecurityPolicyHandler instance.
|
||||||
|
*
|
||||||
|
* @param NonceGeneratorInterface $nonceGenerator The generator for creating secure nonces
|
||||||
|
*/
|
||||||
public function __construct(private readonly NonceGeneratorInterface $nonceGenerator)
|
public function __construct(private readonly NonceGeneratorInterface $nonceGenerator)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -62,7 +89,12 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
|||||||
/**
|
/**
|
||||||
* Returns nonces from headers if existing, otherwise null.
|
* Returns nonces from headers if existing, otherwise null.
|
||||||
*
|
*
|
||||||
* @return array{csp_script_nonce: ?string, csp_style_nonce: ?string}|null
|
* This method checks if the necessary nonce headers are present in the provided
|
||||||
|
* request or response object and returns their values if found.
|
||||||
|
*
|
||||||
|
* @param RequestInterface|ResponseInterface $object The object to check for nonce headers
|
||||||
|
*
|
||||||
|
* @return array{csp_script_nonce: ?string, csp_style_nonce: ?string}|null Nonce values or null if not found
|
||||||
*/
|
*/
|
||||||
private function getHeaderNonces(RequestInterface|ResponseInterface $object): ?array
|
private function getHeaderNonces(RequestInterface|ResponseInterface $object): ?array
|
||||||
{
|
{
|
||||||
@@ -76,12 +108,27 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes temporary nonce headers from the response.
|
||||||
|
*
|
||||||
|
* These headers are used internally to pass nonces between components but
|
||||||
|
* should not be sent to the client.
|
||||||
|
*
|
||||||
|
* @param ResponseInterface $response The response to clean
|
||||||
|
*/
|
||||||
private function cleanHeaders(ResponseInterface $response): void
|
private function cleanHeaders(ResponseInterface $response): void
|
||||||
{
|
{
|
||||||
$response->removeHeader(self::SCRIPT_NONCE_HEADER);
|
$response->removeHeader(self::SCRIPT_NONCE_HEADER);
|
||||||
$response->removeHeader(self::STYLE_NONCE_HEADER);
|
$response->removeHeader(self::STYLE_NONCE_HEADER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all CSP headers from the response.
|
||||||
|
*
|
||||||
|
* This is used when CSP handling is disabled to ensure no CSP restrictions are applied.
|
||||||
|
*
|
||||||
|
* @param ResponseInterface $response The response to modify
|
||||||
|
*/
|
||||||
private function removeCspHeaders(ResponseInterface $response): void
|
private function removeCspHeaders(ResponseInterface $response): void
|
||||||
{
|
{
|
||||||
$response->removeHeader('X-Content-Security-Policy');
|
$response->removeHeader('X-Content-Security-Policy');
|
||||||
@@ -92,9 +139,13 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
|||||||
/**
|
/**
|
||||||
* Updates Content-Security-Policy headers in a response.
|
* Updates Content-Security-Policy headers in a response.
|
||||||
*
|
*
|
||||||
* @param array{csp_script_nonce?: ?string, csp_style_nonce?: ?string} $nonces
|
* This method modifies existing CSP headers to include nonces for PHPFlasher's
|
||||||
|
* JavaScript and CSS, allowing them to execute without being blocked by CSP.
|
||||||
*
|
*
|
||||||
* @return array{csp_script_nonce?: ?string, csp_style_nonce?: ?string}
|
* @param ResponseInterface $response The response to modify
|
||||||
|
* @param array{csp_script_nonce?: ?string, csp_style_nonce?: ?string} $nonces The nonces to add to CSP
|
||||||
|
*
|
||||||
|
* @return array{csp_script_nonce?: ?string, csp_style_nonce?: ?string} The nonces used
|
||||||
*/
|
*/
|
||||||
private function updateCspHeaders(ResponseInterface $response, array $nonces = []): array
|
private function updateCspHeaders(ResponseInterface $response, array $nonces = []): array
|
||||||
{
|
{
|
||||||
@@ -153,6 +204,8 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a valid Content-Security-Policy nonce.
|
* Generates a valid Content-Security-Policy nonce.
|
||||||
|
*
|
||||||
|
* @return string The generated nonce
|
||||||
*/
|
*/
|
||||||
private function generateNonce(): string
|
private function generateNonce(): string
|
||||||
{
|
{
|
||||||
@@ -160,9 +213,11 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a directive set array into Content-Security-Policy header.
|
* Converts a directive set array into Content-Security-Policy header value.
|
||||||
*
|
*
|
||||||
* @param array<string, string[]> $directives
|
* @param array<string, string[]> $directives The CSP directives to convert
|
||||||
|
*
|
||||||
|
* @return string The formatted CSP header value
|
||||||
*/
|
*/
|
||||||
private function generateCspHeader(array $directives): string
|
private function generateCspHeader(array $directives): string
|
||||||
{
|
{
|
||||||
@@ -172,7 +227,9 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
|||||||
/**
|
/**
|
||||||
* Converts a Content-Security-Policy header value into a directive set array.
|
* Converts a Content-Security-Policy header value into a directive set array.
|
||||||
*
|
*
|
||||||
* @return array<string, string[]>
|
* @param string|null $header The CSP header value to parse
|
||||||
|
*
|
||||||
|
* @return array<string, string[]> The parsed directive set
|
||||||
*/
|
*/
|
||||||
private function parseDirectives(?string $header): array
|
private function parseDirectives(?string $header): array
|
||||||
{
|
{
|
||||||
@@ -191,9 +248,15 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Detects if the 'unsafe-inline' is prevented for a directive within the directive set.
|
* Detects if the 'unsafe-inline' is permitted for a directive within the directive set.
|
||||||
*
|
*
|
||||||
* @param array<string, string[]> $directivesSet
|
* This method checks if a specific CSP directive allows inline scripts or styles,
|
||||||
|
* taking into account CSP level 2+ hash and nonce exceptions.
|
||||||
|
*
|
||||||
|
* @param array<string, string[]> $directivesSet The directives to check
|
||||||
|
* @param string $type The directive type to check
|
||||||
|
*
|
||||||
|
* @return bool True if inline content is permitted
|
||||||
*/
|
*/
|
||||||
private function authorizesInline(array $directivesSet, string $type): bool
|
private function authorizesInline(array $directivesSet, string $type): bool
|
||||||
{
|
{
|
||||||
@@ -207,7 +270,14 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param string[] $directives
|
* Checks if a directive list contains hash or nonce restrictions.
|
||||||
|
*
|
||||||
|
* This is important for CSP processing because in CSP Level 2+, the presence of a
|
||||||
|
* hash or nonce invalidates 'unsafe-inline' even if it's present.
|
||||||
|
*
|
||||||
|
* @param string[] $directives The CSP directive values to check
|
||||||
|
*
|
||||||
|
* @return bool True if the directive list contains a hash or nonce restriction
|
||||||
*/
|
*/
|
||||||
private function hasHashOrNonce(array $directives): bool
|
private function hasHashOrNonce(array $directives): bool
|
||||||
{
|
{
|
||||||
@@ -227,9 +297,15 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param array<string, string[]> $directiveSet
|
* Finds the fallback directive for a specific directive type.
|
||||||
*
|
*
|
||||||
* @return string[]|null
|
* In CSP, if a specific directive isn't defined, browsers fall back to default-src.
|
||||||
|
* This method implements that behavior for the PHPFlasher CSP handler.
|
||||||
|
*
|
||||||
|
* @param array<string, string[]> $directiveSet The complete directive set
|
||||||
|
* @param string $type The directive type to find a fallback for
|
||||||
|
*
|
||||||
|
* @return string[]|null The fallback directive values, or null if no fallback exists
|
||||||
*/
|
*/
|
||||||
private function getDirectiveFallback(array $directiveSet, string $type): ?array
|
private function getDirectiveFallback(array $directiveSet, string $type): ?array
|
||||||
{
|
{
|
||||||
@@ -242,14 +318,18 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the Content-Security-Policy headers (either X-Content-Security-Policy or Content-Security-Policy) from
|
* Retrieves the Content-Security-Policy headers from a response.
|
||||||
* a response.
|
*
|
||||||
|
* This method extracts all CSP-related headers from the response
|
||||||
|
* and parses their values into directive sets.
|
||||||
|
*
|
||||||
|
* @param ResponseInterface $response The response to extract CSP headers from
|
||||||
*
|
*
|
||||||
* @return array{
|
* @return array{
|
||||||
* Content-Security-Policy?: array<string, string[]>,
|
* Content-Security-Policy?: array<string, string[]>,
|
||||||
* Content-Security-Policy-Report-Only?: array<string, string[]>,
|
* Content-Security-Policy-Report-Only?: array<string, string[]>,
|
||||||
* X-Content-Security-Policy?: array<string, string[]>,
|
* X-Content-Security-Policy?: array<string, string[]>,
|
||||||
* }
|
* } Mapped CSP headers and their parsed directive sets
|
||||||
*/
|
*/
|
||||||
private function getCspHeaders(ResponseInterface $response): array
|
private function getCspHeaders(ResponseInterface $response): array
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,30 +7,49 @@ namespace Flasher\Prime\Http\Csp;
|
|||||||
use Flasher\Prime\Http\RequestInterface;
|
use Flasher\Prime\Http\RequestInterface;
|
||||||
use Flasher\Prime\Http\ResponseInterface;
|
use Flasher\Prime\Http\ResponseInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ContentSecurityPolicyHandlerInterface - Contract for handling Content Security Policy.
|
||||||
|
*
|
||||||
|
* This interface defines operations for managing Content Security Policy (CSP) headers
|
||||||
|
* and nonces, which are necessary for securely injecting JavaScript and CSS into HTML pages.
|
||||||
|
* It ensures that PHPFlasher's injected content doesn't violate the site's CSP.
|
||||||
|
*
|
||||||
|
* Design pattern: Strategy - Defines a common interface for CSP handling strategies.
|
||||||
|
*/
|
||||||
interface ContentSecurityPolicyHandlerInterface
|
interface ContentSecurityPolicyHandlerInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Returns an array of nonces to be used in html templates and Content-Security-Policy headers.
|
* Returns an array of nonces to be used in HTML templates and Content-Security-Policy headers.
|
||||||
*
|
*
|
||||||
* Nonce can be provided by;
|
* Nonce can be provided by:
|
||||||
* - The request - In case HTML content is fetched via AJAX and inserted in DOM, it must use the same nonce as origin
|
* - The request - In case HTML content is fetched via AJAX and inserted in DOM, it must use the same nonce as origin
|
||||||
* - The response - A call to getNonces() has already been done previously. Same nonce are returned
|
* - The response - A call to getNonces() has already been done previously. Same nonce are returned
|
||||||
* - They are otherwise randomly generated
|
* - They are otherwise randomly generated
|
||||||
*
|
*
|
||||||
* @return array{csp_script_nonce: ?string, csp_style_nonce: ?string}
|
* @param RequestInterface $request The current request
|
||||||
|
* @param ResponseInterface|null $response The current response (optional)
|
||||||
|
*
|
||||||
|
* @return array{csp_script_nonce: ?string, csp_style_nonce: ?string} Array with script and style nonces
|
||||||
*/
|
*/
|
||||||
public function getNonces(RequestInterface $request, ?ResponseInterface $response = null): array;
|
public function getNonces(RequestInterface $request, ?ResponseInterface $response = null): array;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disables Content-Security-Policy.
|
* Disables Content-Security-Policy.
|
||||||
*
|
*
|
||||||
* All related headers will be removed.
|
* All related headers will be removed. This is useful in environments where CSP
|
||||||
|
* is not needed or when debugging.
|
||||||
*/
|
*/
|
||||||
public function disableCsp(): void;
|
public function disableCsp(): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cleanup temporary headers and updates Content-Security-Policy headers.
|
* Cleanup temporary headers and updates Content-Security-Policy headers.
|
||||||
*
|
*
|
||||||
|
* This method modifies CSP headers in the response to allow PHPFlasher's
|
||||||
|
* JavaScript and CSS to execute without being blocked by CSP.
|
||||||
|
*
|
||||||
|
* @param RequestInterface $request The current request
|
||||||
|
* @param ResponseInterface $response The current response
|
||||||
|
*
|
||||||
* @return array{csp_script_nonce?: ?string, csp_style_nonce?: ?string} Nonces used in Content-Security-Policy header
|
* @return array{csp_script_nonce?: ?string, csp_style_nonce?: ?string} Nonces used in Content-Security-Policy header
|
||||||
*/
|
*/
|
||||||
public function updateResponseHeaders(RequestInterface $request, ResponseInterface $response): array;
|
public function updateResponseHeaders(RequestInterface $request, ResponseInterface $response): array;
|
||||||
|
|||||||
@@ -4,8 +4,24 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Flasher\Prime\Http\Csp;
|
namespace Flasher\Prime\Http\Csp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NonceGenerator - Default implementation for generating CSP nonces.
|
||||||
|
*
|
||||||
|
* This class provides a straightforward implementation for generating
|
||||||
|
* cryptographically secure nonces using PHP's random_bytes function.
|
||||||
|
* The nonces are encoded as hexadecimal strings for compatibility with
|
||||||
|
* HTML attributes and CSP headers.
|
||||||
|
*
|
||||||
|
* Design pattern: Strategy - Implements a specific nonce generation strategy.
|
||||||
|
*/
|
||||||
final readonly class NonceGenerator implements NonceGeneratorInterface
|
final readonly class NonceGenerator implements NonceGeneratorInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* {@inheritdoc}
|
||||||
|
*
|
||||||
|
* This implementation generates a 16-byte (128-bit) random value and
|
||||||
|
* encodes it as a hexadecimal string.
|
||||||
|
*/
|
||||||
public function generate(): string
|
public function generate(): string
|
||||||
{
|
{
|
||||||
return bin2hex(random_bytes(16));
|
return bin2hex(random_bytes(16));
|
||||||
|
|||||||
@@ -4,7 +4,24 @@ declare(strict_types=1);
|
|||||||
|
|
||||||
namespace Flasher\Prime\Http\Csp;
|
namespace Flasher\Prime\Http\Csp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* NonceGeneratorInterface - Contract for generating CSP nonces.
|
||||||
|
*
|
||||||
|
* This interface defines the essential operation for generating secure nonces
|
||||||
|
* (number used once) for Content Security Policy purposes. Nonces are used to
|
||||||
|
* whitelist specific inline scripts and styles in a CSP-protected environment.
|
||||||
|
*
|
||||||
|
* Design pattern: Strategy - Allows for different implementations of nonce generation.
|
||||||
|
*/
|
||||||
interface NonceGeneratorInterface
|
interface NonceGeneratorInterface
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Generates a cryptographically secure nonce.
|
||||||
|
*
|
||||||
|
* The generated nonce should be suitable for use in Content-Security-Policy headers
|
||||||
|
* and should provide sufficient entropy to be secure.
|
||||||
|
*
|
||||||
|
* @return string The generated nonce
|
||||||
|
*/
|
||||||
public function generate(): string;
|
public function generate(): string;
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user