diff --git a/composer.json b/composer.json
index 24f46728..dd719028 100644
--- a/composer.json
+++ b/composer.json
@@ -13,7 +13,15 @@
],
"require": {
"php": ">=5.3",
- "ext-json": "*"
+ "ext-json": "*",
+ "symfony/config": "^2.7|^3.0|^4.0|^5.0",
+ "symfony/dependency-injection": "^2.7|^3.0|^4.0|^5.0",
+ "symfony/http-kernel": "^2.7|^3.0|^4.0|^5.0",
+ "symfony/yaml": "^2.7|^3.0|^4.0|^5.0",
+ "twig/twig": "^1.34|^2.0|^3.0"
+ },
+ "require-dev": {
+ "phpunit/phpunit": "^4.8|^5.0|^6.0|^7.0|^8.0|^9.0"
},
"autoload": {
"psr-4": {
diff --git a/src/Laravel/FlasherServiceProvider.php b/src/Laravel/FlasherServiceProvider.php
index df1d0b98..8c0cd051 100644
--- a/src/Laravel/FlasherServiceProvider.php
+++ b/src/Laravel/FlasherServiceProvider.php
@@ -68,4 +68,12 @@ final class FlasherServiceProvider extends ServiceProvider
{
parent::loadTranslationsFrom($path, $namespace);
}
+
+ /**
+ * {@inheritdoc}
+ */
+ public function loadViewsFrom($path, $namespace)
+ {
+ parent::loadViewsFrom($path, $namespace);
+ }
}
diff --git a/src/Laravel/Observer/FlasherModelObserver.php b/src/Laravel/Observer/FlasherModelObserver.php
index 42340e83..589a885b 100644
--- a/src/Laravel/Observer/FlasherModelObserver.php
+++ b/src/Laravel/Observer/FlasherModelObserver.php
@@ -4,34 +4,43 @@ namespace Flasher\Laravel\Observer;
use Flasher\Prime\Config\ConfigInterface;
use Flasher\Prime\FlasherInterface;
+use Illuminate\Contracts\Translation\Translator;
use Illuminate\Database\Eloquent\Model;
final class FlasherModelObserver
{
- /**
- * @var FlasherInterface
- */
- private $flasher;
-
/**
* @var ConfigInterface
*/
private $config;
/**
- * @param FlasherInterface $flasher
- * @param ConfigInterface $config
+ * @var FlasherInterface
*/
- public function __construct(FlasherInterface $flasher, ConfigInterface $config)
+ private $flasher;
+
+ /**
+ * @var Translator
+ */
+ private $translator;
+
+ /**
+ * @param ConfigInterface $config
+ * @param FlasherInterface $flasher
+ * @param Translator $translator
+ */
+ public function __construct(ConfigInterface $config, FlasherInterface $flasher, Translator $translator)
{
- $this->flasher = $flasher;
$this->config = $config;
+ $this->flasher = $flasher;
+ $this->translator = $translator;
}
/**
* Handle the Model "created" event.
*
- * @param Model $model
+ * @param Model $model
+ *
* @return void
*/
public function created(Model $model)
@@ -42,7 +51,8 @@ final class FlasherModelObserver
/**
* Handle the Model "updated" event.
*
- * @param Model $model
+ * @param Model $model
+ *
* @return void
*/
public function updated(Model $model)
@@ -53,7 +63,8 @@ final class FlasherModelObserver
/**
* Handle the Model "deleted" event.
*
- * @param Model $model
+ * @param Model $model
+ *
* @return void
*/
public function deleted(Model $model)
@@ -64,7 +75,8 @@ final class FlasherModelObserver
/**
* Handle the Model "restored" event.
*
- * @param Model $model
+ * @param Model $model
+ *
* @return void
*/
public function restored(Model $model)
@@ -75,7 +87,8 @@ final class FlasherModelObserver
/**
* Handle the Model "force deleted" event.
*
- * @param Model $model
+ * @param Model $model
+ *
* @return void
*/
public function forceDeleted(Model $model)
@@ -87,12 +100,21 @@ final class FlasherModelObserver
* @param string $method
* @param Model $model
*/
- private function addFlash(string $method, Model $model)
+ private function addFlash($method, Model $model)
{
- $message = $this->config->get(sprintf('flashable.%s.%s', get_class($model), $method));
+ $exludes = $this->config->get('observer_events.exclude', array());
+ if (in_array($method, $exludes)) {
+ return;
+ }
- if(null === $message) {
- $message = $this->config->get(sprintf('flashable.default.%s', $method));
+ if (isset($exludes[$method]) && in_array(get_class($model), $exludes[$method])) {
+ return;
+ }
+
+ if ($this->translator->has(sprintf('flasher::messages.flashable.%s.%s', get_class($model), $method))) {
+ $message = $this->translator->get(sprintf('flasher::messages.flashable.%s.%s', get_class($model), $method));
+ } else {
+ $message = $this->translator->get(sprintf('flasher::messages.flashable.default.%s', $method));
$message = str_replace('{{ model }}', substr(strrchr(get_class($model), "\\"), 1), $message);
}
diff --git a/src/Laravel/Resources/config/config.php b/src/Laravel/Resources/config/config.php
index 2999fcaa..47c70476 100644
--- a/src/Laravel/Resources/config/config.php
+++ b/src/Laravel/Resources/config/config.php
@@ -1,10 +1,10 @@
'toastr',
+ 'default' => 'template',
'scripts' => array(
- '/vendor/php-flasher/flasher/assets/js/flasher.js'
+ '/vendor/flasher/flasher.js',
),
'auto_create_from_session' => true,
@@ -15,4 +15,30 @@ return array(
'warning' => array('warning', 'alarm'),
'info' => array('info', 'notice', 'alert'),
),
+
+ 'observer_events' => array(
+ 'exclude' => array(
+ 'forceDeleted',
+ 'restored',
+ ),
+ ),
+
+ 'adapters' => array(
+ 'template' => array(
+ 'default' => 'tailwindcss',
+ 'views' => array(
+ 'tailwindcss' => 'flasher::tailwindcss',
+ ),
+ 'scripts' => array(
+ '/vendor/flasher/flasher-template.js',
+ ),
+ 'styles' => array(
+ 'https://unpkg.com/tailwindcss@^2/dist/tailwind.min.css',
+ ),
+ 'options' => array(
+ 'timeout' => 5000,
+ 'position' => 'top-right',
+ ),
+ ),
+ ),
);
diff --git a/src/Laravel/Resources/public/flasher-template.js b/src/Laravel/Resources/public/flasher-template.js
new file mode 100644
index 00000000..2a85cdd3
--- /dev/null
+++ b/src/Laravel/Resources/public/flasher-template.js
@@ -0,0 +1,137 @@
+PHPFlasher.addFactory('template', (function () {
+ 'use strict';
+
+ var exports = {};
+ var options = {
+ timeout: 5000,
+ fps: 30,
+ position: 'top-right',
+ direction: 'top'
+ };
+
+ exports.render = function (envelope) {
+ var position = options.position;
+
+ if (undefined !== envelope.options && undefined !== envelope.options.position) {
+ position = envelope.options.position;
+ }
+
+ var container = document.getElementById('flasher-container-' + position);
+ if (null === container) {
+ container = document.createElement('div');
+ container.id = "flasher-container-" + options.position;
+ container.style.position = "fixed";
+ container.style.maxWidth = "304px";
+ container.style.width = "100%";
+
+ switch (options.position) {
+ case "top-left":
+ container.style.top = 0;
+ container.style.left = "0.5em";
+ break;
+ case "top-right":
+ container.style.top = 0;
+ container.style.right = "0.5em";
+ break;
+ case "bottom-left":
+ container.style.bottom = 0;
+ container.style.left = "0.5em";
+ break;
+ case "bottom-right":
+ default:
+ container.style.bottom = 0;
+ container.style.right = "0.5em";
+ break;
+ }
+ document.getElementsByTagName('body')[0].appendChild(container);
+ }
+
+ var template = stringToHTML(envelope.template);
+ template.style.transition = '0.8s';
+
+ switch (options.direction) {
+ case "top":
+ container.insertBefore(template, container.firstChild);
+ break;
+ case "bottom":
+ default:
+ container.appendChild(template);
+ break;
+ }
+
+ var progressBar = template.querySelector('.flasher-progress');
+
+ var width = 0;
+ var lapse = 1000 / options.fps;
+
+ var showProgress = function () {
+ width++;
+ var percent = (1 - lapse * width / options.timeout) * 100;
+ progressBar.style.width = percent + '%';
+
+ if (percent <= 0) {
+ template.style.opacity = 0;
+ clearInterval(progress);
+
+ setTimeout(function () {
+ template.remove();
+ }, 900);
+ }
+ }
+
+ var progress = setInterval(showProgress, lapse);
+
+ template.addEventListener('mouseover', function () {
+ clearInterval(progress);
+ });
+
+ template.addEventListener("mouseout", function () {
+ progress = setInterval(showProgress, lapse);
+ });
+ };
+
+ exports.renderOptions = function (_setting) {
+ options = extend({}, options, _setting);
+ };
+
+ var stringToHTML = function (str) {
+ var support = (function () {
+ if (!window.DOMParser) return false;
+ var parser = new DOMParser();
+ try {
+ parser.parseFromString('x', 'text/html');
+ } catch (err) {
+ return false;
+ }
+ return true;
+ })();
+
+ if (support) {
+ var parser = new DOMParser();
+ var doc = parser.parseFromString(str, 'text/html');
+ return doc.body.firstChild;
+ }
+
+ var dom = document.createElement('div');
+ dom.innerHTML = str;
+ return dom.firstElementChild;
+ };
+
+ var extend = function (out) {
+ out = out || {};
+
+ for (var i = 1; i < arguments.length; i++) {
+ if (!arguments[i])
+ continue;
+
+ for (var key in arguments[i]) {
+ if (arguments[i].hasOwnProperty(key))
+ out[key] = arguments[i][key];
+ }
+ }
+
+ return out;
+ };
+
+ return exports;
+})());
diff --git a/src/Laravel/Resources/public/flasher.js b/src/Laravel/Resources/public/flasher.js
index 4581795c..259c9661 100644
--- a/src/Laravel/Resources/public/flasher.js
+++ b/src/Laravel/Resources/public/flasher.js
@@ -8,7 +8,7 @@ var PHPFlasher = (function () {
exports.addStyles(_options.styles, function () {
exports.addScripts(_options.scripts, function () {
exports.renderOptions(_options.options);
- exports.renderNotifications(_options.notifications);
+ exports.renderEnvelopes(_options.envelopes);
});
});
};
@@ -76,9 +76,9 @@ var PHPFlasher = (function () {
});
};
- exports.renderNotifications = function (notifications) {
- notifications.forEach(function (flash) {
- factories[flash.handler].render(flash.notification);
+ exports.renderEnvelopes = function (envelopes) {
+ envelopes.forEach(function (envelope) {
+ factories[envelope.handler].render(envelope);
})
};
diff --git a/src/Laravel/Resources/views/tailwindcss.blade.php b/src/Laravel/Resources/views/tailwindcss.blade.php
new file mode 100644
index 00000000..a3c7681a
--- /dev/null
+++ b/src/Laravel/Resources/views/tailwindcss.blade.php
@@ -0,0 +1,51 @@
+getType()) {
+ case 'success':
+ $textColor = 'text-green-600';
+ $backgroundColor = 'bg-green-600';
+ $progressBackgroundColor = 'bg-green-100';
+ $borderColor = 'border-green-600';
+ $icon = '';
+ break;
+ case 'error':
+ $textColor = 'text-red-600';
+ $backgroundColor = 'bg-red-600';
+ $progressBackgroundColor = 'bg-red-100';
+ $borderColor = 'border-red-600';
+ $icon = '';
+ break;
+ case 'warning':
+ $textColor = 'text-yellow-600';
+ $backgroundColor = 'bg-yellow-600';
+ $progressBackgroundColor = 'bg-yellow-100';
+ $borderColor = 'border-yellow-600';
+ $icon = '';
+ break;
+ case 'info':
+ default:
+ $textColor = 'text-blue-600';
+ $backgroundColor = 'bg-blue-600';
+ $progressBackgroundColor = 'bg-blue-100';
+ $borderColor = 'border-blue-600';
+ $icon = '';
+ break;
+ }
+?>
+
+
+
+ {!! $icon !!}
+
+
+
+ {{ $envelope->getType() }}
+
+
+ {{ $envelope->getMessage() }}
+
+
+
+
+
+
+
diff --git a/src/Laravel/ServiceProvider/Providers/Laravel.php b/src/Laravel/ServiceProvider/Providers/Laravel.php
index 5af3916a..7cb104c3 100644
--- a/src/Laravel/ServiceProvider/Providers/Laravel.php
+++ b/src/Laravel/ServiceProvider/Providers/Laravel.php
@@ -5,14 +5,18 @@ namespace Flasher\Laravel\ServiceProvider\Providers;
use Flasher\Laravel\Config\Config;
use Flasher\Laravel\FlasherServiceProvider;
use Flasher\Laravel\Storage\Storage;
+use Flasher\Laravel\Template\BladeEngine;
use Flasher\Prime\EventDispatcher\EventDispatcher;
use Flasher\Prime\EventDispatcher\EventListener\StampsListener;
use Flasher\Prime\EventDispatcher\EventListener\FilterListener;
use Flasher\Prime\EventDispatcher\EventListener\RemoveListener;
+use Flasher\Prime\EventDispatcher\EventListener\TemplateListener;
+use Flasher\Prime\Factory\NotificationFactory;
use Flasher\Prime\Filter\Filter;
use Flasher\Prime\Flasher;
use Flasher\Prime\Renderer\Renderer;
use Flasher\Prime\Storage\StorageManager;
+use Flasher\Toastr\Prime\ToastrFactory;
use Illuminate\Container\Container;
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Blade;
@@ -31,24 +35,16 @@ class Laravel implements ServiceProviderInterface
return $this->app instanceof Application;
}
- public function publishConfig(FlasherServiceProvider $provider)
- {
- $source = realpath($raw = flasher_path(__DIR__.'/../../Resources/config/config.php')) ?: $raw;
-
- $provider->publishes(array($source => config_path('flasher.php')), 'config');
-
- $provider->mergeConfigFrom($source, 'flasher');
- }
-
- public function publishAssets(FlasherServiceProvider $provider)
- {
- $provider->publishes(array(flasher_path(__DIR__.'/../../Resources/public') => public_path(flasher_path('vendor/php-flasher/flasher/assets/js'))), 'public');
- }
-
- public function publishTranslations(FlasherServiceProvider $provider)
+ public function publishes(FlasherServiceProvider $provider)
{
+ $provider->mergeConfigFrom(flasher_path(__DIR__.'/../../Resources/config/config.php'), 'flasher');
$provider->loadTranslationsFrom(flasher_path(__DIR__.'/../../Resources/lang'), 'flasher');
- $provider->publishes(array(flasher_path(__DIR__.'/../../Resources/lang') => resource_path(flasher_path('lang/vendor/flasher'))));
+ $provider->loadViewsFrom(flasher_path(__DIR__.'/../../Resources/views'), 'flasher');
+
+ $provider->publishes(array(flasher_path(__DIR__.'/../../Resources/config/config.php') => config_path('flasher.php')), 'flasher-config');
+ $provider->publishes(array(flasher_path(__DIR__.'/../../Resources/public') => public_path(flasher_path('vendor/flasher'))), 'flasher-public');
+ $provider->publishes(array(flasher_path(__DIR__.'/../../Resources/lang') => resource_path(flasher_path('lang/vendor/flasher'))), 'flasher-lang');
+ $provider->publishes(array(flasher_path(__DIR__.'/../../Resources/views') => resource_path(flasher_path('views/vendor/flasher'))), 'flasher-views');
}
public function registerServices()
@@ -63,7 +59,10 @@ class Laravel implements ServiceProviderInterface
public function registerCommonServices()
{
$this->app->singleton('flasher', function (Application $app) {
- return new Flasher($app['flasher.config']);
+ $flasher = new Flasher($app['flasher.config']);
+ $flasher->addFactory('template', $app['flasher.template']);
+
+ return $flasher;
});
$this->app->singleton('flasher.renderer', function (Application $app) {
@@ -82,16 +81,25 @@ class Laravel implements ServiceProviderInterface
return new Filter();
});
+ $this->app->singleton('flasher.template_engine', function (Application $app) {
+ return new BladeEngine($app['view']);
+ });
+
$this->app->singleton('flasher.event_dispatcher', function (Application $app) {
$eventDispatcher = new EventDispatcher();
$eventDispatcher->addSubscriber(new FilterListener($app['flasher.filter']));
$eventDispatcher->addSubscriber(new RemoveListener());
$eventDispatcher->addSubscriber(new StampsListener());
+ $eventDispatcher->addSubscriber(new TemplateListener($app['flasher.config'], $app['flasher.template_engine']));
return $eventDispatcher;
});
+ $this->app->singleton('flasher.notification_factory', function (Application $app) {
+ return new NotificationFactory($app['flasher.storage_manager']);
+ });
+
$this->app->alias('flasher.config', 'Flasher\Laravel\Config\Config');
$this->app->alias('flasher', 'Flasher\Prime\Flasher');
$this->app->alias('flasher.renderer', 'Flasher\Prime\Renderer\Renderer');
@@ -99,6 +107,9 @@ class Laravel implements ServiceProviderInterface
$this->app->alias('flasher.storage', 'Flasher\Laravel\Storage\Storage');
$this->app->alias('flasher.storage_manager', 'Flasher\Laravel\Storage\StorageManager');
$this->app->alias('flasher.filter', 'Flasher\Prime\Filter\Filter');
+ $this->app->alias('flasher.template_engine', 'Flasher\Laravel\Template\BladeEngine');
+ $this->app->alias('flasher.notification_factory', 'Flasher\Prime\Factory\NotificationFactory');
+ $this->app->alias('Flasher\Prime\Factory\NotificationFactory', 'flasher.template');
$this->app->bind('Flasher\Prime\Config\ConfigInterface', 'flasher.config');
@@ -108,6 +119,8 @@ class Laravel implements ServiceProviderInterface
$this->app->bind('Flasher\Prime\Filter\FilterInterface', 'flasher.filter');
$this->app->bind('Flasher\Prime\EventDispatcher\EventDispatcherInterface', 'flasher.event_dispatcher');
$this->app->bind('Flasher\Prime\Storage\StorageInterface', 'flasher.storage');
+ $this->app->bind('Flasher\Prime\Template\EngineInterface', 'flasher.template_engine');
+ $this->app->bind('Flasher\Prime\Factory\NotificationFactoryInterface', 'flasher.notification_factory');
}
public function registerBladeDirectives()
@@ -129,7 +142,7 @@ class Laravel implements ServiceProviderInterface
$criteria = "array()";
}
- return "render($criteria, 'html'); ?>";
+ return "render($criteria, array('format' => 'html')); ?>";
});
}
}
diff --git a/src/Laravel/ServiceProvider/Providers/Laravel4.php b/src/Laravel/ServiceProvider/Providers/Laravel4.php
index b1d9a99e..1cf6983e 100644
--- a/src/Laravel/ServiceProvider/Providers/Laravel4.php
+++ b/src/Laravel/ServiceProvider/Providers/Laravel4.php
@@ -15,19 +15,11 @@ final class Laravel4 extends Laravel
return $this->app instanceof Application && 0 === strpos(Application::VERSION, '4.');
}
- public function publishConfig(FlasherServiceProvider $provider)
+ public function publishes(FlasherServiceProvider $provider)
{
$provider->package('php-flasher/flasher-laravel', 'flasher', flasher_path(__DIR__.'/../../Resources'));
}
- public function publishAssets(FlasherServiceProvider $provider)
- {
- }
-
- public function publishTranslations(FlasherServiceProvider $provider)
- {
- }
-
public function registerServices()
{
$this->app->singleton('flasher.config', function (Application $app) {
diff --git a/src/Laravel/ServiceProvider/Providers/Laravel50.php b/src/Laravel/ServiceProvider/Providers/Laravel50.php
index ca7de456..538711c2 100644
--- a/src/Laravel/ServiceProvider/Providers/Laravel50.php
+++ b/src/Laravel/ServiceProvider/Providers/Laravel50.php
@@ -14,7 +14,7 @@ final class Laravel50 extends Laravel
return $this->app instanceof Application && 0 === strpos(Application::VERSION, '5.0');
}
- public function publishTranslations(FlasherServiceProvider $provider)
+ public function publishes(FlasherServiceProvider $provider)
{
$provider->loadTranslationsFrom(flasher_path(__DIR__.'/../../Resources/lang'), 'flasher');
$provider->publishes(array(flasher_path(__DIR__.'/../../Resources/lang') => base_path(flasher_path('resources/lang/vendor/flasher'))));
diff --git a/src/Laravel/ServiceProvider/Providers/Laravel51.php b/src/Laravel/ServiceProvider/Providers/Laravel51.php
index 712f3b58..f4cc9c88 100644
--- a/src/Laravel/ServiceProvider/Providers/Laravel51.php
+++ b/src/Laravel/ServiceProvider/Providers/Laravel51.php
@@ -12,7 +12,7 @@ final class Laravel51 extends Laravel
return $this->app instanceof Application && 0 === strpos(Application::VERSION, '5.1');
}
- public function publishTranslations(FlasherServiceProvider $provider)
+ public function publishes(FlasherServiceProvider $provider)
{
$provider->loadTranslationsFrom(flasher_path(__DIR__.'/../../Resources/lang'), 'flasher');
$provider->publishes(array(flasher_path(__DIR__.'/../../Resources/lang') => base_path(flasher_path('resources/lang/vendor/flasher'))));
diff --git a/src/Laravel/ServiceProvider/Providers/Lumen.php b/src/Laravel/ServiceProvider/Providers/Lumen.php
index 5ab828bd..6e15c8f1 100644
--- a/src/Laravel/ServiceProvider/Providers/Lumen.php
+++ b/src/Laravel/ServiceProvider/Providers/Lumen.php
@@ -12,7 +12,7 @@ final class Lumen extends Laravel
return $this->app instanceof Application;
}
- public function publishConfig(FlasherServiceProvider $provider)
+ public function publishes(FlasherServiceProvider $provider)
{
$source = realpath($raw = flasher_path(__DIR__.'/../../../Resources/config/config.php')) ?: $raw;
diff --git a/src/Laravel/ServiceProvider/Providers/ServiceProviderInterface.php b/src/Laravel/ServiceProvider/Providers/ServiceProviderInterface.php
index 0a4302c1..f6213d72 100644
--- a/src/Laravel/ServiceProvider/Providers/ServiceProviderInterface.php
+++ b/src/Laravel/ServiceProvider/Providers/ServiceProviderInterface.php
@@ -8,11 +8,7 @@ interface ServiceProviderInterface
{
public function shouldBeUsed();
- public function publishConfig(FlasherServiceProvider $provider);
-
- public function publishAssets(FlasherServiceProvider $provider);
-
- public function publishTranslations(FlasherServiceProvider $provider);
+ public function publishes(FlasherServiceProvider $provider);
public function registerServices();
diff --git a/src/Laravel/ServiceProvider/ServiceProviderManager.php b/src/Laravel/ServiceProvider/ServiceProviderManager.php
index 506b30aa..199f0614 100644
--- a/src/Laravel/ServiceProvider/ServiceProviderManager.php
+++ b/src/Laravel/ServiceProvider/ServiceProviderManager.php
@@ -31,9 +31,7 @@ final class ServiceProviderManager
{
$provider = $this->resolveServiceProvider();
- $provider->publishConfig($this->notifyServiceProvider);
- $provider->publishAssets($this->notifyServiceProvider);
- $provider->publishTranslations($this->notifyServiceProvider);
+ $provider->publishes($this->notifyServiceProvider);
$provider->registerBladeDirectives();
}
diff --git a/src/Laravel/Template/BladeEngine.php b/src/Laravel/Template/BladeEngine.php
new file mode 100644
index 00000000..8c4ec61d
--- /dev/null
+++ b/src/Laravel/Template/BladeEngine.php
@@ -0,0 +1,29 @@
+engine = $engine;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function render($name, array $context = array())
+ {
+ return (string) $this->engine->make($name, $context);
+ }
+}
diff --git a/src/Noty/Laravel/Resources/public/flasher-noty.js b/src/Noty/Laravel/Resources/public/flasher-noty.js
index f654f7d9..d6b20820 100644
--- a/src/Noty/Laravel/Resources/public/flasher-noty.js
+++ b/src/Noty/Laravel/Resources/public/flasher-noty.js
@@ -4,10 +4,11 @@ PHPFlasher.addFactory('noty', (function () {
var exports = {};
exports.render = function (data) {
+ var notification = data.notification;
var options = {
- text: data.message,
- type: data.type,
- ...data.options
+ text: notification.message,
+ type: notification.type,
+ ...notification.options
}
new Noty(options).show();
diff --git a/src/Noty/Prime/NotyFactory.php b/src/Noty/Prime/NotyFactory.php
index 60f9a337..7c931ebf 100644
--- a/src/Noty/Prime/NotyFactory.php
+++ b/src/Noty/Prime/NotyFactory.php
@@ -2,12 +2,12 @@
namespace Flasher\Noty\Prime;
-use Flasher\Prime\Factory\AbstractFactory;
+use Flasher\Prime\Factory\NotificationFactory;
/**
* @mixin NotyBuilder
*/
-final class NotyFactory extends AbstractFactory
+final class NotyFactory extends NotificationFactory
{
/**
* @inheritDoc
diff --git a/src/Noty/Symfony/Resources/config/config.yaml b/src/Noty/Symfony/Resources/config/config.yaml
index 094e84b9..ebbebcae 100644
--- a/src/Noty/Symfony/Resources/config/config.yaml
+++ b/src/Noty/Symfony/Resources/config/config.yaml
@@ -1,6 +1,6 @@
services:
flasher.noty:
- parent: 'flasher.abstract_factory'
+ parent: 'flasher.notification_factory'
class: Flasher\Noty\Prime\NotyFactory
tags:
- { name: 'flasher.factory', alias: 'noty' }
diff --git a/src/Noty/Symfony/Resources/public/flasher-noty.js b/src/Noty/Symfony/Resources/public/flasher-noty.js
index f654f7d9..d6b20820 100644
--- a/src/Noty/Symfony/Resources/public/flasher-noty.js
+++ b/src/Noty/Symfony/Resources/public/flasher-noty.js
@@ -4,10 +4,11 @@ PHPFlasher.addFactory('noty', (function () {
var exports = {};
exports.render = function (data) {
+ var notification = data.notification;
var options = {
- text: data.message,
- type: data.type,
- ...data.options
+ text: notification.message,
+ type: notification.type,
+ ...notification.options
}
new Noty(options).show();
diff --git a/src/Notyf/Laravel/Resources/public/flasher-notyf.js b/src/Notyf/Laravel/Resources/public/flasher-notyf.js
index dd6fe205..5876c77f 100644
--- a/src/Notyf/Laravel/Resources/public/flasher-notyf.js
+++ b/src/Notyf/Laravel/Resources/public/flasher-notyf.js
@@ -4,7 +4,7 @@ PHPFlasher.addFactory('notyf', (function () {
var exports = {};
exports.render = function (data) {
- window.notyf.open(data);
+ window.notyf.open(data.notification);
};
exports.renderOptions = function (options) {
diff --git a/src/Notyf/Prime/NotyfFactory.php b/src/Notyf/Prime/NotyfFactory.php
index 9e1a3860..e5499c3f 100644
--- a/src/Notyf/Prime/NotyfFactory.php
+++ b/src/Notyf/Prime/NotyfFactory.php
@@ -2,12 +2,12 @@
namespace Flasher\Notyf\Prime;
-use Flasher\Prime\Factory\AbstractFactory;
+use Flasher\Prime\Factory\NotificationFactory;
/**
* @mixin NotyfBuilder
*/
-final class NotyfFactory extends AbstractFactory
+final class NotyfFactory extends NotificationFactory
{
/**
* @inheritDoc
diff --git a/src/Notyf/Symfony/Resources/config/config.yaml b/src/Notyf/Symfony/Resources/config/config.yaml
index f4950e70..58b63c31 100644
--- a/src/Notyf/Symfony/Resources/config/config.yaml
+++ b/src/Notyf/Symfony/Resources/config/config.yaml
@@ -1,6 +1,6 @@
services:
flasher.notyf:
- parent: 'flasher.abstract_factory'
+ parent: 'flasher.notification_factory'
class: Flasher\Notyf\Prime\NotyfFactory
tags:
- { name: 'flasher.factory', alias: 'notyf' }
diff --git a/src/Notyf/Symfony/Resources/public/flasher-notyf.js b/src/Notyf/Symfony/Resources/public/flasher-notyf.js
index dd6fe205..5876c77f 100644
--- a/src/Notyf/Symfony/Resources/public/flasher-notyf.js
+++ b/src/Notyf/Symfony/Resources/public/flasher-notyf.js
@@ -4,7 +4,7 @@ PHPFlasher.addFactory('notyf', (function () {
var exports = {};
exports.render = function (data) {
- window.notyf.open(data);
+ window.notyf.open(data.notification);
};
exports.renderOptions = function (options) {
diff --git a/src/Pnotify/Laravel/Resources/public/flasher-pnotify.js b/src/Pnotify/Laravel/Resources/public/flasher-pnotify.js
index 1a8ca8d0..a03d66a4 100644
--- a/src/Pnotify/Laravel/Resources/public/flasher-pnotify.js
+++ b/src/Pnotify/Laravel/Resources/public/flasher-pnotify.js
@@ -4,10 +4,11 @@ PHPFlasher.addFactory('pnotify', (function () {
var exports = {};
exports.render = function (data) {
+ var notification = data.notification;
var options = {
- text: data.message,
- type: data.type,
- ...data.options
+ text: notification.message,
+ type: notification.type,
+ ...notification.options
}
new PNotify(options);
diff --git a/src/Pnotify/Prime/PnotifyFactory.php b/src/Pnotify/Prime/PnotifyFactory.php
index 3a8fb34a..70c50dba 100644
--- a/src/Pnotify/Prime/PnotifyFactory.php
+++ b/src/Pnotify/Prime/PnotifyFactory.php
@@ -2,12 +2,12 @@
namespace Flasher\Pnotify\Prime;
-use Flasher\Prime\Factory\AbstractFactory;
+use Flasher\Prime\Factory\NotificationFactory;
/**
* @mixin PnotifyBuilder
*/
-final class PnotifyFactory extends AbstractFactory
+final class PnotifyFactory extends NotificationFactory
{
/**
* @inheritDoc
diff --git a/src/Pnotify/Symfony/Resources/config/config.yaml b/src/Pnotify/Symfony/Resources/config/config.yaml
index b5323526..f0db663f 100644
--- a/src/Pnotify/Symfony/Resources/config/config.yaml
+++ b/src/Pnotify/Symfony/Resources/config/config.yaml
@@ -1,6 +1,6 @@
services:
flasher.pnotify:
- parent: 'flasher.abstract_factory'
+ parent: 'flasher.notification_factory'
class: Flasher\Pnotify\Prime\PnotifyFactory
tags:
- { name: 'flasher.factory', alias: 'pnotify' }
diff --git a/src/Pnotify/Symfony/Resources/public/flasher-pnotify.js b/src/Pnotify/Symfony/Resources/public/flasher-pnotify.js
index 1a8ca8d0..a03d66a4 100644
--- a/src/Pnotify/Symfony/Resources/public/flasher-pnotify.js
+++ b/src/Pnotify/Symfony/Resources/public/flasher-pnotify.js
@@ -4,10 +4,11 @@ PHPFlasher.addFactory('pnotify', (function () {
var exports = {};
exports.render = function (data) {
+ var notification = data.notification;
var options = {
- text: data.message,
- type: data.type,
- ...data.options
+ text: notification.message,
+ type: notification.type,
+ ...notification.options
}
new PNotify(options);
diff --git a/src/Prime/Envelope.php b/src/Prime/Envelope.php
index f0be3dbf..4367959e 100644
--- a/src/Prime/Envelope.php
+++ b/src/Prime/Envelope.php
@@ -3,6 +3,7 @@
namespace Flasher\Prime;
use Flasher\Prime\Notification\NotificationInterface;
+use Flasher\Prime\Stamp\PresentableStampInterface;
use Flasher\Prime\Stamp\StampInterface;
final class Envelope implements NotificationInterface
@@ -181,6 +182,16 @@ final class Envelope implements NotificationInterface
*/
public function toArray()
{
- return $this->notification->toArray();
+ $array = array(
+ 'notification' => $this->notification->toArray(),
+ );
+
+ foreach ($this->all() as $stamp) {
+ if ($stamp instanceof PresentableStampInterface) {
+ $array = array_merge($array, $stamp->toArray());
+ }
+ }
+
+ return $array;
}
}
diff --git a/src/Prime/EventDispatcher/Event/ResponseEvent.php b/src/Prime/EventDispatcher/Event/ResponseEvent.php
new file mode 100644
index 00000000..aee83619
--- /dev/null
+++ b/src/Prime/EventDispatcher/Event/ResponseEvent.php
@@ -0,0 +1,37 @@
+envelopes = $envelopes;
+ }
+
+ /**
+ * @return Envelope[]
+ */
+ public function getEnvelopes()
+ {
+ return $this->envelopes;
+ }
+
+ /**
+ * @param Envelope[] $envelopes
+ */
+ public function setEnvelopes(array $envelopes)
+ {
+ $this->envelopes = $envelopes;
+ }
+}
diff --git a/src/Prime/EventDispatcher/EventListener/ResponseListener.php b/src/Prime/EventDispatcher/EventListener/ResponseListener.php
new file mode 100644
index 00000000..95e58a59
--- /dev/null
+++ b/src/Prime/EventDispatcher/EventListener/ResponseListener.php
@@ -0,0 +1,44 @@
+filter = $filter;
+ }
+
+ /**
+ * @param FilterEvent $event
+ */
+ public function __invoke(FilterEvent $event)
+ {
+ $criteria = $event->getCriteria();
+ $criteria['delay'] = 0;
+ $criteria['hops']['min'] = 1;
+
+ $envelopes = $this->filter->filter($event->getEnvelopes(), $criteria);
+
+ $event->setEnvelopes($envelopes);
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public static function getSubscribedEvents()
+ {
+ return 'Flasher\Prime\EventDispatcher\Event\FilterEvent';
+ }
+}
diff --git a/src/Prime/EventDispatcher/EventListener/TemplateListener.php b/src/Prime/EventDispatcher/EventListener/TemplateListener.php
new file mode 100644
index 00000000..c3836455
--- /dev/null
+++ b/src/Prime/EventDispatcher/EventListener/TemplateListener.php
@@ -0,0 +1,72 @@
+config = $config;
+ $this->templateEngine = $templateEngine;
+ }
+
+ public function __invoke(ResponseEvent $event)
+ {
+ $envelopes = array();
+
+ foreach ($event->getEnvelopes() as $envelope) {
+ $handler = $envelope->get('Flasher\Prime\Stamp\HandlerStamp')->getHandler();
+
+ if ('template' !== $handler) {
+ $envelopes[] = $envelope;
+ continue;
+ }
+
+ $viewStamp = $envelope->get('Flasher\Prime\Stamp\TemplateStamp');
+ $view = 'default';
+ if (null !== $viewStamp) {
+ $view = $viewStamp->getView();
+ }
+
+ $template = $this->config->get('adapters.template.views.'.$view);
+
+ if (null === $template) {
+ $default = $this->config->get('adapters.template.default');
+ $template = $this->config->get('adapters.template.views.'.$default);
+ }
+
+ $compiled = $this->templateEngine->render($template, array(
+ 'envelope' => $envelope,
+ ));
+
+ $envelope->withStamp(new TemplateStamp($view, $compiled));
+ $envelopes[] = $envelope;
+ }
+
+ $event->setEnvelopes($envelopes);
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return 'Flasher\Prime\EventDispatcher\Event\ResponseEvent';
+ }
+}
diff --git a/src/Prime/Factory/NotificationFactory.php b/src/Prime/Factory/NotificationFactory.php
new file mode 100644
index 00000000..8fbf9745
--- /dev/null
+++ b/src/Prime/Factory/NotificationFactory.php
@@ -0,0 +1,52 @@
+storageManager = $storageManager;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function createNotificationBuilder()
+ {
+ return new NotificationBuilder($this->getStorageManager(), new Notification(), 'template');
+ }
+
+ /**
+ * Dynamically call the default driver instance.
+ *
+ * @param string $method
+ * @param array $parameters
+ *
+ * @return mixed
+ */
+ public function __call($method, array $parameters)
+ {
+ return call_user_func_array(array($this->createNotificationBuilder(), $method), $parameters);
+ }
+
+ /**
+ * @return StorageManagerInterface
+ */
+ public function getStorageManager()
+ {
+ return $this->storageManager;
+ }
+}
diff --git a/src/Prime/Factory/NotificationFactoryInterface.php b/src/Prime/Factory/NotificationFactoryInterface.php
new file mode 100644
index 00000000..2100bca0
--- /dev/null
+++ b/src/Prime/Factory/NotificationFactoryInterface.php
@@ -0,0 +1,16 @@
+factories[$alias] = $factory;
diff --git a/src/Prime/FlasherInterface.php b/src/Prime/FlasherInterface.php
index a5a2a7e7..fb7780f9 100644
--- a/src/Prime/FlasherInterface.php
+++ b/src/Prime/FlasherInterface.php
@@ -2,7 +2,7 @@
namespace Flasher\Prime;
-use Flasher\Prime\Factory\FactoryInterface;
+use Flasher\Prime\Factory\NotificationFactoryInterface;
use Flasher\Prime\Notification\NotificationBuilderInterface;
/**
@@ -15,7 +15,7 @@ interface FlasherInterface
*
* @param string|null $alias
*
- * @return FactoryInterface
+ * @return NotificationFactoryInterface
*
* @throws \InvalidArgumentException
*/
@@ -25,9 +25,9 @@ interface FlasherInterface
* Register a custom driver creator.
*
* @param string $alias
- * @param FactoryInterface $factory
+ * @param NotificationFactoryInterface $factory
*
* @return $this
*/
- public function addFactory($alias, FactoryInterface $factory);
+ public function addFactory($alias, NotificationFactoryInterface $factory);
}
diff --git a/src/Prime/Notification/NotificationBuilder.php b/src/Prime/Notification/NotificationBuilder.php
index a2288480..415fa448 100644
--- a/src/Prime/Notification/NotificationBuilder.php
+++ b/src/Prime/Notification/NotificationBuilder.php
@@ -9,6 +9,7 @@ use Flasher\Prime\Stamp\HopsStamp;
use Flasher\Prime\Stamp\PriorityStamp;
use Flasher\Prime\Stamp\StampInterface;
use Flasher\Prime\Storage\StorageManagerInterface;
+use Flasher\Toastr\Prime\ToastrBuilder;
class NotificationBuilder implements NotificationBuilderInterface
{
diff --git a/src/Prime/Renderer/Presenter/AbstractPresenter.php b/src/Prime/Renderer/Presenter/AbstractPresenter.php
new file mode 100644
index 00000000..71ff83c1
--- /dev/null
+++ b/src/Prime/Renderer/Presenter/AbstractPresenter.php
@@ -0,0 +1,116 @@
+config = $config;
+ }
+
+ /**
+ * @param Envelope[] $envelopes
+ *
+ * @return array[]
+ */
+ protected function getEnvelopes(array $envelopes)
+ {
+ return array_map(function (Envelope $envelope) {
+ return $envelope->toArray();
+ }, $envelopes);
+ }
+
+ /**
+ * @param Envelope[] $envelopes
+ *
+ * @return string[]
+ */
+ protected function getStyles(array $envelopes)
+ {
+ return $this->getAssets('styles', $envelopes);
+ }
+
+ /**
+ * @param Envelope[] $envelopes
+ *
+ * @return string[]
+ */
+ protected function getScripts(array $envelopes)
+ {
+ return $this->getAssets('scripts', $envelopes);
+ }
+
+ /**
+ * @param Envelope[] $envelopes
+ *
+ * @return string[]
+ */
+ protected function getOptions(array $envelopes)
+ {
+ $options = array();
+ $handlers = array();
+
+ foreach ($envelopes as $envelope) {
+ $handler = $envelope->get('Flasher\Prime\Stamp\HandlerStamp')->getHandler();
+ if (in_array($handler, $handlers)) {
+ continue;
+ }
+
+ $handlers[] = $handler;
+ $options[$handler] = $this->config->get(sprintf('adapters.%s.options', $handler), array());
+ }
+
+ return array_filter($options);
+ }
+
+ /**
+ * @param Envelope[] $envelopes
+ *
+ * @return array
+ */
+ protected function toArray(array $envelopes = array())
+ {
+ return array(
+ 'scripts' => $this->getScripts($envelopes),
+ 'styles' => $this->getStyles($envelopes),
+ 'options' => $this->getOptions($envelopes),
+ 'envelopes' => $this->getEnvelopes($envelopes),
+ );
+ }
+
+ /**
+ * @param string $keyword
+ * @param Envelope[] $envelopes
+ *
+ * @return string[]
+ */
+ private function getAssets($keyword, $envelopes)
+ {
+ $files = $this->config->get($keyword, array());
+ $handlers = array();
+
+ foreach ($envelopes as $envelope) {
+ $handler = $envelope->get('Flasher\Prime\Stamp\HandlerStamp')->getHandler();
+ if (in_array($handler, $handlers)) {
+ continue;
+ }
+
+ $handlers[] = $handler;
+ $files = array_merge($files, $this->config->get(sprintf('adapters.%s.%s', $handler, $keyword), array()));
+ }
+
+ return array_values(array_filter(array_unique($files)));
+ }
+}
diff --git a/src/Prime/Renderer/Presenter/ArrayPresenter.php b/src/Prime/Renderer/Presenter/ArrayPresenter.php
new file mode 100644
index 00000000..4113119d
--- /dev/null
+++ b/src/Prime/Renderer/Presenter/ArrayPresenter.php
@@ -0,0 +1,14 @@
+toArray($envelopes);
+ }
+}
diff --git a/src/Prime/Renderer/Presenter/HtmlPresenter.php b/src/Prime/Renderer/Presenter/HtmlPresenter.php
new file mode 100644
index 00000000..8d2276b3
--- /dev/null
+++ b/src/Prime/Renderer/Presenter/HtmlPresenter.php
@@ -0,0 +1,49 @@
+renderScripts($this->getScripts($envelopes), $context);
+ $response = json_encode($this->toArray($envelopes));
+
+ return <<
+if ("undefined" === typeof PHPFlasher) {
+ alert("[PHPFlasher] not found, please include the '/bundles/flasher/flasher.js' file");
+} else {
+ PHPFlasher.render({$response});
+}
+
+HTML;
+ }
+
+ /**
+ * @param string[] $scripts
+ * @param array $context
+ *
+ * @return string
+ */
+ public function renderScripts($scripts, array $context)
+ {
+ $html = '';
+
+ foreach ($scripts as $file) {
+ if (empty($context['content']) || false === strpos($context['content'], $file)) {
+ $html .= sprintf('', $file).PHP_EOL;
+ }
+ }
+
+ return $html;
+ }
+}
diff --git a/src/Prime/Renderer/Presenter/PresenterInterface.php b/src/Prime/Renderer/Presenter/PresenterInterface.php
new file mode 100644
index 00000000..70bdbfb8
--- /dev/null
+++ b/src/Prime/Renderer/Presenter/PresenterInterface.php
@@ -0,0 +1,16 @@
+
+ */
+ private $presenters;
+
+ public function __construct(ConfigInterface $config)
+ {
+ $this->addPresenter('array', new ArrayPresenter($config));
+ $this->addPresenter('html', new HtmlPresenter($config));
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function addPresenter($alias, PresenterInterface $response)
+ {
+ $this->presenters[$alias] = $response;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function create($alias)
+ {
+ if (!isset($this->presenters[$alias])) {
+ throw new \InvalidArgumentException(sprintf('[%s] presenter not supported.', $alias));
+ }
+
+ return $this->presenters[$alias];
+ }
+}
diff --git a/src/Prime/Renderer/Presenter/PresenterManagerInterface.php b/src/Prime/Renderer/Presenter/PresenterManagerInterface.php
new file mode 100644
index 00000000..c4a8eea0
--- /dev/null
+++ b/src/Prime/Renderer/Presenter/PresenterManagerInterface.php
@@ -0,0 +1,19 @@
+storageManager = $storageManager;
$this->eventDispatcher = $eventDispatcher;
$this->config = $config;
- $this->responseManager = $responseManager ?: new ResponseManager();
+ $this->presenterManager = $presenterManager ?: new PresenterManager($config);
}
/**
@@ -57,20 +58,14 @@ final class Renderer implements RendererInterface
{
$envelopes = $this->getEnvelopes($criteria);
- if (empty($envelopes)) {
- return array();
- }
-
- $response = array(
- 'scripts' => $this->getScripts($envelopes),
- 'styles' => $this->getStyles($envelopes),
- 'options' => $this->getOptions($envelopes),
- 'notifications' => $this->getNotifications($envelopes),
- );
-
$this->storageManager->remove($envelopes);
- return $this->responseManager->create(isset($context['format']) ? $context['format'] : 'array')->render($response, $context);
+ $event = new ResponseEvent($envelopes);
+ $this->eventDispatcher->dispatch($event);
+
+ $format = isset($context['format']) ? $context['format'] : 'array';
+
+ return $this->presenterManager->create($format)->render($event->getEnvelopes(), $context);
}
/**
@@ -87,87 +82,4 @@ final class Renderer implements RendererInterface
return $event->getEnvelopes();
}
-
- /**
- * @param Envelope[] $envelopes
- *
- * @return string[]
- */
- private function getStyles(array $envelopes)
- {
- return $this->getAssets('styles', $envelopes);
- }
-
- /**
- * @param Envelope[] $envelopes
- *
- * @return string[]
- */
- private function getScripts(array $envelopes)
- {
- return $this->getAssets('scripts', $envelopes);
- }
-
- /**
- * @param Envelope[] $envelopes
- *
- * @return string[]
- */
- private function getOptions(array $envelopes)
- {
- $options = array();
- $handlers = array();
-
- foreach ($envelopes as $envelope) {
- $handler = $envelope->get('Flasher\Prime\Stamp\HandlerStamp')->getHandler();
- if (in_array($handler, $handlers)) {
- continue;
- }
-
- $handlers[] = $handler;
- $options[$handler] = $this->config->get(sprintf('adapters.%s.options', $handler), array());
- }
-
- return array_filter($options);
- }
-
- /**
- * @param Envelope[] $envelopes
- *
- * @return array[]
- */
- private function getNotifications(array $envelopes)
- {
- return array_map(function (Envelope $envelope) {
- return array(
- 'handler' => $envelope->get('Flasher\Prime\Stamp\HandlerStamp')->getHandler(),
- 'notification' => $envelope->toArray(),
- );
- },
- $envelopes);
- }
-
- /**
- * @param string $keyword
- * @param Envelope[] $envelopes
- *
- * @return string[]
- */
- private function getAssets($keyword, $envelopes)
- {
- $files = $this->config->get($keyword, array());
- $handlers = array();
-
- foreach ($envelopes as $envelope) {
- $handler = $envelope->get('Flasher\Prime\Stamp\HandlerStamp')->getHandler();
- if (in_array($handler, $handlers)) {
- continue;
- }
-
- $handlers[] = $handler;
- $files = array_merge($files, $this->config->get(sprintf('adapters.%s.%s', $handler, $keyword), array()));
- }
-
- return array_values(array_filter(array_unique($files)));
- }
}
diff --git a/src/Prime/Resources/views/tailwindcss.php b/src/Prime/Resources/views/tailwindcss.php
new file mode 100644
index 00000000..e69de29b
diff --git a/src/Prime/Stamp/CreatedAtStamp.php b/src/Prime/Stamp/CreatedAtStamp.php
index ea11de0a..37953002 100644
--- a/src/Prime/Stamp/CreatedAtStamp.php
+++ b/src/Prime/Stamp/CreatedAtStamp.php
@@ -6,21 +6,28 @@ use DateTime;
use DateTimeZone;
use Exception;
-final class CreatedAtStamp implements StampInterface, OrderableStampInterface
+final class CreatedAtStamp implements StampInterface, OrderableStampInterface, PresentableStampInterface
{
/**
* @var DateTime
*/
private $createdAt;
+ /**
+ * @var string
+ */
+ private $format;
+
/**
* @param DateTime|null $createdAt
+ * @param string|null $format
*
* @throws Exception
*/
- public function __construct(DateTime $createdAt = null)
+ 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';
}
/**
@@ -44,4 +51,14 @@ final class CreatedAtStamp implements StampInterface, OrderableStampInterface
return $this->createdAt->getTimestamp() - $orderable->createdAt->getTimestamp();
}
+
+ /**
+ * @inheritDoc
+ */
+ public function toArray()
+ {
+ return array(
+ 'created_at' => $this->getCreatedAt()->format($this->format),
+ );
+ }
}
diff --git a/src/Prime/Stamp/HandlerStamp.php b/src/Prime/Stamp/HandlerStamp.php
index f9c2d667..de42bbe4 100644
--- a/src/Prime/Stamp/HandlerStamp.php
+++ b/src/Prime/Stamp/HandlerStamp.php
@@ -2,7 +2,7 @@
namespace Flasher\Prime\Stamp;
-final class HandlerStamp implements StampInterface
+final class HandlerStamp implements StampInterface, PresentableStampInterface
{
/**
* @var string
@@ -24,4 +24,14 @@ final class HandlerStamp implements StampInterface
{
return $this->handler;
}
+
+ /**
+ * @inheritDoc
+ */
+ public function toArray()
+ {
+ return array(
+ 'handler' => $this->getHandler(),
+ );
+ }
}
diff --git a/src/Prime/Stamp/PresentableStampInterface.php b/src/Prime/Stamp/PresentableStampInterface.php
new file mode 100644
index 00000000..682a05b8
--- /dev/null
+++ b/src/Prime/Stamp/PresentableStampInterface.php
@@ -0,0 +1,11 @@
+
+ */
+ public function toArray();
+}
diff --git a/src/Prime/Stamp/PriorityStamp.php b/src/Prime/Stamp/PriorityStamp.php
index b72894bb..cd5439dc 100644
--- a/src/Prime/Stamp/PriorityStamp.php
+++ b/src/Prime/Stamp/PriorityStamp.php
@@ -2,7 +2,7 @@
namespace Flasher\Prime\Stamp;
-final class PriorityStamp implements StampInterface, OrderableStampInterface
+final class PriorityStamp implements StampInterface, OrderableStampInterface, PresentableStampInterface
{
/**
* @var int
@@ -38,4 +38,14 @@ final class PriorityStamp implements StampInterface, OrderableStampInterface
return $this->priority - $orderable->priority;
}
+
+ /**
+ * @inheritDoc
+ */
+ public function toArray()
+ {
+ return array(
+ 'priority' => $this->getPriority(),
+ );
+ }
}
diff --git a/src/Prime/Stamp/TemplateStamp.php b/src/Prime/Stamp/TemplateStamp.php
new file mode 100644
index 00000000..3b52c420
--- /dev/null
+++ b/src/Prime/Stamp/TemplateStamp.php
@@ -0,0 +1,52 @@
+view = $view;
+ $this->template = $template;
+ }
+
+ /**
+ * @return string
+ */
+ public function getView()
+ {
+ return $this->view;
+ }
+
+ /**
+ * @return string
+ */
+ public function getTemplate()
+ {
+ return $this->template;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function toArray()
+ {
+ return array(
+ 'template' => $this->getTemplate(),
+ );
+ }
+}
diff --git a/src/Prime/Template/Engine.php b/src/Prime/Template/Engine.php
new file mode 100644
index 00000000..e34397d0
--- /dev/null
+++ b/src/Prime/Template/Engine.php
@@ -0,0 +1,11 @@
+children()
->scalarNode('default')
->cannotBeEmpty()
- ->defaultValue('toastr')
->end()
->arrayNode('scripts')
->prototype('scalar')->end()
->defaultValue(array(
- '/bundles/flasher/flasher.js'
+ '/bundles/flasher/flasher.js',
))
->end()
->arrayNode('styles')
diff --git a/src/Symfony/Resources/config/config.yaml b/src/Symfony/Resources/config/config.yaml
index 4079d1d5..52d4fb72 100644
--- a/src/Symfony/Resources/config/config.yaml
+++ b/src/Symfony/Resources/config/config.yaml
@@ -12,11 +12,12 @@ services:
arguments:
- '@flasher.config'
- flasher.abstract_factory:
- class: Flasher\Prime\Factory\AbstractFactory
- abstract: true
+ flasher.notification_factory:
+ class: Flasher\Prime\Factory\NotificationFactory
arguments:
- '@flasher.storage_manager'
+ tags:
+ - { name: 'flasher.factory', alias: 'template' }
flasher.storage:
class: Flasher\Symfony\Storage\Storage
@@ -55,6 +56,15 @@ services:
tags:
- { name: 'flasher.event_subscriber' }
+ flasher.event_listener.template_listener:
+ class: Flasher\Prime\EventDispatcher\EventListener\TemplateListener
+ public: false
+ arguments:
+ - '@flasher.config'
+ - '@flasher.template_engine'
+ tags:
+ - { name: 'flasher.event_subscriber' }
+
flasher.twig.extension:
class: Flasher\Symfony\Twig\FlasherTwigExtension
arguments:
@@ -78,6 +88,11 @@ services:
tags:
- { name: 'kernel.event_subscriber' }
+ flasher.template_engine:
+ class: Flasher\Symfony\Template\TwigEngine
+ arguments:
+ - '@twig'
+
Flasher\Prime\Config\Config: '@flasher.config'
Flasher\Prime\Flasher: '@flasher'
Flasher\Prime\Renderer\Renderer: '@flasher.renderer'
@@ -85,6 +100,8 @@ services:
Flasher\Symfony\Storage\Storage: '@flasher.storage'
Flasher\Prime\Storage\StorageManager: '@flasher.storage_manager'
Flasher\Prime\Filter\Filter: '@flasher.filter'
+ Flasher\Prime\Factory\NotificationFactory: '@flasher.notification_factory'
+ Flasher\Symfony\Template\TwigEngine: '@flasher.template_engine'
Flasher\Prime\Config\ConfigInterface: '@flasher.config'
Flasher\Prime\FlasherInterface: '@flasher'
@@ -93,3 +110,5 @@ services:
Flasher\Prime\Filter\FilterInterface: '@flasher.filter'
Flasher\Prime\EventDispatcher\EventDispatcherInterface: '@flasher.event_dispatcher'
Flasher\Prime\Storage\StorageInterface: '@flasher.storage'
+ Flasher\Prime\Factory\NotificationFactoryInterface: '@flasher.notification_factory'
+ Flasher\Prime\Template\EngineInterface: '@flasher.template_engine'
diff --git a/src/Symfony/Resources/public/flasher-template.js b/src/Symfony/Resources/public/flasher-template.js
new file mode 100644
index 00000000..2a85cdd3
--- /dev/null
+++ b/src/Symfony/Resources/public/flasher-template.js
@@ -0,0 +1,137 @@
+PHPFlasher.addFactory('template', (function () {
+ 'use strict';
+
+ var exports = {};
+ var options = {
+ timeout: 5000,
+ fps: 30,
+ position: 'top-right',
+ direction: 'top'
+ };
+
+ exports.render = function (envelope) {
+ var position = options.position;
+
+ if (undefined !== envelope.options && undefined !== envelope.options.position) {
+ position = envelope.options.position;
+ }
+
+ var container = document.getElementById('flasher-container-' + position);
+ if (null === container) {
+ container = document.createElement('div');
+ container.id = "flasher-container-" + options.position;
+ container.style.position = "fixed";
+ container.style.maxWidth = "304px";
+ container.style.width = "100%";
+
+ switch (options.position) {
+ case "top-left":
+ container.style.top = 0;
+ container.style.left = "0.5em";
+ break;
+ case "top-right":
+ container.style.top = 0;
+ container.style.right = "0.5em";
+ break;
+ case "bottom-left":
+ container.style.bottom = 0;
+ container.style.left = "0.5em";
+ break;
+ case "bottom-right":
+ default:
+ container.style.bottom = 0;
+ container.style.right = "0.5em";
+ break;
+ }
+ document.getElementsByTagName('body')[0].appendChild(container);
+ }
+
+ var template = stringToHTML(envelope.template);
+ template.style.transition = '0.8s';
+
+ switch (options.direction) {
+ case "top":
+ container.insertBefore(template, container.firstChild);
+ break;
+ case "bottom":
+ default:
+ container.appendChild(template);
+ break;
+ }
+
+ var progressBar = template.querySelector('.flasher-progress');
+
+ var width = 0;
+ var lapse = 1000 / options.fps;
+
+ var showProgress = function () {
+ width++;
+ var percent = (1 - lapse * width / options.timeout) * 100;
+ progressBar.style.width = percent + '%';
+
+ if (percent <= 0) {
+ template.style.opacity = 0;
+ clearInterval(progress);
+
+ setTimeout(function () {
+ template.remove();
+ }, 900);
+ }
+ }
+
+ var progress = setInterval(showProgress, lapse);
+
+ template.addEventListener('mouseover', function () {
+ clearInterval(progress);
+ });
+
+ template.addEventListener("mouseout", function () {
+ progress = setInterval(showProgress, lapse);
+ });
+ };
+
+ exports.renderOptions = function (_setting) {
+ options = extend({}, options, _setting);
+ };
+
+ var stringToHTML = function (str) {
+ var support = (function () {
+ if (!window.DOMParser) return false;
+ var parser = new DOMParser();
+ try {
+ parser.parseFromString('x', 'text/html');
+ } catch (err) {
+ return false;
+ }
+ return true;
+ })();
+
+ if (support) {
+ var parser = new DOMParser();
+ var doc = parser.parseFromString(str, 'text/html');
+ return doc.body.firstChild;
+ }
+
+ var dom = document.createElement('div');
+ dom.innerHTML = str;
+ return dom.firstElementChild;
+ };
+
+ var extend = function (out) {
+ out = out || {};
+
+ for (var i = 1; i < arguments.length; i++) {
+ if (!arguments[i])
+ continue;
+
+ for (var key in arguments[i]) {
+ if (arguments[i].hasOwnProperty(key))
+ out[key] = arguments[i][key];
+ }
+ }
+
+ return out;
+ };
+
+ return exports;
+})());
diff --git a/src/Symfony/Resources/public/flasher.js b/src/Symfony/Resources/public/flasher.js
index 4581795c..259c9661 100644
--- a/src/Symfony/Resources/public/flasher.js
+++ b/src/Symfony/Resources/public/flasher.js
@@ -8,7 +8,7 @@ var PHPFlasher = (function () {
exports.addStyles(_options.styles, function () {
exports.addScripts(_options.scripts, function () {
exports.renderOptions(_options.options);
- exports.renderNotifications(_options.notifications);
+ exports.renderEnvelopes(_options.envelopes);
});
});
};
@@ -76,9 +76,9 @@ var PHPFlasher = (function () {
});
};
- exports.renderNotifications = function (notifications) {
- notifications.forEach(function (flash) {
- factories[flash.handler].render(flash.notification);
+ exports.renderEnvelopes = function (envelopes) {
+ envelopes.forEach(function (envelope) {
+ factories[envelope.handler].render(envelope);
})
};
diff --git a/src/Symfony/Resources/views/tailwindcss.html.twig b/src/Symfony/Resources/views/tailwindcss.html.twig
new file mode 100644
index 00000000..2c9ce051
--- /dev/null
+++ b/src/Symfony/Resources/views/tailwindcss.html.twig
@@ -0,0 +1,44 @@
+{% if 'success' == envelope.type %}
+ {% set text_color = 'text-green-600' %}
+ {% set background_color = 'bg-green-600' %}
+ {% set progress_background_color = 'bg-green-100' %}
+ {% set border_color = 'border-green-600' %}
+ {% set icon = '' %}
+{% elseif 'error' == envelope.type %}
+ {% set text_color = 'text-red-600' %}
+ {% set background_color = 'bg-red-600' %}
+ {% set progress_background_color = 'bg-red-100' %}
+ {% set border_color = 'border-red-600' %}
+ {% set icon = '' %}
+{% elseif 'warning' == envelope.type %}
+ {% set text_color = 'text-yellow-600' %}
+ {% set background_color = 'bg-yellow-600' %}
+ {% set progress_background_color = 'bg-yellow-100' %}
+ {% set border_color = 'border-yellow-600' %}
+ {% set icon = '' %}
+{% else %}
+ {% set text_color = 'text-blue-600' %}
+ {% set background_color = 'bg-blue-600' %}
+ {% set progress_background_color = 'bg-blue-100' %}
+ {% set border_color = 'border-blue-600' %}
+ {% set icon = '' %}
+{% endif %}
+
+
+
+
+ {{ icon | raw }}
+
+
+
+ {{ envelope.type }}
+
+
+ {{ envelope.message }}
+
+
+
+
+
+
+
diff --git a/src/Symfony/Template/TwigEngine.php b/src/Symfony/Template/TwigEngine.php
new file mode 100644
index 00000000..d20786f7
--- /dev/null
+++ b/src/Symfony/Template/TwigEngine.php
@@ -0,0 +1,30 @@
+engine = $engine;
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function render($name, array $context = array())
+ {
+ return $this->engine->render($name, $context);
+ }
+}
diff --git a/src/Symfony/composer.json b/src/Symfony/composer.json
index 08dc28e5..caed0bfe 100644
--- a/src/Symfony/composer.json
+++ b/src/Symfony/composer.json
@@ -39,9 +39,6 @@
"require-dev": {
"phpunit/phpunit": "^4.8|^5.0|^6.0|^7.0|^8.0|^9.0"
},
- "suggest": {
- "twig/twig": "Twig support for Htmlpresenter"
- },
"autoload": {
"psr-4": {
"Flasher\\Symfony\\": ""
diff --git a/src/Toastr/Laravel/Resources/public/flasher-toastr.js b/src/Toastr/Laravel/Resources/public/flasher-toastr.js
index 5f3d8f48..6d3fd4e2 100644
--- a/src/Toastr/Laravel/Resources/public/flasher-toastr.js
+++ b/src/Toastr/Laravel/Resources/public/flasher-toastr.js
@@ -4,7 +4,8 @@ PHPFlasher.addFactory('toastr', (function () {
var exports = {};
exports.render = function (data) {
- toastr[data.type](data.message, data.title, data.options);
+ var notification = data.notification;
+ toastr[notification.type](notification.message, notification.title, notification.options);
};
exports.renderOptions = function (options) {
diff --git a/src/Toastr/Prime/ToastrFactory.php b/src/Toastr/Prime/ToastrFactory.php
index 9cdbb93f..0a2d8788 100644
--- a/src/Toastr/Prime/ToastrFactory.php
+++ b/src/Toastr/Prime/ToastrFactory.php
@@ -2,12 +2,12 @@
namespace Flasher\Toastr\Prime;
-use Flasher\Prime\Factory\AbstractFactory;
+use Flasher\Prime\Factory\NotificationFactory;
/**
* @mixin ToastrBuilder
*/
-final class ToastrFactory extends AbstractFactory
+final class ToastrFactory extends NotificationFactory
{
/**
* {@inheritdoc}
diff --git a/src/Toastr/Symfony/Resources/config/config.yaml b/src/Toastr/Symfony/Resources/config/config.yaml
index 7f18015c..619a168d 100644
--- a/src/Toastr/Symfony/Resources/config/config.yaml
+++ b/src/Toastr/Symfony/Resources/config/config.yaml
@@ -1,6 +1,6 @@
services:
flasher.toastr:
- parent: 'flasher.abstract_factory'
+ parent: 'flasher.notification_factory'
class: Flasher\Toastr\Prime\ToastrFactory
tags:
- { name: 'flasher.factory', alias: 'toastr' }
diff --git a/src/Toastr/Symfony/Resources/public/flasher-toastr.js b/src/Toastr/Symfony/Resources/public/flasher-toastr.js
index 5f3d8f48..6d3fd4e2 100644
--- a/src/Toastr/Symfony/Resources/public/flasher-toastr.js
+++ b/src/Toastr/Symfony/Resources/public/flasher-toastr.js
@@ -4,7 +4,8 @@ PHPFlasher.addFactory('toastr', (function () {
var exports = {};
exports.render = function (data) {
- toastr[data.type](data.message, data.title, data.options);
+ var notification = data.notification;
+ toastr[notification.type](notification.message, notification.title, notification.options);
};
exports.renderOptions = function (options) {