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,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);
}

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\Stamp;
interface PresentableStampInterface
{
/**
* @return array<string, mixed>
*/
public function toArray();
}

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\Stamp;
final class PresetStamp implements StampInterface
{
/**
* @var string
*/
private $preset;
/**
* @var array<string, mixed>
*/
private $parameters;
/**
* @param string $preset
* @param array<string, mixed> $parameters
*/
public function __construct($preset, array $parameters = array())
{
$this->preset = $preset;
$this->parameters = $parameters;
}
/**
* @return string
*/
public function getPreset()
{
return $this->preset;
}
/**
* @return array<string, mixed>
*/
public function getParameters()
{
return $this->parameters;
}
}

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\Stamp;
final class PriorityStamp implements StampInterface, OrderableStampInterface, PresentableStampInterface
{
/**
* @var int
*/
private $priority;
/**
* @param int $priority
*/
public function __construct($priority)
{
$this->priority = $priority;
}
/**
* @return int
*/
public function getPriority()
{
return $this->priority;
}
/**
* {@inheritdoc}
*/
public function compare($orderable)
{
if (!$orderable instanceof self) {
return 1;
}
return $this->priority - $orderable->priority;
}
/**
* {@inheritdoc}
*/
public function toArray()
{
return array('priority' => $this->getPriority());
}
}

View File

@ -0,0 +1,12 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Stamp;
interface StampInterface
{
}

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\Stamp;
final class TranslationStamp implements StampInterface
{
/**
* @var array<string, mixed>
*/
private $parameters;
/**
* @var string|null
*/
private $locale;
/**
* @param array<string, mixed> $parameters
* @param string|null $locale
*/
public function __construct($parameters = array(), $locale = null)
{
$order = self::parametersOrder($parameters, $locale);
$parameters = $order['parameters'];
$locale = $order['locale'];
$this->parameters = $parameters;
$this->locale = $locale;
}
/**
* @return array<string, mixed>
*/
public function getParameters()
{
return $this->parameters;
}
/**
* @return string|null
*/
public function getLocale()
{
return $this->locale;
}
/**
* @param mixed $parameters
* @param mixed|null $locale
*
* @return array{parameters: array<string, mixed>, locale: string|null}
*/
public static function parametersOrder($parameters = array(), $locale = null)
{
if (\is_string($parameters)) {
$locale = $parameters;
$parameters = array();
@trigger_error('Since php-flasher/flasher v1.4, passing the locale as first parameter is deprecated and will be removed in v2.0. Use the second parameter instead.', \E_USER_DEPRECATED);
}
return array('parameters' => $parameters, 'locale' => $locale); // @phpstan-ignore-line
}
}

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 UnlessStamp implements StampInterface
{
/**
* @var bool
*/
private $condition;
/**
* @param bool $condition
*/
public function __construct($condition)
{
$this->condition = $condition;
}
/**
* @return bool
*/
public function getCondition()
{
return $this->condition;
}
}

View File

