mirror of
https://github.com/php-flasher/php-flasher.git
synced 2026-03-31 15:07:47 +01:00
Simplify PHPDoc comments in Laravel and Symfony integrations
Remove verbose documentation pattern references and redundant explanations, keeping only essential type annotations.
This commit is contained in:
@@ -16,15 +16,7 @@ use Symfony\Component\Console\Output\OutputInterface;
|
|||||||
use Symfony\Component\Finder\Finder;
|
use Symfony\Component\Finder\Finder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* InstallCommand - Artisan command for installing PHPFlasher resources.
|
* 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
|
||||||
{
|
{
|
||||||
@@ -35,21 +27,11 @@ final class InstallCommand extends Command
|
|||||||
*/
|
*/
|
||||||
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
|
||||||
@@ -60,20 +42,6 @@ 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('');
|
||||||
@@ -162,13 +130,7 @@ final class InstallCommand extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Publish assets from a plugin to the public directory.
|
* @return string[]
|
||||||
*
|
|
||||||
* @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
|
||||||
{
|
{
|
||||||
@@ -202,12 +164,6 @@ 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)) {
|
||||||
|
|||||||
@@ -7,38 +7,14 @@ namespace Flasher\Laravel\Component;
|
|||||||
use Illuminate\View\Component;
|
use Illuminate\View\Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FlasherComponent - Blade component for rendering notifications.
|
* Blade component for rendering PHPFlasher 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 */
|
||||||
|
|||||||
@@ -14,27 +14,10 @@ use Livewire\LivewireManager;
|
|||||||
use Livewire\Mechanisms\HandleComponents\ComponentContext;
|
use Livewire\Mechanisms\HandleComponents\ComponentContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LivewireListener - Integrates PHPFlasher with Livewire component lifecycle.
|
* 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,
|
||||||
@@ -43,15 +26,6 @@ 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)) {
|
||||||
@@ -67,14 +41,7 @@ final readonly class LivewireListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dispatches notifications as Livewire events.
|
* @param array{envelopes: Envelope[]} $data
|
||||||
*
|
|
||||||
* 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
|
||||||
{
|
{
|
||||||
@@ -89,30 +56,13 @@ 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']);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the security context for rendering notifications.
|
* @return array<string, mixed>
|
||||||
*
|
|
||||||
* 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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -8,25 +8,10 @@ use Flasher\Prime\EventDispatcher\EventListener\NotificationLoggerListener;
|
|||||||
use Laravel\Octane\Events\RequestReceived;
|
use Laravel\Octane\Events\RequestReceived;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OctaneListener - Resets notification logger between Octane requests.
|
* 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,28 +10,7 @@ use Flasher\Prime\Stamp\StampInterface;
|
|||||||
use Illuminate\Support\Facades\Facade;
|
use Illuminate\Support\Facades\Facade;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flasher - Laravel Facade for the PHPFlasher service.
|
* Laravel facade for PHPFlasher with IDE autocompletion support.
|
||||||
*
|
|
||||||
* 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)
|
||||||
@@ -71,11 +50,6 @@ 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';
|
||||||
|
|||||||
@@ -43,27 +43,10 @@ use Laravel\Octane\Events\RequestReceived;
|
|||||||
use Livewire\LivewireManager;
|
use Livewire\LivewireManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FlasherServiceProvider - Main service provider for Laravel integration.
|
* 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();
|
||||||
@@ -80,17 +63,6 @@ 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());
|
||||||
@@ -102,22 +74,11 @@ 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) {
|
||||||
@@ -135,12 +96,6 @@ 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 () {
|
||||||
@@ -148,12 +103,6 @@ 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) {
|
||||||
@@ -165,11 +114,6 @@ 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) {
|
||||||
@@ -179,12 +123,6 @@ 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) {
|
||||||
@@ -208,12 +146,6 @@ 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) {
|
||||||
@@ -228,12 +160,6 @@ 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());
|
||||||
@@ -259,11 +185,6 @@ 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()) {
|
||||||
@@ -281,11 +202,6 @@ 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)) {
|
||||||
@@ -310,22 +226,12 @@ 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')) {
|
||||||
@@ -345,11 +251,6 @@ 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')) {
|
||||||
@@ -368,11 +269,6 @@ 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) {
|
||||||
@@ -380,11 +276,6 @@ 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 () {
|
||||||
@@ -392,11 +283,6 @@ 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 () {
|
||||||
@@ -407,11 +293,6 @@ 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 = '') {
|
||||||
@@ -425,11 +306,6 @@ 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')) {
|
||||||
|
|||||||
@@ -9,24 +9,10 @@ use Illuminate\Contracts\Session\Session;
|
|||||||
use Illuminate\Http\Request as LaravelRequest;
|
use Illuminate\Http\Request as LaravelRequest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request - Adapter for Laravel HTTP requests.
|
* 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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -90,11 +76,6 @@ 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 {
|
||||||
|
|||||||
@@ -10,24 +10,10 @@ 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.
|
* 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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -74,12 +60,6 @@ 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;
|
||||||
|
|||||||
@@ -11,39 +11,14 @@ 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.
|
* 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);
|
||||||
|
|||||||
@@ -11,39 +11,14 @@ 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.
|
* 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);
|
||||||
|
|||||||
@@ -9,38 +9,16 @@ use Flasher\Prime\Storage\Bag\BagInterface;
|
|||||||
use Illuminate\Session\SessionManager;
|
use Illuminate\Session\SessionManager;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SessionBag - Laravel session storage for PHPFlasher notifications.
|
* 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 */
|
||||||
@@ -49,13 +27,6 @@ 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);
|
||||||
|
|||||||
@@ -12,18 +12,7 @@ use Illuminate\Contracts\Foundation\CachesConfiguration;
|
|||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PluginServiceProvider - Base service provider for PHPFlasher plugins.
|
* Base service provider for PHPFlasher plugins in Laravel.
|
||||||
*
|
|
||||||
* 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
|
||||||
{
|
{
|
||||||
@@ -32,23 +21,8 @@ abstract class PluginServiceProvider extends ServiceProvider
|
|||||||
*/
|
*/
|
||||||
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();
|
||||||
@@ -57,37 +31,17 @@ 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 */
|
||||||
@@ -96,11 +50,6 @@ 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);
|
||||||
@@ -108,12 +57,6 @@ 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()) {
|
||||||
@@ -136,32 +79,14 @@ 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) {
|
||||||
|
|||||||
@@ -8,37 +8,14 @@ use Flasher\Prime\Template\TemplateEngineInterface;
|
|||||||
use Illuminate\View\Factory;
|
use Illuminate\View\Factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* BladeTemplateEngine - Laravel Blade adapter for PHPFlasher templates.
|
* 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();
|
||||||
|
|||||||
@@ -8,42 +8,14 @@ use Flasher\Prime\Translation\TranslatorInterface;
|
|||||||
use Illuminate\Translation\Translator as LaravelTranslator;
|
use Illuminate\Translation\Translator as LaravelTranslator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translator - Laravel adapter for PHPFlasher translations.
|
* 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);
|
||||||
@@ -61,27 +33,15 @@ 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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)
|
* @return array<string, mixed>
|
||||||
* and Laravel's parameter format (parameter).
|
|
||||||
*
|
|
||||||
* @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
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,33 +5,11 @@ declare(strict_types=1);
|
|||||||
namespace Flasher\Symfony\Attribute;
|
namespace Flasher\Symfony\Attribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AsFlasherFactory - Attribute for tagging notification factories.
|
* Attribute for tagging notification factories.
|
||||||
*
|
|
||||||
* This attribute enables auto-configuration of notification factory services in Symfony.
|
|
||||||
* When applied to a factory class, it automatically registers the class with the container
|
|
||||||
* using the specified alias, making it available to the PHPFlasher system.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Attribute-based Configuration: Uses PHP 8 attributes for declarative service configuration
|
|
||||||
* - Service Tagging: Implements Symfony's tag-based service discovery mechanism
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* ```php
|
|
||||||
* #[AsFlasherFactory('toastr')]
|
|
||||||
* class ToastrFactory implements NotificationFactoryInterface
|
|
||||||
* {
|
|
||||||
* // ...
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
*/
|
||||||
#[\Attribute(\Attribute::TARGET_CLASS)]
|
#[\Attribute(\Attribute::TARGET_CLASS)]
|
||||||
final readonly class AsFlasherFactory
|
final readonly class AsFlasherFactory
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Creates a new AsFlasherFactory attribute.
|
|
||||||
*
|
|
||||||
* @param string $alias The unique alias for the notification factory (e.g., 'toastr', 'noty')
|
|
||||||
*/
|
|
||||||
public function __construct(public string $alias)
|
public function __construct(public string $alias)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,34 +5,11 @@ declare(strict_types=1);
|
|||||||
namespace Flasher\Symfony\Attribute;
|
namespace Flasher\Symfony\Attribute;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AsFlasherPresenter - Attribute for tagging response presenters.
|
* Attribute for tagging response presenters.
|
||||||
*
|
|
||||||
* This attribute enables auto-configuration of response presenter services in Symfony.
|
|
||||||
* When applied to a presenter class, it automatically registers the class with the
|
|
||||||
* container using the specified alias, making it available to PHPFlasher's response system.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Attribute-based Configuration: Uses PHP 8 attributes for declarative service configuration
|
|
||||||
* - Service Tagging: Implements Symfony's tag-based service discovery mechanism
|
|
||||||
* - Strategy Pattern: Supports pluggable response formatting strategies
|
|
||||||
*
|
|
||||||
* Usage:
|
|
||||||
* ```php
|
|
||||||
* #[AsFlasherPresenter('html')]
|
|
||||||
* class HtmlPresenter implements PresenterInterface
|
|
||||||
* {
|
|
||||||
* // ...
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
*/
|
||||||
#[\Attribute(\Attribute::TARGET_CLASS)]
|
#[\Attribute(\Attribute::TARGET_CLASS)]
|
||||||
final readonly class AsFlasherPresenter
|
final readonly class AsFlasherPresenter
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Creates a new AsFlasherPresenter attribute.
|
|
||||||
*
|
|
||||||
* @param string $alias The unique alias for the presenter (e.g., 'html', 'json')
|
|
||||||
*/
|
|
||||||
public function __construct(public string $alias)
|
public function __construct(public string $alias)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,32 +17,15 @@ use Symfony\Component\Finder\Finder;
|
|||||||
use Symfony\Component\HttpKernel\KernelInterface;
|
use Symfony\Component\HttpKernel\KernelInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* InstallCommand - Console command for installing PHPFlasher resources.
|
* Console 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 Pattern: Implements the command pattern for console interaction
|
|
||||||
* - Discovery Pattern: Automatically discovers and processes registered plugins
|
|
||||||
* - Template Method Pattern: Defines a structured workflow with specific steps
|
|
||||||
*/
|
*/
|
||||||
final class InstallCommand extends Command
|
final class InstallCommand extends Command
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* 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 options and help text.
|
|
||||||
*/
|
|
||||||
protected function configure(): void
|
protected function configure(): void
|
||||||
{
|
{
|
||||||
$this
|
$this
|
||||||
@@ -53,17 +36,6 @@ 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 to install PHPFlasher resources.
|
|
||||||
*
|
|
||||||
* This method processes each registered bundle that implements PluginBundleInterface,
|
|
||||||
* installing its assets and configuration files as requested.
|
|
||||||
*
|
|
||||||
* @param InputInterface $input The input interface
|
|
||||||
* @param OutputInterface $output The output interface
|
|
||||||
*
|
|
||||||
* @return int Command status code (SUCCESS or FAILURE)
|
|
||||||
*/
|
|
||||||
protected function execute(InputInterface $input, OutputInterface $output): int
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
{
|
{
|
||||||
// Display PHPFlasher banner and info message
|
// Display PHPFlasher banner and info message
|
||||||
@@ -166,16 +138,7 @@ final class InstallCommand extends Command
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Publishes assets from the plugin's assets directory to the public directory.
|
* @return string[]
|
||||||
*
|
|
||||||
* This method copies or symlinks asset files from the plugin's assets directory
|
|
||||||
* to the public directory for web access.
|
|
||||||
*
|
|
||||||
* @param PluginInterface $plugin The plugin containing assets
|
|
||||||
* @param string $publicDir Target directory for assets
|
|
||||||
* @param bool $useSymlinks Whether to symlink files instead of copying
|
|
||||||
*
|
|
||||||
* @return string[] List of target paths for generated manifest
|
|
||||||
*/
|
*/
|
||||||
private function publishAssets(PluginInterface $plugin, string $publicDir, bool $useSymlinks): array
|
private function publishAssets(PluginInterface $plugin, string $publicDir, bool $useSymlinks): array
|
||||||
{
|
{
|
||||||
@@ -207,16 +170,6 @@ final class InstallCommand extends Command
|
|||||||
return $files;
|
return $files;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Publishes configuration files to the application's config directory.
|
|
||||||
*
|
|
||||||
* This method copies plugin configuration files to the Symfony config directory,
|
|
||||||
* but only if the target file doesn't already exist (to avoid overwriting user customizations).
|
|
||||||
*
|
|
||||||
* @param PluginInterface $plugin The plugin containing configuration
|
|
||||||
* @param string|null $configDir Target config directory
|
|
||||||
* @param string $configFile Source configuration file path
|
|
||||||
*/
|
|
||||||
private function publishConfig(PluginInterface $plugin, ?string $configDir, string $configFile): void
|
private function publishConfig(PluginInterface $plugin, ?string $configDir, string $configFile): void
|
||||||
{
|
{
|
||||||
if (null === $configDir || !file_exists($configFile)) {
|
if (null === $configDir || !file_exists($configFile)) {
|
||||||
@@ -232,15 +185,6 @@ final class InstallCommand extends Command
|
|||||||
$filesystem->copy($configFile, $target);
|
$filesystem->copy($configFile, $target);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the path to the public directory.
|
|
||||||
*
|
|
||||||
* This method tries to locate the public directory using multiple strategies:
|
|
||||||
* 1. First, it looks for a standard 'public' directory in the project
|
|
||||||
* 2. If not found, it falls back to the composer.json configuration
|
|
||||||
*
|
|
||||||
* @return string|null Path to the public directory or null if not found
|
|
||||||
*/
|
|
||||||
private function getPublicDir(): ?string
|
private function getPublicDir(): ?string
|
||||||
{
|
{
|
||||||
$projectDir = $this->getProjectDir();
|
$projectDir = $this->getProjectDir();
|
||||||
@@ -257,15 +201,6 @@ final class InstallCommand extends Command
|
|||||||
return $this->getComposerDir('public-dir');
|
return $this->getComposerDir('public-dir');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the path to the config directory.
|
|
||||||
*
|
|
||||||
* This method tries to locate the config/packages directory using multiple strategies:
|
|
||||||
* 1. First, it looks for a standard 'config/packages' directory in the project
|
|
||||||
* 2. If not found, it falls back to the composer.json configuration
|
|
||||||
*
|
|
||||||
* @return string|null Path to the config directory or null if not found
|
|
||||||
*/
|
|
||||||
private function getConfigDir(): ?string
|
private function getConfigDir(): ?string
|
||||||
{
|
{
|
||||||
$projectDir = $this->getProjectDir();
|
$projectDir = $this->getProjectDir();
|
||||||
@@ -283,11 +218,6 @@ final class InstallCommand extends Command
|
|||||||
return $this->getComposerDir('config-dir');
|
return $this->getComposerDir('config-dir');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the project root directory from the kernel.
|
|
||||||
*
|
|
||||||
* @return string|null The project directory path or null if not available
|
|
||||||
*/
|
|
||||||
private function getProjectDir(): ?string
|
private function getProjectDir(): ?string
|
||||||
{
|
{
|
||||||
$kernel = $this->getKernel();
|
$kernel = $this->getKernel();
|
||||||
@@ -303,13 +233,6 @@ final class InstallCommand extends Command
|
|||||||
return \is_string($projectDir) ? $projectDir : null;
|
return \is_string($projectDir) ? $projectDir : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets a directory path from composer.json extra configuration.
|
|
||||||
*
|
|
||||||
* @param string $dir The directory key to look for in composer.json extra section
|
|
||||||
*
|
|
||||||
* @return string|null The directory path or null if not found
|
|
||||||
*/
|
|
||||||
private function getComposerDir(string $dir): ?string
|
private function getComposerDir(string $dir): ?string
|
||||||
{
|
{
|
||||||
$projectDir = $this->getProjectDir();
|
$projectDir = $this->getProjectDir();
|
||||||
@@ -330,11 +253,6 @@ final class InstallCommand extends Command
|
|||||||
return $composerConfig['extra'][$dir] ?? null;
|
return $composerConfig['extra'][$dir] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the kernel instance from the application.
|
|
||||||
*
|
|
||||||
* @return KernelInterface|null The Symfony kernel or null if not available
|
|
||||||
*/
|
|
||||||
private function getKernel(): ?KernelInterface
|
private function getKernel(): ?KernelInterface
|
||||||
{
|
{
|
||||||
$application = $this->getApplication();
|
$application = $this->getApplication();
|
||||||
|
|||||||
@@ -5,42 +5,15 @@ declare(strict_types=1);
|
|||||||
namespace Flasher\Symfony\Component;
|
namespace Flasher\Symfony\Component;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FlasherComponent - Twig component for rendering notifications.
|
* Twig component for rendering PHPFlasher notifications.
|
||||||
*
|
|
||||||
* This class implements a Twig component that can be used in templates to render
|
|
||||||
* PHPFlasher notifications. It supports customizing the filtering criteria,
|
|
||||||
* presenter format, and rendering context.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Component-based Architecture: Implements Twig's component pattern
|
|
||||||
* - Data Transfer Object: Holds configuration for notification rendering
|
|
||||||
*
|
|
||||||
* Usage in templates:
|
|
||||||
* ```twig
|
|
||||||
* <twig:flasher
|
|
||||||
* criteria="{{ {limit: 5} }}"
|
|
||||||
* presenter="html"
|
|
||||||
* context="{{ {foo: 'bar'} }}" />
|
|
||||||
* ```
|
|
||||||
*/
|
*/
|
||||||
final class FlasherComponent
|
final class FlasherComponent
|
||||||
{
|
{
|
||||||
/**
|
/** @var array<string, mixed> */
|
||||||
* Filtering criteria for notifications.
|
|
||||||
*
|
|
||||||
* @var array<string, mixed>
|
|
||||||
*/
|
|
||||||
public array $criteria = [];
|
public array $criteria = [];
|
||||||
|
|
||||||
/**
|
|
||||||
* Presentation format (e.g., 'html', 'json').
|
|
||||||
*/
|
|
||||||
public string $presenter = 'html';
|
public string $presenter = 'html';
|
||||||
|
|
||||||
/**
|
/** @var array<string, mixed> */
|
||||||
* Additional context for rendering.
|
|
||||||
*
|
|
||||||
* @var array<string, mixed>
|
|
||||||
*/
|
|
||||||
public array $context = [];
|
public array $context = [];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,24 +9,10 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
|
|||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* EventListenerCompilerPass - Registers event listeners with the event dispatcher.
|
* Registers event listeners with the event dispatcher.
|
||||||
*
|
|
||||||
* This compiler pass finds all services tagged with 'flasher.event_listener'
|
|
||||||
* and registers them with the PHPFlasher event dispatcher. This allows for
|
|
||||||
* automatic discovery and registration of event listeners.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Compiler Pass: Modifies container definitions during compilation
|
|
||||||
* - Service Discovery: Automatically discovers tagged services
|
|
||||||
* - Observer Pattern: Helps set up the event dispatch/observer system
|
|
||||||
*/
|
*/
|
||||||
final class EventListenerCompilerPass implements CompilerPassInterface
|
final class EventListenerCompilerPass implements CompilerPassInterface
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Process the container to register event listeners.
|
|
||||||
*
|
|
||||||
* @param ContainerBuilder $container The service container builder
|
|
||||||
*/
|
|
||||||
public function process(ContainerBuilder $container): void
|
public function process(ContainerBuilder $container): void
|
||||||
{
|
{
|
||||||
$definition = $container->findDefinition('flasher.event_dispatcher');
|
$definition = $container->findDefinition('flasher.event_dispatcher');
|
||||||
|
|||||||
@@ -10,24 +10,10 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
|
|||||||
use Symfony\Component\DependencyInjection\Reference;
|
use Symfony\Component\DependencyInjection\Reference;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PresenterCompilerPass - Registers response presenters with the response manager.
|
* Registers response presenters with the response manager.
|
||||||
*
|
|
||||||
* This compiler pass finds all services tagged with 'flasher.presenter'
|
|
||||||
* and registers them with the PHPFlasher response manager. This allows for
|
|
||||||
* automatic discovery and registration of response presenters.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Compiler Pass: Modifies container definitions during compilation
|
|
||||||
* - Service Discovery: Automatically discovers tagged services
|
|
||||||
* - Strategy Pattern: Helps set up pluggable response presentation strategies
|
|
||||||
*/
|
*/
|
||||||
final class PresenterCompilerPass implements CompilerPassInterface
|
final class PresenterCompilerPass implements CompilerPassInterface
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Process the container to register presenters.
|
|
||||||
*
|
|
||||||
* @param ContainerBuilder $container The service container builder
|
|
||||||
*/
|
|
||||||
public function process(ContainerBuilder $container): void
|
public function process(ContainerBuilder $container): void
|
||||||
{
|
{
|
||||||
$definition = $container->findDefinition('flasher.response_manager');
|
$definition = $container->findDefinition('flasher.response_manager');
|
||||||
|
|||||||
@@ -11,36 +11,14 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
|||||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FlasherListener - Injects PHPFlasher assets into responses.
|
* Injects PHPFlasher assets into responses.
|
||||||
*
|
|
||||||
* This event subscriber listens for kernel.response events and injects
|
|
||||||
* PHPFlasher JavaScript and CSS assets into appropriate HTTP responses.
|
|
||||||
* It adapts Symfony's request and response objects to PHPFlasher's interfaces.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Observer Pattern: Observes Symfony's kernel events
|
|
||||||
* - Adapter Pattern: Adapts Symfony's request/response to PHPFlasher's interfaces
|
|
||||||
* - Event Subscriber: Subscribes to Symfony's event dispatcher system
|
|
||||||
*/
|
*/
|
||||||
final readonly class FlasherListener implements EventSubscriberInterface
|
final readonly class FlasherListener implements EventSubscriberInterface
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Creates a new FlasherListener instance.
|
|
||||||
*
|
|
||||||
* @param ResponseExtensionInterface $responseExtension Service for extending responses with notifications
|
|
||||||
*/
|
|
||||||
public function __construct(private ResponseExtensionInterface $responseExtension)
|
public function __construct(private ResponseExtensionInterface $responseExtension)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes the response to inject PHPFlasher assets.
|
|
||||||
*
|
|
||||||
* This handler adapts Symfony's request and response objects to PHPFlasher's
|
|
||||||
* interfaces, then delegates to the response extension for asset injection.
|
|
||||||
*
|
|
||||||
* @param ResponseEvent $event The response event
|
|
||||||
*/
|
|
||||||
public function onKernelResponse(ResponseEvent $event): void
|
public function onKernelResponse(ResponseEvent $event): void
|
||||||
{
|
{
|
||||||
$request = new Request($event->getRequest());
|
$request = new Request($event->getRequest());
|
||||||
@@ -49,14 +27,6 @@ final readonly class FlasherListener implements EventSubscriberInterface
|
|||||||
$this->responseExtension->render($request, $response);
|
$this->responseExtension->render($request, $response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*
|
|
||||||
* Returns events this subscriber listens to and their corresponding handlers.
|
|
||||||
* The low priority (-20) ensures this runs after most other response listeners.
|
|
||||||
*
|
|
||||||
* @return array<string, array<int, int|string>> The events and handlers
|
|
||||||
*/
|
|
||||||
public static function getSubscribedEvents(): array
|
public static function getSubscribedEvents(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -11,36 +11,14 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
|||||||
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
use Symfony\Component\HttpKernel\Event\ResponseEvent;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SessionListener - Processes session flash messages.
|
* Processes session flash messages.
|
||||||
*
|
|
||||||
* This event subscriber listens for kernel.response events and converts
|
|
||||||
* Symfony's session flash messages to PHPFlasher notifications. This enables
|
|
||||||
* PHPFlasher to work with existing code that uses Symfony's flash messaging.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Observer Pattern: Observes Symfony's kernel events
|
|
||||||
* - Adapter Pattern: Adapts Symfony's flash messages to PHPFlasher notifications
|
|
||||||
* - Transformer Pattern: Transforms data from one format to another
|
|
||||||
*/
|
*/
|
||||||
final readonly class SessionListener implements EventSubscriberInterface
|
final readonly class SessionListener implements EventSubscriberInterface
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Creates a new SessionListener instance.
|
|
||||||
*
|
|
||||||
* @param RequestExtensionInterface $requestExtension Service for processing request flash messages
|
|
||||||
*/
|
|
||||||
public function __construct(private RequestExtensionInterface $requestExtension)
|
public function __construct(private RequestExtensionInterface $requestExtension)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Processes the request to convert flash messages to notifications.
|
|
||||||
*
|
|
||||||
* This handler adapts Symfony's request and response objects to PHPFlasher's
|
|
||||||
* interfaces, then delegates to the request extension for flash processing.
|
|
||||||
*
|
|
||||||
* @param ResponseEvent $event The response event
|
|
||||||
*/
|
|
||||||
public function onKernelResponse(ResponseEvent $event): void
|
public function onKernelResponse(ResponseEvent $event): void
|
||||||
{
|
{
|
||||||
$request = new Request($event->getRequest());
|
$request = new Request($event->getRequest());
|
||||||
@@ -49,13 +27,6 @@ final readonly class SessionListener implements EventSubscriberInterface
|
|||||||
$this->requestExtension->flash($request, $response);
|
$this->requestExtension->flash($request, $response);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*
|
|
||||||
* Returns events this subscriber listens to and their corresponding handlers.
|
|
||||||
*
|
|
||||||
* @return array<string, array<int, int|string>> The events and handlers
|
|
||||||
*/
|
|
||||||
public static function getSubscribedEvents(): array
|
public static function getSubscribedEvents(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
|
|||||||
@@ -8,51 +8,20 @@ use Flasher\Prime\Factory\NotificationFactoryInterface;
|
|||||||
use Flasher\Prime\Factory\NotificationFactoryLocatorInterface;
|
use Flasher\Prime\Factory\NotificationFactoryLocatorInterface;
|
||||||
use Symfony\Component\DependencyInjection\ServiceLocator;
|
use Symfony\Component\DependencyInjection\ServiceLocator;
|
||||||
|
|
||||||
/**
|
|
||||||
* NotificationFactoryLocator - Locator for notification factories using Symfony's ServiceLocator.
|
|
||||||
*
|
|
||||||
* This class adapts Symfony's ServiceLocator to PHPFlasher's NotificationFactoryLocatorInterface,
|
|
||||||
* enabling runtime discovery and lazy-loading of notification factories.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Adapter Pattern: Adapts Symfony's ServiceLocator to PHPFlasher's interface
|
|
||||||
* - Service Locator Pattern: Provides unified access to notification factory services
|
|
||||||
* - Lazy Loading: Services are only instantiated when requested
|
|
||||||
*/
|
|
||||||
final readonly class NotificationFactoryLocator implements NotificationFactoryLocatorInterface
|
final readonly class NotificationFactoryLocator implements NotificationFactoryLocatorInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Creates a new NotificationFactoryLocator instance.
|
* @param ServiceLocator<NotificationFactoryInterface> $serviceLocator
|
||||||
*
|
|
||||||
* @param ServiceLocator<NotificationFactoryInterface> $serviceLocator Symfony's service locator
|
|
||||||
*/
|
*/
|
||||||
public function __construct(private ServiceLocator $serviceLocator)
|
public function __construct(private ServiceLocator $serviceLocator)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*
|
|
||||||
* Checks if a notification factory with the given ID exists.
|
|
||||||
*
|
|
||||||
* @param string $id The factory identifier
|
|
||||||
*
|
|
||||||
* @return bool True if the factory exists, false otherwise
|
|
||||||
*/
|
|
||||||
public function has(string $id): bool
|
public function has(string $id): bool
|
||||||
{
|
{
|
||||||
return $this->serviceLocator->has($id);
|
return $this->serviceLocator->has($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*
|
|
||||||
* Gets a notification factory by ID.
|
|
||||||
*
|
|
||||||
* @param string $id The factory identifier
|
|
||||||
*
|
|
||||||
* @return NotificationFactoryInterface The notification factory
|
|
||||||
*/
|
|
||||||
public function get(string $id): NotificationFactoryInterface
|
public function get(string $id): NotificationFactoryInterface
|
||||||
{
|
{
|
||||||
return $this->serviceLocator->get($id);
|
return $this->serviceLocator->get($id);
|
||||||
|
|||||||
@@ -14,24 +14,10 @@ use Symfony\Component\DependencyInjection\ContainerBuilder;
|
|||||||
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
|
use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FlasherSymfonyBundle - Main bundle for PHPFlasher Symfony integration.
|
* Main bundle for PHPFlasher Symfony integration.
|
||||||
*
|
|
||||||
* This bundle serves as the entry point for integrating PHPFlasher with Symfony.
|
|
||||||
* It registers compiler passes, configures the container extension, and sets up
|
|
||||||
* the global container instance for PHPFlasher.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Bundle: Implements Symfony's bundle pattern for packaging functionality
|
|
||||||
* - Registry: Sets up the container registry for PHPFlasher
|
|
||||||
* - Extension: Extends the base plugin bundle with PHPFlasher-specific functionality
|
|
||||||
*/
|
*/
|
||||||
final class FlasherSymfonyBundle extends Support\PluginBundle // Symfony\Component\HttpKernel\Bundle\Bundle
|
final class FlasherSymfonyBundle extends Support\PluginBundle // Symfony\Component\HttpKernel\Bundle\Bundle
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Set up the global container reference when the bundle boots.
|
|
||||||
*
|
|
||||||
* This allows PHPFlasher to access services from Symfony's container.
|
|
||||||
*/
|
|
||||||
public function boot(): void
|
public function boot(): void
|
||||||
{
|
{
|
||||||
if ($this->container instanceof ContainerInterface) {
|
if ($this->container instanceof ContainerInterface) {
|
||||||
@@ -39,32 +25,17 @@ final class FlasherSymfonyBundle extends Support\PluginBundle // Symfony\Compone
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Register compiler passes with the container.
|
|
||||||
*
|
|
||||||
* @param ContainerBuilder $container The container builder
|
|
||||||
*/
|
|
||||||
public function build(ContainerBuilder $container): void
|
public function build(ContainerBuilder $container): void
|
||||||
{
|
{
|
||||||
$container->addCompilerPass(new EventListenerCompilerPass());
|
$container->addCompilerPass(new EventListenerCompilerPass());
|
||||||
$container->addCompilerPass(new PresenterCompilerPass());
|
$container->addCompilerPass(new PresenterCompilerPass());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the container extension for this bundle.
|
|
||||||
*
|
|
||||||
* @return ExtensionInterface The bundle extension
|
|
||||||
*/
|
|
||||||
public function getContainerExtension(): ExtensionInterface
|
public function getContainerExtension(): ExtensionInterface
|
||||||
{
|
{
|
||||||
return new FlasherExtension($this->createPlugin());
|
return new FlasherExtension($this->createPlugin());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the core PHPFlasher plugin.
|
|
||||||
*
|
|
||||||
* @return FlasherPlugin The core PHPFlasher plugin
|
|
||||||
*/
|
|
||||||
public function createPlugin(): FlasherPlugin
|
public function createPlugin(): FlasherPlugin
|
||||||
{
|
{
|
||||||
return new FlasherPlugin();
|
return new FlasherPlugin();
|
||||||
|
|||||||
@@ -11,24 +11,10 @@ use Symfony\Component\HttpFoundation\Session\FlashBagAwareSessionInterface;
|
|||||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request - Adapter for Symfony's HTTP request.
|
* Adapter for Symfony's HTTP request.
|
||||||
*
|
|
||||||
* This class implements PHPFlasher's RequestInterface for Symfony's HTTP request,
|
|
||||||
* providing a consistent interface for request inspection and session interaction
|
|
||||||
* regardless of the underlying framework.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Adapter Pattern: Adapts framework-specific request to PHPFlasher's interface
|
|
||||||
* - Decorator Pattern: Adds PHPFlasher-specific functionality to request objects
|
|
||||||
* - Null Object Pattern: Gracefully handles missing sessions
|
|
||||||
*/
|
*/
|
||||||
final readonly class Request implements RequestInterface
|
final readonly class Request implements RequestInterface
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Creates a new Request adapter.
|
|
||||||
*
|
|
||||||
* @param SymfonyRequest $request The underlying Symfony request object
|
|
||||||
*/
|
|
||||||
public function __construct(private SymfonyRequest $request)
|
public function __construct(private SymfonyRequest $request)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -92,11 +78,6 @@ final readonly class Request implements RequestInterface
|
|||||||
$this->getType($type);
|
$this->getType($type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the session from the request, with graceful handling of missing sessions.
|
|
||||||
*
|
|
||||||
* @return SessionInterface|null The session or null if not available
|
|
||||||
*/
|
|
||||||
private function getSession(): ?SessionInterface
|
private function getSession(): ?SessionInterface
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -9,24 +9,10 @@ use Symfony\Component\HttpFoundation\JsonResponse;
|
|||||||
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
|
use Symfony\Component\HttpFoundation\Response as SymfonyResponse;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Response - Adapter for Symfony's HTTP response.
|
* Adapter for Symfony's HTTP response.
|
||||||
*
|
|
||||||
* This class implements PHPFlasher's ResponseInterface for Symfony's HTTP response,
|
|
||||||
* providing a consistent interface for response manipulation regardless of the framework.
|
|
||||||
* It allows PHPFlasher to work with Symfony responses in a framework-agnostic way.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Adapter Pattern: Adapts framework-specific response to PHPFlasher's interface
|
|
||||||
* - Decorator Pattern: 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 response object
|
|
||||||
*/
|
|
||||||
public function __construct(private SymfonyResponse $response)
|
public function __construct(private SymfonyResponse $response)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,16 +15,7 @@ use Symfony\Component\HttpKernel\Kernel;
|
|||||||
use Symfony\Component\VarDumper\Cloner\Data;
|
use Symfony\Component\VarDumper\Cloner\Data;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FlasherDataCollector - Collects PHPFlasher data for the Symfony profiler.
|
* Collects PHPFlasher data for the Symfony profiler.
|
||||||
*
|
|
||||||
* This data collector captures information about PHPFlasher notifications,
|
|
||||||
* both dispatched and displayed, for the Symfony web profiler. It also collects
|
|
||||||
* configuration and version information.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Data Collector: Implements Symfony's data collector pattern for profiling
|
|
||||||
* - Late Collection: Collects data after a request is completed
|
|
||||||
* - Type Safety: Uses PHPDoc annotations for complex type declarations
|
|
||||||
*
|
*
|
||||||
* @phpstan-type NotificationShape array{
|
* @phpstan-type NotificationShape array{
|
||||||
* title: string,
|
* title: string,
|
||||||
@@ -62,11 +53,6 @@ use Symfony\Component\VarDumper\Cloner\Data;
|
|||||||
final class FlasherDataCollector extends AbstractDataCollector implements LateDataCollectorInterface
|
final class FlasherDataCollector extends AbstractDataCollector implements LateDataCollectorInterface
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Creates a new FlasherDataCollector instance.
|
|
||||||
*
|
|
||||||
* @param NotificationLoggerListener $logger The notification logger for accessing dispatched notifications
|
|
||||||
* @param array<string, mixed> $config The PHPFlasher configuration
|
|
||||||
*
|
|
||||||
* @phpstan-param ConfigShare $config
|
* @phpstan-param ConfigShare $config
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
@@ -75,25 +61,11 @@ final class FlasherDataCollector extends AbstractDataCollector implements LateDa
|
|||||||
) {
|
) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initial data collection - called during request processing.
|
|
||||||
*
|
|
||||||
* This implementation doesn't collect data here, deferring to lateCollect.
|
|
||||||
*
|
|
||||||
* @param Request $request The request object
|
|
||||||
* @param Response $response The response object
|
|
||||||
* @param \Throwable|null $exception Any exception that occurred
|
|
||||||
*/
|
|
||||||
public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
|
public function collect(Request $request, Response $response, ?\Throwable $exception = null): void
|
||||||
{
|
{
|
||||||
// No action needed here since we're collecting data in lateCollect
|
// No action needed here since we're collecting data in lateCollect
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Late data collection - called after response is sent.
|
|
||||||
*
|
|
||||||
* Collects information about notifications, configuration, and versions.
|
|
||||||
*/
|
|
||||||
public function lateCollect(): void
|
public function lateCollect(): void
|
||||||
{
|
{
|
||||||
$this->data = [
|
$this->data = [
|
||||||
@@ -111,28 +83,18 @@ final class FlasherDataCollector extends AbstractDataCollector implements LateDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the collector data.
|
* @return array<string, mixed>|Data
|
||||||
*
|
|
||||||
* @return DataShape|Data<DataShape>
|
|
||||||
*/
|
*/
|
||||||
public function getData(): array|Data
|
public function getData(): array|Data
|
||||||
{
|
{
|
||||||
return $this->data;
|
return $this->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the collector name for the profiler panel.
|
|
||||||
*
|
|
||||||
* @return string The collector name
|
|
||||||
*/
|
|
||||||
public function getName(): string
|
public function getName(): string
|
||||||
{
|
{
|
||||||
return 'flasher';
|
return 'flasher';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Resets the collector between requests when using kernel.reset.
|
|
||||||
*/
|
|
||||||
public function reset(): void
|
public function reset(): void
|
||||||
{
|
{
|
||||||
$this->logger->reset();
|
$this->logger->reset();
|
||||||
@@ -140,9 +102,7 @@ final class FlasherDataCollector extends AbstractDataCollector implements LateDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the displayed notification envelopes.
|
* @return array<NotificationShape>|Data
|
||||||
*
|
|
||||||
* @return NotificationShape[]|Data<NotificationShape>
|
|
||||||
*/
|
*/
|
||||||
public function getDisplayedEnvelopes(): array|Data
|
public function getDisplayedEnvelopes(): array|Data
|
||||||
{
|
{
|
||||||
@@ -150,9 +110,7 @@ final class FlasherDataCollector extends AbstractDataCollector implements LateDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the dispatched notification envelopes.
|
* @return array<NotificationShape>|Data
|
||||||
*
|
|
||||||
* @return NotificationShape[]|Data<NotificationShape>
|
|
||||||
*/
|
*/
|
||||||
public function getDispatchedEnvelopes(): array|Data
|
public function getDispatchedEnvelopes(): array|Data
|
||||||
{
|
{
|
||||||
@@ -160,8 +118,6 @@ final class FlasherDataCollector extends AbstractDataCollector implements LateDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the PHPFlasher configuration.
|
|
||||||
*
|
|
||||||
* @phpstan-return ConfigShare|Data
|
* @phpstan-return ConfigShare|Data
|
||||||
*/
|
*/
|
||||||
public function getConfig(): array|Data
|
public function getConfig(): array|Data
|
||||||
@@ -170,20 +126,13 @@ final class FlasherDataCollector extends AbstractDataCollector implements LateDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets version information.
|
* @return array<string, string>|Data
|
||||||
*
|
|
||||||
* @return array{php_flasher: string, php: string, symfony: string}|Data
|
|
||||||
*/
|
*/
|
||||||
public function getVersions(): array|Data
|
public function getVersions(): array|Data
|
||||||
{
|
{
|
||||||
return $this->data['versions'] ?? [];
|
return $this->data['versions'] ?? [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the template path for the profiler panel.
|
|
||||||
*
|
|
||||||
* @return string The template path
|
|
||||||
*/
|
|
||||||
public static function getTemplate(): string
|
public static function getTemplate(): string
|
||||||
{
|
{
|
||||||
return '@FlasherSymfony/profiler/flasher.html.twig';
|
return '@FlasherSymfony/profiler/flasher.html.twig';
|
||||||
|
|||||||
@@ -5,24 +5,11 @@ declare(strict_types=1);
|
|||||||
namespace Flasher\Symfony\Storage;
|
namespace Flasher\Symfony\Storage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FallbackSession - In-memory session storage fallback.
|
* In-memory session storage fallback.
|
||||||
*
|
|
||||||
* This class provides a simple in-memory storage mechanism that can be used
|
|
||||||
* when the regular Symfony session is not available. It stores values in a
|
|
||||||
* static array, making them available for the duration of the request.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Null Object Pattern: Provides a non-failing alternative to a missing session
|
|
||||||
* - In-Memory Repository: Stores data in memory as a simple alternative to persistence
|
|
||||||
* - Singleton-like Pattern: Uses a static storage array shared across instances
|
|
||||||
*/
|
*/
|
||||||
final class FallbackSession implements FallbackSessionInterface
|
final class FallbackSession implements FallbackSessionInterface
|
||||||
{
|
{
|
||||||
/**
|
/** @var array<string, mixed> */
|
||||||
* In-memory storage for session data.
|
|
||||||
*
|
|
||||||
* @var array<string, mixed>
|
|
||||||
*/
|
|
||||||
private static array $storage = [];
|
private static array $storage = [];
|
||||||
|
|
||||||
public function get(string $name, mixed $default = null): mixed
|
public function get(string $name, mixed $default = null): mixed
|
||||||
|
|||||||
@@ -5,34 +5,11 @@ declare(strict_types=1);
|
|||||||
namespace Flasher\Symfony\Storage;
|
namespace Flasher\Symfony\Storage;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FallbackSessionInterface - Contract for alternative session storage.
|
* Contract for alternative session storage.
|
||||||
*
|
|
||||||
* This interface defines methods for a fallback storage mechanism when the
|
|
||||||
* regular Symfony session is not available. This is particularly useful in
|
|
||||||
* stateless contexts or when the session hasn't been started.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Interface Segregation: Defines a minimal interface for session-like storage
|
|
||||||
* - Strategy Pattern: Allows different storage implementations to be used
|
|
||||||
* - Fallback Strategy: Provides an alternative when primary storage is unavailable
|
|
||||||
*/
|
*/
|
||||||
interface FallbackSessionInterface
|
interface FallbackSessionInterface
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Retrieves a value from the fallback session storage.
|
|
||||||
*
|
|
||||||
* @param string $name the name of the value
|
|
||||||
* @param mixed $default the default value to return if the name is not found
|
|
||||||
*
|
|
||||||
* @return mixed the value from storage or default
|
|
||||||
*/
|
|
||||||
public function get(string $name, mixed $default = null): mixed;
|
public function get(string $name, mixed $default = null): mixed;
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores a value in the fallback session storage.
|
|
||||||
*
|
|
||||||
* @param string $name the name of the value to store
|
|
||||||
* @param mixed $value the value to store
|
|
||||||
*/
|
|
||||||
public function set(string $name, mixed $value): void;
|
public function set(string $name, mixed $value): void;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,48 +11,19 @@ use Symfony\Component\HttpFoundation\RequestStack;
|
|||||||
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
use Symfony\Component\HttpFoundation\Session\SessionInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SessionBag - Symfony session storage for PHPFlasher notifications.
|
* Symfony session storage for PHPFlasher notifications.
|
||||||
*
|
|
||||||
* This class implements PHPFlasher's storage interface using Symfony's session
|
|
||||||
* system, providing persistence for notifications across requests. It includes
|
|
||||||
* fallback behavior for stateless contexts.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Adapter Pattern: Adapts Symfony's session to PHPFlasher's storage interface
|
|
||||||
* - Strategy Pattern: Uses different storage strategies based on context
|
|
||||||
* - Fallback Strategy: Falls back to in-memory storage when session unavailable
|
|
||||||
* - Repository Pattern: 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';
|
||||||
|
|
||||||
/**
|
|
||||||
* Fallback storage for contexts where session is unavailable.
|
|
||||||
*/
|
|
||||||
private FallbackSessionInterface $fallbackSession;
|
private FallbackSessionInterface $fallbackSession;
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new SessionBag instance.
|
|
||||||
*
|
|
||||||
* @param RequestStack $requestStack Symfony's request stack for accessing session
|
|
||||||
* @param FallbackSessionInterface|null $fallbackSession Optional custom fallback storage
|
|
||||||
*/
|
|
||||||
public function __construct(private RequestStack $requestStack, ?FallbackSessionInterface $fallbackSession = null)
|
public function __construct(private RequestStack $requestStack, ?FallbackSessionInterface $fallbackSession = null)
|
||||||
{
|
{
|
||||||
$this->fallbackSession = $fallbackSession ?: new FallbackSession();
|
$this->fallbackSession = $fallbackSession ?: new FallbackSession();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*
|
|
||||||
* Gets all notification envelopes from storage.
|
|
||||||
*
|
|
||||||
* @return Envelope[] The stored notification envelopes
|
|
||||||
*/
|
|
||||||
public function get(): array
|
public function get(): array
|
||||||
{
|
{
|
||||||
$session = $this->getSession();
|
$session = $this->getSession();
|
||||||
@@ -63,13 +34,6 @@ final readonly class SessionBag implements BagInterface
|
|||||||
return $envelopes;
|
return $envelopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*
|
|
||||||
* Stores notification envelopes in storage.
|
|
||||||
*
|
|
||||||
* @param array<Envelope> $envelopes The notification envelopes to store
|
|
||||||
*/
|
|
||||||
public function set(array $envelopes): void
|
public function set(array $envelopes): void
|
||||||
{
|
{
|
||||||
$session = $this->getSession();
|
$session = $this->getSession();
|
||||||
@@ -77,14 +41,6 @@ final readonly class SessionBag implements BagInterface
|
|||||||
$session->set(self::ENVELOPES_NAMESPACE, $envelopes);
|
$session->set(self::ENVELOPES_NAMESPACE, $envelopes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the appropriate session storage implementation.
|
|
||||||
*
|
|
||||||
* Uses Symfony session if available and request is not stateless,
|
|
||||||
* otherwise falls back to the fallback session implementation.
|
|
||||||
*
|
|
||||||
* @return SessionInterface|FallbackSessionInterface The storage implementation
|
|
||||||
*/
|
|
||||||
private function getSession(): SessionInterface|FallbackSessionInterface
|
private function getSession(): SessionInterface|FallbackSessionInterface
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -11,40 +11,14 @@ use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigura
|
|||||||
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
|
use Symfony\Component\HttpKernel\Bundle\AbstractBundle;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PluginBundle - Base class for PHPFlasher plugin bundles.
|
* Base class for PHPFlasher plugin bundles.
|
||||||
*
|
|
||||||
* This abstract class provides common functionality for all PHPFlasher plugin bundles.
|
|
||||||
* It extends Symfony's AbstractBundle to integrate with the kernel bundle system,
|
|
||||||
* while implementing PluginBundleInterface to provide PHPFlasher-specific functionality.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Template Method: Defines skeleton of common bundle operations
|
|
||||||
* - Factory Method: Creates plugin instances
|
|
||||||
* - Bridge: Connects Symfony bundle system with PHPFlasher plugin system
|
|
||||||
* - Extension: Extends AbstractBundle with PHPFlasher-specific functionality
|
|
||||||
*/
|
*/
|
||||||
abstract class PluginBundle extends AbstractBundle implements PluginBundleInterface
|
abstract class PluginBundle extends AbstractBundle implements PluginBundleInterface
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Creates an instance of the plugin.
|
|
||||||
*
|
|
||||||
* This factory method must be implemented by child classes to instantiate
|
|
||||||
* the specific plugin that the bundle integrates.
|
|
||||||
*
|
|
||||||
* @return PluginInterface The plugin instance
|
|
||||||
*/
|
|
||||||
abstract public function createPlugin(): PluginInterface;
|
abstract public function createPlugin(): PluginInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads bundle configuration into the Symfony container.
|
* @param array<string, mixed> $config
|
||||||
*
|
|
||||||
* This method registers the plugin's factory service in the container and
|
|
||||||
* configures it appropriately. The core FlasherSymfonyBundle is exempt from
|
|
||||||
* this process since it has special handling.
|
|
||||||
*
|
|
||||||
* @param array<string, mixed> $config The processed bundle configuration
|
|
||||||
* @param ContainerConfigurator $container The container configurator
|
|
||||||
* @param ContainerBuilder $builder The container builder
|
|
||||||
*/
|
*/
|
||||||
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
|
public function loadExtension(array $config, ContainerConfigurator $container, ContainerBuilder $builder): void
|
||||||
{
|
{
|
||||||
@@ -67,15 +41,6 @@ abstract class PluginBundle extends AbstractBundle implements PluginBundleInterf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Prepends default plugin configuration for Flasher.
|
|
||||||
*
|
|
||||||
* This method adds the plugin's scripts, styles, and options to the Flasher
|
|
||||||
* configuration before the container is compiled.
|
|
||||||
*
|
|
||||||
* @param ContainerConfigurator $container The container configurator
|
|
||||||
* @param ContainerBuilder $builder The container builder
|
|
||||||
*/
|
|
||||||
public function prependExtension(ContainerConfigurator $container, ContainerBuilder $builder): void
|
public function prependExtension(ContainerConfigurator $container, ContainerBuilder $builder): void
|
||||||
{
|
{
|
||||||
if ($this instanceof FlasherSymfonyBundle) {
|
if ($this instanceof FlasherSymfonyBundle) {
|
||||||
@@ -95,27 +60,11 @@ abstract class PluginBundle extends AbstractBundle implements PluginBundleInterf
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the path to the plugin's configuration file.
|
|
||||||
*
|
|
||||||
* Returns the absolute path to the plugin's configuration file
|
|
||||||
* based on the bundle's path.
|
|
||||||
*
|
|
||||||
* @return string Absolute path to the configuration file
|
|
||||||
*/
|
|
||||||
public function getConfigurationFile(): string
|
public function getConfigurationFile(): string
|
||||||
{
|
{
|
||||||
return rtrim($this->getPath(), '/').'/Resources/config/config.yaml';
|
return rtrim($this->getPath(), '/').'/Resources/config/config.yaml';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the bundle's directory path.
|
|
||||||
*
|
|
||||||
* Uses reflection to determine the location of the bundle class file,
|
|
||||||
* then returns its directory.
|
|
||||||
*
|
|
||||||
* @return string The bundle directory path
|
|
||||||
*/
|
|
||||||
public function getPath(): string
|
public function getPath(): string
|
||||||
{
|
{
|
||||||
if (!isset($this->path)) {
|
if (!isset($this->path)) {
|
||||||
|
|||||||
@@ -7,32 +7,11 @@ namespace Flasher\Symfony\Support;
|
|||||||
use Flasher\Prime\Plugin\PluginInterface;
|
use Flasher\Prime\Plugin\PluginInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PluginBundleInterface - Contract for PHPFlasher plugin bundles.
|
* Contract for PHPFlasher plugin bundles.
|
||||||
*
|
|
||||||
* This interface defines the basic requirements for a Symfony bundle that
|
|
||||||
* integrates a PHPFlasher plugin. It focuses on plugin creation and configuration.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Factory Method: Defines interface for creating plugin instances
|
|
||||||
* - Plugin Architecture: Supports extensible plugin system
|
|
||||||
* - Bridge: Connects Symfony bundle system with PHPFlasher plugin system
|
|
||||||
*/
|
*/
|
||||||
interface PluginBundleInterface
|
interface PluginBundleInterface
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Creates an instance of the plugin.
|
|
||||||
*
|
|
||||||
* This factory method is responsible for instantiating the plugin that
|
|
||||||
* this bundle integrates with Symfony.
|
|
||||||
*
|
|
||||||
* @return PluginInterface The plugin instance
|
|
||||||
*/
|
|
||||||
public function createPlugin(): PluginInterface;
|
public function createPlugin(): PluginInterface;
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the path to the plugin's configuration file.
|
|
||||||
*
|
|
||||||
* @return string Absolute path to the configuration file
|
|
||||||
*/
|
|
||||||
public function getConfigurationFile(): string;
|
public function getConfigurationFile(): string;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,37 +8,14 @@ use Flasher\Prime\Template\TemplateEngineInterface;
|
|||||||
use Twig\Environment;
|
use Twig\Environment;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TwigTemplateEngine - Adapter for Symfony's Twig template engine.
|
* Adapter for Symfony's Twig template engine.
|
||||||
*
|
|
||||||
* This class adapts Symfony's Twig environment to PHPFlasher's template engine
|
|
||||||
* interface, enabling notification templates to be rendered using Twig.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Adapter Pattern: Adapts Twig to PHPFlasher's template interface
|
|
||||||
* - Null Object Pattern: Gracefully handles a missing Twig dependency
|
|
||||||
* - Bridge Pattern: Bridges PHPFlasher's templating needs with Symfony's templating system
|
|
||||||
*/
|
*/
|
||||||
final readonly class TwigTemplateEngine implements TemplateEngineInterface
|
final readonly class TwigTemplateEngine implements TemplateEngineInterface
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Creates a new TwigTemplateEngine instance.
|
|
||||||
*
|
|
||||||
* @param Environment|null $twig The Twig environment or null if Twig is not available
|
|
||||||
*/
|
|
||||||
public function __construct(private ?Environment $twig = null)
|
public function __construct(private ?Environment $twig = null)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders a template using Twig.
|
|
||||||
*
|
|
||||||
* @param string $name The template name or path
|
|
||||||
* @param array<string, mixed> $context The template variables
|
|
||||||
*
|
|
||||||
* @return string The rendered template
|
|
||||||
*
|
|
||||||
* @throws \LogicException If Twig is not available
|
|
||||||
*/
|
|
||||||
public function render(string $name, array $context = []): string
|
public function render(string $name, array $context = []): string
|
||||||
{
|
{
|
||||||
if (null === $this->twig) {
|
if (null === $this->twig) {
|
||||||
|
|||||||
@@ -9,42 +9,14 @@ use Symfony\Component\Translation\TranslatorBagInterface;
|
|||||||
use Symfony\Contracts\Translation\TranslatorInterface as SymfonyTranslatorInterface;
|
use Symfony\Contracts\Translation\TranslatorInterface as SymfonyTranslatorInterface;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translator - Adapter for Symfony's translation service.
|
* Adapter for Symfony's translation service.
|
||||||
*
|
|
||||||
* This class adapts Symfony's translation system to PHPFlasher's TranslatorInterface,
|
|
||||||
* enabling notification messages to be translated using Symfony's translation capabilities.
|
|
||||||
* It searches for messages in multiple domains with cascading fallbacks.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Adapter Pattern: Adapts Symfony's translator interface to PHPFlasher's interface
|
|
||||||
* - Facade Pattern: Simplifies the translation process with a unified interface
|
|
||||||
* - Chain of Responsibility: Tries multiple translation domains in sequence
|
|
||||||
*/
|
*/
|
||||||
final readonly class Translator implements TranslatorInterface
|
final readonly class Translator implements TranslatorInterface
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Creates a new Translator instance.
|
|
||||||
*
|
|
||||||
* @param SymfonyTranslatorInterface $translator The Symfony translator service
|
|
||||||
*/
|
|
||||||
public function __construct(private SymfonyTranslatorInterface $translator)
|
public function __construct(private SymfonyTranslatorInterface $translator)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Translates a message using Symfony's translation system.
|
|
||||||
*
|
|
||||||
* This method attempts to translate the message in the following order:
|
|
||||||
* 1. In the 'flasher' domain (flasher-specific translations)
|
|
||||||
* 2. In the 'messages' domain (application-wide translations)
|
|
||||||
* 3. Returns the original ID if no translation is found
|
|
||||||
*
|
|
||||||
* @param string $id The message ID or key
|
|
||||||
* @param array<string, mixed> $parameters The translation parameters
|
|
||||||
* @param string|null $locale The locale or null to use the 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
|
||||||
{
|
{
|
||||||
if (!$this->translator instanceof TranslatorBagInterface) {
|
if (!$this->translator instanceof TranslatorBagInterface) {
|
||||||
@@ -62,13 +34,6 @@ final readonly class Translator implements TranslatorInterface
|
|||||||
return $id;
|
return $id;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the current locale from Symfony's translator.
|
|
||||||
*
|
|
||||||
* Falls back to system default locale if translator doesn't provide one.
|
|
||||||
*
|
|
||||||
* @return string The current locale code
|
|
||||||
*/
|
|
||||||
public function getLocale(): string
|
public function getLocale(): string
|
||||||
{
|
{
|
||||||
if (method_exists($this->translator, 'getLocale')) { // @phpstan-ignore-line
|
if (method_exists($this->translator, 'getLocale')) { // @phpstan-ignore-line
|
||||||
|
|||||||
@@ -9,33 +9,14 @@ use Twig\Extension\AbstractExtension;
|
|||||||
use Twig\TwigFunction;
|
use Twig\TwigFunction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* FlasherTwigExtension - Twig extension for rendering notifications.
|
* Twig extension for rendering PHPFlasher notifications.
|
||||||
*
|
|
||||||
* This class provides Twig functions that allow notification rendering
|
|
||||||
* directly from Twig templates. It exposes PHPFlasher's rendering
|
|
||||||
* capabilities to template files.
|
|
||||||
*
|
|
||||||
* Design patterns:
|
|
||||||
* - Extension Pattern: Extends Twig's functionality
|
|
||||||
* - Adapter Pattern: Adapts PHPFlasher's API for Twig templates
|
|
||||||
* - Delegation: Delegates actual rendering to the Flasher service
|
|
||||||
*/
|
*/
|
||||||
final class FlasherTwigExtension extends AbstractExtension
|
final class FlasherTwigExtension extends AbstractExtension
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Creates a new FlasherTwigExtension instance.
|
|
||||||
*
|
|
||||||
* @param FlasherInterface $flasher The PHPFlasher service
|
|
||||||
*/
|
|
||||||
public function __construct(private readonly FlasherInterface $flasher)
|
public function __construct(private readonly FlasherInterface $flasher)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the Twig functions provided by this extension.
|
|
||||||
*
|
|
||||||
* @return TwigFunction[] Array of Twig functions
|
|
||||||
*/
|
|
||||||
public function getFunctions(): array
|
public function getFunctions(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
@@ -44,13 +25,8 @@ final class FlasherTwigExtension extends AbstractExtension
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the flash notifications based on the specified criteria, presenter, and context.
|
* @param array<string, mixed> $criteria
|
||||||
*
|
* @param array<string, mixed> $context
|
||||||
* @param array<string, mixed> $criteria the criteria to filter the notifications
|
|
||||||
* @param "html"|"json"|string $presenter The presenter format for rendering the notifications (e.g., 'html', 'json').
|
|
||||||
* @param array<string, mixed> $context additional context or options for rendering
|
|
||||||
*
|
|
||||||
* @return mixed The rendered output (HTML string, JSON string, etc.)
|
|
||||||
*/
|
*/
|
||||||
public function render(array $criteria = [], string $presenter = 'html', array $context = []): mixed
|
public function render(array $criteria = [], string $presenter = 'html', array $context = []): mixed
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user