Compare commits

...

59 Commits

Author SHA1 Message Date
Younes ENNAJI ff2cd6e384 chore: update CHANGELOG 2024-09-19 07:44:09 +01:00
Younes ENNAJI 2012b6f5af Merge pull request #196 from php-flasher/issue-193
Introduce escapeHtml Option for Secure HTML Escaping in PHPFlasher
2024-09-19 07:41:45 +01:00
Younes ENNAJI 889fc4701e chore: add escapeHtml option for secure HTML escaping in notifications 2024-09-19 07:40:10 +01:00
Younes ENNAJI 74a71b36dc style: compile assets 2024-09-19 07:39:03 +01:00
Younes ENNAJI ae0b5e8f9a style: replace deprecated function darken with scss color module color.adjust 2024-09-19 07:38:53 +01:00
Younes ENNAJI e44c1d675e ci: fix phpstan errors 2024-09-19 07:32:04 +01:00
Younes ENNAJI 61bd5f7a96 chore: add rollup progress plugin 2024-09-19 07:00:51 +01:00
Younes ENNAJI faf827f248 docs: update inertia js documentation 2024-09-19 06:42:29 +01:00
Younes ENNAJI d59e37812d chore: run php-cs-fixer 2024-09-19 06:42:10 +01:00
Younes ENNAJI 51dd7dc6fb chore: upgrade dependencies 2024-09-19 06:39:52 +01:00
Younes ENNAJI 2c2326a4a9 chore: upgrade dependencies 2024-06-16 00:02:33 +01:00
Younes ENNAJI fb34c1525d chore: upgrade dependencies 2024-06-16 00:01:48 +01:00
Younes ENNAJI d496046d50 chore: upgrade dependencies 2024-06-15 21:34:46 +01:00
Younes ENNAJI 1c5b47ab52 chore: update dependencies 2024-05-31 16:02:55 +01:00
Younes ENNAJI 87f015341e chore: add parallel run php-cs-fixer config 2024-05-31 10:04:29 +01:00
Younes ENNAJI 6087a940c6 chore: upgrade npm dependencies 2024-05-31 10:01:33 +01:00
Younes ENNAJI be82ad0b69 chore: upgrade composer dependencies 2024-05-31 10:01:18 +01:00
Younes ENNAJI 88271276fc chore: add support for symfony v7.1 2024-05-31 09:59:01 +01:00
Younes ENNAJI 456e434474 chore: remove pr auto_closer github action 2024-05-27 00:40:47 +01:00
Younes ENNAJI b28525d718 chore: add and run phpstan phpunit 2024-05-27 00:34:47 +01:00
Younes ENNAJI a820277f25 chore: update CHANGELOG 2024-05-26 13:26:08 +01:00
Younes ENNAJI 10883353f2 Merge pull request #184 from php-flasher/issue-176
chore: Refactor middleware to use Symfony's base response class
2024-05-26 13:22:01 +01:00
Younes ENNAJI 6de67f7fb3 chore: Refactor middleware to use Symfony's base response class
This commit updates the FlasherMiddleware and SessionMiddleware to utilize Symfony's base response class instead of Laravel's. This change ensures broader compatibility and addresses the issue with flash message rendering after page refreshes as identified by the community. Preparing for release in v2.0.2.
2024-05-26 13:20:48 +01:00
Younes ENNAJI b08161f9ec docs: add Ahmed Gamal to the list of contributors 2024-05-26 01:51:51 +01:00
Younes ENNAJI c35e973524 Merge pull request #183 from AhmedGamal/2.x
Default configuration options
2024-05-26 01:21:49 +01:00
Ahmed Gamal f985ea2999 chore: Symfony config options update 2024-05-25 21:24:39 +03:00
Ahmed Gamal e42e91a1e0 chore: laravel config options update 2024-05-25 21:24:30 +03:00
Ahmed Gamal 08eb6089e1 docs: adding config options 2024-05-25 21:24:19 +03:00
Younes ENNAJI dd93f6e66d docs: allow users to switch between versions 2024-05-25 15:00:18 +01:00
Younes ENNAJI b6989336e7 chore: upgrade dependencies 2024-05-24 16:15:23 +01:00
Younes ENNAJI 79c6fc3bcb chore: restore .github/workflows/tests.yaml accidentally deleted in commit d2f019f 2024-05-24 13:39:01 +01:00
Younes ENNAJI f61a7d83ce test: add tests for FlasherMiddleware and SessionMiddleware registration 2024-05-24 13:33:25 +01:00
Younes ENNAJI b07c52e643 chore: bump flasher dependency to v2.0.1 2024-05-23 10:51:41 +01:00
Younes ENNAJI 9d2ccc21c9 chore: update CHANGELOG 2024-05-23 10:50:03 +01:00
Younes ENNAJI c98a15dc0e chore: update CHANGELOG 2024-05-23 10:49:21 +01:00
Younes ENNAJI 8f4552bf4c chore: update CHANGELOG 2024-05-23 10:48:58 +01:00
Younes ENNAJI 87463be485 chore: update CHANGELOG 2024-05-23 10:48:09 +01:00
Younes ENNAJI 42eacbe570 demo: update laravel demo 2024-05-23 10:36:00 +01:00
Younes ENNAJI 6d9515d26c chore: update CHANGELOG 2024-05-23 10:32:57 +01:00
Younes ENNAJI 3d893a68eb demo: update laravel demo 2024-05-23 10:32:30 +01:00
Younes ENNAJI f34bd1385a chore: format code 2024-05-23 10:32:30 +01:00
Younes ENNAJI 1b2a778ba2 Merge pull request #182 from php-flasher/fix/issue-176
fix: Ensure flash_bag config overrides default values instead of appending
2024-05-23 10:31:23 +01:00
Younes ENNAJI 953fb78489 fix: Ensure flash_bag config overrides default values instead of appending 2024-05-23 10:29:54 +01:00
Younes ENNAJI 6d05508f97 chore: update CHANGELOG 2024-05-23 10:20:29 +01:00
Younes ENNAJI 5264899310 Merge pull request #181 from php-flasher/fix/issue-176
fix: Allow disabling of default flash replacement by setting flash_bag to false
2024-05-23 10:19:11 +01:00
Younes ENNAJI c500acbc94 fix: Allow disabling of default flash replacement by setting flash_bag to false 2024-05-23 10:17:29 +01:00
Younes ENNAJI 9123f481d8 chore: update CHANGELOG 2024-05-22 23:18:11 +01:00
Younes ENNAJI 9b356ac711 demo: update laravel flasher config timeout option 2024-05-22 23:17:15 +01:00
Younes ENNAJI 0bf6c57569 Merge pull request #180 from php-flasher/fix/issue-176
fix: Ensure global timeout setting applies to all requests
2024-05-22 23:16:26 +01:00
Younes ENNAJI 69e0f71d30 fix: Ensure global timeout setting applies to all requests 2024-05-22 23:14:36 +01:00
Younes ENNAJI 2805115fd7 Merge pull request #179 from php-flasher/fix/issue-176
chore: update CHANGELOG
2024-05-22 22:59:39 +01:00
Younes ENNAJI 47f6b54e06 chore: update CHANGELOG 2024-05-22 22:59:27 +01:00
Younes ENNAJI 6ac46e400e Merge pull request #178 from php-flasher/fix/issue-176
chore: upgrade CHANGELOG
2024-05-22 22:56:27 +01:00
Younes ENNAJI 5476d33112 chore: upgrade CHANGELOG 2024-05-22 22:55:36 +01:00
Younes ENNAJI 95beddfafc Merge pull request #177 from php-flasher/fix/issue-176
fix: Correctly disable FlasherMiddleware when inject_assets is set to false
2024-05-22 22:51:00 +01:00
Younes ENNAJI bbccf0bc4e fix: Correctly disable FlasherMiddleware when inject_assets is set to false 2024-05-22 22:48:17 +01:00
Younes ENNAJI c0709b0747 chore: upgrade dependencies 2024-05-22 22:46:12 +01:00
Younes ENNAJI 39f1f3885e chore: fix phpstan bleeding edge errors 2024-05-13 10:24:42 +01:00
Younes ENNAJI 816529029b Update README.md 2024-05-05 23:35:32 +01:00
191 changed files with 3583 additions and 2369 deletions
+10
View File
@@ -85,6 +85,16 @@
"contributions": [
"design"
]
},
{
"login": "AhmedGamal",
"name": "Ahmed Gamal",
"avatar_url": "https://avatars.githubusercontent.com/u/11786167?v=4",
"profile": "https://github.com/AhmedGamal",
"contributions": [
"code",
"doc"
]
}
]
}
+171
View File
@@ -0,0 +1,171 @@
name: 🧪 Run Tests & 🛠️ Static Analysis
on:
push:
branches:
- main
- 2.x
pull_request:
schedule:
- cron: '0 0 * * *' # Daily at midnight
jobs:
static-analysis:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php: [ 8.2 ]
name: 🐘 PHP ${{ matrix.php }} Static Analysis
steps:
- name: 📥 Checkout Code
uses: actions/checkout@v4
- name: 🔧 Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
- name: 🚚 Cache Composer Dependencies
uses: actions/cache@v4
with:
path: ~/.composer/cache
key: ${{ runner.os }}-composer-${{ matrix.php }}-${{ hashFiles('composer.json') }}
restore-keys: ${{ runner.os }}-composer-${{ matrix.php }}-
- name: 📦 Install Dependencies
run: |
composer config --global allow-plugins true
composer install
- name: 🧹 Run PHP CS Fixer (Code Style)
run: vendor/bin/php-cs-fixer fix --dry-run
- name: 🔍 Run PHPStan (Static Analysis)
run: vendor/bin/phpstan analyse
- name: 🚀 Run PHPLint (Syntax Check)
run: vendor/bin/phplint
prime-test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- { php: 8.4, phpunit: 10.5.* }
- { php: 8.3, phpunit: 10.5.* }
- { php: 8.2, phpunit: 10.5.* }
name: 🐘 PHP ${{ matrix.php }}
steps:
- name: 📥 Checkout code
uses: actions/checkout@v4
- name: 🔧 Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
- name: 🚚 Cache dependencies
uses: actions/cache@v4
with:
path: ~/.composer/cache
key: ${{ runner.os }}-composer-${{ matrix.php }}-${{ hashFiles('composer.json') }}
restore-keys: ${{ runner.os }}-composer-${{ matrix.php }}-
- name: 📦 Install dependencies
run: |
sed -i '/"require": {/,/},/d; /"require-dev": {/,/},/d' composer.json
composer config --global allow-plugins true
composer require "phpunit/phpunit:${{ matrix.phpunit }}" "mockery/mockery" "psr/container" --no-interaction --no-update
composer update --prefer-lowest -W
- name: ✅ Execute tests
run: vendor/bin/phpunit --testsuite prime
symfony-test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- { symfony: 7.2.*, php: 8.4, phpunit: 10.5.* }
- { symfony: 7.2.*, php: 8.3, phpunit: 10.5.* }
- { symfony: 7.2.*, php: 8.2, phpunit: 10.5.* }
- { symfony: 7.1.*, php: 8.2, phpunit: 10.5.* }
- { symfony: 7.0.*, php: 8.2, phpunit: 10.5.* }
name: 🌉 Symfony ${{ matrix.symfony }} PHP ${{ matrix.php }}
steps:
- name: 📥 Checkout code
uses: actions/checkout@v4
- name: 🔧 Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
coverage: none
- name: 🚚 Cache dependencies
uses: actions/cache@v4
with:
path: ~/.composer/cache
key: ${{ runner.os }}-composer-${{ matrix.php }}-${{ hashFiles('composer.json') }}
restore-keys: ${{ runner.os }}-composer-${{ matrix.php }}-
- name: 📦 Install dependencies
run: |
sed -i '/"require": {/,/},/d; /"require-dev": {/,/},/d' composer.json
composer config --global allow-plugins true
composer config extra.symfony.require "${{ matrix.symfony }}"
composer require "symfony/config:${{ matrix.symfony }}" "symfony/console:${{ matrix.symfony }}" "symfony/dependency-injection:${{ matrix.symfony }}" "symfony/framework-bundle:${{ matrix.symfony }}" "symfony/http-kernel:${{ matrix.symfony }}" "symfony/translation:${{ matrix.symfony }}" "symfony/twig-bundle:${{ matrix.symfony }}" "phpunit/phpunit:${{ matrix.phpunit }}" "mockery/mockery" "psr/container" "monolog/monolog" --no-interaction --no-update
composer update --prefer-lowest -W
- name: ✅ Execute tests
run: vendor/bin/phpunit --testsuite symfony
laravel-test:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- { laravel: 11.*, testbench: 9.*, php: 8.3, phpunit: 10.5.* }
- { laravel: 11.*, testbench: 9.*, php: 8.2, phpunit: 10.5.* }
name: 🏗 Laravel ${{ matrix.laravel }} PHP ${{ matrix.php }}
steps:
- name: 📥 Checkout code
uses: actions/checkout@v4
- name: 🔧 Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php }}
extensions: fileinfo
coverage: none
- name: 🚚 Cache dependencies
uses: actions/cache@v4
with:
path: ~/.composer/cache
key: ${{ matrix.php }}-composer-${{ hashFiles('composer.json') }}
restore-keys: ${{ matrix.php }}-composer
- name: 📦 Install dependencies
run: |
sed -i '/\"require\": {/,/},/d; /\"require-dev\": {/,/},/d' composer.json
composer config --global allow-plugins true
composer require "laravel/framework:${{ matrix.laravel }}" "phpunit/phpunit:${{ matrix.phpunit }}" "orchestra/testbench:${{ matrix.testbench }}" --no-interaction --no-update
composer update --prefer-lowest -W
- name: ✅ Execute tests
run: vendor/bin/phpunit --testsuite laravel
+1 -1
View File
@@ -1 +1 @@
20.11.0
22.9.0
+7 -2
View File
@@ -2,7 +2,11 @@
declare(strict_types=1);
$finder = PhpCsFixer\Finder::create()
use PhpCsFixer\Config;
use PhpCsFixer\Finder;
use PhpCsFixer\Runner\Parallel\ParallelConfigFactory;
$finder = Finder::create()
->in([
__DIR__.'/src',
__DIR__.'/tests',
@@ -11,7 +15,8 @@ $finder = PhpCsFixer\Finder::create()
->append([__FILE__])
;
return (new PhpCsFixer\Config())
return (new Config())
->setParallelConfig(ParallelConfigFactory::detect())
->setRiskyAllowed(true)
->setRules([
'@PSR12' => true,
+16
View File
@@ -0,0 +1,16 @@
# CHANGELOG for 2.x
## [Unreleased](https://github.com/php-flasher/php-flasher/compare/v2.0.2...2.x)
## [v2.0.2](https://github.com/php-flasher/php-flasher/compare/v2.0.1...v2.0.2) - 2024-09-19
* feature [Flasher] add escapeHtml option for secure HTML escaping in notifications. See [PR #196](https://github.com/php-flasher/php-flasher/pull/196) by [yoeunes](https://github.com/yoeunes)
* feature [Flasher] add Default configuration options. See [PR #183](https://github.com/php-flasher/php-flasher/pull/183) by [AhmedGamal](https://github.com/AhmedGamal)
* feature [Laravel] Refactor middleware to use Symfony's base response class, addressing compatibility issues. See [PR #184](https://github.com/php-flasher/php-flasher/pull/184) by [yoeunes](https://github.com/yoeunes)
## [v2.0.1](https://github.com/php-flasher/php-flasher/compare/v2.0.0...v2.0.1) - 2024-05-23
* bug [#176](https://github.com/php-flasher/php-flasher/issues/176) [Laravel] Correctly disable FlasherMiddleware when `inject_assets` is set to false. See [PR #177](https://github.com/php-flasher/php-flasher/pull/177) by [yoeunes](https://github.com/yoeunes)
* bug [#176](https://github.com/php-flasher/php-flasher/issues/176) [Flasher] Ensure global `timeout` option applies to all requests. See [PR #180](https://github.com/php-flasher/php-flasher/pull/180) by [yoeunes](https://github.com/yoeunes)
* bug [#176](https://github.com/php-flasher/php-flasher/issues/176) [Laravel] Allow disabling of default flash replacement by setting `flash_bag` to false. See [PR #181](https://github.com/php-flasher/php-flasher/pull/181) by [yoeunes](https://github.com/yoeunes)
* bug [#176](https://github.com/php-flasher/php-flasher/issues/176) [Flasher] Ensure `flash_bag` option overrides default values instead of appending. See [PR #182](https://github.com/php-flasher/php-flasher/pull/182) by [yoeunes](https://github.com/yoeunes)
+2 -2
View File
@@ -36,7 +36,7 @@ Shining stars of our community:
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/younes-ennaji/"><img src="https://avatars.githubusercontent.com/u/10859693?v=4?s=100" width="100px;" alt="Younes ENNAJI"/><br /><sub><b>Younes ENNAJI</b></sub></a><br /><a href="https://github.com/php-flasher/php-flasher/commits?author=yoeunes" title="Code">💻</a> <a href="https://github.com/php-flasher/php-flasher/commits?author=yoeunes" title="Documentation">📖</a> <a href="#maintenance-yoeunes" title="Maintenance">🚧</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/younes--ennaji/"><img src="https://avatars.githubusercontent.com/u/10859693?v=4?s=100" width="100px;" alt="Younes ENNAJI"/><br /><sub><b>Younes ENNAJI</b></sub></a><br /><a href="https://github.com/php-flasher/php-flasher/commits?author=yoeunes" title="Code">💻</a> <a href="https://github.com/php-flasher/php-flasher/commits?author=yoeunes" title="Documentation">📖</a> <a href="#maintenance-yoeunes" title="Maintenance">🚧</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/salmayno"><img src="https://avatars.githubusercontent.com/u/27933199?v=4?s=100" width="100px;" alt="Salma Mourad"/><br /><sub><b>Salma Mourad</b></sub></a><br /><a href="#financial-salmayno" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.youtube.com/rstacode"><img src="https://avatars.githubusercontent.com/u/35005761?v=4?s=100" width="100px;" alt="Nashwan Abdullah"/><br /><sub><b>Nashwan Abdullah</b></sub></a><br /><a href="#financial-codenashwan" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://darvis.nl/"><img src="https://avatars.githubusercontent.com/u/7394837?v=4?s=100" width="100px;" alt="Arvid de Jong"/><br /><sub><b>Arvid de Jong</b></sub></a><br /><a href="#financial-darviscommerce" title="Financial">💵</a></td>
@@ -46,7 +46,7 @@ Shining stars of our community:
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.instagram.com/lucas.maciel_z"><img src="https://avatars.githubusercontent.com/u/80225404?v=4?s=100" width="100px;" alt="Lucas Maciel"/><br /><sub><b>Lucas Maciel</b></sub></a><br /><a href="#design-LucasStorm" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://siek.io/"><img src="https://avatars.githubusercontent.com/u/5730766?v=4?s=100" width="100px;" alt="Antoni Siek"/><br /><sub><b>Antoni Siek</b></sub></a><br /><a href="https://github.com/php-flasher/php-flasher/commits?author=ImJustToNy" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/AhmedGamal"><img src="https://avatars.githubusercontent.com/u/11786167?v=4?s=100" width="100px;" alt="Ahmed Gamal"/><br /><sub><b>Ahmed Gamal</b></sub></a><br /><a href="https://github.com/php-flasher/php-flasher/commits?author=AhmedGamal" title="Code">💻</a> <a href="https://github.com/php-flasher/php-flasher/commits?author=AhmedGamal" title="Documentation">📖</a></td>
</tr>
</tbody>
</table>
+16 -14
View File
@@ -26,20 +26,22 @@
"require-dev": {
"illuminate/routing": "^11.0",
"illuminate/support": "^11.0",
"larastan/larastan": "^2.9.5",
"larastan/larastan": "^2.9",
"laravel/octane": "^2.3",
"livewire/livewire": "^3.3",
"mockery/mockery": "^1.6.11",
"orchestra/testbench": "^9.0.4",
"overtrue/phplint": "^9.2.0",
"php-cs-fixer/shim": "^3.54.0",
"phpstan/phpstan": "^1.10.67",
"phpstan/phpstan-mockery": "^1.1.2",
"phpstan/phpstan-symfony": "^1.3.12",
"phpunit/phpunit": "^10.5.13",
"livewire/livewire": "^3.5",
"mockery/mockery": "^1.6",
"orchestra/testbench": "^9.4",
"overtrue/phplint": "^9.4",
"php-cs-fixer/shim": "^3.64",
"phpstan/phpstan": "^1.12",
"phpstan/phpstan-mockery": "^1.1",
"phpstan/phpstan-phpunit": "^1.4",
"phpstan/phpstan-symfony": "^1.4",
"phpunit/phpunit": "^10.5",
"psr/container": "^1.1|^2.0",
"rector/rector": "^1.0.4",
"rector/swiss-knife": "^0.2.2",
"rector/rector": "^1.2",
"rector/swiss-knife": "^0.2",
"spatie/ray": "^1.41",
"symfony/config": "^7.0",
"symfony/console": "^7.0",
"symfony/dependency-injection": "^7.0",
@@ -47,8 +49,8 @@
"symfony/http-kernel": "^7.0",
"symfony/translation": "^7.0",
"symfony/twig-bundle": "^7.0",
"symfony/ux-twig-component": "^2.14",
"symplify/monorepo-builder": "^11.2.20"
"symfony/ux-twig-component": "^2.19",
"symplify/monorepo-builder": "^11.2"
},
"autoload": {
"psr-4": {
Generated
+407 -206
View File
File diff suppressed because it is too large Load Diff
+345 -328
View File
File diff suppressed because it is too large Load Diff
+14
View File
@@ -0,0 +1,14 @@
<?php
return [
'inject_assets' => true,
'options' => [
'timeout' => 5000, // in milliseconds
'position' => 'top-right',
],
'flash_bag' => [
'success' => ['success', 'ok', 'completed', 'passed', 'achieved'],
],
];
+9 -3
View File
@@ -10,8 +10,14 @@ Route::get('/', function () {
// toastr()->positionClass('toast-bottom-left')->error('hello from Home Controller');
// flash()->use('flasher')->success('hello from flasher factory');
flash()->created(new Book('lord of the rings'));
flash()->saved(new Book('harry potter'));
// flash()->created(new Book('lord of the rings'));
// flash()->saved(new Book('harry potter'));
return view('welcome');
session()->flash('success', 'this from laravel session flash');
return redirect('/redirect');
})->name('app_home');
Route::get('/redirect', function () {
return view('welcome');
});
+293 -290
View File
File diff suppressed because it is too large Load Diff
+35
View File
@@ -0,0 +1,35 @@
flasher:
# Default notification library (e.g., 'flasher', 'toastr', 'noty', etc.)
default: flasher
# Path to the main JavaScript file of PHPFlasher
main_script: '/vendor/flasher/flasher.min.js'
# Path to the stylesheets for PHPFlasher notifications
styles:
- '/vendor/flasher/flasher.min.css'
# Enable translation of PHPFlasher messages using Symfony's translator service
translate: true
# Automatically inject PHPFlasher assets in HTML response
inject_assets: true
# Global options
options:
# timeout in milliseconds
timeout: 5000
position: 'top-right'
# Map Symfony session keys to PHPFlasher notification types
flash_bag:
success: ['success']
error: ['error', 'danger']
warning: ['warning', 'alarm']
info: ['info', 'notice', 'alert']
# Criteria to filter displayed notifications (limit, types)
filter:
# Limit number of displayed notifications
limit: 5
+2 -2
View File
@@ -1,6 +1,6 @@
{
"dist/main.css": "/dist/main.73b25228.css",
"dist/main.js": "/dist/main.09f63ce9.js",
"dist/main.css": "/dist/main.27d36c82.css",
"dist/main.js": "/dist/main.513c5cd1.js",
"dist/455.3a7b4474.css": "/dist/455.3a7b4474.css",
"dist/455.095e6545.js": "/dist/455.095e6545.js",
"dist/411.29cd993e.css": "/dist/411.29cd993e.css",
+4
View File
@@ -3,3 +3,7 @@ version: "2.x"
title: "Easily add flash messages to your #Laravel or #Symfony projects with PHPFlasher - a powerful, easy-to-use package for improved user engagement & experience"
description: "PHPFlasher - A powerful & easy-to-use package for adding flash messages to Laravel or Symfony projects. Provides feedback to users, improves engagement & enhances user experience. Intuitive design for beginners & experienced developers. A reliable, flexible solution."
versions:
2.x: "https://php-flasher.io/"
1.x: "https://php-flasher.github.io/"
+6 -4
View File
@@ -18,12 +18,14 @@
<div class="h-16 z-10 top-0 w-screen bg-white border-b border-indigo-200 shadow">
<div id="header-logo" class="lg:container lg:mx-auto px-4 py-2">
<div class="flex items-center flex-no-shrink pt-1">
<a href="/" class="flex items-center">
<span class="pr-2 font-normal font-normal leading-none text-3xl text-indigo-900 hidden sm:block">
<div class="flex items-center">
<span class="pr-2 font-normal leading-none text-3xl text-indigo-900 hidden sm:block">
<img class="fill-current h-8 mr-2" src="/static/images/php-flasher-logo.svg" />
<sup class="text-xs relative text-grey-dark" style="top: -20px;">{{ site.data.project.version }}</sup>
{% for version in site.data.project.versions %}
<a href="{{ version[1] }}" class="{% if forloop.first %}text-white bg-indigo-500{% else %}text-indigo-600{% endif %} p-1 rounded text-xs relative text-grey-dark hover:bg-indigo-500 hover:scale-110 hover:text-white" style="top: -20px;">{{ version[0] }}</a>
{% endfor %}
</span>
</a>
</div>
<div class="flex-grow"></div>
<a href="#" id="menu-toggle" class="block lg:hidden h-8 w-8 border p-1 border-transparent text-gray-200 hover:text-grey menu-closed">
<svg class="menu-closed:shown fill-current h-full w-full" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
+2 -2
View File
@@ -2,10 +2,10 @@
"entrypoints": {
"main": {
"css": [
"/dist/main.73b25228.css"
"/dist/main.27d36c82.css"
],
"js": [
"/dist/main.09f63ce9.js"
"/dist/main.513c5cd1.js"
]
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+4 -4
View File
@@ -20,7 +20,7 @@
"noty": "^3.2.0-beta-deprecated",
"notyf": "^3.10.0",
"prismjs": "^1.29.0",
"sweetalert2": "^11.10.8",
"sweetalert2": "^11.11.0",
"toastr": "^2.1.4"
},
"devDependencies": {
@@ -8157,9 +8157,9 @@
}
},
"node_modules/sweetalert2": {
"version": "11.10.8",
"resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.10.8.tgz",
"integrity": "sha512-oAkYROBfXBY+4sVbQEIcN+ZxAx69lsmz5WEBwdEpyS4m59vOBNlRU5/fJpAI1MVfiDwFZiGwVzB/KBpOyfLNtg==",
"version": "11.11.0",
"resolved": "https://registry.npmjs.org/sweetalert2/-/sweetalert2-11.11.0.tgz",
"integrity": "sha512-wKCTtoE6lQVDKaJ5FFq+znk/YykJmJlD8RnLZps8C7DyivctCoRlVeeOwnKfgwKS+QJYon7s++3dmNi3/am1tw==",
"funding": {
"type": "individual",
"url": "https://github.com/sponsors/limonte"
+1 -1
View File
@@ -21,7 +21,7 @@
"noty": "^3.2.0-beta-deprecated",
"notyf": "^3.10.0",
"prismjs": "^1.29.0",
"sweetalert2": "^11.10.8",
"sweetalert2": "^11.11.0",
"toastr": "^2.1.4"
},
"devDependencies": {
+1 -1
View File
@@ -37,7 +37,7 @@ class HandleInertiaRequests extends Middleware
public function share(Request $request): array
{
return array_merge(parent::share($request), [
'messages' => flash()->render([], 'array'),
'messages' => flash()->render('array'),
]);
}
}
+6
View File
@@ -68,6 +68,12 @@ return [
// Automatically inject PHPFlasher assets in HTML response
'inject_assets' => true,
// Global options
'options' => [
'timeout' => 5000, // in milliseconds
'position' => 'top-right',
],
// Configuration for the flash bag (converting Laravel flash messages)
// Map Laravel session keys to PHPFlasher types
'flash_bag' => [
+6
View File
@@ -66,6 +66,12 @@ flasher:
# Automatically inject PHPFlasher assets in HTML response
inject_assets: true
# Global options
options:
# timeout in milliseconds
timeout: 5000
position: 'top-right'
# Map Symfony session keys to PHPFlasher notification types
flash_bag:
success: ['success']
+1565 -859
View File
File diff suppressed because it is too large Load Diff
+17 -15
View File
@@ -19,39 +19,41 @@
},
"devDependencies": {
"@antfu/eslint-config": "2.12.2",
"@babel/core": "^7.24.5",
"@babel/preset-env": "^7.24.5",
"@babel/core": "^7.25.2",
"@babel/preset-env": "^7.25.4",
"@rollup/plugin-babel": "^6.0.4",
"@rollup/plugin-commonjs": "^25.0.7",
"@rollup/plugin-commonjs": "^25.0.8",
"@rollup/plugin-eslint": "^9.0.5",
"@rollup/plugin-node-resolve": "^15.2.3",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.6",
"@types/node": "^20.12.8",
"@types/node": "^20.16.5",
"@typescript-eslint/eslint-plugin": "7.5.0",
"@typescript-eslint/parser": "^7.8.0",
"autoprefixer": "^10.4.19",
"browserslist": "^4.23.0",
"@typescript-eslint/parser": "^7.18.0",
"all-contributors-cli": "^6.26.1",
"autoprefixer": "^10.4.20",
"browserslist": "^4.23.3",
"cross-env": "7.0.3",
"cssnano": "^6.1.2",
"eslint": "^8.57.0",
"eslint": "^8.57.1",
"eslint-config-airbnb-typescript": "^18.0.0",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-import-resolver-typescript": "^3.6.3",
"eslint-plugin-babel": "5.3.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.1.3",
"eslint-plugin-import": "^2.30.0",
"eslint-plugin-prettier": "^5.2.1",
"postcss-discard-comments": "^6.0.2",
"punycode": "2.3.1",
"rollup": "^4.17.2",
"rollup": "^4.22.0",
"rollup-plugin-cleanup": "^3.2.1",
"rollup-plugin-clear": "^2.0.7",
"rollup-plugin-copy": "3.5.0",
"rollup-plugin-filesize": "^10.0.0",
"rollup-plugin-postcss": "^4.0.2",
"sass": "^1.76.0",
"rollup-plugin-progress": "^1.1.2",
"sass": "^1.79.1",
"ts-node": "^10.9.2",
"tslib": "^2.6.2",
"typescript": "^5.4.5"
"tslib": "^2.7.0",
"typescript": "^5.6.2"
}
}
+6
View File
@@ -1,9 +1,12 @@
includes:
- extension.neon
- vendor/phpstan/phpstan/conf/bleedingEdge.neon
- vendor/phpstan/phpstan-symfony/extension.neon
- vendor/phpstan/phpstan-symfony/rules.neon
- vendor/larastan/larastan/extension.neon
- vendor/phpstan/phpstan-mockery/extension.neon
- vendor/phpstan/phpstan-phpunit/extension.neon
- vendor/phpstan/phpstan-phpunit/rules.neon
parameters:
level: 9
@@ -13,3 +16,6 @@ parameters:
- tests/
tmpDir: .cache/phpstan
ignoreErrors:
- '#Call to method .+ with .+ will always evaluate to true.#'
+2
View File
@@ -12,6 +12,7 @@ import postcss from 'rollup-plugin-postcss'
import cssnano from 'cssnano'
import autoprefixer from 'autoprefixer'
import discardComments from 'postcss-discard-comments'
import progress from 'rollup-plugin-progress'
const isProduction = process.env.NODE_ENV === 'production'
@@ -68,6 +69,7 @@ function createPlugins({ name, path, assets }) {
: []
return [
progress(),
...(isProduction ? [clear({ targets: [`${path}/dist`, `${path}/public`] })] : []),
postcss({ extract: filename, plugins: isProduction ? postcssPlugins : [] }),
...commonPlugins(path),
-23
View File
@@ -1,23 +0,0 @@
name: Auto Closer PR
on:
pull_request_target:
types: [ opened ]
jobs:
run:
name: 🤖 PR Auto-Closure
runs-on: ubuntu-latest
steps:
- uses: superbrothers/close-pull-request@v3
with:
comment: |
Hi there 👋,
First off, thanks for your effort! 🎉 Unfortunately, this repository is read-only because it's split from our primary monorepo repository.
🙏 We kindly ask if you could direct your valuable contribution to our main repository at https://github.com/php-flasher/php-flasher.
Once you've moved your contribution there, we'll review it and provide feedback. 🕵️‍♂️
Thanks again for your understanding and cooperation. We really appreciate it! 🙌
+4 -4
View File
@@ -90,12 +90,12 @@ final class InstallCommand extends Command
$this->publishConfig($plugin, $configFile);
}
$status = sprintf('<fg=green;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'OK' : "\xE2\x9C\x94" /* HEAVY CHECK MARK (U+2714) */);
$output->writeln(sprintf(' %s <fg=blue;options=bold>%s</>', $status, $plugin->getAlias()));
$status = \sprintf('<fg=green;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'OK' : "\xE2\x9C\x94" /* HEAVY CHECK MARK (U+2714) */);
$output->writeln(\sprintf(' %s <fg=blue;options=bold>%s</>', $status, $plugin->getAlias()));
} catch (\Exception $e) {
$exitCode = self::FAILURE;
$status = sprintf('<fg=red;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'ERROR' : "\xE2\x9C\x98" /* HEAVY BALLOT X (U+2718) */);
$output->writeln(sprintf(' %s <fg=blue;options=bold>%s</> <error>%s</error>', $status, $plugin->getAlias(), $e->getMessage()));
$status = \sprintf('<fg=red;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'ERROR' : "\xE2\x9C\x98" /* HEAVY BALLOT X (U+2718) */);
$output->writeln(\sprintf(' %s <fg=blue;options=bold>%s</> <error>%s</error>', $status, $plugin->getAlias(), $e->getMessage()));
}
}
+1 -1
View File
@@ -12,7 +12,7 @@ final class FlasherComponent extends Component
{
}
public function render()
public function render(): string
{
/** @var array<string, mixed> $criteria */
$criteria = json_decode($this->criteria, true, 512, \JSON_THROW_ON_ERROR) ?: [];
+10 -15
View File
@@ -13,37 +13,32 @@ use Illuminate\Support\Facades\Facade;
* @method static NotificationBuilder title(string $message)
* @method static NotificationBuilder message(string $message)
* @method static NotificationBuilder type(string $message)
* @method static NotificationBuilder options(array $options, bool $merge = true)
* @method static NotificationBuilder options(array<string, mixed> $options, bool $merge = true)
* @method static NotificationBuilder option(string $name, $value)
* @method static NotificationBuilder priority(int $priority)
* @method static NotificationBuilder hops(int $amount)
* @method static NotificationBuilder keep()
* @method static NotificationBuilder delay(int $delay)
* @method static NotificationBuilder translate(array $parameters = [], ?string $locale = null)
* @method static NotificationBuilder translate(array<string, mixed> $parameters = [], ?string $locale = null)
* @method static NotificationBuilder handler(string $handler)
* @method static NotificationBuilder context(array $context)
* @method static NotificationBuilder context(array<string, mixed> $context)
* @method static NotificationBuilder when(bool|\Closure $condition)
* @method static NotificationBuilder unless(bool|\Closure $condition)
* @method static NotificationBuilder with(StampInterface[] $stamps = array())
* @method static NotificationBuilder withStamp(StampInterface $stamp)
* @method static Envelope success(string $message, array $options = [], ?string $title = null)
* @method static Envelope error(string $message, array $options = [], ?string $title = null)
* @method static Envelope info(string $message, array $options = [], ?string $title = null)
* @method static Envelope warning(string $message, array $options = [], ?string $title = null)
* @method static Envelope flash(?string $type = null, ?string $message = null, array $options = [], ?string $title = null)
* @method static Envelope preset(string $preset, array $parameters = [])
* @method static Envelope success(string $message, array<string, mixed> $options = [], ?string $title = null)
* @method static Envelope error(string $message, array<string, mixed> $options = [], ?string $title = null)
* @method static Envelope info(string $message, array<string, mixed> $options = [], ?string $title = null)
* @method static Envelope warning(string $message, array<string, mixed> $options = [], ?string $title = null)
* @method static Envelope flash(?string $type = null, ?string $message = null, array<string, mixed> $options = [], ?string $title = null)
* @method static Envelope preset(string $preset, array<string, mixed> $parameters = [])
* @method static Envelope operation(string $operation, string|object|null $resource = null)
* @method static Envelope created(string|object|null $resource = null)
* @method static Envelope updated(string|object|null $resource = null)
* @method static Envelope saved(string|object|null $resource = null)
* @method static Envelope deleted(string|object|null $resource = null)
* @method static Envelope push()
* @method static Envelope addSuccess(string $message, array $options = [], ?string $title = null)
* @method static Envelope addError(string $message, array $options = [], ?string $title = null)
* @method static Envelope addInfo(string $message, array $options = [], ?string $title = null)
* @method static Envelope addWarning(string $message, array $options = [], ?string $title = null)
* @method static Envelope addFlash(?string $type = null, ?string $message = null, array $options = [], ?string $title = null)
* @method static Envelope addPreset(string $preset, array $parameters = [])
* @method static Envelope addPreset(string $preset, array<string, mixed> $parameters = [])
* @method static Envelope addCreated(string|object|null $resource = null)
* @method static Envelope addUpdated(string|object|null $resource = null)
* @method static Envelope addDeleted(string|object|null $resource = null)
+10 -2
View File
@@ -210,7 +210,7 @@ final class FlasherServiceProvider extends PluginServiceProvider
AboutCommand::add('PHPFlasher', [
'Version' => Flasher::VERSION,
'Factories' => implode(' <fg=gray;options=bold>/</> ', array_map(fn ($factory) => sprintf('<fg=yellow;options=bold>%s</>', $factory), $factories)),
'Factories' => implode(' <fg=gray;options=bold>/</> ', array_map(fn ($factory) => \sprintf('<fg=yellow;options=bold>%s</>', $factory), $factories)),
]);
}
@@ -222,6 +222,10 @@ final class FlasherServiceProvider extends PluginServiceProvider
private function registerFlasherMiddleware(): void
{
if (!$this->getConfig('inject_assets')) {
return;
}
$this->app->singleton(FlasherMiddleware::class, static function (Application $app) {
$flasher = $app->make('flasher');
$cspHandler = $app->make('flasher.csp_handler');
@@ -251,11 +255,15 @@ final class FlasherServiceProvider extends PluginServiceProvider
private function registerSessionMiddleware(): void
{
if (!$this->getConfig('flash_bag')) {
return;
}
$this->app->singleton(SessionMiddleware::class, static function (Application $app) {
$config = $app->make('config');
$flasher = $app->make('flasher');
$mapping = $config->get('flasher.flash_bag', []);
$mapping = $config->get('flasher.flash_bag', []) ?: [];
return new SessionMiddleware(new RequestExtension($flasher, $mapping));
});
+1
View File
@@ -51,6 +51,7 @@ final readonly class Request implements RequestInterface
{
$session = $this->getSession();
/** @var false|string|string[] $type */
$type = $session?->get($type);
if (!\is_string($type) && !\is_array($type)) {
+6 -5
View File
@@ -5,12 +5,13 @@ declare(strict_types=1);
namespace Flasher\Laravel\Http;
use Flasher\Prime\Http\ResponseInterface;
use Illuminate\Http\JsonResponse as LaravelJsonResponse;
use Illuminate\Http\Response as LaravelResponse;
use Symfony\Component\HttpFoundation\JsonResponse as SymfonyJsonResponse;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
final readonly class Response implements ResponseInterface
{
public function __construct(private LaravelJsonResponse|LaravelResponse $response)
public function __construct(private SymfonyResponse $response)
{
}
@@ -21,7 +22,7 @@ final readonly class Response implements ResponseInterface
public function isJson(): bool
{
return $this->response instanceof LaravelJsonResponse;
return $this->response instanceof SymfonyJsonResponse;
}
public function isHtml(): bool
@@ -39,7 +40,7 @@ final readonly class Response implements ResponseInterface
{
$contentDisposition = $this->response->headers->get('Content-Disposition', '');
if (!\is_string($contentDisposition)) {
if (!$contentDisposition) {
return false;
}
@@ -66,7 +67,7 @@ final readonly class Response implements ResponseInterface
$this->response->setContent($content);
// Restore original response (eg. the View or Ajax data)
if ($original) {
if ($original && $this->response instanceof LaravelResponse) {
$this->response->original = $original;
}
}
+2 -3
View File
@@ -7,9 +7,8 @@ namespace Flasher\Laravel\Middleware;
use Flasher\Laravel\Http\Request;
use Flasher\Laravel\Http\Response;
use Flasher\Prime\Http\ResponseExtensionInterface;
use Illuminate\Http\JsonResponse as LaravelJsonResponse;
use Illuminate\Http\Request as LaravelRequest;
use Illuminate\Http\Response as LaravelResponse;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
final readonly class FlasherMiddleware
{
@@ -21,7 +20,7 @@ final readonly class FlasherMiddleware
{
$response = $next($request);
if ($response instanceof LaravelJsonResponse || $response instanceof LaravelResponse) {
if ($response instanceof SymfonyResponse) {
$this->responseExtension->render(new Request($request), new Response($response));
}
+2 -3
View File
@@ -7,9 +7,8 @@ namespace Flasher\Laravel\Middleware;
use Flasher\Laravel\Http\Request;
use Flasher\Laravel\Http\Response;
use Flasher\Prime\Http\RequestExtensionInterface;
use Illuminate\Http\JsonResponse as LaravelJsonResponse;
use Illuminate\Http\Request as LaravelRequest;
use Illuminate\Http\Response as LaravelResponse;
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
final readonly class SessionMiddleware
{
@@ -21,7 +20,7 @@ final readonly class SessionMiddleware
{
$response = $next($request);
if ($response instanceof LaravelJsonResponse || $response instanceof LaravelResponse) {
if ($response instanceof SymfonyResponse) {
$this->requestExtension->flash(new Request($request), new Response($response));
}
+94 -24
View File
@@ -5,30 +5,102 @@
</picture>
</p>
## About PHPFlasher
PHPFlasher is a powerful and easy-to-use package that allows you to quickly and easily add flash messages to your Laravel or Symfony projects.
Whether you need to alert users of a successful form submission, an error, or any other important information, flash messages are a simple and effective solution for providing feedback to your users.
With PHPFlasher, you can easily record and store messages within the session, making it simple to retrieve and display them on the current or next page.
This improves user engagement and enhances the overall user experience on your website or application.
Whether you're a beginner or an experienced developer, PHPFlasher's intuitive and straightforward design makes it easy to integrate into your projects.
So, if you're looking for a reliable, flexible and easy to use flash messages solution, PHPFlasher is the perfect choice.
# PHPFlasher for Laravel
PHPFlasher provides a powerful and intuitive way to add flash notifications to your Laravel applications. With PHPFlasher, you can enhance user feedback efficiently and elegantly.
## Official Documentation
Documentation for PHPFlasher can be found on the [https://php-flasher.io](https://php-flasher.io).
For more comprehensive documentation, please visit [PHPFlasher's Official Documentation](https://php-flasher.io).
## Contributors and sponsors
## Requirements
Join our team of contributors and make a lasting impact on our project!
- **PHP** v8.2 or higher
- **Laravel** v11.0 or higher
We are always looking for passionate individuals who want to contribute their skills and ideas.
Whether you're a developer, designer, or simply have a great idea, we welcome your participation and collaboration.
## Installation
Shining stars of our community:
To install PHPFlasher for Laravel, use Composer:
```bash
composer require php-flasher/flasher-laravel
```
After installation, publish the assets using:
```bash
php artisan flasher:install
```
## Usage
Quickly integrate flash notifications in your Laravel project using the simple methods provided by PHPFlasher.
- Display a success message.
```php
flash()->success('Operation completed successfully.');
```
- Display an error message.
```php
flash()->error('Oops, something went wrong.');
```
- Display a warning message.
```php
flash()->warning('Your account may have been compromised.');
```
- Display an informational message.
```php
flash()->info('This may take some time. Do not refresh the page.');
```
- Set multiple options at once.
```php
flash()
->options(['timeout' => 5000, 'position' => 'top-right'])
->success('Your profile has been updated.');
```
- Set a single option.
```php
flash()
->option('timer', 5000)
->success('Your reservation has been confirmed.');
```
- Set the priority of the message.
```php
flash()
->priority(1)
->success('Your subscription has been activated.');
```
- Set how many requests a message should persist through.
```php
flash()
->hops(2)
->info('Your account has been created, but requires verification.');
```
- Translate a message into the specified language.
```php
flash()
->translate('ar')
->success('Your message has been sent.');
```
## Contributors
<!-- ALL-CONTRIBUTORS-LIST:START -->
<!-- prettier-ignore-start -->
@@ -36,7 +108,7 @@ Shining stars of our community:
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/younes--ennaji//"><img src="https://avatars.githubusercontent.com/u/10859693?v=4?s=100" width="100px;" alt="Younes ENNAJI"/><br /><sub><b>Younes ENNAJI</b></sub></a><br /><a href="https://github.com/php-flasher/php-flasher/commits?author=yoeunes" title="Code">💻</a> <a href="https://github.com/php-flasher/php-flasher/commits?author=yoeunes" title="Documentation">📖</a> <a href="#maintenance-yoeunes" title="Maintenance">🚧</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/younes-ennaji/"><img src="https://avatars.githubusercontent.com/u/10859693?v=4?s=100" width="100px;" alt="Younes ENNAJI"/><br /><sub><b>Younes ENNAJI</b></sub></a><br /><a href="https://github.com/php-flasher/php-flasher/commits?author=yoeunes" title="Code">💻</a> <a href="https://github.com/php-flasher/php-flasher/commits?author=yoeunes" title="Documentation">📖</a> <a href="#maintenance-yoeunes" title="Maintenance">🚧</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/salmayno"><img src="https://avatars.githubusercontent.com/u/27933199?v=4?s=100" width="100px;" alt="Salma Mourad"/><br /><sub><b>Salma Mourad</b></sub></a><br /><a href="#financial-salmayno" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.youtube.com/rstacode"><img src="https://avatars.githubusercontent.com/u/35005761?v=4?s=100" width="100px;" alt="Nashwan Abdullah"/><br /><sub><b>Nashwan Abdullah</b></sub></a><br /><a href="#financial-codenashwan" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://darvis.nl/"><img src="https://avatars.githubusercontent.com/u/7394837?v=4?s=100" width="100px;" alt="Arvid de Jong"/><br /><sub><b>Arvid de Jong</b></sub></a><br /><a href="#financial-darviscommerce" title="Financial">💵</a></td>
@@ -58,17 +130,15 @@ Shining stars of our community:
## Contact
PHPFlasher is being actively developed by <a href="https://github.com/yoeunes">yoeunes</a>.
You can reach out with questions, bug reports, or feature requests on any of the following:
For support, feature requests, or contributions, reach out via:
- [Github Issues](https://github.com/php-flasher/php-flasher/issues)
- [Github](https://github.com/yoeunes)
- [GitHub Issues](https://github.com/php-flasher/php-flasher/issues)
- [Twitter](https://twitter.com/yoeunes)
- [Linkedin](https://www.linkedin.com/in/younes--ennaji//)
- [Email me directly](mailto:younes.ennaji.pro@gmail.com)
- [LinkedIn](https://www.linkedin.com/in/younes--ennaji//)
- [Email](mailto:younes.ennaji.pro@gmail.com)
## License
PHPFlasher is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
PHPFlasher is licensed under the [MIT license](https://opensource.org/licenses/MIT).
<p align="center"> <b>Made with ❤️ by <a href="https://www.linkedin.com/in/younes--ennaji//">Younes ENNAJI</a> </b> </p>
+6
View File
@@ -22,6 +22,12 @@ return [
// Automatically inject PHPFlasher assets into HTML response
'inject_assets' => true,
// Global options
'options' => [
'timeout' => 5000, // in milliseconds
'position' => 'top-right',
],
// Configuration for the flash bag (converting Laravel flash messages)
// Map Laravel session keys to PHPFlasher types
'flash_bag' => [
@@ -6,6 +6,7 @@ namespace Flasher\Laravel\Support;
use Flasher\Prime\Factory\NotificationFactoryLocator;
use Flasher\Prime\Plugin\PluginInterface;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Contracts\Foundation\CachesConfiguration;
use Illuminate\Support\ServiceProvider;
@@ -35,6 +36,14 @@ abstract class PluginServiceProvider extends ServiceProvider
return rtrim($this->getResourcesDir(), '/').'/config.php';
}
protected function getConfig(?string $key = null, mixed $default = null): mixed
{
/** @var Repository $config */
$config = $this->app->make('config');
return $key ? $config->get('flasher.'.$key, $default) : $config->get('flasher');
}
protected function getResourcesDir(): string
{
$r = new \ReflectionClass($this);
+1 -1
View File
@@ -29,7 +29,7 @@
"require": {
"php": ">=8.2",
"illuminate/support": "^11.0",
"php-flasher/flasher": "^2.0"
"php-flasher/flasher": "^2.0.1"
},
"autoload": {
"psr-4": {
-23
View File
@@ -1,23 +0,0 @@
name: Auto Closer PR
on:
pull_request_target:
types: [ opened ]
jobs:
run:
name: 🤖 PR Auto-Closure
runs-on: ubuntu-latest
steps:
- uses: superbrothers/close-pull-request@v3
with:
comment: |
Hi there 👋,
First off, thanks for your effort! 🎉 Unfortunately, this repository is read-only because it's split from our primary monorepo repository.
🙏 We kindly ask if you could direct your valuable contribution to our main repository at https://github.com/php-flasher/php-flasher.
Once you've moved your contribution there, we'll review it and provide feedback. 🕵️‍♂️
Thanks again for your understanding and cooperation. We really appreciate it! 🙌
+8 -15
View File
@@ -6,25 +6,18 @@ namespace Flasher\Noty\Laravel\Facade;
use Flasher\Noty\Prime\NotyBuilder;
use Flasher\Prime\Notification\Envelope;
use Flasher\Prime\Notification\NotificationInterface;
use Flasher\Prime\Stamp\StampInterface;
use Illuminate\Support\Facades\Facade;
/**
* @method static NotyBuilder addSuccess(string $message, array $options = array())
* @method static NotyBuilder addError(string $message, array $options = array())
* @method static NotyBuilder addWarning(string $message, array $options = array())
* @method static NotyBuilder addInfo(string $message, array $options = array())
* @method static NotyBuilder addFlash(NotificationInterface|string $type, string $message = null, array $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 warning(string $message, array<string, mixed> $options = array())
* @method static NotyBuilder info(string $message, array<string, mixed> $options = array())
* @method static NotyBuilder flash(StampInterface[] $stamps = array())
* @method static NotyBuilder type(string $type, string $message = null, array $options = array())
* @method static NotyBuilder message(string $message)
* @method static NotyBuilder options(array $options, bool $merge = true)
* @method static NotyBuilder options(array<string, mixed> $options, bool $merge = true)
* @method static NotyBuilder option(string $name, string $value)
* @method static NotyBuilder success(string $message = null, array $options = array())
* @method static NotyBuilder error(string $message = null, array $options = array())
* @method static NotyBuilder info(string $message = null, array $options = array())
* @method static NotyBuilder warning(string $message = null, array $options = array())
* @method static NotyBuilder priority(int $priority)
* @method static NotyBuilder hops(int $amount)
* @method static NotyBuilder keep()
@@ -35,12 +28,12 @@ use Illuminate\Support\Facades\Facade;
* @method static NotyBuilder handler(string $handler)
* @method static Envelope getEnvelope()
* @method static NotyBuilder text(string $text)
* @method static NotyBuilder alert(string $message = null, array $options = array())
* @method static NotyBuilder alert(string $message = null, array<string, mixed> $options = array())
* @method static NotyBuilder layout(string $layout)
* @method static NotyBuilder theme(string $theme)
* @method static NotyBuilder timeout(bool|int $timeout)
* @method static NotyBuilder progressBar(bool $progressBar = false)
* @method static NotyBuilder closeWith(array|string $closeWith)
* @method static NotyBuilder closeWith(string|string[] $closeWith)
* @method static NotyBuilder animation(string $animation, string $effect)
* @method static NotyBuilder sounds(string $option, mixed $value)
* @method static NotyBuilder docTitle(string $option, mixed $docTitle)
@@ -50,7 +43,7 @@ use Illuminate\Support\Facades\Facade;
* @method static NotyBuilder queue(string $queue)
* @method static NotyBuilder killer(bool|string $killer)
* @method static NotyBuilder container(bool|string $container)
* @method static NotyBuilder buttons(array $buttons)
* @method static NotyBuilder buttons(string[] $buttons)
* @method static NotyBuilder visibilityControl(bool $visibilityControl)
*/
final class Noty extends Facade
+2 -2
View File
@@ -28,8 +28,8 @@
"prefer-stable": true,
"require": {
"php": ">=8.2",
"php-flasher/flasher-laravel": "^2.0",
"php-flasher/flasher-noty": "^2.0"
"php-flasher/flasher-laravel": "^2.0.1",
"php-flasher/flasher-noty": "^2.0.1"
},
"autoload": {
"psr-4": {
-23
View File
@@ -1,23 +0,0 @@
name: Auto Closer PR
on:
pull_request_target:
types: [ opened ]
jobs:
run:
name: 🤖 PR Auto-Closure
runs-on: ubuntu-latest
steps:
- uses: superbrothers/close-pull-request@v3
with:
comment: |
Hi there 👋,
First off, thanks for your effort! 🎉 Unfortunately, this repository is read-only because it's split from our primary monorepo repository.
🙏 We kindly ask if you could direct your valuable contribution to our main repository at https://github.com/php-flasher/php-flasher.
Once you've moved your contribution there, we'll review it and provide feedback. 🕵️‍♂️
Thanks again for your understanding and cooperation. We really appreciate it! 🙌
+8 -2
View File
@@ -23,7 +23,10 @@ final class NotyPlugin extends Plugin
return NotyInterface::class;
}
public function getScripts(): string|array
/**
* @return string[]
*/
public function getScripts(): array
{
return [
'/vendor/flasher/noty.min.js',
@@ -31,7 +34,10 @@ final class NotyPlugin extends Plugin
];
}
public function getStyles(): string|array
/**
* @return string[]
*/
public function getStyles(): array
{
return [
'/vendor/flasher/noty.css',
+1 -1
View File
@@ -33,7 +33,7 @@
"prefer-stable": true,
"require": {
"php": ">=8.2",
"php-flasher/flasher": "^2.0"
"php-flasher/flasher": "^2.0.1"
},
"autoload": {
"psr-4": {
-23
View File
@@ -1,23 +0,0 @@
name: Auto Closer PR
on:
pull_request_target:
types: [ opened ]
jobs:
run:
name: 🤖 PR Auto-Closure
runs-on: ubuntu-latest
steps:
- uses: superbrothers/close-pull-request@v3
with:
comment: |
Hi there 👋,
First off, thanks for your effort! 🎉 Unfortunately, this repository is read-only because it's split from our primary monorepo repository.
🙏 We kindly ask if you could direct your valuable contribution to our main repository at https://github.com/php-flasher/php-flasher.
Once you've moved your contribution there, we'll review it and provide feedback. 🕵️‍♂️
Thanks again for your understanding and cooperation. We really appreciate it! 🙌
+2 -2
View File
@@ -28,8 +28,8 @@
"prefer-stable": true,
"require": {
"php": ">=8.2",
"php-flasher/flasher-noty": "^2.0",
"php-flasher/flasher-symfony": "^2.0"
"php-flasher/flasher-noty": "^2.0.1",
"php-flasher/flasher-symfony": "^2.0.1"
},
"autoload": {
"psr-4": {
-23
View File
@@ -1,23 +0,0 @@
name: Auto Closer PR
on:
pull_request_target:
types: [ opened ]
jobs:
run:
name: 🤖 PR Auto-Closure
runs-on: ubuntu-latest
steps:
- uses: superbrothers/close-pull-request@v3
with:
comment: |
Hi there 👋,
First off, thanks for your effort! 🎉 Unfortunately, this repository is read-only because it's split from our primary monorepo repository.
🙏 We kindly ask if you could direct your valuable contribution to our main repository at https://github.com/php-flasher/php-flasher.
Once you've moved your contribution there, we'll review it and provide feedback. 🕵️‍♂️
Thanks again for your understanding and cooperation. We really appreciate it! 🙌
+5 -12
View File
@@ -6,25 +6,18 @@ namespace Flasher\Notyf\Laravel\Facade;
use Flasher\Notyf\Prime\NotyfBuilder;
use Flasher\Prime\Notification\Envelope;
use Flasher\Prime\Notification\NotificationInterface;
use Flasher\Prime\Stamp\StampInterface;
use Illuminate\Support\Facades\Facade;
/**
* @method static NotyfBuilder addSuccess(string $message, array $options = array())
* @method static NotyfBuilder addError(string $message, array $options = array())
* @method static NotyfBuilder addWarning(string $message, array $options = array())
* @method static NotyfBuilder addInfo(string $message, array $options = array())
* @method static NotyfBuilder addFlash(NotificationInterface|string $type, string $message = null, array $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 warning(string $message, array<string, mixed> $options = array())
* @method static NotyfBuilder info(string $message, array<string, mixed> $options = array())
* @method static NotyfBuilder flash(StampInterface[] $stamps = array())
* @method static NotyfBuilder type(string $type, string $message = null, array $options = array())
* @method static NotyfBuilder message(string $message)
* @method static NotyfBuilder options(array $options, bool $merge = true)
* @method static NotyfBuilder options(array<string, mixed> $options, bool $merge = true)
* @method static NotyfBuilder option(string $name, string $value)
* @method static NotyfBuilder success(string $message = null, array $options = array())
* @method static NotyfBuilder error(string $message = null, array $options = array())
* @method static NotyfBuilder info(string $message = null, array $options = array())
* @method static NotyfBuilder warning(string $message = null, array $options = array())
* @method static NotyfBuilder priority(int $priority)
* @method static NotyfBuilder hops(int $amount)
* @method static NotyfBuilder keep()
+2 -2
View File
@@ -29,8 +29,8 @@
"prefer-stable": true,
"require": {
"php": ">=8.2",
"php-flasher/flasher-laravel": "^2.0",
"php-flasher/flasher-notyf": "^2.0"
"php-flasher/flasher-laravel": "^2.0.1",
"php-flasher/flasher-notyf": "^2.0.1"
},
"autoload": {
"psr-4": {
-23
View File
@@ -1,23 +0,0 @@
name: Auto Closer PR
on:
pull_request_target:
types: [ opened ]
jobs:
run:
name: 🤖 PR Auto-Closure
runs-on: ubuntu-latest
steps:
- uses: superbrothers/close-pull-request@v3
with:
comment: |
Hi there 👋,
First off, thanks for your effort! 🎉 Unfortunately, this repository is read-only because it's split from our primary monorepo repository.
🙏 We kindly ask if you could direct your valuable contribution to our main repository at https://github.com/php-flasher/php-flasher.
Once you've moved your contribution there, we'll review it and provide feedback. 🕵️‍♂️
Thanks again for your understanding and cooperation. We really appreciate it! 🙌
+8 -2
View File
@@ -23,14 +23,20 @@ final class NotyfPlugin extends Plugin
return NotyfInterface::class;
}
public function getScripts(): string|array
/**
* @return string[]
*/
public function getScripts(): array
{
return [
'/vendor/flasher/flasher-notyf.min.js',
];
}
public function getStyles(): string|array
/**
* @return string[]
*/
public function getStyles(): array
{
return [
'/vendor/flasher/flasher-notyf.min.css',
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -33,7 +33,7 @@
"prefer-stable": true,
"require": {
"php": ">=8.2",
"php-flasher/flasher": "^2.0"
"php-flasher/flasher": "^2.0.1"
},
"autoload": {
"psr-4": {
-23
View File
@@ -1,23 +0,0 @@
name: Auto Closer PR
on:
pull_request_target:
types: [ opened ]
jobs:
run:
name: 🤖 PR Auto-Closure
runs-on: ubuntu-latest
steps:
- uses: superbrothers/close-pull-request@v3
with:
comment: |
Hi there 👋,
First off, thanks for your effort! 🎉 Unfortunately, this repository is read-only because it's split from our primary monorepo repository.
🙏 We kindly ask if you could direct your valuable contribution to our main repository at https://github.com/php-flasher/php-flasher.
Once you've moved your contribution there, we'll review it and provide feedback. 🕵️‍♂️
Thanks again for your understanding and cooperation. We really appreciate it! 🙌
+2 -2
View File
@@ -29,8 +29,8 @@
"prefer-stable": true,
"require": {
"php": ">=8.2",
"php-flasher/flasher-notyf": "^2.0",
"php-flasher/flasher-symfony": "^2.0"
"php-flasher/flasher-notyf": "^2.0.1",
"php-flasher/flasher-symfony": "^2.0.1"
},
"autoload": {
"psr-4": {
-23
View File
@@ -1,23 +0,0 @@
name: Auto Closer PR
on:
pull_request_target:
types: [ opened ]
jobs:
run:
name: 🤖 PR Auto-Closure
runs-on: ubuntu-latest
steps:
- uses: superbrothers/close-pull-request@v3
with:
comment: |
Hi there 👋,
First off, thanks for your effort! 🎉 Unfortunately, this repository is read-only because it's split from our primary monorepo repository.
🙏 We kindly ask if you could direct your valuable contribution to our main repository at https://github.com/php-flasher/php-flasher.
Once you've moved your contribution there, we'll review it and provide feedback. 🕵️‍♂️
Thanks again for your understanding and cooperation. We really appreciate it! 🙌
+3 -3
View File
@@ -44,7 +44,7 @@ final class AssetManager implements AssetManagerInterface
}
if (false === file_put_contents($this->manifestPath, json_encode($this->entries, \JSON_PRETTY_PRINT | \JSON_UNESCAPED_SLASHES))) {
throw new \RuntimeException(sprintf('Failed to write manifest file to "%s"', $this->manifestPath));
throw new \RuntimeException(\sprintf('Failed to write manifest file to "%s"', $this->manifestPath));
}
}
@@ -67,10 +67,10 @@ final class AssetManager implements AssetManagerInterface
$entries = json_decode($content ?: '', true);
if (!\is_array($entries)) {
throw new \InvalidArgumentException(sprintf('There was a problem JSON decoding the "%s" file.', $this->manifestPath));
throw new \InvalidArgumentException(\sprintf('There was a problem JSON decoding the "%s" file.', $this->manifestPath));
}
return $this->entries = $entries;
return $this->entries = $entries; // @phpstan-ignore-line
}
private function computeHash(string $path): string
+3 -3
View File
@@ -57,13 +57,13 @@ final class FlasherContainer
public static function create(string $id): FlasherInterface|NotificationFactoryInterface
{
if (!self::has($id)) {
throw new \InvalidArgumentException(sprintf('The container does not have the requested service "%s".', $id));
throw new \InvalidArgumentException(\sprintf('The container does not have the requested service "%s".', $id));
}
$factory = self::getContainer()->get($id);
if (!$factory instanceof FlasherInterface && !$factory instanceof NotificationFactoryInterface) {
throw new \InvalidArgumentException(sprintf('Expected an instance of "%s" or "%s", got "%s".', FlasherInterface::class, NotificationFactoryInterface::class, get_debug_type($factory)));
throw new \InvalidArgumentException(\sprintf('Expected an instance of "%s" or "%s", got "%s".', FlasherInterface::class, NotificationFactoryInterface::class, get_debug_type($factory)));
}
return $factory;
@@ -93,7 +93,7 @@ final class FlasherContainer
$resolved = $container instanceof \Closure || \is_callable($container) ? $container() : $container;
if (!$resolved instanceof ContainerInterface) {
throw new \InvalidArgumentException(sprintf('Expected an instance of "%s", got "%s".', ContainerInterface::class, get_debug_type($resolved)));
throw new \InvalidArgumentException(\sprintf('Expected an instance of "%s", got "%s".', ContainerInterface::class, get_debug_type($resolved)));
}
return $resolved;
@@ -34,7 +34,7 @@ final class EventDispatcher implements EventDispatcherInterface
}
if (!\is_callable($listener)) {
throw new \InvalidArgumentException(sprintf('Listener "%s" is not callable. Listeners must implement __invoke method.', $listener::class));
throw new \InvalidArgumentException(\sprintf('Listener "%s" is not callable. Listeners must implement __invoke method.', $listener::class));
}
$listener($event);
@@ -25,7 +25,10 @@ final readonly class AttachDefaultStampsListener implements EventListenerInterfa
}
}
public function getSubscribedEvents(): string|array
/**
* @return string[]
*/
public function getSubscribedEvents(): array
{
return [
PersistEvent::class,
@@ -31,7 +31,7 @@ final class NotificationLoggerListener implements EventListenerInterface
return $this->events;
}
public function getSubscribedEvents(): string|array
public function getSubscribedEvents(): string
{
return PresentationEvent::class;
}
@@ -66,7 +66,7 @@ final readonly class TranslationListener implements EventListenerInterface
foreach ($preset->getParameters() as $key => $value) {
if (!\is_string($value)) {
throw new \InvalidArgumentException(sprintf('Value must be "string", got "%s".', get_debug_type($value)));
throw new \InvalidArgumentException(\sprintf('Value must be "string", got "%s".', get_debug_type($value)));
}
$parameters[$key] = $this->translator->translate($value, $parameters, $locale);
@@ -11,10 +11,10 @@ final class CriteriaNotRegisteredException extends \Exception
*/
public static function create(string $alias, array $availableCriteria = []): self
{
$message = sprintf('Criteria "%s" is not found, did you forget to register it?', $alias);
$message = \sprintf('Criteria "%s" is not found, did you forget to register it?', $alias);
if ([] !== $availableCriteria) {
$message .= sprintf(' Available criteria: [%s]', implode(', ', $availableCriteria));
$message .= \sprintf(' Available criteria: [%s]', implode(', ', $availableCriteria));
}
return new self($message);
@@ -11,10 +11,10 @@ final class FactoryNotFoundException extends \Exception
*/
public static function create(string $alias, array $availableFactories = []): self
{
$message = sprintf('Factory "%s" not found, did you forget to register it?', $alias);
$message = \sprintf('Factory "%s" not found, did you forget to register it?', $alias);
if ([] !== $availableFactories) {
$message .= sprintf(' Available factories: [%s]', implode(', ', $availableFactories));
$message .= \sprintf(' Available factories: [%s]', implode(', ', $availableFactories));
}
return new self($message);
@@ -11,10 +11,10 @@ final class PresenterNotFoundException extends \Exception
*/
public static function create(string $alias, array $availablePresenters = []): self
{
$message = sprintf('Presenter "%s" not found, did you forget to register it?', $alias);
$message = \sprintf('Presenter "%s" not found, did you forget to register it?', $alias);
if ([] !== $availablePresenters) {
$message .= sprintf(' Available presenters: [%s]', implode(', ', $availablePresenters));
$message .= \sprintf(' Available presenters: [%s]', implode(', ', $availablePresenters));
}
return new self($message);
@@ -12,10 +12,10 @@ final class PresetNotFoundException extends \Exception
*/
public static function create(string $preset, array $availablePresets = []): self
{
$message = sprintf('Preset "%s" not found, did you forget to register it?', $preset);
$message = \sprintf('Preset "%s" not found, did you forget to register it?', $preset);
if ([] !== $availablePresets) {
$message .= sprintf(' Available presets: "%s"', implode('", "', $availablePresets));
$message .= \sprintf(' Available presets: "%s"', implode('", "', $availablePresets));
}
return new self($message);
@@ -136,7 +136,7 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
if (!\in_array('\'unsafe-inline\'', $headers[$header][$type], true)) {
$headers[$header][$type][] = '\'unsafe-inline\'';
}
$headers[$header][$type][] = sprintf('\'nonce-%s\'', $nonces[$tokenName]);
$headers[$header][$type][] = \sprintf('\'nonce-%s\'', $nonces[$tokenName]);
}
}
@@ -166,7 +166,7 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
*/
private function generateCspHeader(array $directives): string
{
return array_reduce(array_keys($directives), fn ($res, $name) => ('' !== $res ? $res.'; ' : '').sprintf('%s %s', $name, implode(' ', $directives[$name])), '');
return array_reduce(array_keys($directives), fn ($res, $name) => ('' !== $res ? $res.'; ' : '').\sprintf('%s %s', $name, implode(' ', $directives[$name])), '');
}
/**
+1 -1
View File
@@ -55,7 +55,7 @@ final readonly class ResponseExtension implements ResponseExtensionInterface
}
if ($alreadyRendered) {
$htmlResponse = sprintf('options.push(%s);', $htmlResponse);
$htmlResponse = \sprintf('options.push(%s);', $htmlResponse);
}
// $htmlResponse = "\n".str_replace("\n", '', (string) $htmlResponse)."\n";
@@ -160,7 +160,7 @@ trait NotificationBuilderMethods
if (!\is_bool($condition)) {
$type = \gettype($condition);
throw new \InvalidArgumentException(sprintf('The condition must be a boolean or a closure that returns a boolean. Got: %s', $type));
throw new \InvalidArgumentException(\sprintf('The condition must be a boolean or a closure that returns a boolean. Got: %s', $type));
}
return $condition;
+10 -7
View File
@@ -69,7 +69,10 @@ final class FlasherPlugin extends Plugin
return '/vendor/flasher/flasher.min.js';
}
public function getScripts(): string|array
/**
* @return string[]
*/
public function getScripts(): array
{
return [];
}
@@ -97,7 +100,11 @@ final class FlasherPlugin extends Plugin
* scripts: string[],
* styles: string[],
* options: array<string, mixed>,
* plugins?: array<string, array<string, mixed>>,
* plugins?: array<string, array{
* scripts?: string[],
* styles?: string[],
* options?: array<string, mixed>,
* }>,
* } $config
*
* @return array{
@@ -267,11 +274,7 @@ final class FlasherPlugin extends Plugin
return $config;
}
foreach ($config['flash_bag'] as $key => $value) {
$config['flash_bag'][$key] = array_values(array_unique(array_merge($mapping[$key] ?? [], (array) $value)));
}
$config['flash_bag'] += $mapping;
$config['flash_bag'] += array_merge($mapping, $config['flash_bag']);
return $config;
}
+29 -3
View File
@@ -7,7 +7,7 @@ import { AbstractPlugin } from './plugin'
export default class FlasherPlugin extends AbstractPlugin {
private theme: Theme
private options = {
timeout: 5000,
timeout: null,
timeouts: {
success: 5000,
info: 5000,
@@ -19,6 +19,7 @@ export default class FlasherPlugin extends AbstractPlugin {
direction: 'top',
rtl: false,
style: {} as Properties,
escapeHtml: false,
}
constructor(theme: Theme) {
@@ -31,11 +32,12 @@ export default class FlasherPlugin extends AbstractPlugin {
const render = () =>
envelopes.forEach((envelope) => {
// @ts-expect-error
const typeTimeout = this.options.timeouts[envelope.type] ?? this.options.timeout
const typeTimeout = this.options.timeout ?? this.options.timeouts[envelope.type] ?? 5000
const options = {
...this.options,
...envelope.options,
timeout: envelope.options.timeout ?? typeTimeout,
escapeHtml: (envelope.options.escapeHtml ?? this.options.escapeHtml) as boolean,
}
this.addToContainer(this.createContainer(options), envelope, options)
@@ -64,7 +66,12 @@ export default class FlasherPlugin extends AbstractPlugin {
return container
}
private addToContainer(container: HTMLDivElement, envelope: Envelope, options: { direction: string, timeout: number, fps: number, rtl: boolean }): void {
private addToContainer(container: HTMLDivElement, envelope: Envelope, options: { direction: string, timeout: number, fps: number, rtl: boolean, escapeHtml: boolean }): void {
if (options.escapeHtml) {
envelope.title = this.escapeHtml(envelope.title)
envelope.message = this.escapeHtml(envelope.message)
}
const notification = this.stringToHTML(this.theme.render(envelope))
notification.classList.add(...`fl-container${options.rtl ? ' fl-rtl' : ''}`.split(' '))
@@ -126,4 +133,23 @@ export default class FlasherPlugin extends AbstractPlugin {
template.innerHTML = str.trim()
return template.content.firstElementChild as HTMLElement
}
private escapeHtml(str: string | null | undefined): string {
if (str == null) {
return ''
}
return str.replace(/[&<>"'`=\/]/g, (char) => {
return {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
'\'': '&#39;',
'`': '&#96;',
'=': '&#61;',
'/': '&#47;',
}[char] as string
})
}
}
@@ -1,3 +1,5 @@
@use "sass:color";
body.fl-dark .fl-flasher,
html.fl-dark .fl-flasher {
--background-color: var(--dark-background-color);
@@ -69,7 +71,7 @@ html.fl-dark .fl-flasher {
transition: color 0.3s ease, transform 0.3s ease;
&:hover {
color: darken(#a8aaab, 10%);
color: color.adjust(#a8aaab, $lightness: -10%);
transform: scale(1.1);
}
}
+1
View File
@@ -15,4 +15,5 @@ export default class FlasherPlugin extends AbstractPlugin {
}): void;
private removeNotification;
private stringToHTML;
private escapeHtml;
}
+26 -4
View File
@@ -80,7 +80,7 @@ class FlasherPlugin extends AbstractPlugin {
constructor(theme) {
super();
this.options = {
timeout: 5000,
timeout: null,
timeouts: {
success: 5000,
info: 5000,
@@ -92,14 +92,15 @@ class FlasherPlugin extends AbstractPlugin {
direction: 'top',
rtl: false,
style: {},
escapeHtml: false,
};
this.theme = theme;
}
renderEnvelopes(envelopes) {
const render = () => envelopes.forEach((envelope) => {
var _a, _b;
const typeTimeout = (_a = this.options.timeouts[envelope.type]) !== null && _a !== void 0 ? _a : this.options.timeout;
const options = Object.assign(Object.assign(Object.assign({}, this.options), envelope.options), { timeout: (_b = envelope.options.timeout) !== null && _b !== void 0 ? _b : typeTimeout });
var _a, _b, _c, _d;
const typeTimeout = (_b = (_a = this.options.timeout) !== null && _a !== void 0 ? _a : this.options.timeouts[envelope.type]) !== null && _b !== void 0 ? _b : 5000;
const options = Object.assign(Object.assign(Object.assign({}, this.options), envelope.options), { timeout: (_c = envelope.options.timeout) !== null && _c !== void 0 ? _c : typeTimeout, escapeHtml: ((_d = envelope.options.escapeHtml) !== null && _d !== void 0 ? _d : this.options.escapeHtml) });
this.addToContainer(this.createContainer(options), envelope, options);
});
document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', render) : render();
@@ -121,6 +122,10 @@ class FlasherPlugin extends AbstractPlugin {
}
addToContainer(container, envelope, options) {
var _a;
if (options.escapeHtml) {
envelope.title = this.escapeHtml(envelope.title);
envelope.message = this.escapeHtml(envelope.message);
}
const notification = this.stringToHTML(this.theme.render(envelope));
notification.classList.add(...`fl-container${options.rtl ? ' fl-rtl' : ''}`.split(' '));
options.direction === 'bottom' ? container.append(notification) : container.prepend(notification);
@@ -170,6 +175,23 @@ class FlasherPlugin extends AbstractPlugin {
template.innerHTML = str.trim();
return template.content.firstElementChild;
}
escapeHtml(str) {
if (str == null) {
return '';
}
return str.replace(/[&<>"'`=\/]/g, (char) => {
return {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
'\'': '&#39;',
'`': '&#96;',
'=': '&#61;',
'/': '&#47;',
}[char];
});
}
}
class Flasher extends AbstractPlugin {
+26 -4
View File
@@ -86,7 +86,7 @@
constructor(theme) {
super();
this.options = {
timeout: 5000,
timeout: null,
timeouts: {
success: 5000,
info: 5000,
@@ -98,14 +98,15 @@
direction: 'top',
rtl: false,
style: {},
escapeHtml: false,
};
this.theme = theme;
}
renderEnvelopes(envelopes) {
const render = () => envelopes.forEach((envelope) => {
var _a, _b;
const typeTimeout = (_a = this.options.timeouts[envelope.type]) !== null && _a !== void 0 ? _a : this.options.timeout;
const options = Object.assign(Object.assign(Object.assign({}, this.options), envelope.options), { timeout: (_b = envelope.options.timeout) !== null && _b !== void 0 ? _b : typeTimeout });
var _a, _b, _c, _d;
const typeTimeout = (_b = (_a = this.options.timeout) !== null && _a !== void 0 ? _a : this.options.timeouts[envelope.type]) !== null && _b !== void 0 ? _b : 5000;
const options = Object.assign(Object.assign(Object.assign({}, this.options), envelope.options), { timeout: (_c = envelope.options.timeout) !== null && _c !== void 0 ? _c : typeTimeout, escapeHtml: ((_d = envelope.options.escapeHtml) !== null && _d !== void 0 ? _d : this.options.escapeHtml) });
this.addToContainer(this.createContainer(options), envelope, options);
});
document.readyState === 'loading' ? document.addEventListener('DOMContentLoaded', render) : render();
@@ -127,6 +128,10 @@
}
addToContainer(container, envelope, options) {
var _a;
if (options.escapeHtml) {
envelope.title = this.escapeHtml(envelope.title);
envelope.message = this.escapeHtml(envelope.message);
}
const notification = this.stringToHTML(this.theme.render(envelope));
notification.classList.add(...`fl-container${options.rtl ? ' fl-rtl' : ''}`.split(' '));
options.direction === 'bottom' ? container.append(notification) : container.prepend(notification);
@@ -176,6 +181,23 @@
template.innerHTML = str.trim();
return template.content.firstElementChild;
}
escapeHtml(str) {
if (str == null) {
return '';
}
return str.replace(/[&<>"'`=\/]/g, (char) => {
return {
'&': '&amp;',
'<': '&lt;',
'>': '&gt;',
'"': '&quot;',
'\'': '&#39;',
'`': '&#96;',
'=': '&#61;',
'/': '&#47;',
}[char];
});
}
}
class Flasher extends AbstractPlugin {
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -21,6 +21,7 @@ final class HtmlPresenter implements PresenterInterface
/** @var array{csp_script_nonce?: ?string, envelopes_only?: bool} $context */
$context = $response->getContext();
/** @var array{envelopes: array<int, array{metadata: array{html?: string}}>} $options */
$options = $response->toArray();
$html = '';
+1 -1
View File
@@ -9,7 +9,7 @@ final readonly class PresenterStamp implements StampInterface
public function __construct(private string $pattern)
{
if (false === @preg_match($pattern, '')) {
throw new \InvalidArgumentException(sprintf("The provided regex pattern '%s' is invalid for the presenter stamp. Please ensure it is a valid regex expression.", $pattern));
throw new \InvalidArgumentException(\sprintf("The provided regex pattern '%s' is invalid for the presenter stamp. Please ensure it is a valid regex expression.", $pattern));
}
}
@@ -17,13 +17,13 @@ final class FilterCriteria implements CriteriaInterface
public function __construct(mixed $criteria)
{
if (!$criteria instanceof \Closure && !\is_array($criteria)) {
throw new \InvalidArgumentException(sprintf('Invalid type for criteria "filter". Expect a closure or array of closure, got "%s".', get_debug_type($criteria)));
throw new \InvalidArgumentException(\sprintf('Invalid type for criteria "filter". Expect a closure or array of closure, got "%s".', get_debug_type($criteria)));
}
$criteria = $criteria instanceof \Closure ? [$criteria] : $criteria;
foreach ($criteria as $callback) {
if (!$callback instanceof \Closure) {
throw new \InvalidArgumentException(sprintf('Each element must be a closure, got got "%s".', get_debug_type($callback)));
throw new \InvalidArgumentException(\sprintf('Each element must be a closure, got got "%s".', get_debug_type($callback)));
}
$this->callbacks[] = $callback;
@@ -49,7 +49,7 @@ final class OrderByCriteria implements CriteriaInterface
public function __construct(mixed $criteria)
{
if (!\is_string($criteria) && !\is_array($criteria)) {
throw new \InvalidArgumentException(sprintf('Invalid type for criteria "order_by". Expect a "string" or an "array", got "%s".', get_debug_type($criteria)));
throw new \InvalidArgumentException(\sprintf('Invalid type for criteria "order_by". Expect a "string" or an "array", got "%s".', get_debug_type($criteria)));
}
foreach ((array) $criteria as $field => $direction) {
@@ -59,18 +59,22 @@ final class OrderByCriteria implements CriteriaInterface
}
if (!\is_string($field)) {
throw new \InvalidArgumentException(sprintf('Invalid Field value, must be "string", got "%s".', get_debug_type($field)));
throw new \InvalidArgumentException(\sprintf('Invalid Field value, must be "string", got "%s".', get_debug_type($field)));
}
$direction = strtoupper((string) $direction);
if (!\is_string($direction)) {
throw new \InvalidArgumentException(\sprintf('Invalid Direction value, must be "string", got "%s".', get_debug_type($direction)));
}
$direction = strtoupper($direction);
if (!\in_array($direction, [self::ASC, self::DESC], true)) {
throw new \InvalidArgumentException(sprintf('Invalid ordering direction: must be "ASC" or "DESC", got "%s".', $direction));
throw new \InvalidArgumentException(\sprintf('Invalid ordering direction: must be "ASC" or "DESC", got "%s".', $direction));
}
$field = $this->aliases[$field] ?? $field;
if (!is_a($field, StampInterface::class, true)) {
throw new \InvalidArgumentException(sprintf('Field "%s" is not a valid class-string of "%s".', $field, StampInterface::class));
throw new \InvalidArgumentException(\sprintf('Field "%s" is not a valid class-string of "%s".', $field, StampInterface::class));
}
$this->orderings[$field] = $direction;
@@ -19,7 +19,7 @@ trait RangeExtractor
private function extractRange(string $name, mixed $criteria): array
{
if (!\is_int($criteria) && !\is_array($criteria)) {
throw new \InvalidArgumentException(sprintf('Invalid type for criteria "%s". Expected int or array, got "%s".', $name, get_debug_type($criteria)));
throw new \InvalidArgumentException(\sprintf('Invalid type for criteria "%s". Expected int or array, got "%s".', $name, get_debug_type($criteria)));
}
if (\is_int($criteria)) {
@@ -30,11 +30,11 @@ trait RangeExtractor
$max = $criteria['max'] ?? null;
if (null !== $min && !\is_int($min)) {
throw new \InvalidArgumentException(sprintf('Invalid type for "min" in criteria "%s". Expected int, got "%s".', $name, get_debug_type($min)));
throw new \InvalidArgumentException(\sprintf('Invalid type for "min" in criteria "%s". Expected int, got "%s".', $name, get_debug_type($min)));
}
if (null !== $max && !\is_int($max)) {
throw new \InvalidArgumentException(sprintf('Invalid type for "max" in criteria "%s". Expected int, got "%s".', $name, get_debug_type($max)));
throw new \InvalidArgumentException(\sprintf('Invalid type for "max" in criteria "%s". Expected int, got "%s".', $name, get_debug_type($max)));
}
return ['min' => $min, 'max' => $max];
+1 -1
View File
@@ -71,7 +71,7 @@ final class FilterFactory implements FilterFactoryInterface
$criteria = \is_callable($criteria) ? $criteria($value) : $criteria;
if (!$criteria instanceof CriteriaInterface) {
throw new \UnexpectedValueException(sprintf('Expected an instance of "%s", got "%s" instead.', CriteriaInterface::class, get_debug_type($criteria)));
throw new \UnexpectedValueException(\sprintf('Expected an instance of "%s", got "%s" instead.', CriteriaInterface::class, get_debug_type($criteria)));
}
return $criteria;
+1 -1
View File
@@ -70,6 +70,6 @@ trait ForwardsCalls
*/
protected static function throwBadMethodCallException(string $method): never
{
throw new \BadMethodCallException(sprintf('Call to undefined method %s::%s()', static::class, $method));
throw new \BadMethodCallException(\sprintf('Call to undefined method %s::%s()', static::class, $method));
}
}
+5 -5
View File
@@ -56,7 +56,7 @@ trait Macroable
$macro = $method->invoke($mixin);
if (!\is_callable($macro) && !\is_object($macro)) {
throw new \InvalidArgumentException(sprintf('Expect the result of method %s::%s from the mixin object to be be a callable or an object, got "%s".', $mixin::class, $method->name, get_debug_type($macro)));
throw new \InvalidArgumentException(\sprintf('Expect the result of method %s::%s from the mixin object to be be a callable or an object, got "%s".', $mixin::class, $method->name, get_debug_type($macro)));
}
if ($replace || !static::hasMacro($method->name)) {
@@ -83,7 +83,7 @@ trait Macroable
public static function __callStatic(string $method, array $parameters): mixed
{
if (!static::hasMacro($method)) {
throw new \BadMethodCallException(sprintf('Method %s::%s does not exist.', static::class, $method));
throw new \BadMethodCallException(\sprintf('Method %s::%s does not exist.', static::class, $method));
}
$macro = static::$macros[$method];
@@ -93,7 +93,7 @@ trait Macroable
}
if (!\is_callable($macro)) {
throw new \BadMethodCallException(sprintf('Macro %s is not callable.', $method));
throw new \BadMethodCallException(\sprintf('Macro %s is not callable.', $method));
}
return $macro(...$parameters);
@@ -109,7 +109,7 @@ trait Macroable
public function __call(string $method, array $parameters): mixed
{
if (!static::hasMacro($method)) {
throw new \BadMethodCallException(sprintf('Method %s::%s does not exist.', static::class, $method));
throw new \BadMethodCallException(\sprintf('Method %s::%s does not exist.', static::class, $method));
}
$macro = static::$macros[$method];
@@ -119,7 +119,7 @@ trait Macroable
}
if (!\is_callable($macro)) {
throw new \BadMethodCallException(sprintf('Macro %s is not callable.', $method));
throw new \BadMethodCallException(\sprintf('Macro %s is not callable.', $method));
}
return $macro(...$parameters);
+1 -1
View File
@@ -9,7 +9,7 @@ final class PHPTemplateEngine implements TemplateEngineInterface
public function render(string $name, array $context = []): string
{
if (!file_exists($name) || !is_readable($name)) {
throw new \InvalidArgumentException(sprintf('Template file "%s" does not exist or is not readable.', $name));
throw new \InvalidArgumentException(\sprintf('Template file "%s" does not exist or is not readable.', $name));
}
ob_start();
+6 -6
View File
@@ -32,15 +32,15 @@ final class Notification extends Constraint
public function toString(): string
{
$details = [
sprintf('type: "%s"', $this->expectedType),
\sprintf('type: "%s"', $this->expectedType),
];
if (null !== $this->expectedMessage) {
$details[] = sprintf('message: "%s"', $this->expectedMessage);
$details[] = \sprintf('message: "%s"', $this->expectedMessage);
}
if (null !== $this->expectedTitle) {
$details[] = sprintf('title: "%s"', $this->expectedTitle);
$details[] = \sprintf('title: "%s"', $this->expectedTitle);
}
if (!empty($this->expectedOptions)) {
@@ -51,7 +51,7 @@ final class Notification extends Constraint
}
/**
* @param NotificationEvents $other
* @param NotificationEvents|mixed $other
*/
protected function matches(mixed $other): bool
{
@@ -82,7 +82,7 @@ final class Notification extends Constraint
protected function failureDescription(mixed $other): string
{
$foundNotifications = array_map(function (NotificationInterface $notification) {
return sprintf(
return \sprintf(
'type: "%s", title: "%s", message: "%s", options: [%s]',
$notification->getType(),
$notification->getTitle(),
@@ -95,7 +95,7 @@ final class Notification extends Constraint
$foundNotifications[] = 'No notifications found';
}
return sprintf(
return \sprintf(
'Failed asserting that NotificationEvents %s. Found: [%s].',
$this->toString(),
implode('; ', $foundNotifications)
@@ -15,13 +15,13 @@ final class NotificationCount extends Constraint
public function toString(): string
{
return sprintf('matches the expected notification count of %d.', $this->expectedValue);
return \sprintf('matches the expected notification count of %d.', $this->expectedValue);
}
/**
* Evaluates if the given NotificationEvents object matches the expected notification count.
*
* @param NotificationEvents $other an instance of NotificationEvents to evaluate
* @param NotificationEvents|mixed $other an instance of NotificationEvents to evaluate
*
* @return bool returns true if the actual notification count matches the expected count
*/
@@ -45,7 +45,7 @@ final class NotificationCount extends Constraint
{
$actualCount = $this->countNotifications($other);
return sprintf('Expected the notification count to be %d, but got %d instead.', $this->expectedValue, $actualCount);
return \sprintf('Expected the notification count to be %d, but got %d instead.', $this->expectedValue, $actualCount);
}
/**
@@ -19,7 +19,7 @@ final class NotificationMessage extends Constraint
public function toString(): string
{
return sprintf('contains a notification with message "%s"', $this->expectedMessage);
return \sprintf('contains a notification with message "%s"', $this->expectedMessage);
}
protected function matches(mixed $other): bool
@@ -44,17 +44,17 @@ final class NotificationMessage extends Constraint
}
$foundMessages = array_map(function (NotificationInterface $notification) {
return sprintf('"%s"', $notification->getMessage());
return \sprintf('"%s"', $notification->getMessage());
}, $other->getNotifications());
if (empty($foundMessages)) {
return sprintf(
return \sprintf(
'Expected to find a notification with a message containing "%s", but no notifications were found.',
$this->expectedMessage
);
}
return sprintf(
return \sprintf(
'Expected to find a notification with a message containing "%s". Found messages: %s.',
$this->expectedMessage,
implode(', ', $foundMessages)
@@ -23,10 +23,10 @@ final class NotificationOption extends Constraint
public function toString(): string
{
$description = sprintf('contains a notification with an option "%s"', $this->expectedKey);
$description = \sprintf('contains a notification with an option "%s"', $this->expectedKey);
if ($this->expectedValue) {
$description .= sprintf(' having the value "%s"', json_encode($this->expectedValue));
$description .= \sprintf(' having the value "%s"', json_encode($this->expectedValue));
}
return $description;
@@ -50,7 +50,7 @@ final class NotificationOptions extends Constraint
$actualOptionsString = implode('; ', $actualOptions) ?: 'none found';
return sprintf(
return \sprintf(
'Failed asserting that NotificationEvents %s. Actual options in notifications: [%s].',
$this->toString(),
$actualOptionsString
@@ -22,7 +22,7 @@ final class NotificationTitle extends Constraint
public function toString(): string
{
return sprintf('contains a notification with a title containing "%s"', $this->expectedTitle);
return \sprintf('contains a notification with a title containing "%s"', $this->expectedTitle);
}
protected function matches(mixed $other): bool
@@ -47,17 +47,17 @@ final class NotificationTitle extends Constraint
}
$foundTitles = array_map(function (NotificationInterface $notification) {
return sprintf('"%s"', $notification->getTitle());
return \sprintf('"%s"', $notification->getTitle());
}, $other->getNotifications());
if (empty($foundTitles)) {
return sprintf(
return \sprintf(
'Expected to find a notification with a title containing "%s", but no notifications were found.',
$this->expectedTitle
);
}
return sprintf(
return \sprintf(
'Expected to find a notification with a title containing "%s". Found titles: %s.',
$this->expectedTitle,
implode(', ', $foundTitles)
@@ -23,14 +23,14 @@ final class NotificationType extends Constraint
public function toString(): string
{
return sprintf('contains a notification of type "%s".', $this->expectedType);
return \sprintf('contains a notification of type "%s".', $this->expectedType);
}
/**
* Evaluates the constraint for the parameter $other.
* If $other is not an instance of NotificationEvents, the method will return false.
*
* @param NotificationEvents $other value or object to evaluate
* @param NotificationEvents|mixed $other value or object to evaluate
*
* @return bool true if the constraint is met, false otherwise
*/
@@ -65,7 +65,7 @@ final class NotificationType extends Constraint
$uniqueTypes = array_unique($actualTypes);
$typesList = implode(', ', $uniqueTypes);
return sprintf(
return \sprintf(
'Expected the NotificationEvents to contain a notification of type "%s", but found types: %s.',
$this->expectedType,
$typesList ?: 'none'

Some files were not shown because too many files have changed in this diff Show More