@ -0,0 +1,77 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Stamp;
use Flasher\Prime\Notification\Envelope;
final class UuidStamp implements StampInterface, PresentableStampInterface
{
/**
* @var string
*/
private $uuid;
/**
* @param string|null $uuid
*/
public function __construct($uuid = null)
{
$this->uuid = $uuid ?: sprintf(
'%04X%04X-%04X-%04X-%04X-%04X%04X%04X',
mt_rand(0, 65535),
mt_rand(0, 65535),
mt_rand(0, 65535),
mt_rand(16384, 20479),
mt_rand(32768, 49151),
mt_rand(0, 65535),
mt_rand(0, 65535),
mt_rand(0, 65535)
);
}
/**
* @param Envelope[]|Envelope... $envelopes
*
* @return array<string, Envelope>
*/
public static function indexByUuid($envelopes)
{
$envelopes = \is_array($envelopes) ? $envelopes : \func_get_args();
$map = array();
foreach ($envelopes as $envelope) {
$uuidStamp = $envelope->get('Flasher\Prime\Stamp\UuidStamp');
if (!$uuidStamp instanceof UuidStamp) {
$uuidStamp = new UuidStamp(spl_object_hash($envelope));
$envelope->withStamp($uuidStamp);
}
$uuid = $uuidStamp->getUuid();
$map[$uuid] = $envelope;
}
return $map;
}
/**
* @return string
*/
public function getUuid()
{
return $this->uuid;
}
/**
* {@inheritdoc}
*/
public function toArray()
{
return array('uuid' => $this->getUuid());
}
}

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 ViewStamp implements StampInterface, PresentableStampInterface
{
/**
* @var string
*/
private $view;
/**
* @param string $template
*/
public function __construct($template)
{
$this->view = $template;
}
/**
* @return string
*/
public function getView()
{
return $this->view;
}
/**
* {@inheritdoc}
*/
public function toArray()
{
return array('view' => $this->getView());
}
}

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 WhenStamp implements StampInterface
{
/**
* @var bool
*/
private $condition;
/**
* @param bool $condition
*/
public function __construct($condition)
{
$this->condition = $condition;
}
/**
* @return bool
*/
public function getCondition()
{
return $this->condition;
}
}

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\Storage\Bag;
use Flasher\Prime\Notification\Envelope;
final class ArrayBag implements BagInterface
{
/**
* @var Envelope[]
*/
private $envelopes = array();
/**
* {@inheritDoc}
*/
public function get()
{
return $this->envelopes;
}
/**
* {@inheritDoc}
*/
public function set(array $envelopes)
{
$this->envelopes = $envelopes;
}
}

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\Storage\Bag;
use Flasher\Prime\Notification\Envelope;
interface BagInterface
{
/**
* @return Envelope[]
*/
public function get();
/**
* @param Envelope[] $envelopes
*
* @return void
*/
public function set(array $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\Storage\Bag;
use Flasher\Prime\Notification\Envelope;
final class StaticBag implements BagInterface
{
/**
* @var Envelope[]
*/
private static $envelopes = array();
/**
* {@inheritDoc}
*/
public function get()
{
return self::$envelopes;
}
/**
* {@inheritDoc}
*/
public function set(array $envelopes)
{
self::$envelopes = $envelopes;
}
}

View File

@ -0,0 +1,83 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Storage;
use Flasher\Prime\Stamp\UuidStamp;
use Flasher\Prime\Storage\Bag\ArrayBag;
use Flasher\Prime\Storage\Bag\BagInterface;
final class StorageBag implements StorageInterface
{
/**
* @var BagInterface
*/
private $bag;
public function __construct(BagInterface $bag = null)
{
$this->bag = null !== $bag && 'cli' !== \PHP_SAPI ? $bag : new ArrayBag();
}
/**
* {@inheritdoc}
*/
public function all()
{
return array_values($this->bag->get());
}
/**
* {@inheritdoc}
*/
public function add($envelopes)
{
$envelopes = \is_array($envelopes) ? $envelopes : \func_get_args();
$envelopes = UuidStamp::indexByUuid($envelopes);
$stored = UuidStamp::indexByUuid($this->all());
$envelopes = array_merge($stored, $envelopes);
$this->bag->set(array_values($envelopes));
}
/**
* {@inheritdoc}
*/
public function update($envelopes)
{
$envelopes = \is_array($envelopes) ? $envelopes : \func_get_args();
$envelopes = UuidStamp::indexByUuid($envelopes);
$stored = UuidStamp::indexByUuid($this->all());
$envelopes = array_merge($stored, $envelopes);
$this->bag->set(array_values($envelopes));
}
/**
* {@inheritdoc}
*/
public function remove($envelopes)
{
$envelopes = \is_array($envelopes) ? $envelopes : \func_get_args();
$envelopes = UuidStamp::indexByUuid($envelopes);
$stored = UuidStamp::indexByUuid($this->all());
$envelopes = array_diff_key($stored, $envelopes);
$this->bag->set(array_values($envelopes));
}
/**
* {@inheritdoc}
*/
public function clear()
{
$this->bag->set(array());
}
}

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\Storage;
use Flasher\Prime\Notification\Envelope;
interface StorageInterface
{
/**
* @return Envelope[]
*/
public function all();
/**
* @param Envelope|Envelope[] $envelopes
*
* @return void
*/
public function add($envelopes);
/**
* @param Envelope|Envelope[] $envelopes
*
* @return void
*/
public function update($envelopes);
/**
* @param Envelope|Envelope[] $envelopes
*
* @return void
*/
public function remove($envelopes);
/**
* Remove all notifications from the storage.
*
* @return void
*/
public function clear();
}

View File

@ -0,0 +1,128 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Storage;
use Flasher\Prime\EventDispatcher\Event\FilterEvent;
use Flasher\Prime\EventDispatcher\Event\PersistEvent;
use Flasher\Prime\EventDispatcher\Event\PostPersistEvent;
use Flasher\Prime\EventDispatcher\Event\PostRemoveEvent;
use Flasher\Prime\EventDispatcher\Event\PostUpdateEvent;
use Flasher\Prime\EventDispatcher\Event\RemoveEvent;
use Flasher\Prime\EventDispatcher\Event\UpdateEvent;
use Flasher\Prime\EventDispatcher\EventDispatcher;
use Flasher\Prime\EventDispatcher\EventDispatcherInterface;
final class StorageManager implements StorageManagerInterface
{
/**
* @var StorageInterface
*/
private $storage;
/**
* @var EventDispatcherInterface
*/
private $eventDispatcher;
/**
* @var mixed[]
*/
private $criteria = array();
/**
* @param mixed[] $criteria
*/
public function __construct(StorageInterface $storage = null, EventDispatcherInterface $eventDispatcher = null, array $criteria = array())
{
$this->storage = $storage ?: new StorageBag();
$this->eventDispatcher = $eventDispatcher ?: new EventDispatcher();
$this->criteria = $criteria;
}
/**
* {@inheritdoc}
*/
public function all()
{
return $this->storage->all();
}
/**
* {@inheritdoc}
*/
public function filter(array $criteria = array())
{
$criteria = array_merge($this->criteria, $criteria);
$criteria['delay'] = 0;
// @phpstan-ignore-next-line
$criteria['hops']['min'] = 1;
$event = new FilterEvent($this->all(), $criteria);
$this->eventDispatcher->dispatch($event);
return $event->getEnvelopes();
}
/**
* {@inheritdoc}
*/
public function add($envelopes)
{
$envelopes = \is_array($envelopes) ? $envelopes : \func_get_args();
$event = new PersistEvent($envelopes);
$this->eventDispatcher->dispatch($event);
$this->storage->add($event->getEnvelopes());
$event = new PostPersistEvent($event->getEnvelopes());
$this->eventDispatcher->dispatch($event);
}
/**
* {@inheritdoc}
*/
public function update($envelopes)
{
$envelopes = \is_array($envelopes) ? $envelopes : \func_get_args();
$event = new UpdateEvent($envelopes);
$this->eventDispatcher->dispatch($event);
$this->storage->update($event->getEnvelopes());
$event = new PostUpdateEvent($event->getEnvelopes());
$this->eventDispatcher->dispatch($event);
}
/**
* {@inheritdoc}
*/
public function remove($envelopes)
{
$envelopes = \is_array($envelopes) ? $envelopes : \func_get_args();
$event = new RemoveEvent($envelopes);
$this->eventDispatcher->dispatch($event);
$this->storage->update($event->getEnvelopesToKeep());
$this->storage->remove($event->getEnvelopesToRemove());
$event = new PostRemoveEvent($event->getEnvelopesToRemove(), $event->getEnvelopesToKeep());
$this->eventDispatcher->dispatch($event);
}
/**
* {@inheritdoc}
*/
public function clear()
{
$this->storage->clear();
}
}

View File

@ -0,0 +1,53 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Storage;
use Flasher\Prime\Notification\Envelope;
interface StorageManagerInterface
{
/**
* @return Envelope[]
*/
public function all();
/**
* @param mixed[] $criteria
*
* @return Envelope[]
*/
public function filter(array $criteria = array());
/**
* @param Envelope|Envelope[] $envelopes
*
* @return void
*/
public function add($envelopes);
/**
* @param Envelope|Envelope[] $envelopes
*
* @return void
*/
public function update($envelopes);
/**
* @param Envelope|Envelope[] $envelopes
*
* @return void
*/
public function remove($envelopes);
/**
* remove All notifications from storage.
*
* @return void
*/
public function clear();
}

View File

@ -0,0 +1,35 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Template;
final class Engine implements EngineInterface
{
public function render($name, array $context = array())
{
ob_start();
extract($context, \EXTR_SKIP);
if (!file_exists($name)) {
$name = __DIR__.'/views/'.$name;
if (!file_exists($name)) {
throw new \Exception(sprintf('Cannot find template "%s"', $name));
}
}
include $name;
$output = ob_get_clean();
if (false === $output) {
return '';
}
return ltrim($output);
}
}

View File

@ -0,0 +1,19 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Template;
interface EngineInterface
{
/**
* @param string $name
* @param array<string, mixed> $context
*
* @return string
*/
public function render($name, array $context = array());
}

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\Template;
final class PHPTemplateEngine implements TemplateEngineInterface
{
/**
* {@inheritdoc}
*/
public function render($name, array $context = array())
{
ob_start();
extract($context, \EXTR_SKIP);
include $name;
$output = ob_get_clean();
if (false === $output) {
return '';
}
return ltrim($output);
}
}

View File

@ -0,0 +1,19 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Template;
interface TemplateEngineInterface
{
/**
* @param string $name
* @param array<string, mixed> $context
*
* @return string
*/
public function render($name, array $context = array());
}

View File

@ -0,0 +1,27 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Translation;
final class EchoTranslator implements TranslatorInterface
{
/**
* {@inheritDoc}
*/
public function translate($id, $parameters = array(), $locale = null)
{
return $id;
}
/**
* {@inheritDoc}
*/
public function getLocale()
{
return 'en';
}
}

View File

@ -0,0 +1,63 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
namespace Flasher\Prime\Translation;
final class Language
{
const LTR = 'ltr';
const RTL = 'rtl';
/**
* @param string $locale
*
* @return string
*/
public static function direction($locale)
{
if (!\extension_loaded('intl')) {
return self::LTR;
}
$resource = \ResourceBundle::create($locale, 'ICUDATA', true);
if (null === $resource) {
return self::LTR;
}
$layout = $resource->get('layout');
if (!$layout instanceof \ResourceBundle) {
return self::LTR;
}
$characters = $layout->get('characters');
if (!\is_string($characters)) {
return self::LTR;
}
return 'right-to-left' === $characters ? self::RTL : self::LTR;
}
/**
* @param string $locale
*
* @return bool
*/
public static function isRTL($locale)
{
return self::RTL === self::direction($locale);
}
/**
* @param string $locale
*
* @return bool
*/
public static function isLTR($locale)
{
return self::LTR === self::direction($locale);
}
}

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\Translation;
final class Messages
{
/**
* @var array<string, string>
*/
public static $ar = array(
'success' => 'نجاح',
'error' => 'خطأ',
'warning' => 'تحذير',
'info' => 'معلومة',
'The resource was created' => 'تم إنشاء :resource',
'The resource was updated' => 'تم تعديل :resource',
'The resource was saved' => 'تم حفظ :resource',
'The resource was deleted' => 'تم حذف :resource',
'resource' => 'الملف',
);
/**
* @var array<string, string>
*/
public static $en = array(
'success' => 'Success',
'error' => 'Error',
'warning' => 'Warning',
'info' => 'Info',
'The resource was created' => 'The :resource was created',
'The resource was updated' => 'The :resource was updated',
'The resource was saved' => 'The :resource was saved',
'The resource was deleted' => 'The :resource was deleted',
'resource' => 'resource',
);
/**
* @var array<string, string>
*/
public static $fr = array(
'success' => 'Succès',
'error' => 'Erreur',
'warning' => 'Avertissement',
'info' => 'Information',
'The resource was created' => 'La ressource :resource a été ajoutée',
'The resource was updated' => 'La ressource :resource a été mise à jour',
'The resource was saved' => 'La ressource :resource a été enregistrée',
'The resource was deleted' => 'La ressource :resource a été supprimée',
'resource' => '',
);
}

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\Translation;
interface ResourceInterface
{
/**
* @return string
*/
public function getResourceType();
/**
* @return string
*/
public function getResourceName();
}

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\Translation;
interface TranslatorInterface
{
/**
* @param string $id
* @param array<string, mixed> $parameters
* @param string|null $locale
*
* @return string
*/
public function translate($id, $parameters = array(), $locale = null);
/**
* @return string
*/
public function getLocale();
}

View File

@ -0,0 +1,55 @@
{
"name": "php-flasher/flasher",
"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"
},
"minimum-stability": "stable",
"prefer-stable": true,
"autoload": {
"psr-4": {
"Flasher\\Prime\\": ""
},
"files": [
"helpers.php"
]
},
"config": {
"preferred-install": "dist",
"sort-packages": true
}
}

48
vendor/php-flasher/flasher/helpers.php vendored Normal file
View File

@ -0,0 +1,48 @@
<?php
/*
* This file is part of the PHPFlasher package.
* (c) Younes KHOUBZA <younes.khoubza@gmail.com>
*/
use Flasher\Prime\Container\FlasherContainer;
use Flasher\Prime\FlasherInterface;
use Flasher\Prime\Notification\Envelope;
use Flasher\Prime\Stamp\StampInterface;
if (!function_exists('flash')) {
/**
* @param string $message
* @param string $type
* @param array<string, mixed> $options
* @param StampInterface[] $stamps
*
* @return Envelope|FlasherInterface
*/
function flash($message = null, $type = 'success', array $options = array(), array $stamps = array())
{
/** @var FlasherInterface $factory */
$factory = FlasherContainer::create('flasher');
if (0 === func_num_args()) {
return $factory;
}
return $factory->with($stamps)->addFlash($type, $message, $options);
}
}
if (!function_exists('flasher')) {
/**
* @param string $message
* @param string $type
* @param array<string, mixed> $options
* @param StampInterface[] $stamps
*
* @return Envelope|FlasherInterface
*/
function flasher($message = null, $type = 'success', array $options = array(), array $stamps = array())
{
return flash($message, $type, $options, $stamps);
}
}