mirror of
https://github.com/php-flasher/php-flasher.git
synced 2026-03-31 15:07:47 +01:00
Simplify PHPDoc comments in Plugin, HTTP, Stamp, and Test constraint classes
Removes verbose documentation while preserving type annotations.
This commit is contained in:
@@ -7,40 +7,13 @@ namespace Flasher\Prime\Http\Csp;
|
||||
use Flasher\Prime\Http\RequestInterface;
|
||||
use Flasher\Prime\Http\ResponseInterface;
|
||||
|
||||
/**
|
||||
* ContentSecurityPolicyHandler - Manages Content Security Policy for PHPFlasher.
|
||||
*
|
||||
* This class handles the complex task of managing Content Security Policy (CSP) headers
|
||||
* to allow PHPFlasher's JavaScript and CSS to run securely. It generates nonces for
|
||||
* scripts and styles, modifies CSP headers to include these nonces, and ensures that
|
||||
* inline code can execute without being blocked by CSP.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Strategy: Implements a specific approach to CSP handling
|
||||
* - Adapter: Works with different request and response implementations
|
||||
*/
|
||||
final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandlerInterface
|
||||
{
|
||||
/**
|
||||
* Header for passing script nonce between components.
|
||||
*/
|
||||
private const SCRIPT_NONCE_HEADER = 'X-PHPFlasher-Script-Nonce';
|
||||
|
||||
/**
|
||||
* Header for passing style nonce between components.
|
||||
*/
|
||||
private const STYLE_NONCE_HEADER = 'X-PHPFlasher-Style-Nonce';
|
||||
|
||||
/**
|
||||
* Whether CSP handling is disabled.
|
||||
*/
|
||||
private bool $cspDisabled = false;
|
||||
|
||||
/**
|
||||
* Creates a new ContentSecurityPolicyHandler instance.
|
||||
*
|
||||
* @param NonceGeneratorInterface $nonceGenerator The generator for creating secure nonces
|
||||
*/
|
||||
public function __construct(private readonly NonceGeneratorInterface $nonceGenerator)
|
||||
{
|
||||
}
|
||||
@@ -87,14 +60,7 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns nonces from headers if existing, otherwise null.
|
||||
*
|
||||
* This method checks if the necessary nonce headers are present in the provided
|
||||
* request or response object and returns their values if found.
|
||||
*
|
||||
* @param RequestInterface|ResponseInterface $object The object to check for nonce headers
|
||||
*
|
||||
* @return array{csp_script_nonce: ?string, csp_style_nonce: ?string}|null Nonce values or null if not found
|
||||
* @return array{csp_script_nonce: ?string, csp_style_nonce: ?string}|null
|
||||
*/
|
||||
private function getHeaderNonces(RequestInterface|ResponseInterface $object): ?array
|
||||
{
|
||||
@@ -108,27 +74,12 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes temporary nonce headers from the response.
|
||||
*
|
||||
* These headers are used internally to pass nonces between components but
|
||||
* should not be sent to the client.
|
||||
*
|
||||
* @param ResponseInterface $response The response to clean
|
||||
*/
|
||||
private function cleanHeaders(ResponseInterface $response): void
|
||||
{
|
||||
$response->removeHeader(self::SCRIPT_NONCE_HEADER);
|
||||
$response->removeHeader(self::STYLE_NONCE_HEADER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all CSP headers from the response.
|
||||
*
|
||||
* This is used when CSP handling is disabled to ensure no CSP restrictions are applied.
|
||||
*
|
||||
* @param ResponseInterface $response The response to modify
|
||||
*/
|
||||
private function removeCspHeaders(ResponseInterface $response): void
|
||||
{
|
||||
$response->removeHeader('X-Content-Security-Policy');
|
||||
@@ -137,15 +88,9 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates Content-Security-Policy headers in a response.
|
||||
* @param array{csp_script_nonce?: ?string, csp_style_nonce?: ?string} $nonces
|
||||
*
|
||||
* This method modifies existing CSP headers to include nonces for PHPFlasher's
|
||||
* JavaScript and CSS, allowing them to execute without being blocked by CSP.
|
||||
*
|
||||
* @param ResponseInterface $response The response to modify
|
||||
* @param array{csp_script_nonce?: ?string, csp_style_nonce?: ?string} $nonces The nonces to add to CSP
|
||||
*
|
||||
* @return array{csp_script_nonce?: ?string, csp_style_nonce?: ?string} The nonces used
|
||||
* @return array{csp_script_nonce?: ?string, csp_style_nonce?: ?string}
|
||||
*/
|
||||
private function updateCspHeaders(ResponseInterface $response, array $nonces = []): array
|
||||
{
|
||||
@@ -202,22 +147,13 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
||||
return $nonces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a valid Content-Security-Policy nonce.
|
||||
*
|
||||
* @return string The generated nonce
|
||||
*/
|
||||
private function generateNonce(): string
|
||||
{
|
||||
return $this->nonceGenerator->generate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a directive set array into Content-Security-Policy header value.
|
||||
*
|
||||
* @param array<string, string[]> $directives The CSP directives to convert
|
||||
*
|
||||
* @return string The formatted CSP header value
|
||||
* @param array<string, string[]> $directives
|
||||
*/
|
||||
private function generateCspHeader(array $directives): string
|
||||
{
|
||||
@@ -225,11 +161,7 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a Content-Security-Policy header value into a directive set array.
|
||||
*
|
||||
* @param string|null $header The CSP header value to parse
|
||||
*
|
||||
* @return array<string, string[]> The parsed directive set
|
||||
* @return array<string, string[]>
|
||||
*/
|
||||
private function parseDirectives(?string $header): array
|
||||
{
|
||||
@@ -248,15 +180,7 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Detects if the 'unsafe-inline' is permitted for a directive within the directive set.
|
||||
*
|
||||
* This method checks if a specific CSP directive allows inline scripts or styles,
|
||||
* taking into account CSP level 2+ hash and nonce exceptions.
|
||||
*
|
||||
* @param array<string, string[]> $directivesSet The directives to check
|
||||
* @param string $type The directive type to check
|
||||
*
|
||||
* @return bool True if inline content is permitted
|
||||
* @param array<string, string[]> $directivesSet
|
||||
*/
|
||||
private function authorizesInline(array $directivesSet, string $type): bool
|
||||
{
|
||||
@@ -270,14 +194,7 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a directive list contains hash or nonce restrictions.
|
||||
*
|
||||
* This is important for CSP processing because in CSP Level 2+, the presence of a
|
||||
* hash or nonce invalidates 'unsafe-inline' even if it's present.
|
||||
*
|
||||
* @param string[] $directives The CSP directive values to check
|
||||
*
|
||||
* @return bool True if the directive list contains a hash or nonce restriction
|
||||
* @param string[] $directives
|
||||
*/
|
||||
private function hasHashOrNonce(array $directives): bool
|
||||
{
|
||||
@@ -297,15 +214,9 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the fallback directive for a specific directive type.
|
||||
* @param array<string, string[]> $directiveSet
|
||||
*
|
||||
* In CSP, if a specific directive isn't defined, browsers fall back to default-src.
|
||||
* This method implements that behavior for the PHPFlasher CSP handler.
|
||||
*
|
||||
* @param array<string, string[]> $directiveSet The complete directive set
|
||||
* @param string $type The directive type to find a fallback for
|
||||
*
|
||||
* @return string[]|null The fallback directive values, or null if no fallback exists
|
||||
* @return string[]|null
|
||||
*/
|
||||
private function getDirectiveFallback(array $directiveSet, string $type): ?array
|
||||
{
|
||||
@@ -318,18 +229,11 @@ final class ContentSecurityPolicyHandler implements ContentSecurityPolicyHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the Content-Security-Policy headers from a response.
|
||||
*
|
||||
* This method extracts all CSP-related headers from the response
|
||||
* and parses their values into directive sets.
|
||||
*
|
||||
* @param ResponseInterface $response The response to extract CSP headers from
|
||||
*
|
||||
* @return array{
|
||||
* Content-Security-Policy?: array<string, string[]>,
|
||||
* Content-Security-Policy-Report-Only?: array<string, string[]>,
|
||||
* X-Content-Security-Policy?: array<string, string[]>,
|
||||
* } Mapped CSP headers and their parsed directive sets
|
||||
* }
|
||||
*/
|
||||
private function getCspHeaders(ResponseInterface $response): array
|
||||
{
|
||||
|
||||
@@ -6,44 +6,21 @@ namespace Flasher\Prime\Http;
|
||||
|
||||
use Flasher\Prime\FlasherInterface;
|
||||
|
||||
/**
|
||||
* RequestExtension - Converts framework flash messages to PHPFlasher notifications.
|
||||
*
|
||||
* This class is responsible for extracting flash messages from request objects
|
||||
* (typically stored in the session) and converting them to PHPFlasher notifications.
|
||||
* It provides a bridge between framework-specific flash messaging systems and
|
||||
* PHPFlasher's notification system.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Adapter: Adapts framework flash message systems to PHPFlasher
|
||||
* - Mediator: Coordinates the interaction between framework and PHPFlasher
|
||||
*/
|
||||
final readonly class RequestExtension implements RequestExtensionInterface
|
||||
{
|
||||
/**
|
||||
* Flattened mapping from flash message keys to notification types.
|
||||
*
|
||||
* @var array<string, string>
|
||||
*/
|
||||
private array $mapping;
|
||||
|
||||
/**
|
||||
* Creates a new RequestExtension instance.
|
||||
*
|
||||
* @param FlasherInterface $flasher The flasher service for creating notifications
|
||||
* @param array<string, string[]> $mapping Mapping from framework flash types to PHPFlasher types
|
||||
* @param array<string, string[]> $mapping
|
||||
*/
|
||||
public function __construct(private FlasherInterface $flasher, array $mapping = [])
|
||||
{
|
||||
$this->mapping = $this->flatMapping($mapping);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* This method processes the request to extract flash messages and convert them
|
||||
* to PHPFlasher notifications. It only processes requests with active sessions.
|
||||
*/
|
||||
public function flash(RequestInterface $request, ResponseInterface $response): ResponseInterface
|
||||
{
|
||||
if (!$request->hasSession()) {
|
||||
@@ -56,14 +33,9 @@ final readonly class RequestExtension implements RequestExtensionInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens a nested mapping array to a simple key-value mapping.
|
||||
* @param array<string, string[]> $mapping
|
||||
*
|
||||
* Converts a mapping like ['success' => ['success', 'ok']] to
|
||||
* ['success' => 'success', 'ok' => 'success'].
|
||||
*
|
||||
* @param array<string, string[]> $mapping The nested mapping array
|
||||
*
|
||||
* @return array<string, string> The flattened mapping
|
||||
* @return array<string, string>
|
||||
*/
|
||||
private function flatMapping(array $mapping): array
|
||||
{
|
||||
@@ -78,14 +50,6 @@ final readonly class RequestExtension implements RequestExtensionInterface
|
||||
return $flatMapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the request and converts flash messages to notifications.
|
||||
*
|
||||
* This method checks for each flash message type in the request and creates
|
||||
* corresponding PHPFlasher notifications for any that are found.
|
||||
*
|
||||
* @param RequestInterface $request The request to process
|
||||
*/
|
||||
private function processRequest(RequestInterface $request): void
|
||||
{
|
||||
foreach ($this->mapping as $alias => $type) {
|
||||
|
||||
@@ -8,26 +8,10 @@ use Flasher\Prime\FlasherInterface;
|
||||
use Flasher\Prime\Http\Csp\ContentSecurityPolicyHandlerInterface;
|
||||
use Flasher\Prime\Response\Presenter\HtmlPresenter;
|
||||
|
||||
/**
|
||||
* ResponseExtension - Injects notification HTML into HTTP responses.
|
||||
*
|
||||
* This class is responsible for injecting the HTML for notifications into HTTP responses.
|
||||
* It handles the placement of notification code at appropriate injection points in HTML
|
||||
* responses, manages Content Security Policy headers, and ensures that notifications are
|
||||
* only injected in suitable responses.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Decorator: Enhances HTTP responses by adding notification HTML
|
||||
* - Chain of Responsibility: Determines whether each response is suitable for modification
|
||||
*/
|
||||
final readonly class ResponseExtension implements ResponseExtensionInterface
|
||||
{
|
||||
/**
|
||||
* Creates a new ResponseExtension instance.
|
||||
*
|
||||
* @param FlasherInterface $flasher The flasher service for rendering notifications
|
||||
* @param ContentSecurityPolicyHandlerInterface $cspHandler The CSP handler for managing security headers
|
||||
* @param list<non-empty-string> $excludedPaths Regex patterns for paths where notifications shouldn't be rendered
|
||||
* @param list<non-empty-string> $excludedPaths
|
||||
*/
|
||||
public function __construct(
|
||||
private FlasherInterface $flasher,
|
||||
@@ -36,16 +20,6 @@ final readonly class ResponseExtension implements ResponseExtensionInterface
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* This method:
|
||||
* 1. Checks if the response is eligible for notification injection
|
||||
* 2. Finds an appropriate insertion point in the HTML
|
||||
* 3. Updates CSP headers if needed
|
||||
* 4. Renders the notification HTML
|
||||
* 5. Injects the rendered HTML into the response
|
||||
*/
|
||||
public function render(RequestInterface $request, ResponseInterface $response): ResponseInterface
|
||||
{
|
||||
if (!$this->isRenderable($request, $response)) {
|
||||
@@ -99,24 +73,6 @@ final readonly class ResponseExtension implements ResponseExtensionInterface
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a response is eligible for notification rendering.
|
||||
*
|
||||
* A response is renderable if:
|
||||
* - The request path is not excluded
|
||||
* - It's not an AJAX request
|
||||
* - It's an HTML request format
|
||||
* - The response is HTML
|
||||
* - The response is successful (2XX)
|
||||
* - It's not a redirection
|
||||
* - It's not an attachment
|
||||
* - It's not JSON
|
||||
*
|
||||
* @param RequestInterface $request The request
|
||||
* @param ResponseInterface $response The response
|
||||
*
|
||||
* @return bool True if notifications should be rendered in this response
|
||||
*/
|
||||
private function isRenderable(RequestInterface $request, ResponseInterface $response): bool
|
||||
{
|
||||
return !$this->isPathExcluded($request)
|
||||
@@ -129,13 +85,6 @@ final readonly class ResponseExtension implements ResponseExtensionInterface
|
||||
&& !$response->isJson();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current request path is excluded from notification rendering.
|
||||
*
|
||||
* @param RequestInterface $request The request
|
||||
*
|
||||
* @return bool True if the path is excluded
|
||||
*/
|
||||
private function isPathExcluded(RequestInterface $request): bool
|
||||
{
|
||||
if (!method_exists($request, 'getUri')) { // @phpstan-ignore-line
|
||||
|
||||
@@ -9,16 +9,6 @@ use Flasher\Prime\FlasherInterface;
|
||||
use Flasher\Prime\Notification\Type;
|
||||
|
||||
/**
|
||||
* FlasherPlugin - Core plugin for PHPFlasher.
|
||||
*
|
||||
* This class represents the core PHPFlasher plugin, which provides the basic
|
||||
* notification functionality. It serves as the default plugin and the foundation
|
||||
* for other plugins to build upon.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Core Plugin: Provides essential functionality that other plugins extend
|
||||
* - Configuration Management: Handles normalization and defaults for system config
|
||||
*
|
||||
* @phpstan-type ConfigType array{
|
||||
* default: string,
|
||||
* main_script: string,
|
||||
@@ -70,21 +60,11 @@ final class FlasherPlugin extends Plugin
|
||||
return FlasherInterface::class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default plugin name.
|
||||
*
|
||||
* @return string The default plugin name
|
||||
*/
|
||||
public function getDefault(): string
|
||||
{
|
||||
return 'flasher';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the path to the main PHPFlasher script.
|
||||
*
|
||||
* @return string The script path
|
||||
*/
|
||||
public function getRootScript(): string
|
||||
{
|
||||
return '/vendor/flasher/flasher.min.js';
|
||||
@@ -103,17 +83,6 @@ final class FlasherPlugin extends Plugin
|
||||
return '/vendor/flasher/flasher.min.css';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* This overridden method extends the parent's normalization process with
|
||||
* additional steps specific to the core plugin:
|
||||
* - Normalizing plugin configurations
|
||||
* - Normalizing preset configurations
|
||||
* - Adding default configuration values
|
||||
* - Normalizing flash bag mappings
|
||||
* - Setting preset defaults
|
||||
*/
|
||||
public function normalizeConfig(array $config = []): array
|
||||
{
|
||||
$config = parent::normalizeConfig($config);
|
||||
@@ -129,11 +98,6 @@ final class FlasherPlugin extends Plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the plugins configuration.
|
||||
*
|
||||
* This method ensures the core plugin is properly configured, merges global options
|
||||
* with plugin-specific options, and normalizes array formats for scripts and styles.
|
||||
*
|
||||
* @param array{
|
||||
* scripts: string[],
|
||||
* styles: string[],
|
||||
@@ -143,14 +107,14 @@ final class FlasherPlugin extends Plugin
|
||||
* styles?: string[],
|
||||
* options?: array<string, mixed>,
|
||||
* }>,
|
||||
* } $config The raw configuration
|
||||
* } $config
|
||||
*
|
||||
* @return array{
|
||||
* scripts: string[],
|
||||
* styles: string[],
|
||||
* options: array<string, mixed>,
|
||||
* plugins: array<string, mixed>,
|
||||
* } The normalized configuration
|
||||
* }
|
||||
*/
|
||||
private function normalizePlugins(array $config): array
|
||||
{
|
||||
@@ -191,11 +155,6 @@ final class FlasherPlugin extends Plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the themes configuration.
|
||||
*
|
||||
* This method ensures that the themes configuration has the correct structure
|
||||
* and includes default themes unless explicitly disabled.
|
||||
*
|
||||
* @param array{
|
||||
* scripts: string[],
|
||||
* styles: string[],
|
||||
@@ -206,7 +165,7 @@ final class FlasherPlugin extends Plugin
|
||||
* styles?: string[],
|
||||
* options?: array<string, mixed>,
|
||||
* }>,
|
||||
* } $config The raw configuration
|
||||
* } $config
|
||||
*
|
||||
* @return array{
|
||||
* scripts: string[],
|
||||
@@ -214,7 +173,7 @@ final class FlasherPlugin extends Plugin
|
||||
* options: array<string, mixed>,
|
||||
* plugins: array<string, mixed>,
|
||||
* themes: array<string, mixed>,
|
||||
* } The normalized configuration
|
||||
* }
|
||||
*/
|
||||
private function normalizeThemes(array $config): array
|
||||
{
|
||||
@@ -261,18 +220,13 @@ final class FlasherPlugin extends Plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the presets configuration.
|
||||
*
|
||||
* This method ensures that string-only preset definitions are expanded to full arrays
|
||||
* with the string value as the message.
|
||||
*
|
||||
* @param array{
|
||||
* scripts: string[],
|
||||
* styles: string[],
|
||||
* options: array<string, mixed>,
|
||||
* presets?: array<string, string|array<string, mixed>>,
|
||||
* plugins: array<string, mixed>,
|
||||
* } $config The raw configuration
|
||||
* } $config
|
||||
*
|
||||
* @return array{
|
||||
* scripts: string[],
|
||||
@@ -280,7 +234,7 @@ final class FlasherPlugin extends Plugin
|
||||
* options: array<string, mixed>,
|
||||
* presets?: array<string, array<string, mixed>>,
|
||||
* plugins: array<string, mixed>,
|
||||
* } The normalized configuration
|
||||
* }
|
||||
*/
|
||||
private function normalizePresets(array $config): array
|
||||
{
|
||||
@@ -296,11 +250,6 @@ final class FlasherPlugin extends Plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds default configuration values.
|
||||
*
|
||||
* This method ensures that all required configuration keys have values,
|
||||
* providing defaults for any that are missing.
|
||||
*
|
||||
* @param array{
|
||||
* default?: string|null,
|
||||
* main_script?: string|null,
|
||||
@@ -313,7 +262,7 @@ final class FlasherPlugin extends Plugin
|
||||
* options: array<string, mixed>,
|
||||
* presets?: array<string, array<string, mixed>>,
|
||||
* plugins: array<string, mixed>,
|
||||
* } $config The raw configuration
|
||||
* } $config
|
||||
*
|
||||
* @return array{
|
||||
* default: string|null,
|
||||
@@ -327,7 +276,7 @@ final class FlasherPlugin extends Plugin
|
||||
* options: array<string, mixed>,
|
||||
* presets: array<string, array<string, mixed>>,
|
||||
* plugins: array<string, mixed>,
|
||||
* } The configuration with defaults added
|
||||
* }
|
||||
*/
|
||||
private function addDefaultConfig(array $config): array
|
||||
{
|
||||
@@ -349,11 +298,6 @@ final class FlasherPlugin extends Plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalizes the flash bag configuration.
|
||||
*
|
||||
* This method ensures that the flash bag mapping has the correct structure
|
||||
* and includes default mappings unless explicitly disabled.
|
||||
*
|
||||
* @param array{
|
||||
* default: string|null,
|
||||
* main_script: string|null,
|
||||
@@ -367,7 +311,7 @@ final class FlasherPlugin extends Plugin
|
||||
* presets: array<string, array<string, mixed>>,
|
||||
* plugins: array<string, mixed>,
|
||||
* flash_bag?: bool|array<string, string[]>,
|
||||
* } $config The raw configuration
|
||||
* } $config
|
||||
*
|
||||
* @return array{
|
||||
* default: string|null,
|
||||
@@ -382,7 +326,7 @@ final class FlasherPlugin extends Plugin
|
||||
* presets: array<string, array<string, mixed>>,
|
||||
* plugins: array<string, mixed>,
|
||||
* flash_bag: false|array<string, string[]>,
|
||||
* } The normalized configuration
|
||||
* }
|
||||
*/
|
||||
private function normalizeFlashBag(array $config): array
|
||||
{
|
||||
@@ -407,10 +351,6 @@ final class FlasherPlugin extends Plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets default values for presets.
|
||||
*
|
||||
* This method ensures that all presets have required fields with default values.
|
||||
*
|
||||
* @param array{
|
||||
* default: string|null,
|
||||
* main_script: string|null,
|
||||
@@ -424,7 +364,7 @@ final class FlasherPlugin extends Plugin
|
||||
* presets: array<string, array<string, mixed>>,
|
||||
* plugins: array<string, mixed>,
|
||||
* flash_bag: false|array<string, string[]>,
|
||||
* } $config The raw configuration
|
||||
* } $config
|
||||
*
|
||||
* @return array{
|
||||
* default: string|null,
|
||||
@@ -439,7 +379,7 @@ final class FlasherPlugin extends Plugin
|
||||
* presets: array<string, array<string, mixed>>,
|
||||
* plugins: array<string, mixed>,
|
||||
* flash_bag: false|array<string, string[]>,
|
||||
* } The normalized configuration
|
||||
* }
|
||||
*/
|
||||
private function setPresetsDefaults(array $config): array
|
||||
{
|
||||
@@ -452,13 +392,11 @@ final class FlasherPlugin extends Plugin
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default themes configuration.
|
||||
*
|
||||
* @return array<string, array{
|
||||
* scripts: string[],
|
||||
* styles: string[],
|
||||
* options: array<string, mixed>
|
||||
* }> The default themes configuration
|
||||
* }>
|
||||
*/
|
||||
private function getDefaultThemes(): array
|
||||
{
|
||||
|
||||
@@ -4,85 +4,38 @@ declare(strict_types=1);
|
||||
|
||||
namespace Flasher\Prime\Plugin;
|
||||
|
||||
/**
|
||||
* Plugin - Base class for PHPFlasher plugins.
|
||||
*
|
||||
* This abstract class provides a common foundation for PHPFlasher plugins,
|
||||
* implementing standard behaviors and conventions. Plugin implementations
|
||||
* should extend this class and customize the specific aspects they need to change.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Template Method: Defines standard algorithms with customizable steps
|
||||
* - Convention over Configuration: Provides sensible defaults based on naming conventions
|
||||
*/
|
||||
abstract class Plugin implements PluginInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* By default, derives the plugin name from its alias with a "flasher_" prefix.
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return 'flasher_'.$this->getAlias();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* By default, derives the service ID from the plugin alias with a "flasher." prefix.
|
||||
*/
|
||||
public function getServiceId(): string
|
||||
{
|
||||
return 'flasher.'.$this->getAlias();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* By default, returns an empty array, meaning no service aliases are registered.
|
||||
*/
|
||||
public function getServiceAliases(): string|array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* By default, returns an empty array, meaning no scripts are included.
|
||||
*/
|
||||
public function getScripts(): string|array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* By default, returns an empty array, meaning no styles are included.
|
||||
*/
|
||||
public function getStyles(): string|array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* By default, returns an empty array, meaning no options are configured.
|
||||
*/
|
||||
public function getOptions(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* By default, locates the assets directory by convention based on the plugin's
|
||||
* class location.
|
||||
*/
|
||||
public function getAssetsDir(): string
|
||||
{
|
||||
$resourcesDir = $this->getResourcesDir();
|
||||
@@ -91,13 +44,6 @@ abstract class Plugin implements PluginInterface
|
||||
return realpath($assetsDir) ?: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* By default, locates the resources directory by convention based on the plugin's
|
||||
* class location. Looks first for a Resources subdirectory in the same directory,
|
||||
* then falls back to a Resources directory one level up.
|
||||
*/
|
||||
public function getResourcesDir(): string
|
||||
{
|
||||
$reflection = new \ReflectionClass($this);
|
||||
@@ -109,13 +55,6 @@ abstract class Plugin implements PluginInterface
|
||||
return realpath($resourcesDir) ?: '';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* This implementation merges the provided config with defaults from the plugin's
|
||||
* getScripts(), getStyles(), and getOptions() methods and ensures arrays are properly
|
||||
* normalized.
|
||||
*/
|
||||
public function normalizeConfig(array $config): array
|
||||
{
|
||||
$config = [
|
||||
|
||||
@@ -7,17 +7,6 @@ namespace Flasher\Prime\Response\Presenter;
|
||||
use Flasher\Prime\Response\Response;
|
||||
|
||||
/**
|
||||
* ArrayPresenter - Presents notifications as a PHP array structure.
|
||||
*
|
||||
* This presenter converts a Response object into a PHP array structure that can
|
||||
* be used for further processing, serialization, or API responses. It's particularly
|
||||
* useful as a base for other presenters that need structured data rather than
|
||||
* rendered output.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Presenter: Transforms domain objects (Notifications) into a presentation format
|
||||
* - Adapter: Converts internal representation to a format suitable for external use
|
||||
*
|
||||
* @phpstan-type ArrayPresenterType array{
|
||||
* envelopes: array<array{
|
||||
* title: string,
|
||||
@@ -35,15 +24,6 @@ use Flasher\Prime\Response\Response;
|
||||
final class ArrayPresenter implements PresenterInterface
|
||||
{
|
||||
/**
|
||||
* Renders a response as a PHP array.
|
||||
*
|
||||
* This method simply calls toArray() on the response object to convert it
|
||||
* to a structured array representation.
|
||||
*
|
||||
* @param Response $response The response to render
|
||||
*
|
||||
* @return array The array representation of the response
|
||||
*
|
||||
* @phpstan-return ArrayPresenterType
|
||||
*/
|
||||
public function render(Response $response): array
|
||||
|
||||
@@ -7,49 +7,14 @@ namespace Flasher\Prime\Response\Presenter;
|
||||
use Flasher\Prime\Response\Response;
|
||||
use Livewire\LivewireManager;
|
||||
|
||||
/**
|
||||
* HtmlPresenter - Presents notifications as JavaScript for HTML pages.
|
||||
*
|
||||
* This presenter generates JavaScript code that can be embedded in HTML pages
|
||||
* to display notifications. It handles resource loading, Content Security Policy
|
||||
* considerations, and special HTML content from notifications.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Presenter: Transforms domain objects into a presentation format
|
||||
* - Template Method: Defines the skeleton of the JavaScript generation algorithm
|
||||
* - Adapter: Integrates with frontend frameworks like Livewire
|
||||
*/
|
||||
final class HtmlPresenter implements PresenterInterface
|
||||
{
|
||||
/**
|
||||
* Placeholder for inserting notification data in already rendered HTML.
|
||||
*/
|
||||
public const FLASHER_REPLACE_ME = '/** {--FLASHER_REPLACE_ME--} **/';
|
||||
|
||||
/**
|
||||
* Placeholder for inserting at the end of head tag.
|
||||
*/
|
||||
public const HEAD_END_PLACE_HOLDER = '</head>';
|
||||
|
||||
/**
|
||||
* Placeholder for inserting at the end of body tag.
|
||||
*/
|
||||
public const BODY_END_PLACE_HOLDER = '</body>';
|
||||
|
||||
/**
|
||||
* Renders a response as JavaScript code for HTML pages.
|
||||
*
|
||||
* This method generates JavaScript code that will:
|
||||
* 1. Extract any direct HTML content from notifications
|
||||
* 2. Create a script that dynamically loads resources if needed
|
||||
* 3. Initialize and render the notifications using the frontend library
|
||||
* 4. Set up event listeners for dynamic notification rendering
|
||||
*
|
||||
* @param Response $response The response to render
|
||||
*
|
||||
* @return string The generated JavaScript code
|
||||
*
|
||||
* @throws \JsonException If JSON encoding fails
|
||||
* @throws \JsonException
|
||||
*/
|
||||
public function render(Response $response): string
|
||||
{
|
||||
@@ -166,14 +131,6 @@ final class HtmlPresenter implements PresenterInterface
|
||||
JAVASCRIPT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates the JavaScript for Livewire integration.
|
||||
*
|
||||
* This method checks if Livewire is available and, if so, generates
|
||||
* the necessary JavaScript to handle Livewire page navigation events.
|
||||
*
|
||||
* @return string The Livewire integration JavaScript, or an empty string if Livewire is not available
|
||||
*/
|
||||
private function getLivewireListenerScript(): string
|
||||
{
|
||||
if (!class_exists(LivewireManager::class)) {
|
||||
|
||||
@@ -12,16 +12,6 @@ use Flasher\Prime\Stamp\PluginStamp;
|
||||
use Flasher\Prime\Template\TemplateEngineInterface;
|
||||
|
||||
/**
|
||||
* ResourceManager - Manages resources for notification responses.
|
||||
*
|
||||
* This class is responsible for populating Response objects with the resources
|
||||
* (scripts, styles, options) required by the notifications they contain. It also
|
||||
* handles rendering HTML templates for notifications that require it.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Builder: Builds complete responses by adding resources incrementally
|
||||
* - Template Method: Defines the algorithm for populating responses with customizable steps
|
||||
*
|
||||
* @phpstan-type ResourceType array{
|
||||
* scripts?: string[],
|
||||
* styles?: string[],
|
||||
@@ -32,12 +22,7 @@ use Flasher\Prime\Template\TemplateEngineInterface;
|
||||
final readonly class ResourceManager implements ResourceManagerInterface
|
||||
{
|
||||
/**
|
||||
* Creates a new ResourceManager instance.
|
||||
*
|
||||
* @param TemplateEngineInterface $templateEngine Engine for rendering notification templates
|
||||
* @param AssetManagerInterface $assetManager Manager for resolving asset paths
|
||||
* @param string|null $mainScript Path to the main PHPFlasher script
|
||||
* @param ResourceType[] $resources Configuration for plugin-specific resources
|
||||
* @param ResourceType[] $resources
|
||||
*/
|
||||
public function __construct(
|
||||
private TemplateEngineInterface $templateEngine,
|
||||
@@ -47,15 +32,6 @@ final readonly class ResourceManager implements ResourceManagerInterface
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* This implementation:
|
||||
* 1. Sets the main script path if available
|
||||
* 2. Identifies unique plugins used by the notifications
|
||||
* 3. Renders HTML templates for notifications that need them
|
||||
* 4. Adds resources (scripts, styles, options) for each plugin
|
||||
*/
|
||||
public function populateResponse(Response $response): Response
|
||||
{
|
||||
if (null !== $this->mainScript) {
|
||||
@@ -85,15 +61,6 @@ final readonly class ResourceManager implements ResourceManagerInterface
|
||||
return $response;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an HTML stamp to a notification envelope.
|
||||
*
|
||||
* This method renders a template for the notification and attaches the
|
||||
* rendered HTML as a stamp on the envelope.
|
||||
*
|
||||
* @param string $view The template view name
|
||||
* @param Envelope $envelope The notification envelope
|
||||
*/
|
||||
private function addHtmlStamp(string $view, Envelope $envelope): void
|
||||
{
|
||||
$compiled = $this->templateEngine->render($view, ['envelope' => $envelope]);
|
||||
@@ -101,15 +68,6 @@ final readonly class ResourceManager implements ResourceManagerInterface
|
||||
$envelope->withStamp(new HtmlStamp($compiled));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds resources for a plugin to a response.
|
||||
*
|
||||
* This method retrieves the resource configuration for a plugin and adds
|
||||
* its scripts, styles, and options to the response.
|
||||
*
|
||||
* @param Response $response The response to populate
|
||||
* @param string $plugin The plugin alias
|
||||
*/
|
||||
private function addResources(Response $response, string $plugin): void
|
||||
{
|
||||
$resource = $this->resources[$plugin] ?? [];
|
||||
|
||||
@@ -6,62 +6,35 @@ namespace Flasher\Prime\Response;
|
||||
|
||||
use Flasher\Prime\Notification\Envelope;
|
||||
|
||||
/**
|
||||
* Response - Container for notification data ready for presentation.
|
||||
*
|
||||
* This class encapsulates all the data needed to render notifications in a response,
|
||||
* including the notification envelopes themselves, scripts, styles, options, and context.
|
||||
* It serves as a data transfer object between the notification storage and presenters.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Data Transfer Object (DTO): Aggregates all data needed for notification rendering
|
||||
* - Immutable Collection: Core envelopes and context are immutable while allowing
|
||||
* controlled mutation of presentation resources
|
||||
*/
|
||||
final class Response
|
||||
{
|
||||
/**
|
||||
* The main script to be included in the response.
|
||||
*/
|
||||
private string $mainScript = '';
|
||||
|
||||
/**
|
||||
* Additional JavaScript files to be included in the response.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private array $scripts = [];
|
||||
|
||||
/**
|
||||
* CSS stylesheets to be included in the response.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
private array $styles = [];
|
||||
|
||||
/**
|
||||
* Plugin-specific options organized by plugin alias.
|
||||
*
|
||||
* @var array<string, array<string, mixed>>
|
||||
*/
|
||||
private array $options = [];
|
||||
|
||||
/**
|
||||
* Creates a new Response instance.
|
||||
*
|
||||
* @param Envelope[] $envelopes The notification envelopes to present
|
||||
* @param array<string, mixed> $context Additional context for the presentation (e.g., CSP nonces)
|
||||
* @param Envelope[] $envelopes
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
public function __construct(private readonly array $envelopes, private readonly array $context)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds JavaScript scripts to the response.
|
||||
*
|
||||
* This method appends new scripts to the existing list, ensuring uniqueness.
|
||||
*
|
||||
* @param string[] $scripts The scripts to add
|
||||
* @param string[] $scripts
|
||||
*/
|
||||
public function addScripts(array $scripts): void
|
||||
{
|
||||
@@ -69,11 +42,7 @@ final class Response
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds CSS stylesheets to the response.
|
||||
*
|
||||
* This method appends new styles to the existing list, ensuring uniqueness.
|
||||
*
|
||||
* @param string[] $styles The styles to add
|
||||
* @param string[] $styles
|
||||
*/
|
||||
public function addStyles(array $styles): void
|
||||
{
|
||||
@@ -81,13 +50,7 @@ final class Response
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds or merges options for a specific plugin.
|
||||
*
|
||||
* This method merges new options with existing ones for the specified alias,
|
||||
* creating the entry if it doesn't exist.
|
||||
*
|
||||
* @param string $alias The plugin alias
|
||||
* @param array<string, mixed> $options The options to add or merge
|
||||
* @param array<string, mixed> $options
|
||||
*/
|
||||
public function addOptions(string $alias, array $options): void
|
||||
{
|
||||
@@ -96,34 +59,24 @@ final class Response
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the notification envelopes to be presented.
|
||||
*
|
||||
* @return Envelope[] The notification envelopes
|
||||
* @return Envelope[]
|
||||
*/
|
||||
public function getEnvelopes(): array
|
||||
{
|
||||
return $this->envelopes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the main script path.
|
||||
*/
|
||||
public function getMainScript(): string
|
||||
{
|
||||
return $this->mainScript;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the main script path.
|
||||
*/
|
||||
public function setMainScript(string $mainScript): void
|
||||
{
|
||||
$this->mainScript = $mainScript;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the CSS stylesheets.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getStyles(): array
|
||||
@@ -132,8 +85,6 @@ final class Response
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the JavaScript scripts.
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public function getScripts(): array
|
||||
@@ -142,9 +93,7 @@ final class Response
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the plugin-specific options.
|
||||
*
|
||||
* @return array<string, array<string, mixed>> The options organized by plugin alias
|
||||
* @return array<string, array<string, mixed>>
|
||||
*/
|
||||
public function getOptions(): array
|
||||
{
|
||||
@@ -152,9 +101,7 @@ final class Response
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the presentation context.
|
||||
*
|
||||
* @return array<string, mixed> The context data
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function getContext(): array
|
||||
{
|
||||
@@ -162,11 +109,6 @@ final class Response
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the response to an array representation.
|
||||
*
|
||||
* This method transforms all data in the response, including converting notification
|
||||
* envelopes to arrays, into a format suitable for serialization or rendering.
|
||||
*
|
||||
* @return array{
|
||||
* envelopes: array<array{
|
||||
* title: string,
|
||||
|
||||
@@ -16,33 +16,15 @@ use Flasher\Prime\Response\Resource\ResourceManagerInterface;
|
||||
use Flasher\Prime\Storage\StorageManagerInterface;
|
||||
|
||||
/**
|
||||
* ResponseManager - Manages notification response generation and presentation.
|
||||
*
|
||||
* This class orchestrates the process of retrieving notifications from storage,
|
||||
* populating them with resources (scripts, styles), and rendering them with the
|
||||
* appropriate presenter. It serves as the central coordinator for notification rendering.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Mediator: Coordinates the interaction between storage, resources, events, and presenters
|
||||
* - Strategy: Uses different presentation strategies based on the requested format
|
||||
* - Factory: Creates presenters on demand
|
||||
* @phpstan-import-type ArrayPresenterType from ArrayPresenter
|
||||
*/
|
||||
final class ResponseManager implements ResponseManagerInterface
|
||||
{
|
||||
/**
|
||||
* Registry of presenter instances or factories.
|
||||
*
|
||||
* @var callable[]|PresenterInterface[]
|
||||
*/
|
||||
private array $presenters = [];
|
||||
|
||||
/**
|
||||
* Creates a new ResponseManager instance.
|
||||
*
|
||||
* @param ResourceManagerInterface $resourceManager Manager for adding resources to responses
|
||||
* @param StorageManagerInterface $storageManager Manager for accessing stored notifications
|
||||
* @param EventDispatcherInterface $eventDispatcher Dispatcher for notification events
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly ResourceManagerInterface $resourceManager,
|
||||
private readonly StorageManagerInterface $storageManager,
|
||||
@@ -54,15 +36,13 @@ final class ResponseManager implements ResponseManagerInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* @param array<string, mixed> $criteria
|
||||
* @param array<string, mixed> $context
|
||||
*
|
||||
* This implementation follows a multi-step process:
|
||||
* 1. Filters notifications from storage based on criteria
|
||||
* 2. Removes rendered notifications from storage
|
||||
* 3. Dispatches a PresentationEvent to allow listeners to modify notifications
|
||||
* 4. Creates a Response object with notifications and context
|
||||
* 5. Uses the appropriate presenter to render the response
|
||||
* 6. Dispatches a ResponseEvent to allow final modifications
|
||||
* @phpstan-return ($presenter is 'html' ? string :
|
||||
* ($presenter is 'array' ? ArrayPresenterType :
|
||||
* ($presenter is 'json' ? ArrayPresenterType :
|
||||
* mixed)))
|
||||
*/
|
||||
public function render(string $presenter = 'html', array $criteria = [], array $context = []): mixed
|
||||
{
|
||||
@@ -87,16 +67,7 @@ final class ResponseManager implements ResponseManagerInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a presenter instance for the specified format.
|
||||
*
|
||||
* This method retrieves a presenter by alias from the registry and instantiates
|
||||
* it if it's a factory closure.
|
||||
*
|
||||
* @param string $alias The presenter alias
|
||||
*
|
||||
* @return PresenterInterface The presenter instance
|
||||
*
|
||||
* @throws PresenterNotFoundException If no presenter is registered with the given alias
|
||||
* @throws PresenterNotFoundException
|
||||
*/
|
||||
private function createPresenter(string $alias): PresenterInterface
|
||||
{
|
||||
@@ -110,11 +81,6 @@ final class ResponseManager implements ResponseManagerInterface
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Response object with notifications and context.
|
||||
*
|
||||
* This method creates a Response object and populates it with resources
|
||||
* (scripts, styles, options) using the ResourceManager.
|
||||
*
|
||||
* @param Envelope[] $envelopes
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
@@ -125,17 +91,6 @@ final class ResponseManager implements ResponseManagerInterface
|
||||
return $this->resourceManager->populateResponse($response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uses a presenter to render a response.
|
||||
*
|
||||
* This method selects the appropriate presenter based on the requested format
|
||||
* and uses it to render the response.
|
||||
*
|
||||
* @param Response $response The response to render
|
||||
* @param string $presenter The presenter format to use
|
||||
*
|
||||
* @return mixed The rendered result
|
||||
*/
|
||||
private function presentResponse(Response $response, string $presenter): mixed
|
||||
{
|
||||
$presenter = $this->createPresenter($presenter);
|
||||
|
||||
@@ -4,44 +4,19 @@ declare(strict_types=1);
|
||||
|
||||
namespace Flasher\Prime\Stamp;
|
||||
|
||||
/**
|
||||
* HtmlStamp - Contains prerendered HTML content for a notification.
|
||||
*
|
||||
* This stamp stores HTML content that should be rendered directly in the page
|
||||
* instead of being processed by the JavaScript notification library. It's useful
|
||||
* for complex notifications that require custom markup or server-rendered content.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Value Object: Immutable object representing a specific concept
|
||||
* - Memento: Captures and externalizes an object's internal state
|
||||
*/
|
||||
final readonly class HtmlStamp implements StampInterface, PresentableStampInterface
|
||||
{
|
||||
/**
|
||||
* Creates a new HtmlStamp instance.
|
||||
*
|
||||
* @param string $html The prerendered HTML content
|
||||
*/
|
||||
public function __construct(private string $html)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the HTML content.
|
||||
*
|
||||
* @return string The prerendered HTML content
|
||||
*/
|
||||
public function getHtml(): string
|
||||
{
|
||||
return $this->html;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the stamp to an array representation.
|
||||
*
|
||||
* This method implements the serialization logic required by PresentableStampInterface.
|
||||
*
|
||||
* @return array{html: string} The array representation
|
||||
* @return array{html: string}
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
|
||||
@@ -4,44 +4,19 @@ declare(strict_types=1);
|
||||
|
||||
namespace Flasher\Prime\Stamp;
|
||||
|
||||
/**
|
||||
* PluginStamp - Associates a notification with a specific plugin.
|
||||
*
|
||||
* This stamp identifies which plugin should handle a notification. It ensures
|
||||
* that notifications are rendered with the correct plugin's resources and options.
|
||||
* This information is also serialized into the notification's metadata.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Value Object: Immutable object representing a specific concept
|
||||
* - Strategy Identifier: Identifies which rendering strategy to use
|
||||
*/
|
||||
final readonly class PluginStamp implements PresentableStampInterface, StampInterface
|
||||
{
|
||||
/**
|
||||
* Creates a new PluginStamp instance.
|
||||
*
|
||||
* @param string $plugin The plugin alias (e.g., 'toastr', 'sweetalert')
|
||||
*/
|
||||
public function __construct(private string $plugin)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the plugin alias.
|
||||
*
|
||||
* @return string The plugin alias
|
||||
*/
|
||||
public function getPlugin(): string
|
||||
{
|
||||
return $this->plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the stamp to an array representation.
|
||||
*
|
||||
* This method implements the serialization logic required by PresentableStampInterface.
|
||||
*
|
||||
* @return array{plugin: string} The array representation
|
||||
* @return array{plugin: string}
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
|
||||
@@ -4,26 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace Flasher\Prime\Stamp;
|
||||
|
||||
/**
|
||||
* PresenterStamp - Controls which presenters can render a notification.
|
||||
*
|
||||
* This stamp restricts which presenters can render a notification by specifying
|
||||
* a regex pattern. Only presenters whose names match the pattern will be allowed
|
||||
* to render the notification. This is useful for creating notifications that
|
||||
* are only meant for specific presentation formats.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Value Object: Immutable object representing a specific concept
|
||||
* - Filter: Restricts which presenters can render a notification
|
||||
*/
|
||||
final readonly class PresenterStamp implements StampInterface
|
||||
{
|
||||
/**
|
||||
* Creates a new PresenterStamp instance.
|
||||
*
|
||||
* @param string $pattern A regex pattern that presenter names must match
|
||||
*
|
||||
* @throws \InvalidArgumentException If the provided pattern is not a valid regex
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function __construct(private string $pattern)
|
||||
{
|
||||
@@ -32,11 +16,6 @@ final readonly class PresenterStamp implements StampInterface
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pattern value.
|
||||
*
|
||||
* @return string The regex pattern
|
||||
*/
|
||||
public function getPattern(): string
|
||||
{
|
||||
return $this->pattern;
|
||||
|
||||
@@ -4,34 +4,10 @@ declare(strict_types=1);
|
||||
|
||||
namespace Flasher\Prime\Template;
|
||||
|
||||
/**
|
||||
* PHPTemplateEngine - Simple PHP-based template rendering engine.
|
||||
*
|
||||
* This implementation provides a straightforward template rendering mechanism using
|
||||
* native PHP as the template language. It works by including PHP files and extracting
|
||||
* context variables into the template's scope.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Strategy: Implements a specific template rendering strategy
|
||||
* - Output Capture: Uses output buffering to capture rendered content
|
||||
*
|
||||
* Security considerations:
|
||||
* - Context variables are extracted with EXTR_SKIP flag to prevent variable overwriting
|
||||
* - Template files must exist and be readable
|
||||
*/
|
||||
final class PHPTemplateEngine implements TemplateEngineInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* This implementation:
|
||||
* 1. Verifies the template file exists and is readable
|
||||
* 2. Starts output buffering
|
||||
* 3. Extracts context variables into the current scope
|
||||
* 4. Includes the template file
|
||||
* 5. Captures and returns the output
|
||||
*
|
||||
* @throws \InvalidArgumentException If the template file doesn't exist or isn't readable
|
||||
* @throws \InvalidArgumentException
|
||||
*/
|
||||
public function render(string $name, array $context = []): string
|
||||
{
|
||||
|
||||
@@ -8,27 +8,10 @@ use Flasher\Prime\EventDispatcher\Event\NotificationEvents;
|
||||
use Flasher\Prime\Notification\NotificationInterface;
|
||||
use PHPUnit\Framework\Constraint\Constraint;
|
||||
|
||||
/**
|
||||
* Notification - PHPUnit constraint for asserting complete notification properties.
|
||||
*
|
||||
* This constraint verifies that a NotificationEvents collection contains at least
|
||||
* one notification matching a combination of type, message, title, and options.
|
||||
* It allows for comprehensive notification assertions by checking multiple properties.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Composite: Part of PHPUnit's constraint composition system
|
||||
* - Strategy: Implements a specific assertion strategy
|
||||
* - Specification: Represents a specification that notifications can satisfy
|
||||
*/
|
||||
final class Notification extends Constraint
|
||||
{
|
||||
/**
|
||||
* Creates a new Notification constraint.
|
||||
*
|
||||
* @param string $expectedType Expected notification type (e.g., 'success', 'error')
|
||||
* @param string|null $expectedMessage Expected message content (null to ignore)
|
||||
* @param array<string, mixed> $expectedOptions Expected options as an associative array
|
||||
* @param string|null $expectedTitle Expected title content (null to ignore)
|
||||
* @param array<string, mixed> $expectedOptions
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly string $expectedType,
|
||||
@@ -38,11 +21,6 @@ final class Notification extends Constraint
|
||||
) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the constraint.
|
||||
*
|
||||
* @return string The constraint description
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
$details = [
|
||||
@@ -64,14 +42,6 @@ final class Notification extends Constraint
|
||||
return 'contains a notification with '.implode(', ', $details);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates if the given NotificationEvents object contains at least one notification
|
||||
* matching all the expected properties.
|
||||
*
|
||||
* @param NotificationEvents|mixed $other An instance of NotificationEvents to evaluate
|
||||
*
|
||||
* @return bool True if a matching notification is found
|
||||
*/
|
||||
protected function matches(mixed $other): bool
|
||||
{
|
||||
if (!$other instanceof NotificationEvents) {
|
||||
@@ -87,19 +57,6 @@ final class Notification extends Constraint
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a specific notification matches all expected properties.
|
||||
*
|
||||
* A notification matches if:
|
||||
* - Its type equals the expected type AND
|
||||
* - Its message equals the expected message (if provided) AND
|
||||
* - Its title equals the expected title (if provided) AND
|
||||
* - Its options contain all expected option key-value pairs (if provided)
|
||||
*
|
||||
* @param NotificationInterface $notification The notification to check
|
||||
*
|
||||
* @return bool True if the notification matches all criteria
|
||||
*/
|
||||
private function isNotificationMatching(NotificationInterface $notification): bool
|
||||
{
|
||||
return $notification->getType() === $this->expectedType
|
||||
@@ -109,14 +66,7 @@ final class Notification extends Constraint
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a detailed failure description when the constraint fails.
|
||||
*
|
||||
* This method lists all actual notifications with their properties,
|
||||
* making test failures easier to diagnose.
|
||||
*
|
||||
* @param NotificationEvents $other The evaluated NotificationEvents instance
|
||||
*
|
||||
* @return string A detailed failure description
|
||||
* @param NotificationEvents $other
|
||||
*/
|
||||
protected function failureDescription(mixed $other): string
|
||||
{
|
||||
|
||||
@@ -7,45 +7,17 @@ namespace Flasher\Prime\Test\Constraint;
|
||||
use Flasher\Prime\EventDispatcher\Event\NotificationEvents;
|
||||
use PHPUnit\Framework\Constraint\Constraint;
|
||||
|
||||
/**
|
||||
* NotificationCount - PHPUnit constraint for asserting notification count.
|
||||
*
|
||||
* This constraint verifies that a NotificationEvents collection contains
|
||||
* exactly the expected number of notifications. It's used by the FlasherAssert
|
||||
* class for count-related assertions.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Composite: Part of PHPUnit's constraint composition system
|
||||
* - Strategy: Implements a specific assertion strategy
|
||||
*/
|
||||
final class NotificationCount extends Constraint
|
||||
{
|
||||
/**
|
||||
* Creates a new NotificationCount constraint.
|
||||
*
|
||||
* @param int $expectedValue The expected number of notifications
|
||||
*/
|
||||
public function __construct(private readonly int $expectedValue)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the constraint.
|
||||
*
|
||||
* @return string The constraint description
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
return \sprintf('matches the expected notification count of %d.', $this->expectedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates if the given NotificationEvents object matches the expected notification count.
|
||||
*
|
||||
* @param NotificationEvents|mixed $other An instance of NotificationEvents to evaluate
|
||||
*
|
||||
* @return bool True if the actual count matches the expected count
|
||||
*/
|
||||
protected function matches(mixed $other): bool
|
||||
{
|
||||
if (!$other instanceof NotificationEvents) {
|
||||
@@ -56,11 +28,7 @@ final class NotificationCount extends Constraint
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a detailed failure description when the constraint fails.
|
||||
*
|
||||
* @param NotificationEvents $other The evaluated NotificationEvents instance
|
||||
*
|
||||
* @return string A detailed failure description
|
||||
* @param NotificationEvents $other
|
||||
*/
|
||||
protected function failureDescription(mixed $other): string
|
||||
{
|
||||
@@ -69,13 +37,6 @@ final class NotificationCount extends Constraint
|
||||
return \sprintf('Expected the notification count to be %d, but got %d instead.', $this->expectedValue, $actualCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Counts the notifications in the given NotificationEvents object.
|
||||
*
|
||||
* @param NotificationEvents $events The NotificationEvents instance
|
||||
*
|
||||
* @return int The number of notifications
|
||||
*/
|
||||
private function countNotifications(NotificationEvents $events): int
|
||||
{
|
||||
return \count($events->getEnvelopes());
|
||||
|
||||
@@ -8,47 +8,17 @@ use Flasher\Prime\EventDispatcher\Event\NotificationEvents;
|
||||
use Flasher\Prime\Notification\NotificationInterface;
|
||||
use PHPUnit\Framework\Constraint\Constraint;
|
||||
|
||||
/**
|
||||
* NotificationMessage - PHPUnit constraint for asserting notification message presence.
|
||||
*
|
||||
* This constraint verifies that a NotificationEvents collection contains at least
|
||||
* one notification with a message containing the expected text. It's used by the
|
||||
* FlasherAssert class for message-related assertions.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Composite: Part of PHPUnit's constraint composition system
|
||||
* - Strategy: Implements a specific assertion strategy
|
||||
* - String Matcher: Performs string matching on notification messages
|
||||
*/
|
||||
final class NotificationMessage extends Constraint
|
||||
{
|
||||
/**
|
||||
* Creates a new NotificationMessage constraint.
|
||||
*
|
||||
* @param string $expectedMessage The expected message text (or substring)
|
||||
*/
|
||||
public function __construct(private readonly string $expectedMessage)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the constraint.
|
||||
*
|
||||
* @return string The constraint description
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
return \sprintf('contains a notification with message "%s"', $this->expectedMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates if the given NotificationEvents object contains at least one notification
|
||||
* with a message containing the expected text.
|
||||
*
|
||||
* @param NotificationEvents|mixed $other An instance of NotificationEvents to evaluate
|
||||
*
|
||||
* @return bool True if a notification with the expected message text is found
|
||||
*/
|
||||
protected function matches(mixed $other): bool
|
||||
{
|
||||
if (!$other instanceof NotificationEvents) {
|
||||
@@ -65,14 +35,7 @@ final class NotificationMessage extends Constraint
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a detailed failure description when the constraint fails.
|
||||
*
|
||||
* This method lists all actual notification messages found, making
|
||||
* test failures easier to diagnose.
|
||||
*
|
||||
* @param NotificationEvents $other The evaluated NotificationEvents instance
|
||||
*
|
||||
* @return string A detailed failure description
|
||||
* @param NotificationEvents $other
|
||||
*/
|
||||
protected function failureDescription(mixed $other): string
|
||||
{
|
||||
|
||||
@@ -8,35 +8,12 @@ use Flasher\Prime\EventDispatcher\Event\NotificationEvents;
|
||||
use Flasher\Prime\Notification\NotificationInterface;
|
||||
use PHPUnit\Framework\Constraint\Constraint;
|
||||
|
||||
/**
|
||||
* NotificationOption - PHPUnit constraint for asserting a specific notification option.
|
||||
*
|
||||
* This constraint verifies that a NotificationEvents collection contains at least
|
||||
* one notification with a specific option key and optionally a specific value. It's
|
||||
* used by the FlasherAssert class for option-specific assertions.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Composite: Part of PHPUnit's constraint composition system
|
||||
* - Strategy: Implements a specific assertion strategy
|
||||
* - Key-Value Matcher: Performs key-value matching on notification options
|
||||
*/
|
||||
final class NotificationOption extends Constraint
|
||||
{
|
||||
/**
|
||||
* Creates a new NotificationOption constraint.
|
||||
*
|
||||
* @param string $expectedKey The expected option key
|
||||
* @param mixed $expectedValue The expected option value (null to check only key existence)
|
||||
*/
|
||||
public function __construct(private readonly string $expectedKey, private readonly mixed $expectedValue = null)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the constraint.
|
||||
*
|
||||
* @return string The constraint description
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
$description = \sprintf('contains a notification with an option "%s"', $this->expectedKey);
|
||||
@@ -48,14 +25,6 @@ final class NotificationOption extends Constraint
|
||||
return $description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates if the given NotificationEvents object contains at least one notification
|
||||
* with the expected option key and value.
|
||||
*
|
||||
* @param NotificationEvents|mixed $other An instance of NotificationEvents to evaluate
|
||||
*
|
||||
* @return bool True if a notification with the expected option is found
|
||||
*/
|
||||
protected function matches(mixed $other): bool
|
||||
{
|
||||
if (!$other instanceof NotificationEvents) {
|
||||
@@ -71,13 +40,6 @@ final class NotificationOption extends Constraint
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a specific notification has the expected option key and value.
|
||||
*
|
||||
* @param NotificationInterface $notification The notification to check
|
||||
*
|
||||
* @return bool True if the notification has the expected option
|
||||
*/
|
||||
private function isOptionMatching(NotificationInterface $notification): bool
|
||||
{
|
||||
$options = $notification->getOptions();
|
||||
@@ -85,21 +47,10 @@ final class NotificationOption extends Constraint
|
||||
return isset($options[$this->expectedKey]) && $options[$this->expectedKey] === $this->expectedValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a detailed failure description when the constraint fails.
|
||||
*
|
||||
* This method lists all actual notification options found, making
|
||||
* test failures easier to diagnose.
|
||||
*
|
||||
* @param NotificationEvents $other The evaluated NotificationEvents instance
|
||||
*
|
||||
* @return string A detailed failure description
|
||||
*/
|
||||
protected function failureDescription(mixed $other): string
|
||||
{
|
||||
$actualOptions = [];
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
if ($other instanceof NotificationEvents) {
|
||||
foreach ($other->getEnvelopes() as $notification) {
|
||||
$actualOptions[] = json_encode($notification->getOptions());
|
||||
|
||||
@@ -7,47 +7,20 @@ namespace Flasher\Prime\Test\Constraint;
|
||||
use Flasher\Prime\EventDispatcher\Event\NotificationEvents;
|
||||
use PHPUnit\Framework\Constraint\Constraint;
|
||||
|
||||
/**
|
||||
* NotificationOptions - PHPUnit constraint for asserting notification options.
|
||||
*
|
||||
* This constraint verifies that a NotificationEvents collection contains at least
|
||||
* one notification with options matching all the expected key-value pairs. It's used
|
||||
* by the FlasherAssert class for options-related assertions.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Composite: Part of PHPUnit's constraint composition system
|
||||
* - Strategy: Implements a specific assertion strategy
|
||||
* - Key-Value Matcher: Performs associative array matching on notification options
|
||||
*/
|
||||
final class NotificationOptions extends Constraint
|
||||
{
|
||||
/**
|
||||
* Creates a new NotificationOptions constraint.
|
||||
*
|
||||
* @param array<string, mixed> $expectedOptions The expected option key-value pairs
|
||||
* @param array<string, mixed> $expectedOptions
|
||||
*/
|
||||
public function __construct(private readonly array $expectedOptions)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the constraint.
|
||||
*
|
||||
* @return string The constraint description
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
return 'contains a notification with options matching '.json_encode($this->expectedOptions, \JSON_PRETTY_PRINT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates if the given NotificationEvents object contains at least one notification
|
||||
* with options containing all the expected key-value pairs.
|
||||
*
|
||||
* @param NotificationEvents|mixed $other An instance of NotificationEvents to evaluate
|
||||
*
|
||||
* @return bool True if a notification with matching options is found
|
||||
*/
|
||||
protected function matches(mixed $other): bool
|
||||
{
|
||||
if (!$other instanceof NotificationEvents) {
|
||||
@@ -63,21 +36,10 @@ final class NotificationOptions extends Constraint
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a detailed failure description when the constraint fails.
|
||||
*
|
||||
* This method lists all actual notification options found, making
|
||||
* test failures easier to diagnose.
|
||||
*
|
||||
* @param NotificationEvents $other The evaluated NotificationEvents instance
|
||||
*
|
||||
* @return string A detailed failure description
|
||||
*/
|
||||
protected function failureDescription(mixed $other): string
|
||||
{
|
||||
$actualOptions = [];
|
||||
|
||||
// @phpstan-ignore-next-line
|
||||
if ($other instanceof NotificationEvents) {
|
||||
foreach ($other->getEnvelopes() as $notification) {
|
||||
$actualOptions[] = json_encode($notification->getOptions());
|
||||
|
||||
@@ -8,47 +8,17 @@ use Flasher\Prime\EventDispatcher\Event\NotificationEvents;
|
||||
use Flasher\Prime\Notification\NotificationInterface;
|
||||
use PHPUnit\Framework\Constraint\Constraint;
|
||||
|
||||
/**
|
||||
* NotificationTitle - PHPUnit constraint for asserting notification title presence.
|
||||
*
|
||||
* This constraint verifies that a NotificationEvents collection contains at least
|
||||
* one notification with a title containing the expected text. It's used by the
|
||||
* FlasherAssert class for title-related assertions.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Composite: Part of PHPUnit's constraint composition system
|
||||
* - Strategy: Implements a specific assertion strategy
|
||||
* - String Matcher: Performs string matching on notification titles
|
||||
*/
|
||||
final class NotificationTitle extends Constraint
|
||||
{
|
||||
/**
|
||||
* Creates a new NotificationTitle constraint.
|
||||
*
|
||||
* @param string $expectedTitle The expected title text (or substring)
|
||||
*/
|
||||
public function __construct(private readonly string $expectedTitle)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the constraint.
|
||||
*
|
||||
* @return string The constraint description
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
return \sprintf('contains a notification with a title containing "%s"', $this->expectedTitle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates if the given NotificationEvents object contains at least one notification
|
||||
* with a title containing the expected text.
|
||||
*
|
||||
* @param NotificationEvents|mixed $other An instance of NotificationEvents to evaluate
|
||||
*
|
||||
* @return bool True if a notification with the expected title text is found
|
||||
*/
|
||||
protected function matches(mixed $other): bool
|
||||
{
|
||||
if (!$other instanceof NotificationEvents) {
|
||||
@@ -64,19 +34,8 @@ final class NotificationTitle extends Constraint
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a detailed failure description when the constraint fails.
|
||||
*
|
||||
* This method lists all actual notification titles found, making
|
||||
* test failures easier to diagnose.
|
||||
*
|
||||
* @param NotificationEvents $other The evaluated NotificationEvents instance
|
||||
*
|
||||
* @return string A detailed failure description
|
||||
*/
|
||||
protected function failureDescription(mixed $other): string
|
||||
{
|
||||
// @phpstan-ignore-next-line
|
||||
if (!$other instanceof NotificationEvents) {
|
||||
return 'Expected an instance of NotificationEvents but received a different type.';
|
||||
}
|
||||
|
||||
@@ -8,46 +8,17 @@ use Flasher\Prime\EventDispatcher\Event\NotificationEvents;
|
||||
use Flasher\Prime\Notification\NotificationInterface;
|
||||
use PHPUnit\Framework\Constraint\Constraint;
|
||||
|
||||
/**
|
||||
* NotificationType - PHPUnit constraint for asserting notification type presence.
|
||||
*
|
||||
* This constraint verifies that a NotificationEvents collection contains at least
|
||||
* one notification of the specified type. It's used by the FlasherAssert class
|
||||
* for type-related assertions.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Composite: Part of PHPUnit's constraint composition system
|
||||
* - Strategy: Implements a specific assertion strategy
|
||||
*/
|
||||
final class NotificationType extends Constraint
|
||||
{
|
||||
/**
|
||||
* Creates a new NotificationType constraint.
|
||||
*
|
||||
* @param string $expectedType The expected notification type (e.g., 'success', 'error')
|
||||
*/
|
||||
public function __construct(private readonly string $expectedType)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the constraint.
|
||||
*
|
||||
* @return string The constraint description
|
||||
*/
|
||||
public function toString(): string
|
||||
{
|
||||
return \sprintf('contains a notification of type "%s".', $this->expectedType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates if the given NotificationEvents object contains at least one notification
|
||||
* of the expected type.
|
||||
*
|
||||
* @param NotificationEvents|mixed $other An instance of NotificationEvents to evaluate
|
||||
*
|
||||
* @return bool True if a notification of the expected type is found
|
||||
*/
|
||||
protected function matches(mixed $other): bool
|
||||
{
|
||||
if (!$other instanceof NotificationEvents) {
|
||||
@@ -64,14 +35,7 @@ final class NotificationType extends Constraint
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a detailed failure description when the constraint fails.
|
||||
*
|
||||
* This method provides context about what types were found instead of
|
||||
* the expected type, making test failures easier to diagnose.
|
||||
*
|
||||
* @param NotificationEvents $other The evaluated NotificationEvents instance
|
||||
*
|
||||
* @return string A detailed failure description
|
||||
* @param NotificationEvents $other
|
||||
*/
|
||||
protected function failureDescription(mixed $other): string
|
||||
{
|
||||
|
||||
@@ -4,34 +4,16 @@ declare(strict_types=1);
|
||||
|
||||
namespace Flasher\Prime\Translation;
|
||||
|
||||
/**
|
||||
* EchoTranslator - Minimal translator implementation that returns message IDs unchanged.
|
||||
*
|
||||
* This implementation simply returns the message identifiers as-is, without
|
||||
* performing any actual translation. It serves as a fallback translator when
|
||||
* no real translation service is available.
|
||||
*
|
||||
* Design patterns:
|
||||
* - Null Object: Provides a do-nothing implementation that maintains API compatibility
|
||||
* - Fallback: Serves as a default implementation when no specific translator is provided
|
||||
*/
|
||||
final readonly class EchoTranslator implements TranslatorInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* This implementation simply returns the message identifier unchanged.
|
||||
* @param array<string, mixed> $parameters
|
||||
*/
|
||||
public function translate(string $id, array $parameters = [], ?string $locale = null): string
|
||||
{
|
||||
return $id;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*
|
||||
* This implementation always returns 'en' as the default locale.
|
||||
*/
|
||||
public function getLocale(): string
|
||||
{
|
||||
return 'en';
|
||||
|
||||
Reference in New Issue
Block a user