first commit

This commit is contained in:
Sampanna Rimal
2024-08-27 17:48:06 +05:45
commit 53c0140f58
10839 changed files with 1125847 additions and 0 deletions

View File

@ -0,0 +1,5 @@
github: yoeunes
patreon: yoeunes
ko_fi: yoeunes
open_collective: php-flasher
custom: https://www.paypal.com/paypalme/yoeunes

View File

@ -0,0 +1,22 @@
name: Auto Closer PR
on:
pull_request_target:
types: [opened]
jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: superbrothers/close-pull-request@v3
with:
comment: |
Hi, thank you for your contribution.
Unfortunately, this repository is read-only. It's a split from our main monorepo repository.
We'd like to kindly ask you to move the contribution there - https://github.com/php-flasher/php-flasher.
We'll check it, review it and give you feed back right way.
Thank you.

View File

@ -0,0 +1,135 @@
<?php
namespace PHPSTORM_META;
override(new \Illuminate\Contracts\Container\Container, map([
'' => '@',
'Flasher\Prime\FlasherInterface' => \Flasher\Prime\Flasher::class,
'flasher' => \Flasher\Prime\Flasher::class,
'flasher.noty' => \Flasher\Noty\Prime\NotyFactory::class,
'flasher.notyf' => \Flasher\Notyf\Prime\NotyfFactory::class,
'flasher.pnotify' => \Flasher\Pnotify\Prime\PnotifyFactory::class,
'flasher.sweetalert' => \Flasher\SweetAlert\Prime\SweetAlertFactory::class,
'flasher.template' => \Flasher\Prime\Factory\FlasherFactory::class,
'flasher.toastr' => \Flasher\Toastr\Prime\ToastrFactory::class,
]));
override(\Illuminate\Container\Container::makeWith(0), map([
'' => '@',
'Flasher\Prime\FlasherInterface' => \Flasher\Prime\Flasher::class,
'flasher' => \Flasher\Prime\Flasher::class,
'flasher.noty' => \Flasher\Noty\Prime\NotyFactory::class,
'flasher.notyf' => \Flasher\Notyf\Prime\NotyfFactory::class,
'flasher.pnotify' => \Flasher\Pnotify\Prime\PnotifyFactory::class,
'flasher.sweetalert' => \Flasher\SweetAlert\Prime\SweetAlertFactory::class,
'flasher.template' => \Flasher\Prime\Factory\FlasherFactory::class,
'flasher.toastr' => \Flasher\Toastr\Prime\ToastrFactory::class,
]));
override(\Illuminate\Contracts\Container\Container::get(0), map([
'' => '@',
'Flasher\Prime\FlasherInterface' => \Flasher\Prime\Flasher::class,
'flasher' => \Flasher\Prime\Flasher::class,
'flasher.noty' => \Flasher\Noty\Prime\NotyFactory::class,
'flasher.notyf' => \Flasher\Notyf\Prime\NotyfFactory::class,
'flasher.pnotify' => \Flasher\Pnotify\Prime\PnotifyFactory::class,
'flasher.sweetalert' => \Flasher\SweetAlert\Prime\SweetAlertFactory::class,
'flasher.template' => \Flasher\Prime\Factory\FlasherFactory::class,
'flasher.toastr' => \Flasher\Toastr\Prime\ToastrFactory::class,
]));
override(\Illuminate\Contracts\Container\Container::make(0), map([
'' => '@',
'Flasher\Prime\FlasherInterface' => \Flasher\Prime\Flasher::class,
'flasher' => \Flasher\Prime\Flasher::class,
'flasher.noty' => \Flasher\Noty\Prime\NotyFactory::class,
'flasher.notyf' => \Flasher\Notyf\Prime\NotyfFactory::class,
'flasher.pnotify' => \Flasher\Pnotify\Prime\PnotifyFactory::class,
'flasher.sweetalert' => \Flasher\SweetAlert\Prime\SweetAlertFactory::class,
'flasher.template' => \Flasher\Prime\Factory\FlasherFactory::class,
'flasher.toastr' => \Flasher\Toastr\Prime\ToastrFactory::class,
]));
override(\Illuminate\Contracts\Container\Container::makeWith(0), map([
'' => '@',
'Flasher\Prime\FlasherInterface' => \Flasher\Prime\Flasher::class,
'flasher' => \Flasher\Prime\Flasher::class,
'flasher.noty' => \Flasher\Noty\Prime\NotyFactory::class,
'flasher.notyf' => \Flasher\Notyf\Prime\NotyfFactory::class,
'flasher.pnotify' => \Flasher\Pnotify\Prime\PnotifyFactory::class,
'flasher.sweetalert' => \Flasher\SweetAlert\Prime\SweetAlertFactory::class,
'flasher.template' => \Flasher\Prime\Factory\FlasherFactory::class,
'flasher.toastr' => \Flasher\Toastr\Prime\ToastrFactory::class,
]));
override(\App::get(0), map([
'' => '@',
'Flasher\Prime\FlasherInterface' => \Flasher\Prime\Flasher::class,
'flasher' => \Flasher\Prime\Flasher::class,
'flasher.noty' => \Flasher\Noty\Prime\NotyFactory::class,
'flasher.notyf' => \Flasher\Notyf\Prime\NotyfFactory::class,
'flasher.pnotify' => \Flasher\Pnotify\Prime\PnotifyFactory::class,
'flasher.sweetalert' => \Flasher\SweetAlert\Prime\SweetAlertFactory::class,
'flasher.template' => \Flasher\Prime\Factory\FlasherFactory::class,
'flasher.toastr' => \Flasher\Toastr\Prime\ToastrFactory::class,
]));
override(\App::make(0), map([
'' => '@',
'Flasher\Prime\FlasherInterface' => \Flasher\Prime\Flasher::class,
'flasher' => \Flasher\Prime\Flasher::class,
'flasher.noty' => \Flasher\Noty\Prime\NotyFactory::class,
'flasher.notyf' => \Flasher\Notyf\Prime\NotyfFactory::class,
'flasher.pnotify' => \Flasher\Pnotify\Prime\PnotifyFactory::class,
'flasher.sweetalert' => \Flasher\SweetAlert\Prime\SweetAlertFactory::class,
'flasher.template' => \Flasher\Prime\Factory\FlasherFactory::class,
'flasher.toastr' => \Flasher\Toastr\Prime\ToastrFactory::class,
]));
override(\App::makeWith(0), map([
'' => '@',
'Flasher\Prime\FlasherInterface' => \Flasher\Prime\Flasher::class,
'flasher' => \Flasher\Prime\Flasher::class,
'flasher.noty' => \Flasher\Noty\Prime\NotyFactory::class,
'flasher.notyf' => \Flasher\Notyf\Prime\NotyfFactory::class,
'flasher.pnotify' => \Flasher\Pnotify\Prime\PnotifyFactory::class,
'flasher.sweetalert' => \Flasher\SweetAlert\Prime\SweetAlertFactory::class,
'flasher.template' => \Flasher\Prime\Factory\FlasherFactory::class,
'flasher.toastr' => \Flasher\Toastr\Prime\ToastrFactory::class,
]));
override(\app(0), map([
'' => '@',
'Flasher\Prime\FlasherInterface' => \Flasher\Prime\Flasher::class,
'flasher' => \Flasher\Prime\Flasher::class,
'flasher.noty' => \Flasher\Noty\Prime\NotyFactory::class,
'flasher.notyf' => \Flasher\Notyf\Prime\NotyfFactory::class,
'flasher.pnotify' => \Flasher\Pnotify\Prime\PnotifyFactory::class,
'flasher.sweetalert' => \Flasher\SweetAlert\Prime\SweetAlertFactory::class,
'flasher.template' => \Flasher\Prime\Factory\FlasherFactory::class,
'flasher.toastr' => \Flasher\Toastr\Prime\ToastrFactory::class,
]));
override(\resolve(0), map([
'' => '@',
'Flasher\Prime\FlasherInterface' => \Flasher\Prime\Flasher::class,
'flasher' => \Flasher\Prime\Flasher::class,
'flasher.noty' => \Flasher\Noty\Prime\NotyFactory::class,
'flasher.notyf' => \Flasher\Notyf\Prime\NotyfFactory::class,
'flasher.pnotify' => \Flasher\Pnotify\Prime\PnotifyFactory::class,
'flasher.sweetalert' => \Flasher\SweetAlert\Prime\SweetAlertFactory::class,
'flasher.template' => \Flasher\Prime\Factory\FlasherFactory::class,
'flasher.toastr' => \Flasher\Toastr\Prime\ToastrFactory::class,
]));
override(\Psr\Container\ContainerInterface::get(0), map([
'' => '@',
'Flasher\Prime\FlasherInterface' => \Flasher\Prime\Flasher::class,
'flasher' => \Flasher\Prime\Flasher::class,
'flasher.noty' => \Flasher\Noty\Prime\NotyFactory::class,
'flasher.notyf' => \Flasher\Notyf\Prime\NotyfFactory::class,
'flasher.pnotify' => \Flasher\Pnotify\Prime\PnotifyFactory::class,
'flasher.sweetalert' => \Flasher\SweetAlert\Prime\SweetAlertFactory::class,
'flasher.template' => \Flasher\Prime\Factory\FlasherFactory::class,
'flasher.toastr' => \Flasher\Toastr\Prime\ToastrFactory::class,
]));

View File

@ -0,0 +1,28 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Bridge\Command;
use Flasher\Laravel\Support\Laravel;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
$class = Laravel::isVersion('11.0', '>=')
? 'Flasher\Laravel\Bridge\Typed\Command\FlasherCommand'
: 'Flasher\Laravel\Bridge\Legacy\Command\FlasherCommand';
class_alias($class, 'Flasher\Laravel\Bridge\Command\FlasherCommand');
if (false) { /** @phpstan-ignore-line */
abstract class FlasherCommand
{
/**
* @return int
*/
abstract protected function flasherExecute(InputInterface $input, OutputInterface $output);
}
}

View File

@ -0,0 +1,25 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Bridge\Legacy\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
abstract class FlasherCommand extends Command
{
protected function execute(InputInterface $input, OutputInterface $output)
{
return $this->flasherExecute($input, $output);
}
/**
* @return int
*/
abstract protected function flasherExecute(InputInterface $input, OutputInterface $output);
}

View File

@ -0,0 +1,25 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Bridge\Typed\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
abstract class FlasherCommand extends Command
{
protected function execute(InputInterface $input, OutputInterface $output): int
{
return $this->flasherExecute($input, $output);
}
/**
* @return int
*/
abstract protected function flasherExecute(InputInterface $input, OutputInterface $output);
}

View File

@ -0,0 +1,128 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Command;
use Flasher\Laravel\Support\ServiceProvider as FlasherServiceProvider;
use Flasher\Prime\Plugin\PluginInterface;
use Flasher\Laravel\Bridge\Command\FlasherCommand;
use Illuminate\Filesystem\Filesystem;
use Illuminate\Support\Facades\App;
use Illuminate\Support\ServiceProvider;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
class InstallCommand extends FlasherCommand
{
/**
* @return void
*/
protected function configure()
{
$this
->setName('flasher:install')
->setDescription('Installs all <fg=blue;options=bold>PHPFlasher</> resources to the <comment>public</comment> and <comment>config</comment> directories.')
->setHelp('The command copies <fg=blue;options=bold>PHPFlasher</> assets to <comment>public/vendor/flasher/</comment> directory and config files to the <comment>config/</comment> directory without overwriting any existing config files.');
}
/**
* @return int
*/
protected function flasherExecute(InputInterface $input, OutputInterface $output)
{
$output->writeln('');
$output->writeln('<fg=blue;options=bold>
██████╗ ██╗ ██╗██████╗ ███████╗██╗ █████╗ ███████╗██╗ ██╗███████╗██████╗
██╔══██╗██║ ██║██╔══██╗██╔════╝██║ ██╔══██╗██╔════╝██║ ██║██╔════╝██╔══██╗
██████╔╝███████║██████╔╝█████╗ ██║ ███████║███████╗███████║█████╗ ██████╔╝
██╔═══╝ ██╔══██║██╔═══╝ ██╔══╝ ██║ ██╔══██║╚════██║██╔══██║██╔══╝ ██╔══██╗
██║ ██║ ██║██║ ██║ ███████╗██║ ██║███████║██║ ██║███████╗██║ ██║
╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝
</>');
$output->writeln('');
$output->writeln('');
$output->writeln('<bg=blue;options=bold> INFO </> Copying <fg=blue;options=bold>PHPFlasher</> resources...');
$output->writeln('');
$publicDir = App::publicPath().'/vendor/flasher/';
$exitCode = 0;
foreach (ServiceProvider::publishableProviders() as $provider) {
if (!is_a($provider, 'Flasher\Laravel\Support\ServiceProvider', true)) {
continue;
}
/** @var FlasherServiceProvider $provider */
$provider = App::getProvider($provider);
$plugin = $provider->createPlugin();
$configFile = $provider->getConfigurationFile();
try {
$this->publishAssets($plugin, $publicDir);
$this->publishConfig($plugin, $configFile);
$status = sprintf('<fg=green;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'OK' : "\xE2\x9C\x94" /* HEAVY CHECK MARK (U+2714) */);
$output->writeln(sprintf(' %s <fg=blue;options=bold>%s</>', $status, $plugin->getAlias()));
} catch (\Exception $e) {
$exitCode = 1;
$status = sprintf('<fg=red;options=bold>%s</>', '\\' === \DIRECTORY_SEPARATOR ? 'ERROR' : "\xE2\x9C\x98" /* HEAVY BALLOT X (U+2718) */);
$output->writeln(sprintf(' %s <fg=blue;options=bold>%s</> <error>%s</error>', $status, $plugin->getAlias(), $e->getMessage()));
}
}
$output->writeln('');
if (0 === $exitCode) {
$output->writeln('<bg=green;options=bold> SUCCESS </> <fg=blue;options=bold>PHPFlasher</> resources have been successfully installed.');
} else {
$output->writeln('<bg=red;options=bold> ERROR </> An error occurred during the installation of <fg=blue;options=bold>PHPFlasher</> resources.');
}
$output->writeln('');
return $exitCode;
}
/**
* @param string $publicDir
*
* @return void
*/
private function publishAssets(PluginInterface $plugin, $publicDir)
{
$originDir = $plugin->getAssetsDir();
if (!is_dir($originDir)) {
return;
}
$filesystem = new Filesystem();
$filesystem->ensureDirectoryExists($originDir, 0777);
$filesystem->copyDirectory($originDir, $publicDir);
}
/**
* @param string $configFile
*
* @return void
*/
private function publishConfig(PluginInterface $plugin, $configFile)
{
if (!file_exists($configFile)) {
return;
}
$target = App::configPath($plugin->getName().'.php');
if (file_exists($target)) {
return;
}
$filesystem = new Filesystem();
$filesystem->copy($configFile, $target);
}
}

View File

@ -0,0 +1,23 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Component;
use Illuminate\View\Component;
class FlasherComponent extends Component
{
/**
* {@inheritdoc}
*/
public function render()
{
@trigger_error('Since php-flasher/flasher-laravel v1.6.0: Using flasher blade component is deprecated and will be removed in v2.0. PHPFlasher will render notification automatically', \E_USER_DEPRECATED);
return '';
}
}

View File

@ -0,0 +1,21 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Container;
use Flasher\Prime\Container\ContainerInterface;
final class LaravelContainer implements ContainerInterface
{
/**
* {@inheritDoc}
*/
public function get($id)
{
return app()->make($id);
}
}

View File

@ -0,0 +1,47 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Facade;
use Flasher\Prime\Notification\Envelope;
use Flasher\Prime\Notification\NotificationBuilder;
use Flasher\Prime\Notification\NotificationInterface;
use Flasher\Prime\Stamp\StampInterface;
use Illuminate\Support\Facades\Facade;
/**
* @method static NotificationBuilder addSuccess(string $message, array $options = array())
* @method static NotificationBuilder addError(string $message, array $options = array())
* @method static NotificationBuilder addWarning(string $message, array $options = array())
* @method static NotificationBuilder addInfo(string $message, array $options = array())
* @method static NotificationBuilder addFlash(NotificationInterface|string $type, string $message = null, array $options = array())
* @method static NotificationBuilder flash(StampInterface[] $stamps = array())
* @method static NotificationBuilder type(string $type, string $message = null, array $options = array())
* @method static NotificationBuilder message(string $message)
* @method static NotificationBuilder options(array $options, bool $merge = true)
* @method static NotificationBuilder option(string $name, $value)
* @method static NotificationBuilder success(string $message = null, array $options = array())
* @method static NotificationBuilder error(string $message = null, array $options = array())
* @method static NotificationBuilder info(string $message = null, array $options = array())
* @method static NotificationBuilder warning(string $message = null, array $options = array())
* @method static NotificationBuilder priority(int $priority)
* @method static NotificationBuilder hops(int $amount)
* @method static NotificationBuilder keep()
* @method static NotificationBuilder delay(int $delay)
* @method static NotificationBuilder now()
* @method static NotificationBuilder with(StampInterface[] $stamps = array())
* @method static NotificationBuilder withStamp(StampInterface $stamp)
* @method static NotificationBuilder handler(string $handler)
* @method static Envelope getEnvelope()
*/
class Flasher extends Facade
{
protected static function getFacadeAccessor()
{
return 'flasher';
}
}

View File

@ -0,0 +1,408 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel;
use Flasher\Laravel\Container\LaravelContainer;
use Flasher\Laravel\Middleware\FlasherMiddleware;
use Flasher\Laravel\Middleware\HttpKernelFlasherMiddleware;
use Flasher\Laravel\Middleware\HttpKernelSessionMiddleware;
use Flasher\Laravel\Middleware\SessionMiddleware;
use Flasher\Laravel\Storage\SessionBag;
use Flasher\Laravel\Support\Laravel;
use Flasher\Laravel\Support\ServiceProvider;
use Flasher\Laravel\Template\BladeTemplateEngine;
use Flasher\Laravel\Translation\Translator;
use Flasher\Prime\Config\Config;
use Flasher\Prime\Config\ConfigInterface;
use Flasher\Prime\Container\FlasherContainer;
use Flasher\Prime\EventDispatcher\EventDispatcher;
use Flasher\Prime\EventDispatcher\EventListener\PresetListener;
use Flasher\Prime\EventDispatcher\EventListener\TranslationListener;
use Flasher\Prime\Flasher;
use Flasher\Prime\FlasherInterface;
use Flasher\Prime\Http\RequestExtension;
use Flasher\Prime\Http\ResponseExtension;
use Flasher\Prime\Notification\Envelope;
use Flasher\Prime\Plugin\FlasherPlugin;
use Flasher\Prime\Response\Resource\ResourceManager;
use Flasher\Prime\Response\ResponseManager;
use Flasher\Prime\Storage\StorageBag;
use Flasher\Prime\Storage\StorageManager;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Foundation\Application;
use Illuminate\Foundation\Http\Kernel;
use Illuminate\Routing\Router;
use Illuminate\Support\Facades\Blade;
use Livewire\Component;
use Livewire\LivewireManager;
use Livewire\Mechanisms\HandleComponents\ComponentContext;
use Livewire\Response;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
final class FlasherServiceProvider extends ServiceProvider
{
/**
* {@inheritdoc}
*/
public function afterBoot()
{
FlasherContainer::init(new LaravelContainer());
$this->registerCommands();
$this->registerBladeDirective();
$this->registerBladeComponent();
$this->registerLivewire();
$this->registerTranslations();
$this->registerMiddlewares();
}
/**
* @{@inheritdoc}
*/
public function createPlugin()
{
return new FlasherPlugin();
}
/**
* {@inheritdoc}
*/
protected function afterRegister()
{
$this->registerConfig();
$this->registerFlasher();
$this->registerResourceManager();
$this->registerResponseManager();
$this->registerStorageManager();
$this->registerEventDispatcher();
}
/**
* @return void
*/
private function registerCommands()
{
if (!in_array(\PHP_SAPI, array('cli', 'phpdbg'))) {
return;
}
$this->commands(array(
'Flasher\Laravel\Command\InstallCommand', // flasher:install
));
}
/**
* @return void
*/
private function registerConfig()
{
$this->app->singleton('flasher.config', function (Application $app) {
/** @var Repository $config */
$config = $app->make('config');
return new Config($config->get('flasher', array())); // @phpstan-ignore-line
});
}
/**
* @return void
*/
private function registerFlasher()
{
$this->app->singleton('flasher', function (Application $app) {
$config = $app->make('flasher.config');
$responseManager = $app->make('flasher.response_manager');
$storageManager = $app->make('flasher.storage_manager');
return new Flasher($config->get('default'), $responseManager, $storageManager); // @phpstan-ignore-line
});
$this->app->alias('flasher', 'Flasher\Prime\Flasher');
$this->app->bind('Flasher\Prime\FlasherInterface', 'flasher');
}
/**
* @return void
*/
private function registerResourceManager()
{
$this->app->singleton('flasher.resource_manager', function (Application $app) {
$config = $app->make('flasher.config');
$view = $app->make('view');
return new ResourceManager($config, new BladeTemplateEngine($view)); // @phpstan-ignore-line
});
}
/**
* @return void
*/
private function registerResponseManager()
{
$this->app->singleton('flasher.response_manager', function (Application $app) {
$resourceManager = $app->make('flasher.resource_manager');
$storageManager = $app->make('flasher.storage_manager');
$eventDispatcher = $app->make('flasher.event_dispatcher');
return new ResponseManager($resourceManager, $storageManager, $eventDispatcher); // @phpstan-ignore-line
});
}
/**
* @return void
*/
private function registerStorageManager()
{
$this->app->singleton('flasher.storage_manager', function (Application $app) {
$config = $app->make('flasher.config');
$eventDispatcher = $app->make('flasher.event_dispatcher');
$session = $app->make('session');
/** @phpstan-ignore-next-line */
$storageBag = new StorageBag(new SessionBag($session));
$criteria = $config->get('filter_criteria', array()); // @phpstan-ignore-line
return new StorageManager($storageBag, $eventDispatcher, $criteria); // @phpstan-ignore-line
});
}
/**
* @return void
*/
private function registerEventDispatcher()
{
$this->app->singleton('flasher.event_dispatcher', function (Application $app) {
$eventDispatcher = new EventDispatcher();
$config = $app->make('flasher.config');
/** @phpstan-ignore-next-line */
$translator = new Translator($app->make('translator'));
/** @phpstan-ignore-next-line */
$autoTranslate = $config->get('auto_translate', true);
$translatorListener = new TranslationListener($translator, $autoTranslate);
$eventDispatcher->addSubscriber($translatorListener);
$presetListener = new PresetListener($config->get('presets', array())); // @phpstan-ignore-line
$eventDispatcher->addSubscriber($presetListener);
return $eventDispatcher;
});
}
/**
* @return void
*/
private function registerTranslations()
{
/** @var \Illuminate\Translation\Translator $translator */
$translator = $this->app->make('translator');
$translator->addNamespace('flasher', __DIR__.'/Translation/lang');
}
/**
* @return void
*/
private function registerLivewire()
{
if (!$this->app->bound('livewire')) {
return;
}
$livewire = $this->app->make('livewire');
if (!$livewire instanceof LivewireManager) {
return;
}
// Livewire v3
if (method_exists($livewire, 'componentHook')) {
$livewire->listen('dehydrate', function (Component $component, ComponentContext $context) {
if ($context->mounting || isset($context->effects['redirect'])) {
return;
}
/** @var FlasherInterface $flasher */
$flasher = app('flasher');
/** @var array{envelopes: Envelope[]} $data */
$data = $flasher->render(array(), 'array');
if (\count($data['envelopes']) > 0) {
$data['context']['livewire'] = array(
'id' => $component->getId(),
'name' => $component->getName(),
);
$dispatches = isset($context->effects['dispatches']) ? $context->effects['dispatches'] : [];
$dispatches[] = array('name' => 'flasher:render', 'params' => $data);
$context->addEffect('dispatches', $dispatches);
}
});
return;
}
$livewire->listen('component.dehydrate.subsequent', function (Component $component, Response $response) {
if (isset($response->effects['redirect'])) {
return;
}
/** @var FlasherInterface $flasher */
$flasher = app('flasher');
/** @var array{envelopes: Envelope[]} $data */
$data = $flasher->render(array(), 'array');
if (\count($data['envelopes']) > 0) {
$data['context']['livewire'] = array(
'id' => $component->id,
'name' => $response->fingerprint['name'],
);
$response->effects['dispatches'][] = array(
'event' => 'flasher:render',
'data' => $data,
);
}
});
}
/**
* @return void
*/
private function registerBladeDirective()
{
Blade::extend(function ($view) {
$pattern = '/(?<!\w)(\s*)@flasher_(livewire_)?render(\(.*?\))?/';
if (!preg_match($pattern, $view)) {
return $view;
}
@trigger_error('Since php-flasher/flasher-laravel v1.6.0: Using @flasher_render or @flasher_livewire_render is deprecated and will be removed in v2.0. PHPFlasher will render notification automatically', \E_USER_DEPRECATED);
return preg_replace($pattern, '', $view);
});
}
/**
* @return void
*/
private function registerBladeComponent()
{
if (Laravel::isVersion('7.0', '<=')) {
return;
}
Blade::component('flasher', 'Flasher\Laravel\Component\FlasherComponent');
}
/**
* @return void
*/
private function registerMiddlewares()
{
$this->registerSessionMiddleware();
$this->registerFlasherMiddleware();
}
/**
* @return void
*/
private function registerFlasherMiddleware()
{
/** @var ConfigInterface $config */
$config = $this->app->make('flasher.config');
if (!$config->get('auto_render', true)) {
return;
}
$this->app->singleton('Flasher\Laravel\Middleware\FlasherMiddleware', function (Application $app) {
/** @var FlasherInterface $flasher */
$flasher = $app->make('flasher');
return new FlasherMiddleware(new ResponseExtension($flasher));
});
$this->appendMiddlewareToWebGroup('Flasher\Laravel\Middleware\FlasherMiddleware');
if (method_exists($this->app, 'middleware')) {
$this->app->middleware(new HttpKernelFlasherMiddleware($this->app)); // @phpstan-ignore-line
}
}
/**
* @return void
*/
private function registerSessionMiddleware()
{
/** @var ConfigInterface $config */
$config = $this->app->make('flasher.config');
if (!$config->get('flash_bag.enabled', true)) {
return;
}
$this->app->singleton('Flasher\Laravel\Middleware\SessionMiddleware', function (Application $app) {
/** @var ConfigInterface $config */
$config = $app->make('flasher.config');
$mapping = $config->get('flash_bag.mapping', array());
$flasher = $app->make('flasher');
return new SessionMiddleware(new RequestExtension($flasher, $mapping)); // @phpstan-ignore-line
});
$this->appendMiddlewareToWebGroup('Flasher\Laravel\Middleware\SessionMiddleware');
if (method_exists($this->app, 'middleware')) {
$this->app->middleware(new HttpKernelSessionMiddleware($this->app)); // @phpstan-ignore-line
}
}
/**
* @param string $middleware
*
* @return void
*/
private function appendMiddlewareToWebGroup($middleware)
{
if (!$this->app->bound($middleware)) {
return;
}
/** @var Router $router */
$router = $this->app->make('router');
if (method_exists($router, 'pushMiddlewareToGroup')) {
$router->pushMiddlewareToGroup('web', $middleware);
return;
}
if (!$this->app->bound('Illuminate\Contracts\Http\Kernel')) {
return;
}
/** @var Kernel $kernel */
$kernel = $this->app->make('Illuminate\Contracts\Http\Kernel');
if (method_exists($kernel, 'appendMiddlewareToGroup')) {
$kernel->appendMiddlewareToGroup('web', $middleware);
return;
}
if (method_exists($kernel, 'pushMiddleware')) {
$kernel->pushMiddleware($middleware);
}
}
}

View File

@ -0,0 +1,78 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Http;
use Flasher\Prime\Http\RequestInterface;
use Illuminate\Http\Request as LaravelRequest;
final class Request implements RequestInterface
{
/**
* @var LaravelRequest
*/
private $request;
public function __construct(LaravelRequest $request)
{
$this->request = $request;
}
/**
* {@inheritDoc}
*/
public function isXmlHttpRequest()
{
return $this->request->ajax();
}
/**
* {@inheritDoc}
*/
public function isHtmlRequestFormat()
{
return 'html' === $this->request->getRequestFormat();
}
/**
* {@inheritDoc}
*/
public function hasSession()
{
return $this->request->hasSession();
}
/**
* {@inheritDoc}
*/
public function hasType($type)
{
$session = $this->request->session();
return $session->has($type);
}
/**
* {@inheritDoc}
*/
public function getType($type)
{
$session = $this->request->session();
return $session->get($type); // @phpstan-ignore-line
}
/**
* {@inheritDoc}
*/
public function forgetType($type)
{
$session = $this->request->session();
$session->forget($type);
}
}

View File

@ -0,0 +1,90 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Http;
use Flasher\Prime\Http\ResponseInterface;
use Illuminate\Http\JsonResponse as LaravelJsonResponse;
use Illuminate\Http\Response as LaravelResponse;
final class Response implements ResponseInterface
{
/**
* @var LaravelJsonResponse|LaravelResponse
*/
private $response;
/**
* @param LaravelJsonResponse|LaravelResponse $response
*/
public function __construct($response)
{
$this->response = $response;
}
/**
* {@inheritDoc}
*/
public function isRedirection()
{
return $this->response->isRedirection();
}
/**
* {@inheritDoc}
*/
public function isJson()
{
return $this->response instanceof LaravelJsonResponse;
}
/**
* {@inheritDoc}
*/
public function isHtml()
{
$contentType = $this->response->headers->get('Content-Type');
return false !== stripos($contentType, 'html'); // @phpstan-ignore-line
}
/**
* {@inheritDoc}
*/
public function isAttachment()
{
$contentDisposition = $this->response->headers->get('Content-Disposition', '');
return false !== stripos($contentDisposition, 'attachment;'); // @phpstan-ignore-line
}
/**
* {@inheritDoc}
*/
public function getContent()
{
return $this->response->getContent(); // @phpstan-ignore-line
}
/**
* {@inheritDoc}
*/
public function setContent($content)
{
$original = null;
if ($this->response instanceof \Illuminate\Http\Response && $this->response->getOriginalContent()) {
$original = $this->response->getOriginalContent();
}
$this->response->setContent($content);
// Restore original response (eg. the View or Ajax data)
if ($original) {
$this->response->original = $original;
}
}
}

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 PHPFlasher
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,40 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Middleware;
use Flasher\Laravel\Http\Request;
use Flasher\Laravel\Http\Response;
use Flasher\Prime\Http\ResponseExtension;
use Illuminate\Http\Request as LaravelRequest;
use Illuminate\Http\Response as LaravelResponse;
final class FlasherMiddleware
{
/**
* @var ResponseExtension
*/
private $responseExtension;
public function __construct(ResponseExtension $responseExtension)
{
$this->responseExtension = $responseExtension;
}
/**
* @return LaravelResponse
*/
public function handle(LaravelRequest $request, \Closure $next)
{
/** @var LaravelResponse $response */
$response = $next($request);
$this->responseExtension->render(new Request($request), new Response($response));
return $response;
}
}

View File

@ -0,0 +1,40 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Middleware;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
use Symfony\Component\HttpKernel\HttpKernelInterface;
final class HttpKernelFlasherMiddleware implements HttpKernelInterface
{
/**
* @var \Symfony\Component\HttpKernel\HttpKernelInterface
*/
private $app;
public function __construct(HttpKernelInterface $app)
{
$this->app = $app;
}
public function handle(SymfonyRequest $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
$response = $this->app->handle($request, $type, $catch);
$request = Request::createFromBase($request);
$next = function () use ($response) {
return $response;
};
/** @var SessionMiddleware $sessionMiddleware */
$sessionMiddleware = $this->app->make('Flasher\Laravel\Middleware\FlasherMiddleware');
return $sessionMiddleware->handle($request, $next);
}
}

View File

@ -0,0 +1,40 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Middleware;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
use Symfony\Component\HttpKernel\HttpKernelInterface;
final class HttpKernelSessionMiddleware implements HttpKernelInterface
{
/**
* @var \Symfony\Component\HttpKernel\HttpKernelInterface
*/
private $app;
public function __construct(HttpKernelInterface $app)
{
$this->app = $app;
}
public function handle(SymfonyRequest $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
$response = $this->app->handle($request, $type, $catch);
$request = Request::createFromBase($request);
$next = function () use ($response) {
return $response;
};
/** @var SessionMiddleware $sessionMiddleware */
$sessionMiddleware = $this->app->make('Flasher\Laravel\Middleware\SessionMiddleware');
return $sessionMiddleware->handle($request, $next);
}
}

View File

@ -0,0 +1,40 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Middleware;
use Flasher\Laravel\Http\Request;
use Flasher\Laravel\Http\Response;
use Flasher\Prime\Http\RequestExtension;
use Illuminate\Http\Request as LaravelRequest;
use Illuminate\Http\Response as LaravelResponse;
final class SessionMiddleware
{
/**
* @var RequestExtension
*/
private $requestExtension;
public function __construct(RequestExtension $requestExtension)
{
$this->requestExtension = $requestExtension;
}
/**
* @return LaravelResponse
*/
public function handle(LaravelRequest $request, \Closure $next)
{
/** @var LaravelResponse $response */
$response = $next($request);
$this->requestExtension->flash(new Request($request), new Response($response));
return $response;
}
}

View File

@ -0,0 +1,74 @@
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/php-flasher/art/main/php-flasher-github-dark.png">
<img src="https://raw.githubusercontent.com/php-flasher/art/main/php-flasher-github.png" alt="PHPFlasher Logo">
</picture>
</p>
## About PHPFlasher
PHPFlasher is a powerful and easy-to-use package that allows you to quickly and easily add flash messages to your Laravel or Symfony projects.
Whether you need to alert users of a successful form submission, an error, or any other important information, flash messages are a simple and effective solution for providing feedback to your users.
With PHPFlasher, you can easily record and store messages within the session, making it simple to retrieve and display them on the current or next page.
This improves user engagement and enhances the overall user experience on your website or application.
Whether you're a beginner or an experienced developer, PHPFlasher's intuitive and straightforward design makes it easy to integrate into your projects.
So, if you're looking for a reliable, flexible and easy to use flash messages solution, PHPFlasher is the perfect choice.
## Official Documentation
Documentation for PHPFlasher can be found on the [https://php-flasher.io](https://php-flasher.io).
## Contributors and sponsors
Join our team of contributors and make a lasting impact on our project!
We are always looking for passionate individuals who want to contribute their skills and ideas.
Whether you're a developer, designer, or simply have a great idea, we welcome your participation and collaboration.
Shining stars of our community:
<!-- ALL-CONTRIBUTORS-LIST:START -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/younes-khoubza/"><img src="https://avatars.githubusercontent.com/u/10859693?v=4?s=100" width="100px;" alt="Younes KHOUBZA"/><br /><sub><b>Younes KHOUBZA</b></sub></a><br /><a href="https://github.com/php-flasher/php-flasher/commits?author=yoeunes" title="Code">💻</a> <a href="https://github.com/php-flasher/php-flasher/commits?author=yoeunes" title="Documentation">📖</a> <a href="#maintenance-yoeunes" title="Maintenance">🚧</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/salmayno"><img src="https://avatars.githubusercontent.com/u/27933199?v=4?s=100" width="100px;" alt="Salma Mourad"/><br /><sub><b>Salma Mourad</b></sub></a><br /><a href="#financial-salmayno" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.youtube.com/rstacode"><img src="https://avatars.githubusercontent.com/u/35005761?v=4?s=100" width="100px;" alt="Nashwan Abdullah"/><br /><sub><b>Nashwan Abdullah</b></sub></a><br /><a href="#financial-codenashwan" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://darvis.nl/"><img src="https://avatars.githubusercontent.com/u/7394837?v=4?s=100" width="100px;" alt="Arvid de Jong"/><br /><sub><b>Arvid de Jong</b></sub></a><br /><a href="#financial-darviscommerce" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://ashallendesign.co.uk/"><img src="https://avatars.githubusercontent.com/u/39652331?v=4?s=100" width="100px;" alt="Ash Allen"/><br /><sub><b>Ash Allen</b></sub></a><br /><a href="#design-ash-jc-allen" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://about.me/murrant"><img src="https://avatars.githubusercontent.com/u/39462?v=4?s=100" width="100px;" alt="Tony Murray"/><br /><sub><b>Tony Murray</b></sub></a><br /><a href="https://github.com/php-flasher/php-flasher/commits?author=murrant" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/n3wborn"><img src="https://avatars.githubusercontent.com/u/10246722?v=4?s=100" width="100px;" alt="Stéphane P"/><br /><sub><b>Stéphane P</b></sub></a><br /><a href="https://github.com/php-flasher/php-flasher/commits?author=n3wborn" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.instagram.com/lucas.maciel_z"><img src="https://avatars.githubusercontent.com/u/80225404?v=4?s=100" width="100px;" alt="Lucas Maciel"/><br /><sub><b>Lucas Maciel</b></sub></a><br /><a href="#design-LucasStorm" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://siek.io/"><img src="https://avatars.githubusercontent.com/u/5730766?v=4?s=100" width="100px;" alt="Antoni Siek"/><br /><sub><b>Antoni Siek</b></sub></a><br /><a href="https://github.com/php-flasher/php-flasher/commits?author=ImJustToNy" title="Code">💻</a></td>
</tr>
</tbody>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
## Contact
PHPFlasher is being actively developed by <a href="https://github.com/yoeunes">yoeunes</a>.
You can reach out with questions, bug reports, or feature requests on any of the following:
- [Github Issues](https://github.com/php-flasher/php-flasher/issues)
- [Github](https://github.com/yoeunes)
- [Twitter](https://twitter.com/yoeunes)
- [Linkedin](https://www.linkedin.com/in/younes-khoubza/)
- [Email me directly](mailto:younes.khoubza@gmail.com)
## License
PHPFlasher is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
<p align="center"> <b>Made with ❤️ by <a href="https://www.linkedin.com/in/younes-khoubza/">Younes KHOUBZA</a> </b> </p>

View File

@ -0,0 +1,193 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
return array(
/*
|---------------------------------------------------------------------------
| Default PHPFlasher library
|---------------------------------------------------------------------------
| This option controls the default library that will be used by PHPFlasher
| to display notifications in your Laravel application. PHPFlasher supports
| several libraries, including "flasher", "toastr", "noty", "notyf",
| "sweetalert" and "pnotify".
|
| The "flasher" library is used by default. If you want to use a different
| library, you will need to install it using composer. For example, to use
| the "toastr" library, run the following command:
| composer require php-flasher/flasher-toastr-laravel
|
| Here is a list of the supported libraries and the corresponding composer
| commands to install them:
|
| "toastr" : composer require php-flasher/flasher-toastr-laravel
| "noty" : composer require php-flasher/flasher-noty-laravel
| "notyf" : composer require php-flasher/flasher-notyf-laravel
| "sweetalert" : composer require php-flasher/flasher-sweetalert-laravel
| "pnotify" : composer require php-flasher/flasher-pnotify-laravel
*/
'default' => 'flasher',
/*
|---------------------------------------------------------------------------
| Main PHPFlasher javascript file
|---------------------------------------------------------------------------
| This option specifies the location of the main javascript file that is
| required by PHPFlasher to display notifications in your Laravel application.
|
| By default, PHPFlasher uses a CDN to serve the latest version of the library.
| However, you can also choose to download the library locally or install it
| using npm.
|
| To use the local version of the library, run the following command:
| php artisan flasher:install
|
| This will copy the necessary assets to your application's public folder.
| You can then specify the local path to the javascript file in the 'local'
| field of this option.
*/
'root_script' => array(
'cdn' => 'https://cdn.jsdelivr.net/npm/@flasher/flasher@1.3.2/dist/flasher.min.js',
'local' => '/vendor/flasher/flasher.min.js',
),
/*
|---------------------------------------------------------------------------
| PHPFlasher Stylesheet
|---------------------------------------------------------------------------
| This option specifies the location of the stylesheet file that is
| required by PHPFlasher to style the notifications in your Laravel application.
|
| By default, PHPFlasher uses a CDN to serve the latest version of the stylesheet.
| However, you can also choose to download the stylesheet locally or include it
| from your assets.
|
| To use the local version of the stylesheet, make sure you have the necessary
| assets in your application's public folder. Then specify the local path to
| the stylesheet file in the 'local' field of this option.
*/
'styles' => array(
'cdn' => 'https://cdn.jsdelivr.net/npm/@flasher/flasher@1.3.2/dist/flasher.min.css',
'local' => '/vendor/flasher/flasher.min.css',
),
/*
|---------------------------------------------------------------------------
| Whether to use CDN for PHPFlasher assets or not
|---------------------------------------------------------------------------
| This option controls whether PHPFlasher should use CDN links or local assets
| for its javascript and CSS files. By default, PHPFlasher uses CDN links
| to serve the latest version of the library. However, you can also choose
| to use local assets by setting this option to 'false'.
|
| If you decide to use local assets, don't forget to publish the necessary
| files to your application's public folder by running the following command:
| php artisan flasher:install
|
| This will copy the necessary assets to your application's public folder.
*/
'use_cdn' => true,
/*
|---------------------------------------------------------------------------
| Translate PHPFlasher messages
|---------------------------------------------------------------------------
| This option controls whether PHPFlasher should pass its messages to the Laravel's
| translation service for localization.
|
| By default, this option is set to 'true', which means that PHPFlasher will
| attempt to translate its messages using the translation service.
|
| If you don't want PHPFlasher to use the Laravel's translation service, you can
| set this option to 'false'. In this case, PHPFlasher will use the messages
| as-is, without attempting to translate them.
*/
'auto_translate' => true,
/*
|---------------------------------------------------------------------------
| Inject PHPFlasher in Response
|---------------------------------------------------------------------------
| This option controls whether PHPFlasher should automatically inject its
| javascript and CSS files into the HTML response of your Laravel application.
|
| By default, this option is set to 'true', which means that PHPFlasher will
| listen to the response of your application and automatically insert its
| scripts and stylesheets into the HTML before the closing `</body>` tag.
|
| If you don't want PHPFlasher to automatically inject its scripts and stylesheets
| into the response, you can set this option to 'false'. In this case, you will
| need to manually include the necessary files in your application's layout.
*/
'auto_render' => true,
'flash_bag' => array(
/*
|-----------------------------------------------------------------------
| Enable flash bag
|-----------------------------------------------------------------------
| This option controls whether PHPFlasher should automatically convert
| Laravel's flash messages to PHPFlasher notifications. This feature is
| useful when you want to migrate from a legacy system or another
| library that uses similar conventions for flash messages.
|
| When this option is set to 'true', PHPFlasher will check for flash
| messages in the session and convert them to notifications using the
| mapping specified in the 'mapping' option. When this option is set
| to 'false', PHPFlasher will ignore flash messages in the session.
*/
'enabled' => true,
/*
|-----------------------------------------------------------------------
| Flash bag type mapping
|-----------------------------------------------------------------------
| This option allows you to map or convert session keys to PHPFlasher
| notification types. On the left side are the PHPFlasher types.
| On the right side are the Laravel session keys that you want to
| convert to PHPFlasher types.
|
| For example, if you want to convert Laravel's 'danger' flash
| messages to PHPFlasher's 'error' notifications, you can add
| the following entry to the mapping:
| 'error' => ['danger'],
*/
'mapping' => array(
'success' => array('success'),
'error' => array('error', 'danger'),
'warning' => array('warning', 'alarm'),
'info' => array('info', 'notice', 'alert'),
),
),
/*
|---------------------------------------------------------------------------
| Global Filter Criteria
|---------------------------------------------------------------------------
| This option allows you to filter the notifications that are displayed
| in your Laravel application. By default, all notifications are displayed,
| but you can use this option to limit the number of notifications or
| filter them by type.
|
| For example, to limit the number of notifications to 5, you can set
| the 'limit' field to 5:
| 'limit' => 5,
|
| To filter the notifications by type, you can specify an array of
| types that you want to display. For example, to only display
| error notifications, you can set the 'types' field to ['error']:
| 'types' => ['error'],
|
| You can also combine multiple criteria by specifying multiple fields.
| For example, to display up to 5 error notifications, you can set
| the 'limit' and 'types' fields like this:
| 'limit' => 5,
| 'types' => ['error'],
*/
'filter_criteria' => array(
'limit' => 5, // Limit the number of notifications to display
),
);

View File

@ -0,0 +1,45 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Storage;
use Flasher\Prime\Storage\Bag\BagInterface;
use Illuminate\Session\Store;
final class SessionBag implements BagInterface
{
const ENVELOPES_NAMESPACE = 'flasher::envelopes';
/**
* @var Store
*/
private $session;
/**
* @param Store $session
*/
public function __construct($session)
{
$this->session = $session;
}
/**
* {@inheritdoc}
*/
public function get()
{
return $this->session->get(self::ENVELOPES_NAMESPACE, array()); // @phpstan-ignore-line
}
/**
* {@inheritdoc}
*/
public function set(array $envelopes)
{
$this->session->put(self::ENVELOPES_NAMESPACE, $envelopes);
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Support;
use Illuminate\Foundation\Application;
final class Laravel
{
/**
* @param string $version
* @param string|null $operator
*
* @return bool
*/
public static function isVersion($version, $operator = null)
{
if (null !== $operator) {
return version_compare(Application::VERSION, $version, $operator);
}
$parts = explode('.', $version);
++$parts[\count($parts) - 1];
$next = implode('.', $parts);
return self::isVersion($version, '>=') && self::isVersion($next, '<');
}
}

View File

@ -0,0 +1,228 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Support;
use Flasher\Prime\FlasherInterface;
use Flasher\Prime\Plugin\PluginInterface;
use Flasher\Prime\Response\Resource\ResourceManagerInterface;
use Illuminate\Container\Container;
use Illuminate\Contracts\Config\Repository;
use Illuminate\Support\ServiceProvider as BaseServiceProvider;
abstract class ServiceProvider extends BaseServiceProvider
{
/**
* @var PluginInterface|null
*/
protected $plugin;
/**
* {@inheritdoc}
*/
public function register()
{
$this->plugin = $this->plugin ?: $this->createPlugin();
$this->processConfiguration();
$this->afterRegister();
}
/**
* @return void
*/
public function boot()
{
$this->registerPublishing();
$this->registerFactory();
$this->afterBoot();
}
/**
* @return PluginInterface
*/
abstract public function createPlugin();
/**
* @return string
*/
public function getConfigurationFile()
{
return rtrim($this->getResourcesDir(), '/').'/config.php';
}
/**
* @return void
*/
protected function registerPublishing()
{
if (!in_array(\PHP_SAPI, array('cli', 'phpdbg'))) {
return;
}
if (Laravel::isVersion('4')) {
return;
}
$this->publishConfiguration();
$this->publishAssets();
}
/**
* @return void
*/
protected function publishConfiguration()
{
if (null === $this->plugin) {
return;
}
$file = $this->getConfigurationFile();
if (!file_exists($file)) {
return;
}
$paths = array($file => config_path($this->plugin->getName().'.php'));
$this->publishes($paths);
$groups = array(
'flasher-config',
str_replace('_', '-', $this->plugin->getName()).'-config',
);
foreach ($groups as $group) {
if (!array_key_exists($group, static::$publishGroups)) {
static::$publishGroups[$group] = array();
}
static::$publishGroups[$group] = array_merge(static::$publishGroups[$group], $paths);
}
}
/**
* @return void
*/
protected function publishAssets()
{
if (null === $this->plugin) {
return;
}
$dir = $this->plugin->getAssetsDir();
if (!is_dir($dir)) {
return;
}
$paths = array($dir => public_path('vendor/flasher/'));
$this->publishes($paths);
$groups = array(
'flasher-assets',
str_replace('_', '-', $this->plugin->getName()).'-assets',
);
foreach ($groups as $group) {
if (!array_key_exists($group, static::$publishGroups)) {
static::$publishGroups[$group] = array();
}
static::$publishGroups[$group] = array_merge(static::$publishGroups[$group], $paths);
}
}
/**
* @return string
*/
protected function getResourcesDir()
{
$r = new \ReflectionClass($this);
return pathinfo($r->getFileName() ?: '', PATHINFO_DIRNAME).'/Resources/';
}
/**
* @return void
*/
protected function processConfiguration()
{
if (null === $this->plugin) {
return;
}
/** @var Repository $config */
$config = $this->app->make('config');
$name = $this->plugin->getName();
/** @var array<string, mixed> $configuration */
$configuration = $config->get($name, array());
$config->set($name, $this->plugin->processConfiguration($configuration));
}
/**
* @return void
*/
protected function afterRegister()
{
}
/**
* @return void
*/
protected function afterBoot()
{
}
/**
* @return void
*/
protected function registerFactory()
{
$plugin = $this->plugin;
if (null === $plugin) {
return;
}
if (!class_exists($plugin->getFactory())) {
return;
}
$this->app->singleton($plugin->getServiceID(), function (Container $app) use ($plugin) {
$factory = $plugin->getFactory();
return new $factory($app->make('flasher.storage_manager'));
});
$this->app->alias($plugin->getServiceID(), $plugin->getFactory());
$this->app->extend('flasher', function (FlasherInterface $flasher, Container $app) use ($plugin) {
$flasher->addFactory($plugin->getAlias(), $app->make($plugin->getServiceID())); // @phpstan-ignore-line
return $flasher;
});
$config = $this->app->make('config')->get($this->plugin->getName(), array()); // @phpstan-ignore-line
$this->app->extend('flasher.resource_manager', function (ResourceManagerInterface $manager) use ($plugin, $config) {
$config = $plugin->normalizeConfig($config);
$scripts = isset($config['scripts']) ? $config['scripts'] : array();
$manager->addScripts($plugin->getAlias(), $scripts);
$styles = isset($config['styles']) ? $config['styles'] : array();
$manager->addStyles($plugin->getAlias(), $styles);
$options = isset($config['options']) ? $config['options'] : array();
$manager->addOptions($plugin->getAlias(), $options);
return $manager;
});
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Template;
use Flasher\Prime\Template\TemplateEngineInterface;
use Illuminate\View\Factory;
final class BladeTemplateEngine implements TemplateEngineInterface
{
/**
* @var Factory
*/
private $engine;
/**
* @param Factory $engine
*/
public function __construct($engine)
{
$this->engine = $engine;
}
public function render($name, array $context = array())
{
$view = $this->engine->make($name, $context);
return $view->render();
}
}

View File

@ -0,0 +1,55 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Laravel\Translation;
use Flasher\Prime\Stamp\TranslationStamp;
use Flasher\Prime\Translation\TranslatorInterface;
use Illuminate\Translation\Translator as LaravelTranslator;
final class Translator implements TranslatorInterface
{
/**
* @var LaravelTranslator
*/
private $translator;
public function __construct(LaravelTranslator $translator)
{
$this->translator = $translator;
}
/**
* {@inheritdoc}
*/
public function translate($id, $parameters = array(), $locale = null)
{
$order = TranslationStamp::parametersOrder($parameters, $locale);
$parameters = $order['parameters'];
$locale = $order['locale'];
$translation = $this->translator->has('flasher::messages.'.$id, $locale)
? $this->translator->get('flasher::messages.'.$id, $parameters, $locale)
: ($this->translator->has('messages.'.$id, $locale)
? $this->translator->get('messages.'.$id, $parameters, $locale)
: $this->translator->get($id, $parameters, $locale));
if (!\is_string($translation)) {
return $id;
}
return $translation;
}
/**
* {@inheritdoc}
*/
public function getLocale()
{
return $this->translator->getLocale();
}
}

View File

@ -0,0 +1,10 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
use Flasher\Prime\Translation\Messages;
return Messages::$ar;

View File

@ -0,0 +1,10 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
use Flasher\Prime\Translation\Messages;
return Messages::$en;

View File

@ -0,0 +1,10 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
use Flasher\Prime\Translation\Messages;
return Messages::$fr;

View File

@ -0,0 +1,64 @@
{
"name": "php-flasher/flasher-laravel",
"description": "PHPFlasher - A powerful & easy-to-use package for adding flash messages to Laravel or Symfony projects. Provides feedback to users, improves engagement & enhances user experience. Intuitive design for beginners & experienced developers. A reliable, flexible solution.",
"license": "MIT",
"type": "library",
"keywords": [
"php-flasher",
"flash-messages",
"notification-system",
"user-feedback",
"toastr",
"sweetalert",
"pnotify",
"noty",
"notyf",
"desktop-notifications",
"php",
"laravel",
"symfony",
"javascript",
"yoeunes",
"framework-agnostic",
"phpstorm-auto-complete",
"custom-adapter",
"user-experience",
"rtl",
"dark-mode"
],
"authors": [
{
"name": "Younes KHOUBZA",
"email": "younes.khoubza@gmail.com",
"homepage": "https://www.linkedin.com/in/younes-khoubza",
"role": "Developer"
}
],
"homepage": "https://php-flasher.io",
"require": {
"php": ">=5.3",
"illuminate/support": "^4.0 || ^5.0 || ^6.0 || ^7.0 || ^8.0 || ^9.0 || ^10.0 || ^11.0",
"php-flasher/flasher": "^1.15.14"
},
"minimum-stability": "stable",
"prefer-stable": true,
"autoload": {
"psr-4": {
"Flasher\\Laravel\\": ""
}
},
"config": {
"preferred-install": "dist",
"sort-packages": true
},
"extra": {
"laravel": {
"aliases": {
"Flasher": "Flasher\\Laravel\\Facade\\Flasher"
},
"providers": [
"Flasher\\Laravel\\FlasherServiceProvider"
]
}
}
}

View File

@ -0,0 +1,5 @@
github: yoeunes
patreon: yoeunes
ko_fi: yoeunes
open_collective: php-flasher
custom: https://www.paypal.com/paypalme/yoeunes

View File

@ -0,0 +1,22 @@
name: Auto Closer PR
on:
pull_request_target:
types: [opened]
jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: superbrothers/close-pull-request@v3
with:
comment: |
Hi, thank you for your contribution.
Unfortunately, this repository is read-only. It's a split from our main monorepo repository.
We'd like to kindly ask you to move the contribution there - https://github.com/php-flasher/php-flasher.
We'll check it, review it and give you feed back right way.
Thank you.

View File

@ -0,0 +1,24 @@
<?php
namespace PHPSTORM_META;
override(Envelope::get(0), type(0));
override(\Flasher\Prime\FlasherInterface::create(), map([
'flasher' => \Flasher\Prime\Factory\NotificationFactory::class,
'theme.' => \Flasher\Prime\Factory\NotificationFactory::class,
]));
override(\Flasher\Prime\FlasherInterface::using(), map([
'flasher' => \Flasher\Prime\Factory\NotificationFactory::class,
'theme.' => \Flasher\Prime\Factory\NotificationFactory::class,
]));
registerArgumentsSet('types', 'success', 'error', 'warning', 'info');
expectedArguments(\Flasher\Prime\Notification\NotificationBuilderInterface::type(), 0, argumentsSet('types'));
expectedArguments(\Flasher\Prime\Notification\NotificationBuilderInterface::addFlash(), 0, argumentsSet('types'));
expectedArguments(\Flasher\Prime\Notification\NotificationInterface::setType(), 0, argumentsSet('types'));
expectedReturnValues(\Flasher\Prime\Notification\NotificationInterface::getType(), argumentsSet('types'));
expectedArguments(\Flasher\Prime\Notification\NotificationBuilderInterface::handler(), 0, 'flasher', 'toastr', 'noty', 'notyf', 'pnotify', 'sweetalert');

View File

@ -0,0 +1,18 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Aware;
use Flasher\Prime\FlasherInterface;
interface FlasherAwareInterface
{
/**
* @return void
*/
public function setFlasher(FlasherInterface $flasher);
}

View File

@ -0,0 +1,23 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Aware;
use Flasher\Prime\FlasherInterface;
trait FlasherAwareTrait
{
/**
* @var FlasherInterface
*/
protected $flasher;
public function setFlasher(FlasherInterface $flasher)
{
$this->flasher = $flasher;
}
}

View File

@ -0,0 +1,45 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Config;
/**
* @phpstan-import-type ConfigType from ConfigInterface
*/
final class Config implements ConfigInterface
{
/**
* @phpstan-var array{}|ConfigType
*/
private $config;
/**
* @phpstan-param array{}|ConfigType $config
*/
public function __construct(array $config = array())
{
$this->config = $config;
}
/**
* {@inheritdoc}
*/
public function get($key, $default = null)
{
$data = $this->config;
foreach (explode('.', $key) as $segment) {
if (!isset($data[$segment])) { // @phpstan-ignore-line
return $default;
}
$data = $data[$segment];
}
return $data;
}
}

View File

@ -0,0 +1,47 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Config;
/**
* @phpstan-type ConfigType array{
* default: string,
* root_script: string,
* options: array<string, string>,
* themes: array<string, array{
* view: string,
* styles: string[],
* scripts: string[],
* options: array<string, mixed>,
* }>,
* auto_render: bool,
* auto_translate: bool,
* filter_criteria: array<string, mixed>,
* flash_bag: array{
* enabled: bool,
* mapping: array<string, string[]>,
* },
* presets: array<string, array{
* type: string,
* title: string,
* message: string,
* options: array<string, mixed>,
* }>,
* }
*/
interface ConfigInterface
{
/**
* Returns an attribute.
*
* @param string $key
* @param mixed $default the default value if not found
*
* @return mixed
*/
public function get($key, $default = null);
}

View File

@ -0,0 +1,18 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Container;
interface ContainerInterface
{
/**
* @param string $id
*
* @return mixed
*/
public function get($id);
}

View File

@ -0,0 +1,57 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Container;
/**
* @internal
*/
final class FlasherContainer
{
/**
* @var self|null
*/
private static $instance = null;
/**
* @var ContainerInterface
*/
private static $container;
private function __construct(ContainerInterface $container)
{
self::$container = $container;
}
/**
* @param string $id
*
* @return mixed
*
* @throws \LogicException
*/
public static function create($id)
{
if (null === self::$instance) {
throw new \LogicException('Container is not initialized yet. Container::init() must be called with a real container.');
}
return self::$container->get($id);
}
/**
* @return void
*/
public static function init(ContainerInterface $container)
{
if (null !== self::$instance) {
return;
}
self::$instance = new self($container);
}
}

View File

@ -0,0 +1,52 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\Event;
use Flasher\Prime\Filter\Filter;
use Flasher\Prime\Notification\Envelope;
final class FilterEvent
{
/**
* @var Filter
*/
private $filter;
/**
* @param Envelope[] $envelopes
* @param array<string, mixed> $criteria
*/
public function __construct(array $envelopes, array $criteria)
{
$this->filter = new Filter($envelopes, $criteria);
}
/**
* @return Envelope[]
*/
public function getEnvelopes()
{
return $this->filter->getResult();
}
/**
* @return Filter
*/
public function getFilter()
{
return $this->filter;
}
/**
* @return void
*/
public function setFilter(Filter $filter)
{
$this->filter = $filter;
}
}

View File

@ -0,0 +1,44 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\Event;
use Flasher\Prime\Notification\Envelope;
final class PersistEvent
{
/**
* @var Envelope[]
*/
private $envelopes;
/**
* @param Envelope[] $envelopes
*/
public function __construct(array $envelopes)
{
$this->envelopes = $envelopes;
}
/**
* @return Envelope[]
*/
public function getEnvelopes()
{
return $this->envelopes;
}
/**
* @param Envelope[] $envelopes
*
* @return void
*/
public function setEnvelopes(array $envelopes)
{
$this->envelopes = $envelopes;
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\Event;
use Flasher\Prime\Notification\Envelope;
final class PostPersistEvent
{
/**
* @var Envelope[]
*/
private $envelopes;
/**
* @param Envelope[] $envelopes
*/
public function __construct(array $envelopes)
{
$this->envelopes = $envelopes;
}
/**
* @return Envelope[]
*/
public function getEnvelopes()
{
return $this->envelopes;
}
}

View File

@ -0,0 +1,49 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\Event;
use Flasher\Prime\Notification\Envelope;
final class PostRemoveEvent
{
/**
* @var Envelope[]
*/
private $envelopesToRemove;
/**
* @var Envelope[]
*/
private $envelopesToKeep;
/**
* @param Envelope[] $envelopesToRemove
* @param Envelope[] $envelopesToKeep
*/
public function __construct(array $envelopesToRemove = array(), array $envelopesToKeep = array())
{
$this->envelopesToRemove = $envelopesToRemove;
$this->envelopesToKeep = $envelopesToKeep;
}
/**
* @return Envelope[]
*/
public function getEnvelopesToRemove()
{
return $this->envelopesToRemove;
}
/**
* @return Envelope[]
*/
public function getEnvelopesToKeep()
{
return $this->envelopesToKeep;
}
}

View File

@ -0,0 +1,34 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\Event;
use Flasher\Prime\Notification\Envelope;
final class PostUpdateEvent
{
/**
* @var Envelope[]
*/
private $envelopes;
/**
* @param Envelope[] $envelopes
*/
public function __construct(array $envelopes)
{
$this->envelopes = $envelopes;
}
/**
* @return Envelope[]
*/
public function getEnvelopes()
{
return $this->envelopes;
}
}

View File

@ -0,0 +1,49 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\Event;
use Flasher\Prime\Notification\Envelope;
final class PresentationEvent
{
/**
* @var Envelope[]
*/
private $envelopes;
/**
* @var mixed[]
*/
private $context;
/**
* @param Envelope[] $envelopes
* @param mixed[] $context
*/
public function __construct(array $envelopes, array $context)
{
$this->envelopes = $envelopes;
$this->context = $context;
}
/**
* @return Envelope[]
*/
public function getEnvelopes()
{
return $this->envelopes;
}
/**
* @return mixed[]
*/
public function getContext()
{
return $this->context;
}
}

View File

@ -0,0 +1,67 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\Event;
use Flasher\Prime\Notification\Envelope;
final class RemoveEvent
{
/**
* @var Envelope[]
*/
private $envelopesToRemove = array();
/**
* @var Envelope[]
*/
private $envelopesToKeep = array();
/**
* @param Envelope[] $envelopesToRemove
*/
public function __construct(array $envelopesToRemove)
{
$this->envelopesToRemove = $envelopesToRemove;
}
/**
* @return Envelope[]
*/
public function getEnvelopesToRemove()
{
return $this->envelopesToRemove;
}
/**
* @param Envelope[] $envelopesToRemove
*
* @return void
*/
public function setEnvelopesToRemove($envelopesToRemove)
{
$this->envelopesToRemove = $envelopesToRemove;
}
/**
* @return Envelope[]
*/
public function getEnvelopesToKeep()
{
return $this->envelopesToKeep;
}
/**
* @param Envelope[] $envelopesToKeep
*
* @return void
*/
public function setEnvelopesToKeep($envelopesToKeep)
{
$this->envelopesToKeep = $envelopesToKeep;
}
}

View File

@ -0,0 +1,57 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\Event;
final class ResponseEvent
{
/**
* @var mixed
*/
private $response;
/**
* @var string
*/
private $presenter;
/**
* @param mixed $response
* @param string $presenter
*/
public function __construct($response, $presenter)
{
$this->response = $response;
$this->presenter = $presenter;
}
/**
* @return mixed
*/
public function getResponse()
{
return $this->response;
}
/**
* @param mixed $response
*
* @return void
*/
public function setResponse($response)
{
$this->response = $response;
}
/**
* @return string
*/
public function getPresenter()
{
return $this->presenter;
}
}

View File

@ -0,0 +1,16 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\Event;
interface StoppableEventInterface
{
/**
* @return bool
*/
public function isPropagationStopped();
}

View File

@ -0,0 +1,44 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\Event;
use Flasher\Prime\Notification\Envelope;
final class UpdateEvent
{
/**
* @var Envelope[]
*/
private $envelopes;
/**
* @param Envelope[] $envelopes
*/
public function __construct(array $envelopes)
{
$this->envelopes = $envelopes;
}
/**
* @return Envelope[]
*/
public function getEnvelopes()
{
return $this->envelopes;
}
/**
* @param Envelope[] $envelopes
*
* @return void
*/
public function setEnvelopes(array $envelopes)
{
$this->envelopes = $envelopes;
}
}

View File

@ -0,0 +1,89 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher;
use Flasher\Prime\EventDispatcher\Event\StoppableEventInterface;
use Flasher\Prime\EventDispatcher\EventListener\AddToStorageListener;
use Flasher\Prime\EventDispatcher\EventListener\EventSubscriberInterface;
use Flasher\Prime\EventDispatcher\EventListener\RemoveListener;
use Flasher\Prime\EventDispatcher\EventListener\StampsListener;
final class EventDispatcher implements EventDispatcherInterface
{
/**
* @var array<string, EventSubscriberInterface[]>
*/
private $listeners = array();
public function __construct()
{
$this->addSubscriber(new RemoveListener());
$this->addSubscriber(new StampsListener());
$this->addSubscriber(new AddToStorageListener());
}
/**
* {@inheritdoc}
*/
public function dispatch($event)
{
$listeners = $this->getListeners(\get_class($event));
$this->callListeners($listeners, $event); // @phpstan-ignore-line
return $event;
}
/**
* {@inheritdoc}
*/
public function addListener($eventName, $listener)
{
$this->listeners[$eventName][] = $listener; // @phpstan-ignore-line
}
/**
* {@inheritdoc}
*/
public function addSubscriber(EventSubscriberInterface $subscriber)
{
foreach ((array) $subscriber->getSubscribedEvents() as $eventName) {
$this->addListener($eventName, array($subscriber, '__invoke')); // @phpstan-ignore-line
}
}
/**
* @param string $eventName
*
* @return array<int, EventSubscriberInterface[]>
*/
public function getListeners($eventName)
{
if (\array_key_exists($eventName, $this->listeners)) {
return $this->listeners[$eventName]; // @phpstan-ignore-line
}
return array();
}
/**
* @param callable[] $listeners
* @param object $event
*
* @return void
*/
private function callListeners(array $listeners, $event)
{
foreach ($listeners as $listener) {
if ($event instanceof StoppableEventInterface && $event->isPropagationStopped()) {
break;
}
\call_user_func($listener, $event);
}
}
}

View File

@ -0,0 +1,33 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher;
use Flasher\Prime\EventDispatcher\EventListener\EventSubscriberInterface;
interface EventDispatcherInterface
{
/**
* @param object $event
*
* @return object
*/
public function dispatch($event);
/**
* @param string $eventName
* @param callable $listener
*
* @return void
*/
public function addListener($eventName, $listener);
/**
* @return void
*/
public function addSubscriber(EventSubscriberInterface $subscriber);
}

View File

@ -0,0 +1,58 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\EventListener;
use Flasher\Prime\EventDispatcher\Event\PersistEvent;
use Flasher\Prime\Notification\Envelope;
use Flasher\Prime\Stamp\UnlessStamp;
use Flasher\Prime\Stamp\WhenStamp;
final class AddToStorageListener implements EventSubscriberInterface
{
/**
* @return void
*/
public function __invoke(PersistEvent $event)
{
$envelopesToKeep = array();
foreach ($event->getEnvelopes() as $envelope) {
if ($this->shouldKeep($envelope)) {
$envelopesToKeep[] = $envelope;
}
}
$event->setEnvelopes($envelopesToKeep);
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return 'Flasher\Prime\EventDispatcher\Event\PersistEvent';
}
/**
* @return bool
*/
private function shouldKeep(Envelope $envelope)
{
$stamp = $envelope->get('Flasher\Prime\Stamp\WhenStamp');
if ($stamp instanceof WhenStamp && false === $stamp->getCondition()) {
return false;
}
$stamp = $envelope->get('Flasher\Prime\Stamp\UnlessStamp');
if ($stamp instanceof UnlessStamp && true === $stamp->getCondition()) {
return false;
}
return true;
}
}

View File

@ -0,0 +1,16 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\EventListener;
interface EventSubscriberInterface
{
/**
* @return string|string[]
*/
public static function getSubscribedEvents();
}

View File

@ -0,0 +1,97 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\EventListener;
use Flasher\Prime\EventDispatcher\Event\PersistEvent;
use Flasher\Prime\Exception\PresetNotFoundException;
use Flasher\Prime\Notification\Envelope;
use Flasher\Prime\Stamp\PresetStamp;
/**
* @phpstan-type PresetType array<string, array{
* type: string,
* title: string,
* message: string,
* options: array<string, mixed>,
* }>
*/
final class PresetListener implements EventSubscriberInterface
{
/**
* @phpstan-var PresetType
*/
private $presets = array();
/**
* @phpstan-param PresetType $presets
*/
public function __construct(array $presets)
{
$this->presets = $presets;
}
/**
* @return void
*
* @throws PresetNotFoundException
*/
public function __invoke(PersistEvent $event)
{
foreach ($event->getEnvelopes() as $envelope) {
$this->attachPresets($envelope);
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return 'Flasher\Prime\EventDispatcher\Event\PersistEvent';
}
/**
* @return void
*
* @throws PresetNotFoundException
*/
private function attachPresets(Envelope $envelope)
{
$presetStamp = $envelope->get('Flasher\Prime\Stamp\PresetStamp');
if (!$presetStamp instanceof PresetStamp) {
return;
}
if (!isset($this->presets[$presetStamp->getPreset()])) {
throw new PresetNotFoundException($presetStamp->getPreset(), array_keys($this->presets));
}
$preset = $this->presets[$presetStamp->getPreset()];
$preset = array_merge(array(
'type' => 'info',
'title' => null,
'message' => null,
'options' => array(),
), $preset);
if (null === $envelope->getType()) {
$envelope->setType($preset['type']);
}
if (null === $envelope->getTitle()) {
$envelope->setTitle($preset['title']);
}
if (null === $envelope->getMessage()) {
$envelope->setMessage($preset['message']);
}
$options = array_merge($preset['options'], $envelope->getOptions());
$envelope->setOptions($options);
}
}

View File

@ -0,0 +1,46 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\EventListener;
use Flasher\Prime\EventDispatcher\Event\RemoveEvent;
use Flasher\Prime\Stamp\HopsStamp;
final class RemoveListener implements EventSubscriberInterface
{
/**
* @return void
*/
public function __invoke(RemoveEvent $event)
{
$envelopesToKeep = $event->getEnvelopesToKeep();
$envelopesToRemove = array();
foreach ($event->getEnvelopesToRemove() as $envelope) {
$hopsStamp = $envelope->get('Flasher\Prime\Stamp\HopsStamp');
if (!$hopsStamp instanceof HopsStamp || 1 === $hopsStamp->getAmount()) {
$envelopesToRemove[] = $envelope;
continue;
}
$envelope->with(new HopsStamp($hopsStamp->getAmount() - 1));
$envelopesToKeep[] = $envelope;
}
$event->setEnvelopesToKeep($envelopesToKeep);
$event->setEnvelopesToRemove($envelopesToRemove);
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return 'Flasher\Prime\EventDispatcher\Event\RemoveEvent';
}
}

View File

@ -0,0 +1,69 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\EventListener;
use Flasher\Prime\EventDispatcher\Event\PersistEvent;
use Flasher\Prime\EventDispatcher\Event\UpdateEvent;
use Flasher\Prime\Notification\Envelope;
use Flasher\Prime\Stamp\CreatedAtStamp;
use Flasher\Prime\Stamp\DelayStamp;
use Flasher\Prime\Stamp\HopsStamp;
use Flasher\Prime\Stamp\PriorityStamp;
use Flasher\Prime\Stamp\UuidStamp;
final class StampsListener implements EventSubscriberInterface
{
/**
* @param PersistEvent|UpdateEvent $event
*
* @return void
*/
public function __invoke($event)
{
foreach ($event->getEnvelopes() as $envelope) {
$this->attachStamps($envelope);
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return array(
'Flasher\Prime\EventDispatcher\Event\PersistEvent',
'Flasher\Prime\EventDispatcher\Event\UpdateEvent',
);
}
/**
* @return void
*/
private function attachStamps(Envelope $envelope)
{
if (null === $envelope->get('Flasher\Prime\Stamp\CreatedAtStamp')) {
$envelope->withStamp(new CreatedAtStamp());
}
if (null === $envelope->get('Flasher\Prime\Stamp\UuidStamp')) {
$envelope->withStamp(new UuidStamp(spl_object_hash($envelope)));
}
if (null === $envelope->get('Flasher\Prime\Stamp\DelayStamp')) {
$envelope->withStamp(new DelayStamp(0));
}
if (null === $envelope->get('Flasher\Prime\Stamp\HopsStamp')) {
$envelope->withStamp(new HopsStamp(1));
}
if (null === $envelope->get('Flasher\Prime\Stamp\PriorityStamp')) {
$envelope->withStamp(new PriorityStamp(0));
}
}
}

View File

@ -0,0 +1,89 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\EventDispatcher\EventListener;
use Flasher\Prime\EventDispatcher\Event\PresentationEvent;
use Flasher\Prime\Stamp\PresetStamp;
use Flasher\Prime\Stamp\TranslationStamp;
use Flasher\Prime\Translation\EchoTranslator;
use Flasher\Prime\Translation\Language;
use Flasher\Prime\Translation\TranslatorInterface;
final class TranslationListener implements EventSubscriberInterface
{
/**
* @var TranslatorInterface
*/
private $translator;
/**
* @var bool
*/
private $autoTranslate;
/**
* @param bool $autoTranslate
*/
public function __construct(TranslatorInterface $translator = null, $autoTranslate = true)
{
$this->translator = $translator ?: new EchoTranslator();
$this->autoTranslate = $autoTranslate;
}
/**
* @return void
*/
public function __invoke(PresentationEvent $event)
{
foreach ($event->getEnvelopes() as $envelope) {
$stamp = $envelope->get('Flasher\Prime\Stamp\TranslationStamp');
if (!$stamp instanceof TranslationStamp && !$this->autoTranslate) {
continue;
}
$locale = $stamp instanceof TranslationStamp && $stamp->getLocale()
? $stamp->getLocale()
: $this->translator->getLocale();
$parameters = $stamp instanceof TranslationStamp && $stamp->getParameters()
? $stamp->getParameters()
: array();
$preset = $envelope->get('Flasher\Prime\Stamp\PresetStamp');
if ($preset instanceof PresetStamp) {
foreach ($preset->getParameters() as $key => $value) {
$parameters[$key] = $this->translator->translate($value, $parameters, $locale); // @phpstan-ignore-line
}
}
$title = $envelope->getTitle() ?: $envelope->getType();
if (null !== $title) {
$title = $this->translator->translate($title, $parameters, $locale);
$envelope->setTitle($title);
}
$message = $envelope->getMessage();
if (null !== $message) {
$message = $this->translator->translate($message, $parameters, $locale);
$envelope->setMessage($message);
}
if (Language::isRTL($locale)) {
$envelope->setOption('rtl', true);
}
}
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return 'Flasher\Prime\EventDispatcher\Event\PresentationEvent';
}
}

View File

@ -0,0 +1,25 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Exception;
final class PresetNotFoundException extends \Exception
{
/**
* @param string $preset
* @param string[] $availablePresets
*/
public function __construct($preset, array $availablePresets = array())
{
$message = sprintf('Preset "%s" not found, did you forget to register it?', $preset);
if (array() !== $availablePresets) {
$message .= sprintf(' Available presets: %s', implode(', ', $availablePresets));
}
parent::__construct($message);
}
}

View File

@ -0,0 +1,65 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Factory;
use Flasher\Prime\Notification\Notification;
use Flasher\Prime\Notification\NotificationBuilder;
use Flasher\Prime\Storage\StorageManager;
use Flasher\Prime\Storage\StorageManagerInterface;
class NotificationFactory implements NotificationFactoryInterface
{
/**
* @var StorageManagerInterface
*/
protected $storageManager;
/**
* @var string|null
*/
protected $handler;
/**
* @param string|null $handler
*/
public function __construct(StorageManagerInterface $storageManager = null, $handler = null)
{
$this->storageManager = $storageManager ?: new StorageManager();
$this->handler = $handler;
}
/**
* @param string $method
* @param mixed[] $parameters
*
* @return mixed
*/
public function __call($method, array $parameters)
{
/** @var callable $callback */
$callback = array($this->createNotificationBuilder(), $method);
return \call_user_func_array($callback, $parameters);
}
/**
* {@inheritdoc}
*/
public function createNotificationBuilder()
{
return new NotificationBuilder($this->getStorageManager(), new Notification(), $this->handler);
}
/**
* @return StorageManagerInterface
*/
public function getStorageManager()
{
return $this->storageManager;
}
}

View File

@ -0,0 +1,21 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Factory;
use Flasher\Prime\Notification\NotificationBuilderInterface;
/**
* @mixin NotificationBuilderInterface
*/
interface NotificationFactoryInterface
{
/**
* @return NotificationBuilderInterface
*/
public function createNotificationBuilder();
}

View File

@ -0,0 +1,233 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Filter;
use Flasher\Prime\Filter\Specification\CallbackSpecification;
use Flasher\Prime\Filter\Specification\DelaySpecification;
use Flasher\Prime\Filter\Specification\HopsSpecification;
use Flasher\Prime\Filter\Specification\PrioritySpecification;
use Flasher\Prime\Filter\Specification\StampsSpecification;
use Flasher\Prime\Stamp\StampInterface;
final class CriteriaBuilder
{
/**
* @var array<string, class-string<StampInterface>>
*/
public $aliases = array(
'context' => 'Flasher\Prime\Stamp\ContextStamp',
'created_at' => 'Flasher\Prime\Stamp\CreatedAtStamp',
'delay' => 'Flasher\Prime\Stamp\DelayStamp',
'handler' => 'Flasher\Prime\Stamp\HandlerStamp',
'hops' => 'Flasher\Prime\Stamp\HopsStamp',
'preset' => 'Flasher\Prime\Stamp\PresetStamp',
'priority' => 'Flasher\Prime\Stamp\PriorityStamp',
'translation' => 'Flasher\Prime\Stamp\TranslationStamp',
'unless' => 'Flasher\Prime\Stamp\UnlessStamp',
'uuid' => 'Flasher\Prime\Stamp\UuidStamp',
'view' => 'Flasher\Prime\Stamp\ViewStamp',
'when' => 'Flasher\Prime\Stamp\WhenStamp',
);
/**
* @var Filter
*/
private $filter;
/**
* @var array<string, mixed>
*/
private $criteria;
/**
* @param array<string, mixed> $criteria
*/
public function __construct(Filter $filter, array $criteria)
{
$this->filter = $filter;
$this->criteria = $criteria;
}
/**
* @return void
*/
public function build()
{
$this->buildPriority();
$this->buildHops();
$this->buildDelay();
$this->buildLife();
$this->buildOrder();
$this->buildLimit();
$this->buildStamps();
$this->buildCallback();
}
/**
* @return void
*/
public function buildPriority()
{
if (!isset($this->criteria['priority'])) {
return;
}
$criteria = $this->extractMinMax($this->criteria['priority']);
$this->filter->addSpecification(new PrioritySpecification($criteria['min'], $criteria['max']));
}
/**
* @return void
*/
public function buildHops()
{
if (!isset($this->criteria['hops'])) {
return;
}
$criteria = $this->extractMinMax($this->criteria['hops']);
$this->filter->addSpecification(new HopsSpecification($criteria['min'], $criteria['max']));
}
/**
* @return void
*/
public function buildDelay()
{
if (!isset($this->criteria['delay'])) {
return;
}
$criteria = $this->extractMinMax($this->criteria['delay']);
$this->filter->addSpecification(new DelaySpecification($criteria['min'], $criteria['max']));
}
/**
* @return void
*/
public function buildLife()
{
if (!isset($this->criteria['life'])) {
return;
}
$criteria = $this->extractMinMax($this->criteria['life']);
$this->filter->addSpecification(new HopsSpecification($criteria['min'], $criteria['max']));
}
/**
* @return void
*/
public function buildOrder()
{
if (!isset($this->criteria['order_by'])) {
return;
}
$orderings = array();
/**
* @var int|string $field
* @var string $direction
*/
foreach ((array) $this->criteria['order_by'] as $field => $direction) {
if (\is_int($field)) {
$field = $direction;
$direction = Filter::ASC;
}
$direction = Filter::ASC === strtoupper($direction) ? Filter::ASC : Filter::DESC;
if (\array_key_exists($field, $this->aliases)) {
$field = $this->aliases[$field];
}
$orderings[$field] = $direction;
}
$this->filter->orderBy($orderings);
}
/**
* @return void
*/
public function buildLimit()
{
if (!isset($this->criteria['limit'])) {
return;
}
/** @var int $limit */
$limit = $this->criteria['limit'];
$this->filter->setMaxResults((int) $limit);
}
/**
* @return void
*/
public function buildStamps()
{
if (!isset($this->criteria['stamps'])) {
return;
}
/** @var string $strategy */
$strategy = isset($this->criteria['stamps_strategy']) ? $this->criteria['stamps_strategy'] : StampsSpecification::STRATEGY_OR;
/** @var array<string, class-string<StampInterface>> $stamps */
$stamps = (array) $this->criteria['stamps'];
/**
* @var string $key
* @var class-string<StampInterface> $value
*/
foreach ($stamps as $key => $value) {
if (\array_key_exists($value, $this->aliases)) {
$stamps[$key] = $this->aliases[$value];
}
}
$this->filter->addSpecification(new StampsSpecification($stamps, $strategy));
}
/**
* @return void
*/
public function buildCallback()
{
if (!isset($this->criteria['filter'])) {
return;
}
/** @var callable $callback */
foreach ((array) $this->criteria['filter'] as $callback) {
$this->filter->addSpecification(new CallbackSpecification($this->filter, $callback));
}
}
/**
* @param mixed $criteria
*
* @return array{min: int, max: int}
*/
private function extractMinMax($criteria)
{
if (!\is_array($criteria)) {
$criteria = array('min' => $criteria);
}
$min = isset($criteria['min']) ? $criteria['min'] : null;
$max = isset($criteria['max']) ? $criteria['max'] : null;
return array('min' => $min, 'max' => $max);
}
}

View File

@ -0,0 +1,177 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Filter;
use Flasher\Prime\Filter\Specification\AndSpecification;
use Flasher\Prime\Filter\Specification\SpecificationInterface;
use Flasher\Prime\Notification\Envelope;
use Flasher\Prime\Stamp\OrderableStampInterface;
use Flasher\Prime\Stamp\StampInterface;
final class Filter
{
const ASC = 'ASC';
const DESC = 'DESC';
/**
* @var Envelope[]
*/
private $envelopes;
/**
* @var array<string, mixed>
*/
private $criteria;
/**
* @var SpecificationInterface
*/
private $specification;
/**
* @var array<string, string>
*/
private $orderings = array();
/**
* @var int|null
*/
private $maxResults;
/**
* @param Envelope[] $envelopes
* @param array<string, mixed> $criteria
*/
public function __construct(array $envelopes, array $criteria)
{
$this->envelopes = $envelopes;
$this->criteria = $criteria;
}
/**
* @return Envelope[]
*/
public function getResult()
{
$criteriaBuilder = new CriteriaBuilder($this, $this->criteria);
$criteriaBuilder->build();
$this->applySpecification();
$this->applyOrdering();
$this->applyLimit();
return array_values($this->envelopes);
}
/**
* @return Envelope[]
*/
public function getEnvelopes()
{
return $this->envelopes;
}
/**
* @return array<string, mixed>
*/
public function getCriteria()
{
return $this->criteria;
}
/**
* @return void
*/
public function addSpecification(SpecificationInterface $specification)
{
$this->specification = null !== $this->specification
? new AndSpecification($this->specification, $specification)
: $specification;
}
/**
* @param array<string, string> $orderings
*
* @return void
*/
public function orderBy(array $orderings)
{
$this->orderings = $orderings;
}
/**
* @param int $maxResults
*
* @return void
*/
public function setMaxResults($maxResults)
{
$this->maxResults = $maxResults;
}
/**
* @return void
*/
private function applySpecification()
{
if (null === $this->specification) {
return;
}
$specification = $this->specification;
$this->envelopes = array_filter($this->envelopes, function (Envelope $envelope) use ($specification) {
return $specification->isSatisfiedBy($envelope);
});
}
/**
* @return void
*/
private function applyOrdering()
{
if (array() === $this->orderings) {
return;
}
$orderings = $this->orderings;
usort($this->envelopes, function (Envelope $first, Envelope $second) use ($orderings) {
/**
* @var class-string<StampInterface> $field
* @var string $ordering
*/
foreach ($orderings as $field => $ordering) {
$stampA = $first->get($field);
$stampB = $second->get($field);
if (!$stampA instanceof OrderableStampInterface || !$stampB instanceof OrderableStampInterface) {
return 0;
}
if (Filter::ASC === $ordering) {
return $stampA->compare($stampB);
}
return $stampB->compare($stampA);
}
return 0;
});
}
/**
* @return void
*/
private function applyLimit()
{
if (null === $this->maxResults) {
return;
}
$this->envelopes = \array_slice($this->envelopes, 0, $this->maxResults, true);
}
}

View File

@ -0,0 +1,42 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Filter\Specification;
use Flasher\Prime\Notification\Envelope;
final class AndSpecification implements SpecificationInterface
{
/**
* @var SpecificationInterface[]
*/
private $specifications;
/**
* @param SpecificationInterface|SpecificationInterface[] $specifications
*/
public function __construct($specifications)
{
$specifications = \is_array($specifications) ? $specifications : \func_get_args();
$this->specifications = $specifications;
}
/**
* {@inheritdoc}
*/
public function isSatisfiedBy(Envelope $envelope)
{
foreach ($this->specifications as $specification) {
if (!$specification->isSatisfiedBy($envelope)) {
return false;
}
}
return true;
}
}

View File

@ -0,0 +1,41 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Filter\Specification;
use Flasher\Prime\Filter\Filter;
use Flasher\Prime\Notification\Envelope;
final class CallbackSpecification implements SpecificationInterface
{
/**
* @var Filter
*/
private $filter;
/**
* @var callable
*/
private $callback;
/**
* @param callable $callback
*/
public function __construct(Filter $filterBuilder, $callback)
{
$this->filter = $filterBuilder;
$this->callback = $callback;
}
/**
* {@inheritdoc}
*/
public function isSatisfiedBy(Envelope $envelope)
{
return (bool) \call_user_func($this->callback, $envelope, $this->filter);
}
}

View File

@ -0,0 +1,52 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Filter\Specification;
use Flasher\Prime\Notification\Envelope;
use Flasher\Prime\Stamp\DelayStamp;
final class DelaySpecification implements SpecificationInterface
{
/**
* @var int
*/
private $minDelay;
/**
* @var int|null
*/
private $maxDelay;
/**
* @param int $minDelay
* @param int|null $maxDelay
*/
public function __construct($minDelay, $maxDelay = null)
{
$this->minDelay = $minDelay;
$this->maxDelay = $maxDelay;
}
/**
* {@inheritdoc}
*/
public function isSatisfiedBy(Envelope $envelope)
{
$stamp = $envelope->get('Flasher\Prime\Stamp\DelayStamp');
if (!$stamp instanceof DelayStamp) {
return false;
}
if (null !== $this->maxDelay && $stamp->getDelay() > $this->maxDelay) {
return false;
}
return $stamp->getDelay() >= $this->minDelay;
}
}

View File

@ -0,0 +1,52 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Filter\Specification;
use Flasher\Prime\Notification\Envelope;
use Flasher\Prime\Stamp\HopsStamp;
final class HopsSpecification implements SpecificationInterface
{
/**
* @var int
*/
private $minAmount;
/**
* @var int|null
*/
private $maxAmount;
/**
* @param int $minAmount
* @param int|null $maxAmount
*/
public function __construct($minAmount, $maxAmount = null)
{
$this->minAmount = $minAmount;
$this->maxAmount = $maxAmount;
}
/**
* {@inheritdoc}
*/
public function isSatisfiedBy(Envelope $envelope)
{
$stamp = $envelope->get('Flasher\Prime\Stamp\HopsStamp');
if (!$stamp instanceof HopsStamp) {
return false;
}
if (null !== $this->maxAmount && $stamp->getAmount() > $this->maxAmount) {
return false;
}
return $stamp->getAmount() >= $this->minAmount;
}
}

View File

@ -0,0 +1,52 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Filter\Specification;
use Flasher\Prime\Notification\Envelope;
use Flasher\Prime\Stamp\PriorityStamp;
final class PrioritySpecification implements SpecificationInterface
{
/**
* @var int
*/
private $minPriority;
/**
* @var int|null
*/
private $maxPriority;
/**
* @param int $minPriority
* @param int|null $maxPriority
*/
public function __construct($minPriority, $maxPriority = null)
{
$this->minPriority = $minPriority;
$this->maxPriority = $maxPriority;
}
/**
* {@inheritdoc}
*/
public function isSatisfiedBy(Envelope $envelope)
{
$stamp = $envelope->get('Flasher\Prime\Stamp\PriorityStamp');
if (!$stamp instanceof PriorityStamp) {
return false;
}
if (null !== $this->maxPriority && $stamp->getPriority() > $this->maxPriority) {
return false;
}
return $stamp->getPriority() >= $this->minPriority;
}
}

View File

@ -0,0 +1,18 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Filter\Specification;
use Flasher\Prime\Notification\Envelope;
interface SpecificationInterface
{
/**
* @return bool
*/
public function isSatisfiedBy(Envelope $envelope);
}

View File

@ -0,0 +1,50 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Filter\Specification;
use Flasher\Prime\Notification\Envelope;
final class StampsSpecification implements SpecificationInterface
{
const STRATEGY_AND = 'and';
const STRATEGY_OR = 'or';
/**
* @var array|string[]
*/
private $stamps;
/**
* @var string
*/
private $strategy;
/**
* @param string|string[] $stamps
* @param string $strategy
*/
public function __construct($stamps, $strategy)
{
$this->stamps = (array) $stamps;
$this->strategy = $strategy;
}
/**
* {@inheritdoc}
*/
public function isSatisfiedBy(Envelope $envelope)
{
$diff = array_diff($this->stamps, array_keys($envelope->all()));
if (self::STRATEGY_AND === $this->strategy) {
return 0 === \count($diff);
}
return \count($diff) < \count($this->stamps);
}
}

118
vendor/php-flasher/flasher/Flasher.php vendored Normal file
View File

@ -0,0 +1,118 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime;
use Flasher\Prime\Factory\NotificationFactory;
use Flasher\Prime\Factory\NotificationFactoryInterface;
use Flasher\Prime\Notification\NotificationBuilderInterface;
use Flasher\Prime\Response\ResponseManager;
use Flasher\Prime\Response\ResponseManagerInterface;
use Flasher\Prime\Storage\StorageManagerInterface;
/**
* @mixin NotificationBuilderInterface
*/
final class Flasher implements FlasherInterface
{
/**
* @var string|null
*/
private $defaultHandler;
/**
* @var ResponseManagerInterface
*/
private $responseManager;
/**
* @var StorageManagerInterface|null
*/
private $storageManager;
/**
* @var array<string, callable|NotificationFactoryInterface>
*/
private $factories = array();
/**
* @param string $defaultHandler
*/
public function __construct($defaultHandler, ResponseManagerInterface $responseManager = null, StorageManagerInterface $storageManager = null)
{
$this->defaultHandler = $defaultHandler ?: 'flasher';
$this->responseManager = $responseManager ?: new ResponseManager();
$this->storageManager = $storageManager;
}
/**
* Dynamically call the default factory instance.
*
* @param string $method
* @param mixed[] $parameters
*
* @return mixed
*/
public function __call($method, array $parameters)
{
/** @var callable $callback */
$callback = array($this->create(), $method);
return \call_user_func_array($callback, $parameters);
}
/**
* {@inheritdoc}
*/
public function create($alias = null)
{
$alias = trim($alias ?: $this->defaultHandler ?: '');
if (0 === strpos($alias, 'template.')) {
$alias = 'theme.'.substr($alias, \strlen('template.'));
@trigger_error('Since php-flasher/flasher v1.0, the "template." prefix is deprecated and will be removed in v2.0. Use "theme." instead.', \E_USER_DEPRECATED);
}
if (empty($alias)) {
throw new \InvalidArgumentException('Unable to resolve empty factory.');
}
if (!isset($this->factories[$alias])) {
$this->addFactory($alias, new NotificationFactory($this->storageManager, $alias));
}
$factory = $this->factories[$alias];
return \is_callable($factory) ? $factory() : $factory;
}
/**
* {@inheritdoc}
*/
public function using($alias)
{
return $this->create($alias);
}
/**
* {@inheritdoc}
*/
public function render(array $criteria = array(), $presenter = 'html', array $context = array())
{
return $this->responseManager->render($criteria, $presenter, $context);
}
/**
* {@inheritdoc}
*/
public function addFactory($alias, $factory)
{
$this->factories[$alias] = $factory;
return $this;
}
}

View File

@ -0,0 +1,60 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime;
use Flasher\Prime\Factory\NotificationFactoryInterface;
use Flasher\Prime\Notification\NotificationBuilderInterface;
/**
* @mixin NotificationBuilderInterface
*/
interface FlasherInterface
{
/**
* Get a driver instance.
*
* @param string|null $alias
*
* @return NotificationFactoryInterface
*
* @throws \InvalidArgumentException
*/
public function create($alias = null);
/**
* Get a driver instance.
*
* @param string|null $alias
*
* @return NotificationFactoryInterface
*
* @throws \InvalidArgumentException
*/
public function using($alias);
/**
* Register a custom driver creator.
*
* @param string $alias
* @param callable|NotificationFactoryInterface $factory
*
* @return static
*/
public function addFactory($alias, $factory);
/**
* @param array<string, mixed> $criteria
* @param string $presenter
* @param array<string, mixed> $context
*
* @return mixed
*
* @phpstan-return ($presenter is 'html' ? string : mixed)
*/
public function render(array $criteria = array(), $presenter = 'html', array $context = array());
}

View File

@ -0,0 +1,76 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Http;
use Flasher\Prime\FlasherInterface;
final class RequestExtension
{
/**
* @var FlasherInterface
*/
private $flasher;
/**
* @var array<string, string>
*/
private $mapping;
/**
* @param array<string, string[]> $mapping
*/
public function __construct(FlasherInterface $flasher, array $mapping = array())
{
$this->flasher = $flasher;
$this->mapping = $this->flatMapping($mapping);
}
/**
* @return ResponseInterface
*/
public function flash(RequestInterface $request, ResponseInterface $response)
{
if (!$request->hasSession()) {
return $response;
}
foreach ($this->mapping as $alias => $type) {
if (false === $request->hasType($alias)) {
continue;
}
$messages = (array) $request->getType($alias);
foreach ($messages as $message) {
$this->flasher->addFlash($type, $message);
}
$request->forgetType($alias);
}
return $response;
}
/**
* @param array<string, string[]> $mapping
*
* @return array<string, string>
*/
private function flatMapping(array $mapping)
{
$flatMapping = array();
foreach ($mapping as $type => $aliases) {
foreach ($aliases as $alias) {
$flatMapping[$alias] = $type;
}
}
return $flatMapping;
}
}

View File

@ -0,0 +1,47 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Http;
interface RequestInterface
{
/**
* @return bool
*/
public function isXmlHttpRequest();
/**
* @return bool
*/
public function isHtmlRequestFormat();
/**
* @return bool
*/
public function hasSession();
/**
* @param string $type
*
* @return bool
*/
public function hasType($type);
/**
* @param string $type
*
* @return string|string[]
*/
public function getType($type);
/**
* @param string $type
*
* @return void
*/
public function forgetType($type);
}

View File

@ -0,0 +1,84 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Http;
use Flasher\Prime\FlasherInterface;
use Flasher\Prime\Response\Presenter\HtmlPresenter;
final class ResponseExtension
{
/**
* @var FlasherInterface
*/
private $flasher;
public function __construct(FlasherInterface $flasher)
{
$this->flasher = $flasher;
}
/**
* @return ResponseInterface
*/
public function render(RequestInterface $request, ResponseInterface $response)
{
if (!$this->isRenderable($request, $response)) {
return $response;
}
$content = $response->getContent() ?: '';
if (!\is_string($content)) {
return $response;
}
$placeHolders = array(
HtmlPresenter::FLASHER_FLASH_BAG_PLACE_HOLDER,
HtmlPresenter::HEAD_END_PLACE_HOLDER,
HtmlPresenter::BODY_END_PLACE_HOLDER,
);
foreach ($placeHolders as $insertPlaceHolder) {
$insertPosition = strripos($content, $insertPlaceHolder);
if (false !== $insertPosition) {
break;
}
}
if (false === $insertPosition) {
return $response;
}
$alreadyRendered = HtmlPresenter::FLASHER_FLASH_BAG_PLACE_HOLDER === $insertPlaceHolder;
$htmlResponse = $this->flasher->render(array(), 'html', array('envelopes_only' => $alreadyRendered));
if (empty($htmlResponse)) {
return $response;
}
$htmlResponse = "\n".str_replace("\n", '', $htmlResponse)."\n";
$offset = $alreadyRendered ? strlen(HtmlPresenter::FLASHER_FLASH_BAG_PLACE_HOLDER) : 0;
$content = substr($content, 0, $insertPosition).$htmlResponse.substr($content, $insertPosition + $offset);
$response->setContent($content);
return $response;
}
/**
* @return bool
*/
private function isRenderable(RequestInterface $request, ResponseInterface $response)
{
return !$request->isXmlHttpRequest()
&& $request->isHtmlRequestFormat()
&& !$response->isRedirection()
&& $response->isHtml()
&& !$response->isAttachment()
&& !$response->isJson();
}
}

View File

@ -0,0 +1,43 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Http;
interface ResponseInterface
{
/**
* @return bool
*/
public function isRedirection();
/**
* @return bool
*/
public function isJson();
/**
* @return bool
*/
public function isHtml();
/**
* @return bool
*/
public function isAttachment();
/**
* @return string
*/
public function getContent();
/**
* @param string $content
*
* @return void
*/
public function setContent($content);
}

21
vendor/php-flasher/flasher/LICENSE vendored Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 PHPFlasher
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,259 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Notification;
use Flasher\Prime\Stamp\PresentableStampInterface;
use Flasher\Prime\Stamp\StampInterface;
final class Envelope implements NotificationInterface
{
/**
* @var NotificationInterface
*/
private $notification;
/**
* @var array<class-string<StampInterface>, StampInterface>
*/
private $stamps = array();
/**
* @param StampInterface|StampInterface[] $stamps
*/
public function __construct(NotificationInterface $notification, $stamps = array())
{
$this->notification = $notification;
$this->with(\is_array($stamps) ? $stamps : \array_slice(\func_get_args(), 1));
}
/**
* Dynamically call methods on the notification.
*
* @param string $method
* @param mixed[] $parameters
*
* @return mixed
*/
public function __call($method, array $parameters)
{
/** @var callable $callback */
$callback = array($this->getNotification(), $method);
return \call_user_func_array($callback, $parameters);
}
/**
* Makes sure the notification is in an Envelope and adds the given stamps.
*
* @param StampInterface|StampInterface[] $stamps
*
* @return static
*/
public static function wrap(NotificationInterface $notification, $stamps = array())
{
$envelope = $notification instanceof self ? $notification : new self($notification);
return $envelope->with(\is_array($stamps) ? $stamps : \array_slice(\func_get_args(), 1));
}
/**
* @param StampInterface|StampInterface[] $stamps
*
* @return static
*/
public function with($stamps)
{
$stamps = \is_array($stamps) ? $stamps : \func_get_args();
foreach ($stamps as $stamp) {
$this->withStamp($stamp);
}
return $this;
}
/**
* @return static
*/
public function withStamp(StampInterface $stamp)
{
$this->stamps[\get_class($stamp)] = $stamp;
return $this;
}
/**
* @param StampInterface|StampInterface[] $stamps
*
* @return static
*/
public function without($stamps)
{
$stamps = \is_array($stamps) ? $stamps : \func_get_args();
foreach ($stamps as $stamp) {
$this->withoutStamp($stamp);
}
return $this;
}
/**
* @param class-string<StampInterface>|StampInterface $type
*
* @return static
*/
public function withoutStamp($type)
{
$type = $type instanceof StampInterface ? \get_class($type) : $type;
unset($this->stamps[$type]);
return $this;
}
/**
* @param class-string<StampInterface> $stampFqcn
*
* @return StampInterface|null
*/
public function get($stampFqcn)
{
if (!isset($this->stamps[$stampFqcn])) {
return null;
}
return $this->stamps[$stampFqcn];
}
/**
* All stamps by their class name.
*
* @return array<class-string<StampInterface>, StampInterface>
*/
public function all()
{
return $this->stamps;
}
/**
* The original notification contained in the envelope.
*
* @return NotificationInterface
*/
public function getNotification()
{
return $this->notification;
}
/**
* {@inheritdoc}
*/
public function getType()
{
return $this->notification->getType();
}
/**
* {@inheritdoc}
*/
public function setType($type)
{
return $this->notification->setType($type); // @phpstan-ignore-line
}
/**
* {@inheritdoc}
*/
public function getMessage()
{
return $this->notification->getMessage();
}
/**
* {@inheritdoc}
*/
public function setMessage($message)
{
return $this->notification->setMessage($message); // @phpstan-ignore-line
}
/**
* {@inheritdoc}
*/
public function getTitle()
{
return $this->notification->getTitle();
}
/**
* {@inheritdoc}
*/
public function setTitle($title)
{
return $this->notification->setTitle($title); // @phpstan-ignore-line
}
/**
* {@inheritdoc}
*/
public function getOptions()
{
return $this->notification->getOptions();
}
/**
* {@inheritdoc}
*/
public function setOptions(array $options)
{
return $this->notification->setOptions($options); // @phpstan-ignore-line
}
/**
* {@inheritdoc}
*/
public function getOption($name, $default = null)
{
return $this->notification->getOption($name, $default);
}
/**
* {@inheritdoc}
*/
public function setOption($name, $value)
{
return $this->notification->setOption($name, $value); // @phpstan-ignore-line
}
/**
* {@inheritdoc}
*/
public function unsetOption($name)
{
return $this->notification->unsetOption($name); // @phpstan-ignore-line
}
/**
* {@inheritdoc}
*/
public function toArray()
{
$array = array(
'notification' => $this->notification->toArray(),
);
foreach ($this->all() as $stamp) {
if ($stamp instanceof PresentableStampInterface) {
$array = array_merge($array, $stamp->toArray());
}
}
return $array;
}
}

View File

@ -0,0 +1,148 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Notification;
class Notification implements NotificationInterface
{
/**
* @var string|null
*/
protected $message;
/**
* @var string|null
*/
protected $type;
/**
* @var array<string, mixed>
*/
protected $options = array();
/**
* @var string|null
*/
private $title;
/**
* {@inheritdoc}
*/
public function getType()
{
return $this->type;
}
/**
* {@inheritdoc}
*/
public function setType($type)
{
$this->type = $type;
return $this;
}
/**
* {@inheritdoc}
*/
public function getMessage()
{
return $this->message;
}
/**
* {@inheritdoc}
*/
public function setMessage($message)
{
$this->message = $message;
return $this;
}
/**
* {@inheritdoc}
*/
public function getTitle()
{
return $this->title;
}
/**
* {@inheritdoc}
*/
public function setTitle($title)
{
$this->title = $title;
return $this;
}
/**
* {@inheritdoc}
*/
public function getOptions()
{
return $this->options;
}
/**
* {@inheritdoc}
*/
public function setOptions(array $options)
{
$this->options = array_replace($this->options, $options);
return $this;
}
/**
* {@inheritdoc}
*/
public function getOption($name, $default = null)
{
if (!isset($this->options[$name])) {
return $default;
}
return $this->options[$name];
}
/**
* {@inheritdoc}
*/
public function setOption($name, $value)
{
$this->options[$name] = $value;
return $this;
}
/**
* {@inheritdoc}
*/
public function unsetOption($name)
{
unset($this->options[$name]);
return $this;
}
/**
* {@inheritdoc}
*/
public function toArray()
{
return array(
'type' => $this->getType(),
'message' => $this->getMessage(),
'title' => $this->getTitle(),
'options' => $this->getOptions(),
);
}
}

View File

@ -0,0 +1,647 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Notification;
use Flasher\Prime\Stamp\ContextStamp;
use Flasher\Prime\Stamp\DelayStamp;
use Flasher\Prime\Stamp\HandlerStamp;
use Flasher\Prime\Stamp\HopsStamp;
use Flasher\Prime\Stamp\PresetStamp;
use Flasher\Prime\Stamp\PriorityStamp;
use Flasher\Prime\Stamp\StampInterface;
use Flasher\Prime\Stamp\TranslationStamp;
use Flasher\Prime\Stamp\UnlessStamp;
use Flasher\Prime\Stamp\WhenStamp;
use Flasher\Prime\Storage\StorageManagerInterface;
use Flasher\Prime\Translation\ResourceInterface;
/**
* @SuppressWarnings(PHPMD.TooManyPublicMethods)
*/
class NotificationBuilder implements NotificationBuilderInterface
{
/**
* @var Envelope
*/
protected $envelope;
/**
* @var StorageManagerInterface
*/
protected $storageManager;
/**
* @var array<string, callable>
*/
protected static $macros = array();
/**
* @param string $handler
*/
public function __construct(StorageManagerInterface $storageManager, NotificationInterface $notification, $handler = null)
{
$this->storageManager = $storageManager;
$this->envelope = Envelope::wrap($notification);
if (null !== $handler) {
$this->handler($handler);
}
}
/**
* @param string $method
* @param mixed[] $parameters
*
* @return mixed
*/
public static function __callStatic($method, $parameters)
{
if (!static::hasMacro($method)) {
throw new \BadMethodCallException(sprintf('Method %s::%s does not exist.', \get_called_class(), $method));
}
$macro = static::$macros[$method];
if ($macro instanceof \Closure) {
/** @var callable $callback */
$callback = \Closure::bind($macro, null, \get_called_class());
return \call_user_func_array($callback, $parameters);
}
return \call_user_func_array($macro, $parameters);
}
/**
* @param string $method
* @param mixed[] $parameters
*
* @return mixed
*/
public function __call($method, $parameters)
{
if (!static::hasMacro($method)) {
throw new \BadMethodCallException(sprintf('Method %s::%s does not exist.', \get_called_class(), $method));
}
$macro = static::$macros[$method];
if ($macro instanceof \Closure) {
/** @var callable $callback */
$callback = $macro->bindTo($this, \get_called_class());
return \call_user_func_array($callback, $parameters);
}
return \call_user_func_array($macro, $parameters);
}
/**
* {@inheritdoc}
*/
public function addSuccess($message, $title = null, array $options = array())
{
return $this->addFlash(NotificationInterface::SUCCESS, $message, $title, $options);
}
/**
* {@inheritdoc}
*/
public function addError($message, $title = null, array $options = array())
{
return $this->addFlash(NotificationInterface::ERROR, $message, $title, $options);
}
/**
* {@inheritdoc}
*/
public function addWarning($message, $title = null, array $options = array())
{
return $this->addFlash(NotificationInterface::WARNING, $message, $title, $options);
}
/**
* {@inheritdoc}
*/
public function addInfo($message, $title = null, array $options = array())
{
return $this->addFlash(NotificationInterface::INFO, $message, $title, $options);
}
/**
* {@inheritdoc}
*/
public function addFlash($type, $message = null, $title = null, array $options = array())
{
if ($type instanceof NotificationInterface) {
$this->envelope = Envelope::wrap($type);
$type = $this->envelope->getType();
}
$this->type($type, $message, $title, $options); // @phpstan-ignore-line
return $this->push();
}
/**
* {@inheritdoc}
*/
public function push(array $stamps = array())
{
if (array() !== $stamps) {
$this->with($stamps);
}
$this->storageManager->add($this->getEnvelope());
return $this->getEnvelope();
}
/**
* {@inheritdoc}
*/
public function flash(array $stamps = array())
{
@trigger_error('Since php-flasher/flasher v1.12: Using "flash()" method is deprecated and will be removed in v2.0. please use the "push()" method instead.', \E_USER_DEPRECATED);
return $this->push($stamps);
}
/**
* {@inheritdoc}
*/
public function type($type, $message = null, $title = null, array $options = array())
{
$this->envelope->setType($type);
if (null !== $message) {
$this->message($message);
}
if (\is_array($title)) {
$options = $title;
$title = null;
@trigger_error('Since php-flasher/flasher v1.0: Passing an array for the "title" parameter is deprecated and will be removed in v2.0. You should pass a string instead.', \E_USER_DEPRECATED);
}
if (null !== $title) {
$this->title($title);
}
if (array() !== $options) {
$this->options($options, false);
}
return $this;
}
/**
* {@inheritdoc}
*/
public function message($message)
{
$this->envelope->setMessage($message);
return $this;
}
/**
* {@inheritdoc}
*/
public function title($title)
{
$this->envelope->setTitle($title);
return $this;
}
/**
* {@inheritdoc}
*/
public function options(array $options, $merge = true)
{
if (true === $merge) {
$options = array_merge($this->envelope->getOptions(), $options);
}
$this->envelope->setOptions($options);
return $this;
}
/**
* {@inheritdoc}
*/
public function option($name, $value)
{
$this->envelope->setOption($name, $value);
return $this;
}
/**
* {@inheritdoc}
*/
public function success($message = null, $title = null, array $options = array())
{
@trigger_error('In php-flasher/flasher v2.0, the "success()" method will be an alias of "addSuccess()" method as it will immediately call the `->flash()` method. Use the "type(\'success\')" method instead to avoid this breaking change.', \E_USER_DEPRECATED);
return $this->type(NotificationInterface::SUCCESS, $message, $title, $options);
}
/**
* {@inheritdoc}
*/
public function error($message = null, $title = null, array $options = array())
{
@trigger_error('In php-flasher/flasher v2.0, the "error()" method will be an alias of "addError()" method as it will immediately call the `->flash()` method. Use the "type(\'error\')" method instead to avoid this breaking change.', \E_USER_DEPRECATED);
return $this->type(NotificationInterface::ERROR, $message, $title, $options);
}
/**
* {@inheritdoc}
*/
public function info($message = null, $title = null, array $options = array())
{
@trigger_error('In php-flasher/flasher v2.0, the "info()" method will be an alias of "addInfo()" method as it will immediately call the `->flash()` method. Use the "type(\'info\')" method instead to avoid this breaking change.', \E_USER_DEPRECATED);
return $this->type(NotificationInterface::INFO, $message, $title, $options);
}
/**
* {@inheritdoc}
*/
public function warning($message = null, $title = null, array $options = array())
{
@trigger_error('In php-flasher/flasher v2.0, the "warning()" method will be an alias of "addWarning()" method as it will immediately call the `->flash()` method. Use the "type(\'warning\')" method instead to avoid this breaking change.', \E_USER_DEPRECATED);
return $this->type(NotificationInterface::WARNING, $message, $title, $options);
}
/**
* {@inheritdoc}
*/
public function when($condition)
{
if ($condition instanceof \Closure) {
$condition = \call_user_func($condition, $this->envelope);
}
if (!\is_bool($condition)) {
throw new \InvalidArgumentException('The condition must be a boolean or a closure that returns a boolean.');
}
$stamp = $this->envelope->get('Flasher\Prime\Stamp\WhenStamp');
if ($stamp instanceof WhenStamp) {
$condition = $stamp->getCondition() && $condition;
}
$this->envelope->withStamp(new WhenStamp($condition));
return $this;
}
/**
* {@inheritdoc}
*/
public function unless($condition)
{
if ($condition instanceof \Closure) {
$condition = \call_user_func($condition, $this->envelope);
}
if (!\is_bool($condition)) {
throw new \InvalidArgumentException('The condition must be a boolean or a closure that returns a boolean.');
}
$stamp = $this->envelope->get('Flasher\Prime\Stamp\UnlessStamp');
if ($stamp instanceof UnlessStamp) {
$condition = $stamp->getCondition() || $condition;
}
$this->envelope->withStamp(new UnlessStamp($condition));
return $this;
}
/**
* {@inheritdoc}
*/
public function priority($priority)
{
$this->envelope->withStamp(new PriorityStamp($priority));
return $this;
}
/**
* {@inheritdoc}
*/
public function hops($amount)
{
$this->envelope->withStamp(new HopsStamp($amount));
return $this;
}
/**
* {@inheritdoc}
*/
public function keep()
{
$hopsStamp = $this->envelope->get('Flasher\Prime\Stamp\HopsStamp');
$amount = $hopsStamp instanceof HopsStamp ? $hopsStamp->getAmount() : 1;
$this->envelope->withStamp(new HopsStamp($amount + 1));
return $this;
}
/**
* {@inheritdoc}
*/
public function delay($delay)
{
$this->envelope->withStamp(new DelayStamp($delay));
return $this;
}
/**
* {@inheritdoc}
*/
public function now()
{
return $this->delay(0);
}
/**
* {@inheritdoc}
*/
public function translate($parameters = array(), $locale = null)
{
$order = TranslationStamp::parametersOrder($parameters, $locale);
$parameters = $order['parameters'];
$locale = $order['locale'];
$this->envelope->withStamp(new TranslationStamp($parameters, $locale));
return $this;
}
/**
* {@inheritdoc}
*/
public function addPreset($preset, $parameters = array())
{
$this->preset($preset, $parameters);
return $this->push();
}
/**
* {@inheritdoc}
*/
public function addOperation($operation, $resource = null)
{
$this->operation($operation, $resource);
return $this->push();
}
/**
* {@inheritdoc}
*/
public function addCreated($resource = null)
{
return $this->addOperation('created', $resource);
}
/**
* {@inheritdoc}
*/
public function addUpdated($resource = null)
{
return $this->addOperation('updated', $resource);
}
/**
* {@inheritdoc}
*/
public function addSaved($resource = null)
{
return $this->addOperation('saved', $resource);
}
/**
* {@inheritdoc}
*/
public function addDeleted($resource = null)
{
return $this->addOperation('deleted', $resource);
}
/**
* {@inheritdoc}
*/
public function preset($preset, $parameters = array())
{
@trigger_error('In php-flasher/flasher v2.0, the "preset()" method will be an alias of "addPreset()" method as will immediately call the `->flash()` method. Use the "addPreset()" method instead to avoid this breaking change.', \E_USER_WARNING);
$flash = false;
if (\is_bool($parameters)) { /** @phpstan-ignore-line */
$flash = $parameters;
$parameters = array();
@trigger_error('Since php-flasher/flasher v1.5: automatically flashing a preset is deprecated and will be removed in v2.0. You should use addPreset() or chain the preset call with flash() instead.', \E_USER_DEPRECATED);
}
$this->envelope->withStamp(new PresetStamp($preset, $parameters));
if (false === $flash) {
return $this;
}
return $this->push(); // @phpstan-ignore-line
}
/**
* {@inheritdoc}
*/
public function operation($operation, $resource = null)
{
@trigger_error('In php-flasher/flasher v2.0, the "operation()" method will be an alias of "addOperation()" method as will immediately call the `->flash()` method. Use the "addOperation()" method instead to avoid this breaking change.', \E_USER_WARNING);
if ($resource instanceof ResourceInterface) {
$type = $resource->getResourceType();
$name = $resource->getResourceName();
$resource = sprintf(
'%s %s',
$type,
empty($name) ? '' : sprintf('"%s"', $name)
);
}
$parameters = array(
'resource' => $resource ?: 'resource',
);
return $this->preset($operation, $parameters);
}
/**
* {@inheritdoc}
*/
public function created($resource = null)
{
@trigger_error('In php-flasher/flasher v2.0, the "created()" method will be an alias of "addCreated()" method as will immediately call the `->flash()` method. Use the "addCreated()" method instead to avoid this breaking change.', \E_USER_WARNING);
return $this->operation('created', $resource);
}
/**
* {@inheritdoc}
*/
public function updated($resource = null)
{
@trigger_error('In php-flasher/flasher v2.0, the "updated()" method will be an alias of "addUpdated()" method as will immediately call the `->flash()` method. Use the "addUpdated()" method instead to avoid this breaking change.', \E_USER_WARNING);
return $this->operation('updated', $resource);
}
/**
* {@inheritdoc}
*/
public function saved($resource = null)
{
@trigger_error('In php-flasher/flasher v2.0, the "saved()" method will be an alias of "addSaved()" method as will immediately call the `->flash()` method. Use the "addSaved()" method instead to avoid this breaking change.', \E_USER_WARNING);
return $this->operation('saved', $resource);
}
/**
* {@inheritdoc}
*/
public function deleted($resource = null)
{
@trigger_error('In php-flasher/flasher v2.0, the "deleted()" method will be an alias of "addDeleted()" method as will immediately call the `->flash()` method. Use the "addDeleted()" method instead to avoid this breaking change.', \E_USER_WARNING);
return $this->operation('deleted', $resource);
}
/**
* {@inheritdoc}
*/
public function with($stamps = array())
{
$this->envelope->with($stamps);
return $this;
}
/**
* {@inheritdoc}
*/
public function withStamp(StampInterface $stamp)
{
$this->envelope->withStamp($stamp);
return $this;
}
/**
* {@inheritdoc}
*/
public function getEnvelope()
{
return $this->envelope;
}
/**
* {@inheritdoc}
*/
public function handler($handler)
{
$stamp = $this->envelope->get('Flasher\Prime\Stamp\HandlerStamp');
if ($stamp instanceof HandlerStamp) {
throw new \LogicException('You cannot change the handler of a notification once it has been set.');
}
$this->envelope->withStamp(new HandlerStamp($handler));
return $this;
}
/**
* {@inheritdoc}
*/
public function context(array $context)
{
$this->envelope->withStamp(new ContextStamp($context));
return $this;
}
/**
* @param string $name
* @param callable $macro
*
* @return void
*/
public static function macro($name, $macro)
{
static::$macros[$name] = $macro;
}
/**
* @param object $mixin
* @param bool $replace
*
* @return void
*/
public static function mixin($mixin, $replace = true)
{
$reflection = new \ReflectionClass($mixin);
$methods = $reflection->getMethods(
\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED
);
foreach ($methods as $method) {
if ($replace || !static::hasMacro($method->name)) {
$method->setAccessible(true);
/** @var callable $callable */
$callable = $method->invoke($mixin);
static::macro($method->name, $callable);
}
}
}
/**
* @param string $name
*
* @return bool
*/
public static function hasMacro($name)
{
return isset(static::$macros[$name]);
}
/**
* {@inheritdoc}
*/
public function livewire(array $context = array())
{
@trigger_error(sprintf('Since php-flasher/flasher v1.0: Using %s method is deprecated and will be removed in v2.0. please use the builder methods directly.', __METHOD__), \E_USER_DEPRECATED);
return $this;
}
}

View File

@ -0,0 +1,354 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Notification;
use Flasher\Prime\Stamp\StampInterface;
use Flasher\Prime\Translation\ResourceInterface;
interface NotificationBuilderInterface
{
/**
* @param string $message
* @param array<string, mixed>|string|null $title
* @param array<string, mixed> $options
*
* @return Envelope
*/
public function addSuccess($message, $title = null, array $options = array());
/**
* @param string $message
* @param array<string, mixed>|string|null $title
* @param array<string, mixed> $options
*
* @return Envelope
*/
public function addError($message, $title = null, array $options = array());
/**
* @param string $message
* @param array<string, mixed>|string|null $title
* @param array<string, mixed> $options
*
* @return Envelope
*/
public function addWarning($message, $title = null, array $options = array());
/**
* @param string $message
* @param array<string, mixed>|string|null $title
* @param array<string, mixed> $options
*
* @return Envelope
*/
public function addInfo($message, $title = null, array $options = array());
/**
* @param NotificationInterface|string $type
* @param string|null $message
* @param array<string, mixed>|string|null $title
* @param array<string, mixed> $options
*
* @return Envelope
*/
public function addFlash($type, $message, $title = null, array $options = array());
/**
* @param string $type
* @param string|null $message
* @param array<string, mixed>|string|null $title
* @param array<string, mixed> $options
*
* @return static
*/
public function type($type, $message = null, $title = null, array $options = array());
/**
* @param string $message
*
* @return static
*/
public function message($message);
/**
* @param string $title
*
* @return static
*/
public function title($title);
/**
* @param array<string, mixed> $options
* @param bool $merge
*
* @return static
*/
public function options(array $options, $merge = true);
/**
* @param string $name
* @param mixed $value
*
* @return static
*/
public function option($name, $value);
/**
* @deprecated In php-flasher/flasher v2.0, the "success()" method will be an alias of "addSuccess()" method as it will immediately call the `->flash()` method. Use the "type('success')" method instead to avoid this breaking change.
*
* @param string|null $message
* @param array<string, mixed>|string|null $title
* @param array<string, mixed> $options
*
* @return static
*/
public function success($message = null, $title = null, array $options = array());
/**
* @deprecated In php-flasher/flasher v2.0, the "error()" method will be an alias of "addError()" method as it will immediately call the `->flash()` method. Use the "type('error')" method instead to avoid this breaking change.
*
* @param string|null $message
* @param array<string, mixed>|string|null $title
* @param array<string, mixed> $options
*
* @return static
*/
public function error($message = null, $title = null, array $options = array());
/**
* @deprecated In php-flasher/flasher v2.0, the "info()" method will be an alias of "addInfo()" method as it will immediately call the `->flash()` method. Use the "type('info')" method instead to avoid this breaking change.
*
* @param string|null $message
* @param array<string, mixed>|string|null $title
* @param array<string, mixed> $options
*
* @return static
*/
public function info($message = null, $title = null, array $options = array());
/**
* @deprecated In php-flasher/flasher v2.0, the "warning()" method will be an alias of "addWarning()" method as it will immediately call the `->flash()` method. Use the "type('warning')" method instead to avoid this breaking change.
*
* @param string|null $message
* @param array<string, mixed>|string|null $title
* @param array<string, mixed> $options
*
* @return static
*/
public function warning($message = null, $title = null, array $options = array());
/**
* @param bool|\Closure $condition
*
* @return static
*/
public function when($condition);
/**
* @param bool|\Closure $condition
*
* @return static
*/
public function unless($condition);
/**
* @param int $priority
*
* @return static
*/
public function priority($priority);
/**
* @return static
*/
public function keep();
/**
* @param int $amount
*
* @return static
*/
public function hops($amount);
/**
* @param string $handler
*
* @return static
*/
public function handler($handler);
/**
* @param mixed[] $context
*
* @return static
*/
public function context(array $context);
/**
* @return static
*/
public function withStamp(StampInterface $stamp);
/**
* @param StampInterface|StampInterface[] $stamps
*
* @return static
*/
public function with($stamps = array());
/**
* @return static
*/
public function now();
/**
* @param int $delay
*
* @return static
*/
public function delay($delay);
/**
* @param array<string, mixed> $parameters
* @param string|null $locale
*
* @return static
*/
public function translate($parameters = array(), $locale = null);
/**
* @param string $preset
* @param array<string, mixed> $parameters
*
* @return Envelope
*/
public function addPreset($preset, $parameters = array());
/**
* @param string $operation
* @param ResourceInterface|string|null $resource
*
* @return Envelope
*/
public function addOperation($operation, $resource = null);
/**
* @param ResourceInterface|string|null $resource
*
* @return Envelope
*/
public function addCreated($resource = null);
/**
* @param ResourceInterface|string|null $resource
*
* @return Envelope
*/
public function addUpdated($resource = null);
/**
* @param ResourceInterface|string|null $resource
*
* @return Envelope
*/
public function addSaved($resource = null);
/**
* @param ResourceInterface|string|null $resource
*
* @return Envelope
*/
public function addDeleted($resource = null);
/**
* @deprecated In php-flasher/flasher v2.0, the "preset()" method will be an alias of "addPreset()" method as will immediately call the `->flash()` method. Use the "addPreset()" method instead to avoid this breaking change.
*
* @param string $preset
* @param array<string, mixed> $parameters
*
* @return static
*/
public function preset($preset, $parameters = array());
/**
* @deprecated In php-flasher/flasher v2.0, the "operation()" method will be an alias of "addOperation()" method as will immediately call the `->flash()` method. Use the "addOperation()" method instead to avoid this breaking change.
*
* @param string $operation
* @param ResourceInterface|string|null $resource
*
* @return static
*/
public function operation($operation, $resource = null);
/**
* @deprecated In php-flasher/flasher v2.0, the "created()" method will be an alias of "addCreated()" method as will immediately call the `->flash()` method. Use the "addCreated()" method instead to avoid this breaking change.
*
* @param ResourceInterface|string|null $resource
*
* @return static
*/
public function created($resource = null);
/**
* @deprecated In php-flasher/flasher v2.0, the "updated()" method will be an alias of "addUpdated()" method as will immediately call the `->flash()` method. Use the "addUpdated()" method instead to avoid this breaking change.
*
* @param ResourceInterface|string|null $resource
*
* @return static
*/
public function updated($resource = null);
/**
* @deprecated In php-flasher/flasher v2.0, the "saved()" method will be an alias of "addSaved()" method as will immediately call the `->flash()` method. Use the "addSaved()" method instead to avoid this breaking change.
*
* @param ResourceInterface|string|null $resource
*
* @return static
*/
public function saved($resource = null);
/**
* @deprecated In php-flasher/flasher v2.0, the "deleted()" method will be an alias of "addDeleted()" method as will immediately call the `->flash()` method. Use the "addDeleted()" method instead to avoid this breaking change.
*
* @param ResourceInterface|string|null $resource
*
* @return static
*/
public function deleted($resource = null);
/**
* @param StampInterface[] $stamps
*
* @return Envelope
*/
public function push(array $stamps = array());
/**
* @deprecated Since php-flasher/flasher v1.12: Using "flash()" method is deprecated and will be removed in v2.0. please use the "push()" method instead.
*
* @param StampInterface[] $stamps
*
* @return Envelope
*/
public function flash(array $stamps = array());
/**
* @return Envelope
*/
public function getEnvelope();
/**
* @deprecated Since php-flasher/flasher v1.0: Using livewire() method is deprecated and will be removed in v2.0. please use the builder methods directly.
* @see https://php-flasher.io/docs/framework/livewire/
*
* @param array<string, mixed> $context
*
* @return static
*/
public function livewire(array $context = array());
}

View File

@ -0,0 +1,92 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Notification;
interface NotificationInterface
{
const SUCCESS = 'success';
const ERROR = 'error';
const INFO = 'info';
const WARNING = 'warning';
/**
* @return string|null
*/
public function getType();
/**
* @param string|null $type
*
* @return static
*/
public function setType($type);
/**
* @return string|null
*/
public function getMessage();
/**
* @param string|null $message
*
* @return static
*/
public function setMessage($message);
/**
* @return string|null
*/
public function getTitle();
/**
* @param string|null $title
*
* @return static
*/
public function setTitle($title);
/**
* @return array<string, mixed>
*/
public function getOptions();
/**
* @param array<string, mixed> $options
*
* @return static
*/
public function setOptions(array $options);
/**
* @param string $name
* @param mixed $default
*
* @return mixed
*/
public function getOption($name, $default = null);
/**
* @param string $name
* @param mixed $value
*
* @return static
*/
public function setOption($name, $value);
/**
* @param string $name
*
* @return static
*/
public function unsetOption($name);
/**
* @return array<string, mixed>
*/
public function toArray();
}

View File

@ -0,0 +1,289 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Plugin;
use Flasher\Prime\Config\ConfigInterface;
use Flasher\Prime\Notification\NotificationInterface;
/**
* @phpstan-import-type ConfigType from ConfigInterface
*/
final class FlasherPlugin extends Plugin
{
/**
* {@inheritdoc}
*/
public function getName()
{
return 'flasher';
}
/**
* {@inheritdoc}
*/
public function getServiceID()
{
return 'flasher';
}
/**
* @return string
*/
public function getDefault()
{
return 'flasher';
}
/**
* @return string|array{cdn: string, local: string}
*/
public function getRootScript()
{
return array(
'cdn' => 'https://cdn.jsdelivr.net/npm/@flasher/flasher@1.3.2/dist/flasher.min.js',
'local' => '/vendor/flasher/flasher.min.js',
);
}
public function getScripts()
{
$rootScript = $this->getRootScript();
return array(
'cdn' => is_string($rootScript) ? array($rootScript) : array($rootScript['cdn']),
'local' => is_string($rootScript) ? '' : array($rootScript['local']),
);
}
/**
* {@inheritDoc}
*/
public function getStyles()
{
return array(
'cdn' => array(
'https://cdn.jsdelivr.net/npm/@flasher/flasher@1.3.2/dist/flasher.min.css',
),
'local' => array(
'/vendor/flasher/flasher.min.css',
),
);
}
/**
* @return string
*/
public function getResourcesDir()
{
return realpath(__DIR__.'/../Resources') ?: '';
}
/**
* @return array<string, string[]>
*/
public function getFlashBagMapping()
{
return array(
'success' => array('success'),
'error' => array('error', 'danger'),
'warning' => array('warning', 'alarm'),
'info' => array('info', 'notice', 'alert'),
);
}
/**
* {@inheritdoc}
*/
public function processConfiguration(array $options = array())
{
$options = $this->normalizeConfig($options); // @phpstan-ignore-line
return array_merge(array(
'default' => $this->getDefault(),
'root_script' => $this->getRootScript(),
'scripts' => array(),
'styles' => $this->getStyles(),
'options' => array(),
'use_cdn' => true,
'auto_translate' => true,
'auto_render' => true,
'flash_bag' => array(
'enabled' => true,
'mapping' => $this->getFlashBagMapping(),
),
'filter_criteria' => array(),
), $options);
}
/**
* @param array{
* root_script?: string|array,
* styles?: string|array,
* scripts ?: string|array,
* template_factory?: array{default: string, templates: array<string, array<string, string>>},
* auto_create_from_session?: bool,
* auto_render?: bool,
* types_mapping?: array<string, string>,
* observer_events?: array<string, string>,
* translate_by_default?: bool,
* presets?: array<string, array{
* type: string,
* title: string,
* message: string,
* options: array<string, mixed>,
* }>,
* } $config
*
* @phpstan-return ConfigType
*/
public function normalizeConfig(array $config)
{
if (isset($config['root_script']) && is_string($config['root_script'])) {
$config['root_script'] = array(
'local' => $config['root_script'],
'cdn' => $config['root_script'],
);
}
if (isset($config['styles'])) {
if (is_string($config['styles'])) {
$config['styles'] = array('cdn' => $config['styles'], 'local' => $config['styles']);
}
$config['styles'] = array_merge(array('cdn' => array(), 'local' => array()), $config['styles']);
$config['styles']['cdn'] = (array) $config['styles']['cdn'];
$config['styles']['local'] = (array) $config['styles']['local'];
}
if (isset($config['scripts'])) {
if (is_string($config['scripts'])) {
$config['scripts'] = array('cdn' => $config['scripts'], 'local' => $config['scripts']);
}
$config['scripts'] = array_merge(array('cdn' => array(), 'local' => array()), $config['scripts']);
$config['scripts']['cdn'] = (array) $config['scripts']['cdn'];
$config['scripts']['local'] = (array) $config['scripts']['local'];
}
$deprecatedKeys = array();
if (isset($config['template_factory']['default'])) {
$deprecatedKeys[] = 'template_factory.default';
unset($config['template_factory']['default']);
}
if (isset($config['template_factory']['templates'])) {
$deprecatedKeys[] = 'template_factory.templates';
$config['themes'] = $config['template_factory']['templates'];
unset($config['template_factory']['templates']);
}
unset($config['template_factory']);
if (isset($config['themes']['flasher']['options'])) {
$deprecatedKeys[] = 'themes.flasher.options';
$config['options'] = $config['themes']['flasher']['options'];
unset($config['themes']['flasher']['options']);
}
if (isset($config['auto_create_from_session'])) {
$deprecatedKeys[] = 'auto_create_from_session';
$config['flash_bag']['enabled'] = $config['auto_create_from_session'];
unset($config['auto_create_from_session']);
}
if (isset($config['types_mapping'])) {
$deprecatedKeys[] = 'types_mapping';
$config['flash_bag']['mapping'] = $config['types_mapping'];
unset($config['types_mapping']);
}
if (isset($config['observer_events'])) {
$deprecatedKeys[] = 'observer_events';
unset($config['observer_events']);
}
if (isset($config['translate_by_default'])) {
$deprecatedKeys[] = 'translate_by_default';
$config['auto_translate'] = $config['translate_by_default'];
unset($config['translate_by_default']);
}
if (array() !== $deprecatedKeys) {
@trigger_error(sprintf('Since php-flasher/flasher-laravel v1.0: The following configuration keys are deprecated and will be removed in v2.0: %s. Please use the new configuration structure.', implode(', ', $deprecatedKeys)), \E_USER_DEPRECATED);
}
if (\array_key_exists('flash_bag', $config)) {
$config['flash_bag'] = $this->normalizeFlashBagConfig($config['flash_bag']);
}
$config['presets'] = array_merge(array(
'created' => array(
'type' => NotificationInterface::SUCCESS,
'message' => 'The resource was created',
),
'updated' => array(
'type' => NotificationInterface::SUCCESS,
'message' => 'The resource was updated',
),
'saved' => array(
'type' => NotificationInterface::SUCCESS,
'message' => 'The resource was saved',
),
'deleted' => array(
'type' => NotificationInterface::SUCCESS,
'message' => 'The resource was deleted',
),
), isset($config['presets']) ? $config['presets'] : array());
return $config; // @phpstan-ignore-line
}
/**
* @param mixed $config
*
* @return array<string, mixed>
*/
private function normalizeFlashBagConfig($config)
{
if (null === $config || false === $config) {
return array('enabled' => false);
}
if (!\is_array($config) || !\array_key_exists('mapping', $config) || !\is_array($config['mapping'])) {
return array('enabled' => true);
}
$mapping = $config['mapping'];
foreach ($mapping as $key => $values) {
if (!\is_string($key)) {
continue;
}
if (!\is_array($values)) {
$mapping[$key] = array($values);
}
foreach ($mapping[$key] as $index => $value) {
if (!\is_string($value)) {
unset($mapping[$key][$index]);
}
}
$mapping[$key] = array_values($mapping[$key]);
}
return array(
'enabled' => true,
'mapping' => $mapping,
);
}
}

View File

@ -0,0 +1,158 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Plugin;
abstract class Plugin implements PluginInterface
{
/**
* {@inheritdoc}
*/
public function getAlias()
{
$alias = basename(str_replace('\\', '/', \get_class($this)));
$alias = str_replace('Plugin', '', $alias);
/** @var string $alias */
$alias = preg_replace('/(?<=\\w)([A-Z])/', '_\\1', $alias);
return strtolower($alias);
}
/**
* {@inheritdoc}
*/
public function getName()
{
return 'flasher_'.$this->getAlias();
}
/**
* {@inheritdoc}
*/
public function getServiceID()
{
return 'flasher.'.$this->getAlias();
}
/**
* {@inheritdoc}
*/
public function getFactory()
{
return str_replace('Plugin', 'Factory', \get_class($this)); // @phpstan-ignore-line
}
/**
* {@inheritdoc}
*/
public function getScripts()
{
return array();
}
/**
* {@inheritdoc}
*/
public function getStyles()
{
return array();
}
/**
* {@inheritdoc}
*/
public function getOptions()
{
return array();
}
/**
* @return string
*/
public function getAssetsDir()
{
$resourcesDir = $this->getResourcesDir();
$assetsDir = rtrim($resourcesDir, '/').'/assets/';
return realpath($assetsDir) ?: '';
}
/**
* @return string
*/
public function getResourcesDir()
{
$r = new \ReflectionClass($this);
$fileName = pathinfo($r->getFileName() ?: '', PATHINFO_DIRNAME).'/Resources/';
return realpath($fileName) ?: '';
}
/**
* @param array{
* scripts?: string|string[]|array{cdn?: string|string[], local?: string|string[]},
* styles?: string|string[]|array{cdn?: string|string[], local?: string|string[]},
* options?: array<string, mixed>,
* } $config
*
* @return array{
* scripts: array{cdn: string[], local: string[]},
* styles: array{cdn: string[], local: string[]},
* options: array<string, mixed>,
* }
*/
public function normalizeConfig(array $config)
{
$config = $this->processConfiguration($config);
$config['styles'] = $this->normalizeAssets($config['styles']);
$config['scripts'] = $this->normalizeAssets($config['scripts']);
return $config;
}
/**
* @param array{
* scripts?: string|string[]|array{cdn?: string|string[], local?: string|string[]},
* styles?: string|string[]|array{cdn?: string|string[], local?: string|string[]},
* options?: array<string, mixed>,
* } $options
*
* @return array{
* scripts: string|string[]|array{cdn?: string|string[], local?: string|string[]},
* styles: string|string[]|array{cdn?: string|string[], local?: string|string[]},
* options: array<string, mixed>,
* }
*/
public function processConfiguration(array $options = array())
{
return array_merge(array(
'scripts' => $this->getScripts(),
'styles' => $this->getStyles(),
'options' => $this->getOptions(),
), $options);
}
/**
* @param string|array{cdn?: string|string[], local?: string|string[]} $assets
*
* @return array{cdn: string[], local: string[]}
*/
protected function normalizeAssets($assets = array())
{
if (is_string($assets)) {
$assets = array('cdn' => $assets, 'local' => $assets);
}
$assets = array_merge(array('cdn' => null, 'local' => null), $assets);
$assets['cdn'] = (array) $assets['cdn'];
$assets['local'] = (array) $assets['local'];
return $assets;
}
}

View File

@ -0,0 +1,80 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Plugin;
use Flasher\Prime\Factory\NotificationFactoryInterface;
interface PluginInterface
{
/**
* @return string
*/
public function getAlias();
/**
* @return string
*/
public function getName();
/**
* @return string
*/
public function getServiceID();
/**
* @return class-string<NotificationFactoryInterface>
*/
public function getFactory();
/**
* @return string|string[]|array{cdn?: string|string[], local?: string|string[]}
*/
public function getScripts();
/**
* @return string|string[]|array{cdn?: string|string[], local?: string|string[]}
*/
public function getStyles();
/**
* @return array<string, mixed>
*/
public function getOptions();
/**
* @return string
*/
public function getAssetsDir();
/**
* @return string
*/
public function getResourcesDir();
/**
* @phpstan-param array{
* scripts?: string|array,
* styles?: string|array,
* options?: array,
* } $config
*
* @phpstan-return array{
* scripts?: array,
* styles?: array,
* options?: array,
* }
*/
public function normalizeConfig(array $config);
/**
* @param array<string, mixed> $options
*
* @return array<string, mixed>
*/
public function processConfiguration(array $options = array());
}

74
vendor/php-flasher/flasher/README.md vendored Normal file
View File

@ -0,0 +1,74 @@
<p align="center">
<picture>
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/php-flasher/art/main/php-flasher-github-dark.png">
<img src="https://raw.githubusercontent.com/php-flasher/art/main/php-flasher-github.png" alt="PHPFlasher Logo">
</picture>
</p>
## About PHPFlasher
PHPFlasher is a powerful and easy-to-use package that allows you to quickly and easily add flash messages to your Laravel or Symfony projects.
Whether you need to alert users of a successful form submission, an error, or any other important information, flash messages are a simple and effective solution for providing feedback to your users.
With PHPFlasher, you can easily record and store messages within the session, making it simple to retrieve and display them on the current or next page.
This improves user engagement and enhances the overall user experience on your website or application.
Whether you're a beginner or an experienced developer, PHPFlasher's intuitive and straightforward design makes it easy to integrate into your projects.
So, if you're looking for a reliable, flexible and easy to use flash messages solution, PHPFlasher is the perfect choice.
## Official Documentation
Documentation for PHPFlasher can be found on the [https://php-flasher.io](https://php-flasher.io).
## Contributors and sponsors
Join our team of contributors and make a lasting impact on our project!
We are always looking for passionate individuals who want to contribute their skills and ideas.
Whether you're a developer, designer, or simply have a great idea, we welcome your participation and collaboration.
Shining stars of our community:
<!-- ALL-CONTRIBUTORS-LIST:START -->
<!-- prettier-ignore-start -->
<!-- markdownlint-disable -->
<table>
<tbody>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.linkedin.com/in/younes-khoubza/"><img src="https://avatars.githubusercontent.com/u/10859693?v=4?s=100" width="100px;" alt="Younes KHOUBZA"/><br /><sub><b>Younes KHOUBZA</b></sub></a><br /><a href="https://github.com/php-flasher/php-flasher/commits?author=yoeunes" title="Code">💻</a> <a href="https://github.com/php-flasher/php-flasher/commits?author=yoeunes" title="Documentation">📖</a> <a href="#maintenance-yoeunes" title="Maintenance">🚧</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/salmayno"><img src="https://avatars.githubusercontent.com/u/27933199?v=4?s=100" width="100px;" alt="Salma Mourad"/><br /><sub><b>Salma Mourad</b></sub></a><br /><a href="#financial-salmayno" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://www.youtube.com/rstacode"><img src="https://avatars.githubusercontent.com/u/35005761?v=4?s=100" width="100px;" alt="Nashwan Abdullah"/><br /><sub><b>Nashwan Abdullah</b></sub></a><br /><a href="#financial-codenashwan" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://darvis.nl/"><img src="https://avatars.githubusercontent.com/u/7394837?v=4?s=100" width="100px;" alt="Arvid de Jong"/><br /><sub><b>Arvid de Jong</b></sub></a><br /><a href="#financial-darviscommerce" title="Financial">💵</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://ashallendesign.co.uk/"><img src="https://avatars.githubusercontent.com/u/39652331?v=4?s=100" width="100px;" alt="Ash Allen"/><br /><sub><b>Ash Allen</b></sub></a><br /><a href="#design-ash-jc-allen" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://about.me/murrant"><img src="https://avatars.githubusercontent.com/u/39462?v=4?s=100" width="100px;" alt="Tony Murray"/><br /><sub><b>Tony Murray</b></sub></a><br /><a href="https://github.com/php-flasher/php-flasher/commits?author=murrant" title="Code">💻</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://github.com/n3wborn"><img src="https://avatars.githubusercontent.com/u/10246722?v=4?s=100" width="100px;" alt="Stéphane P"/><br /><sub><b>Stéphane P</b></sub></a><br /><a href="https://github.com/php-flasher/php-flasher/commits?author=n3wborn" title="Documentation">📖</a></td>
</tr>
<tr>
<td align="center" valign="top" width="14.28%"><a href="https://www.instagram.com/lucas.maciel_z"><img src="https://avatars.githubusercontent.com/u/80225404?v=4?s=100" width="100px;" alt="Lucas Maciel"/><br /><sub><b>Lucas Maciel</b></sub></a><br /><a href="#design-LucasStorm" title="Design">🎨</a></td>
<td align="center" valign="top" width="14.28%"><a href="https://siek.io/"><img src="https://avatars.githubusercontent.com/u/5730766?v=4?s=100" width="100px;" alt="Antoni Siek"/><br /><sub><b>Antoni Siek</b></sub></a><br /><a href="https://github.com/php-flasher/php-flasher/commits?author=ImJustToNy" title="Code">💻</a></td>
</tr>
</tbody>
</table>
<!-- markdownlint-restore -->
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
## Contact
PHPFlasher is being actively developed by <a href="https://github.com/yoeunes">yoeunes</a>.
You can reach out with questions, bug reports, or feature requests on any of the following:
- [Github Issues](https://github.com/php-flasher/php-flasher/issues)
- [Github](https://github.com/yoeunes)
- [Twitter](https://twitter.com/yoeunes)
- [Linkedin](https://www.linkedin.com/in/younes-khoubza/)
- [Email me directly](mailto:younes.khoubza@gmail.com)
## License
PHPFlasher is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT).
<p align="center"> <b>Made with ❤️ by <a href="https://www.linkedin.com/in/younes-khoubza/">Younes KHOUBZA</a> </b> </p>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,21 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Response\Presenter;
use Flasher\Prime\Response\Response;
final class ArrayPresenter implements PresenterInterface
{
/**
* {@inheritdoc}
*/
public function render(Response $response)
{
return $response->toArray();
}
}

View File

@ -0,0 +1,129 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Response\Presenter;
use Flasher\Prime\Response\Response;
final class HtmlPresenter implements PresenterInterface
{
const FLASHER_FLASH_BAG_PLACE_HOLDER = 'FLASHER_FLASH_BAG_PLACE_HOLDER';
const HEAD_END_PLACE_HOLDER = '</head>';
const BODY_END_PLACE_HOLDER = '</body>';
/**
* {@inheritdoc}
*/
public function render(Response $response)
{
$options = json_encode($response->toArray(true));
$context = $response->getContext();
if (isset($context['envelopes_only']) && true === $context['envelopes_only']) {
return $options;
}
$rootScript = $response->getRootScript();
$placeHolder = self::FLASHER_FLASH_BAG_PLACE_HOLDER;
$livewireListener = $this->getLivewireListenerScript();
return <<<JAVASCRIPT
<script type="text/javascript" class="flasher-js">
(function() {
var rootScript = '{$rootScript}';
var {$placeHolder} = {};
var options = mergeOptions({$options}, {$placeHolder});
function mergeOptions(first, second) {
return {
context: merge(first.context || {}, second.context || {}),
envelopes: merge(first.envelopes || [], second.envelopes || []),
options: merge(first.options || {}, second.options || {}),
scripts: merge(first.scripts || [], second.scripts || []),
styles: merge(first.styles || [], second.styles || []),
};
}
function merge(first, second) {
if (Array.isArray(first) && Array.isArray(second)) {
return first.concat(second).filter(function(item, index, array) {
return array.indexOf(item) === index;
});
}
return Object.assign({}, first, second);
}
function renderOptions(options) {
if(!window.hasOwnProperty('flasher')) {
console.error('Flasher is not loaded');
return;
}
requestAnimationFrame(function () {
window.flasher.render(options);
});
}
function render(options) {
if ('loading' !== document.readyState) {
renderOptions(options);
return;
}
document.addEventListener('DOMContentLoaded', function() {
renderOptions(options);
});
}
if (1 === document.querySelectorAll('script.flasher-js').length) {
document.addEventListener('flasher:render', function (event) {
render(event.detail);
});
{$livewireListener}
}
if (window.hasOwnProperty('flasher') || !rootScript || document.querySelector('script[src="' + rootScript + '"]')) {
render(options);
} else {
var tag = document.createElement('script');
tag.setAttribute('src', rootScript);
tag.setAttribute('type', 'text/javascript');
tag.onload = function () {
render(options);
};
document.head.appendChild(tag);
}
})();
</script>
JAVASCRIPT;
}
/**
* Generate the script for Livewire event handling.
*
* @return string
*/
private function getLivewireListenerScript()
{
if (!class_exists('Livewire\LivewireManager')) {
return '';
}
return <<<JAVASCRIPT
document.addEventListener('livewire:navigating', function () {
var elements = document.querySelectorAll('.fl-no-cache');
for (var i = 0; i < elements.length; i++) {
elements[i].remove();
}
});
JAVASCRIPT;
}
}

View File

@ -0,0 +1,18 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Response\Presenter;
use Flasher\Prime\Response\Response;
interface PresenterInterface
{
/**
* @return mixed
*/
public function render(Response $response);
}

View File

@ -0,0 +1,241 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Response\Resource;
use Flasher\Prime\Config\Config;
use Flasher\Prime\Config\ConfigInterface;
use Flasher\Prime\Notification\Envelope;
use Flasher\Prime\Response\Response;
use Flasher\Prime\Stamp\HandlerStamp;
use Flasher\Prime\Stamp\ViewStamp;
use Flasher\Prime\Template\TemplateEngineInterface;
final class ResourceManager implements ResourceManagerInterface
{
/**
* @var ConfigInterface
*/
private $config;
/**
* @var TemplateEngineInterface|null
*/
private $templateEngine;
/**
* @var array<string, string[]>
*/
private $scripts = array();
/**
* @var array<string, string[]>
*/
private $styles = array();
/**
* @var array<string, array<string, mixed>>
*/
private $options = array();
public function __construct(ConfigInterface $config = null, TemplateEngineInterface $templateEngine = null)
{
$this->config = $config ?: new Config();
$this->templateEngine = $templateEngine;
}
/**
* {@inheritdoc}
*/
public function buildResponse(Response $response)
{
$rootScript = $this->selectAssets($this->config->get('root_script'));
$rootScript = is_string($rootScript) ? $rootScript : null;
$response->setRootScript($rootScript);
$handlers = array();
foreach ($response->getEnvelopes() as $envelope) {
$handler = $this->resolveHandler($envelope);
if (null === $handler || \in_array($handler, $handlers, true)) {
continue;
}
$handlers[] = $handler;
$this->populateResponse($response, $handler);
}
return $response;
}
/**
* {@inheritdoc}
*/
public function addScripts($handler, array $scripts)
{
$this->scripts[$handler] = $scripts;
}
/**
* {@inheritdoc}
*/
public function addStyles($handler, array $styles)
{
$this->styles[$handler] = $styles;
}
/**
* {@inheritdoc}
*/
public function addOptions($handler, array $options)
{
$this->options[$handler] = $options;
}
/**
* @return ConfigInterface
*/
public function getConfig()
{
return $this->config;
}
/**
* @param mixed $assets
*
* @return string[]|string
*/
private function selectAssets($assets)
{
$use = $this->config->get('use_cdn', true) ? 'cdn' : 'local';
return is_array($assets) && array_key_exists($use, $assets) ? $assets[$use] : $assets;
}
/**
* @return string|null
*/
private function resolveHandler(Envelope $envelope)
{
$handlerStamp = $envelope->get('Flasher\Prime\Stamp\HandlerStamp');
if (!$handlerStamp instanceof HandlerStamp) {
return null;
}
$handler = $handlerStamp->getHandler();
if ('flasher' !== $handler && 0 !== strpos($handler, 'theme.')) {
return $handler;
}
$theme = $this->getTheme($handler);
if (null === $theme) {
return $handler;
}
if (!isset($this->scripts[$handler])) {
$scripts = $this->config->get('themes.'.$theme.'.scripts', array());
$this->addScripts('theme.'.$theme, (array) $scripts);
}
if (!isset($this->styles[$handler])) {
$styles = $this->config->get('themes.'.$theme.'.styles', array());
$this->addStyles('theme.'.$theme, (array) $styles);
}
if (!isset($this->options[$handler])) {
$options = $this->config->get('themes.'.$theme.'.options', array());
$this->addOptions('theme.'.$theme, $options);
}
if ('flasher' === $theme) {
$scripts = $this->config->get('scripts', array());
if (isset($this->scripts['theme.flasher'])) {
$scripts = array_merge($this->scripts['theme.flasher'], $scripts);
}
if (isset($this->scripts['flasher'])) {
$scripts = array_merge($this->scripts['flasher'], $scripts);
}
$this->addScripts('theme.flasher', (array) $scripts);
$styles = $this->config->get('styles', array());
if (isset($this->styles['theme.flasher'])) {
$styles = array_merge($this->styles['theme.flasher'], $styles);
}
if (isset($this->scripts['flasher'])) {
$styles = array_merge($this->styles['flasher'], $styles);
}
$this->addStyles('theme.flasher', (array) $styles);
$options = $this->config->get('options', array());
if (isset($this->options['theme.flasher'])) {
$options = array_merge($this->options['theme.flasher'], $options);
}
if (isset($this->options['flasher'])) {
$options = array_merge($this->options['flasher'], $options);
}
$this->addOptions('theme.flasher', $options);
}
/** @var string|null $view */
$view = $this->config->get('themes.'.$theme.'.view');
if (null === $view || null === $this->templateEngine) {
return 'theme.'.$theme;
}
$compiled = $this->templateEngine->render($view, array('envelope' => $envelope));
$envelope->withStamp(new ViewStamp($compiled));
return 'theme.'.$theme;
}
/**
* @param string $handler
*
* @return string|null
*/
private function getTheme($handler)
{
if ('flasher' === $handler) {
return 'flasher';
}
if (0 === strpos($handler, 'theme.')) {
return substr($handler, \strlen('theme.'));
}
return null;
}
/**
* @param string $handler
*
* @return void
*/
private function populateResponse(Response $response, $handler)
{
if (isset($this->scripts[$handler])) {
$scripts = $this->selectAssets($this->scripts[$handler]);
$scripts = is_array($scripts) ? $scripts : array();
$response->addScripts($scripts);
}
if (isset($this->styles[$handler])) {
$styles = $this->selectAssets($this->styles[$handler]);
$styles = is_array($styles) ? $styles : array();
$response->addStyles($styles);
}
if (isset($this->options[$handler])) {
$response->addOptions($handler, $this->options[$handler]);
}
}
}

View File

@ -0,0 +1,42 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Response\Resource;
use Flasher\Prime\Response\Response;
interface ResourceManagerInterface
{
/**
* @return Response
*/
public function buildResponse(Response $response);
/**
* @param string $handler
* @param string[] $scripts
*
* @return void
*/
public function addScripts($handler, array $scripts);
/**
* @param string $handler
* @param string[] $styles
*
* @return void
*/
public function addStyles($handler, array $styles);
/**
* @param string $handler
* @param array<string, mixed> $options
*
* @return void
*/
public function addOptions($handler, array $options);
}

View File

@ -0,0 +1,167 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Response;
use Flasher\Prime\Notification\Envelope;
final class Response
{
/**
* @var Envelope[]
*/
private $envelopes;
/**
* @var string|null
*/
private $rootScript;
/**
* @var string[]
*/
private $scripts = array();
/**
* @var string[]
*/
private $styles = array();
/**
* @var array<string, array<string, mixed>>
*/
private $options = array();
/**
* @var array<string, mixed>
*/
private $context;
/**
* @param Envelope[] $envelopes
* @param array<string, mixed> $context
*/
public function __construct(array $envelopes, array $context)
{
$this->envelopes = $envelopes;
$this->context = $context;
}
/**
* @param string[] $scripts
*
* @return void
*/
public function addScripts(array $scripts)
{
$this->scripts = array_merge($this->scripts, $scripts);
}
/**
* @param string[] $styles
*
* @return void
*/
public function addStyles(array $styles)
{
$this->styles = array_merge($this->styles, $styles);
}
/**
* @param string $alias
* @param array<string, mixed> $options
*
* @return void
*/
public function addOptions($alias, array $options)
{
$this->options[$alias] = $options;
}
/**
* @return Envelope[]
*/
public function getEnvelopes()
{
return $this->envelopes;
}
/**
* @return string|null
*/
public function getRootScript()
{
return $this->rootScript;
}
/**
* @param string|null $rootScript
*
* @return void
*/
public function setRootScript($rootScript)
{
$this->rootScript = $rootScript;
}
/**
* @return string[]
*/
public function getStyles()
{
return array_values(array_filter(array_unique($this->styles)));
}
/**
* @return string[]
*/
public function getScripts()
{
return array_values(array_filter(array_unique($this->scripts)));
}
/**
* @return array<string, array<string, mixed>>
*/
public function getOptions()
{
return $this->options;
}
/**
* @return array<string, mixed>
*/
public function getContext()
{
return $this->context;
}
/**
* @param mixed $filter
*
* @return array<string, mixed>
*/
public function toArray($filter = false)
{
$envelopes = array_map(function (Envelope $envelope) {
return $envelope->toArray();
}, $this->getEnvelopes());
$response = array(
'envelopes' => $envelopes,
'scripts' => $this->getScripts(),
'styles' => $this->getStyles(),
'options' => $this->getOptions(),
);
if (false === $filter) {
return $response;
}
return array_filter($response);
}
}

View File

@ -0,0 +1,113 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Response;
use Flasher\Prime\EventDispatcher\Event\PresentationEvent;
use Flasher\Prime\EventDispatcher\Event\ResponseEvent;
use Flasher\Prime\EventDispatcher\EventDispatcher;
use Flasher\Prime\EventDispatcher\EventDispatcherInterface;
use Flasher\Prime\Notification\Envelope;
use Flasher\Prime\Response\Presenter\ArrayPresenter;
use Flasher\Prime\Response\Presenter\HtmlPresenter;
use Flasher\Prime\Response\Presenter\PresenterInterface;
use Flasher\Prime\Response\Resource\ResourceManager;
use Flasher\Prime\Response\Resource\ResourceManagerInterface;
use Flasher\Prime\Storage\StorageManager;
use Flasher\Prime\Storage\StorageManagerInterface;
final class ResponseManager implements ResponseManagerInterface
{
/**
* @var array<string, callable|PresenterInterface>
*/
private $presenters;
/**
* @var ResourceManagerInterface
*/
private $resourceManager;
/**
* @var StorageManagerInterface
*/
private $storageManager;
/**
* @var EventDispatcherInterface
*/
private $eventDispatcher;
public function __construct(ResourceManagerInterface $resourceManager = null, StorageManagerInterface $storageManager = null, EventDispatcherInterface $eventDispatcher = null)
{
$this->resourceManager = $resourceManager ?: new ResourceManager();
$this->storageManager = $storageManager ?: new StorageManager();
$this->eventDispatcher = $eventDispatcher ?: new EventDispatcher();
$this->addPresenter('html', new HtmlPresenter());
$this->addPresenter('json', new ArrayPresenter());
$this->addPresenter('array', new ArrayPresenter());
}
/**
* {@inheritdoc}
*/
public function render(array $criteria = array(), $presenter = 'html', array $context = array())
{
$envelopes = $this->storageManager->filter($criteria);
$this->storageManager->remove($envelopes);
$event = new PresentationEvent($envelopes, $context);
$this->eventDispatcher->dispatch($event);
$response = $this->createResponse($event->getEnvelopes(), $context);
$response = $this->createPresenter($presenter)->render($response);
$event = new ResponseEvent($response, $presenter);
$this->eventDispatcher->dispatch($event);
return $event->getResponse();
}
/**
* {@inheritdoc}
*/
public function addPresenter($alias, $presenter)
{
$this->presenters[$alias] = $presenter;
}
/**
* @param string $alias
*
* @return PresenterInterface
*/
private function createPresenter($alias)
{
if (!isset($this->presenters[$alias])) {
throw new \InvalidArgumentException(sprintf('Presenter [%s] not supported.', $alias));
}
$presenter = $this->presenters[$alias];
return \is_callable($presenter) ? $presenter() : $presenter;
}
/**
* @param Envelope[] $envelopes
* @param mixed[] $context
*
* @return Response
*/
private function createResponse($envelopes, $context)
{
$response = new Response($envelopes, $context);
return $this->resourceManager->buildResponse($response);
}
}

View File

@ -0,0 +1,30 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Response;
use Flasher\Prime\Response\Presenter\PresenterInterface;
interface ResponseManagerInterface
{
/**
* @param mixed[] $criteria
* @param string $presenter
* @param mixed[] $context
*
* @return mixed
*/
public function render(array $criteria = array(), $presenter = 'html', array $context = array());
/**
* @param string $alias
* @param callable|PresenterInterface $presenter
*
* @return void
*/
public function addPresenter($alias, $presenter);
}

View File

@ -0,0 +1,40 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Stamp;
final class ContextStamp implements StampInterface, PresentableStampInterface
{
/**
* @var mixed[]
*/
private $context;
/**
* @param mixed[] $context
*/
public function __construct(array $context)
{
$this->context = $context;
}
/**
* @return mixed[]
*/
public function getContext()
{
return $this->context;
}
/**
* {@inheritdoc}
*/
public function toArray()
{
return array('context' => $this->getContext());
}
}

View File

@ -0,0 +1,62 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Stamp;
final class CreatedAtStamp implements StampInterface, OrderableStampInterface, PresentableStampInterface
{
/**
* @var \DateTime
*/
private $createdAt;
/**
* @var string
*/
private $format;
/**
* @param string|null $format
*
* @throws \Exception
*/
public function __construct(\DateTime $createdAt = null, $format = null)
{
$this->createdAt = $createdAt ?: new \DateTime('now', new \DateTimeZone('Africa/Casablanca'));
$this->format = $format ?: 'Y-m-d H:i:s';
}
/**
* @return \DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
/**
* {@inheritdoc}
*/
public function compare($orderable)
{
if (!$orderable instanceof self) {
return 1;
}
return $this->createdAt->getTimestamp() - $orderable->createdAt->getTimestamp();
}
/**
* {@inheritdoc}
*/
public function toArray()
{
$createdAt = $this->getCreatedAt();
return array('created_at' => $createdAt->format($this->format));
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Stamp;
final class DelayStamp implements StampInterface
{
/**
* @var int
*/
private $delay;
/**
* @param int $delay
*/
public function __construct($delay)
{
$this->delay = $delay;
}
/**
* @return int
*/
public function getDelay()
{
return $this->delay;
}
}

View File

@ -0,0 +1,40 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Stamp;
final class HandlerStamp implements StampInterface, PresentableStampInterface
{
/**
* @var string
*/
private $handler;
/**
* @param string $handler
*/
public function __construct($handler)
{
$this->handler = $handler;
}
/**
* @return string
*/
public function getHandler()
{
return $this->handler;
}
/**
* {@inheritdoc}
*/
public function toArray()
{
return array('handler' => $this->getHandler());
}
}

View File

@ -0,0 +1,32 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Stamp;
final class HopsStamp implements StampInterface
{
/**
* @var int
*/
private $amount;
/**
* @param int $amount
*/
public function __construct($amount)
{
$this->amount = $amount;
}
/**
* @return int
*/
public function getAmount()
{
return $this->amount;
}
}

View File

@ -0,0 +1,18 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Stamp;
interface OrderableStampInterface
{
/**
* @param mixed $orderable
*
* @return int
*/
public function compare($orderable);
}

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