commit 03895823a5fc9b4aaac76d596f424ed41358e2eb Author: KHOUBZA Younes Date: Wed Dec 2 00:54:31 2020 +0100 add php-notify classes and rename namespaces diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..3383d44b --- /dev/null +++ b/.gitattributes @@ -0,0 +1,13 @@ + +# Path-based git attributes +# https://www.kernel.org/pub/software/scm/git/docs/gitattributes.html + +# Ignore all test and documentation with "export-ignore". +/.gitattributes export-ignore +/.gitignore export-ignore +/.travis.yml export-ignore +/phpunit.xml.dist export-ignore +/.scrutinizer.yml export-ignore +/.styleci.yml export-ignore +/tests export-ignore +/.editorconfig export-ignore diff --git a/.github/workflows/tests.yaml b/.github/workflows/tests.yaml new file mode 100644 index 00000000..c09f0dbc --- /dev/null +++ b/.github/workflows/tests.yaml @@ -0,0 +1,48 @@ +name: Running tests + +on: + push: + pull_request: + schedule: + - cron: '0 * * * *' + +jobs: + test: + runs-on: ubuntu-latest + strategy: + fail-fast: true + matrix: + php: [ 8.0, 7.4, 7.3, 7.2, 7.1, 7.0, 5.6, 5.5, 5.4 ] + dependency-version: [ prefer-lowest, prefer-stable ] + + name: php ${{ matrix.php }} - ${{ matrix.dependency-version }} + + steps: + - name: Checkout code + uses: actions/checkout@v1 + + - name: Cache dependencies + uses: actions/cache@v1 + with: + path: ~/.composer/cache/files + key: php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} + + - name: Setup PHP + uses: shivammathur/setup-php@v2 + with: + php-version: ${{ matrix.php }} + coverage: none + + - name: Require phpunit 6 for php >= 7.0 + if: matrix.php >= 7.0 + run: COMPOSER_MEMORY_LIMIT=-1 composer require "phpunit/phpunit:6.*" --no-interaction --no-update + + - name: Require phpunit 9 for php >= 7.3 + if: matrix.php >= 7.3 + run: COMPOSER_MEMORY_LIMIT=-1 composer require "phpunit/phpunit:9.*" --no-interaction --no-update + + - name: Install dependencies + run: COMPOSER_MEMORY_LIMIT=-1 composer update --${{ matrix.dependency-version }} --prefer-dist --no-interaction --no-suggest + + - name: Execute tests + run: vendor/bin/phpunit diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..409f0e32 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.idea/ +vendor/ +composer.lock +.phpunit.result.cache +.phpcs-cache diff --git a/.phpcs.xml.dist b/.phpcs.xml.dist new file mode 100644 index 00000000..93d245bc --- /dev/null +++ b/.phpcs.xml.dist @@ -0,0 +1,625 @@ + + + + + + + + + + + + + src + tests + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + error + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Variable "%s" not allowed in double quoted string; use sprintf() or concatenation instead + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.phpstorm.meta.php b/.phpstorm.meta.php new file mode 100644 index 00000000..aa712a5c --- /dev/null +++ b/.phpstorm.meta.php @@ -0,0 +1,14 @@ + '@'])); +override(RendererManager::make(''), map(['' => '@'])); +override(PresenterManager::make(''), map(['' => '@'])); diff --git a/AbstractFlasher.php b/AbstractFlasher.php new file mode 100644 index 00000000..74fbde88 --- /dev/null +++ b/AbstractFlasher.php @@ -0,0 +1,60 @@ +createNotification()); + } + + /** + * {@inheritdoc} + */ + public function createNotification() + { + return new Notification(); + } + + /** + * @inheritDoc + */ + public function supports($name = null, array $context = array()) + { + return get_class($this) === $name; + } + + /** + * 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); + } +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 00000000..e69de29b diff --git a/Config/Config.php b/Config/Config.php new file mode 100644 index 00000000..9a5f8b19 --- /dev/null +++ b/Config/Config.php @@ -0,0 +1,34 @@ + + */ + private $config; + + public function __construct(array $config) + { + $this->config = $config; + } + + /** + * @inheritDoc + */ + public function get($key, $default = null) + { + $data = $this->config; + + foreach (explode('.', $key) as $segment) { + if (!isset($data[$segment])) { + return $default; + } + + $data = $data[$segment]; + } + + return $data; + } +} diff --git a/Config/ConfigInterface.php b/Config/ConfigInterface.php new file mode 100644 index 00000000..a43f10f3 --- /dev/null +++ b/Config/ConfigInterface.php @@ -0,0 +1,16 @@ +notification = $notification; + $stamps = is_array($stamps) ? $stamps : array_slice(func_get_args(), 1); + call_user_func_array(array($this, 'with'), $stamps); + } + + /** + * Makes sure the notification is in an Envelope and adds the given stamps. + * + * @param NotificationInterface|Envelope $notification + * @param StampInterface[] $stamps + * + * @return Envelope + */ + public static function wrap($notification, array $stamps = array()) + { + $envelope = $notification instanceof self ? $notification : new self($notification); + + return call_user_func_array(array($envelope, 'with'), $stamps); + } + + /** + * @param array|StampInterface $stamps + * + * @return Envelope a new Envelope instance with additional stamp + */ + public function with($stamps = array()) + { + $stamps = is_array($stamps) ? $stamps : func_get_args(); + + foreach ($stamps as $stamp) { + $this->withStamp($stamp); + } + + return $this; + } + + /** + * @param StampInterface $stamp + * + * @return $this + */ + public function withStamp(StampInterface $stamp) + { + $this->stamps[get_class($stamp)] = $stamp; + + return $this; + } + + /** + * @param string $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 StampInterface[] + */ + public function all() + { + return $this->stamps; + } + + /** + * The original notification contained in the envelope + * + * @return NotificationInterface + */ + public function getNotification() + { + return $this->notification; + } +} diff --git a/Filter/CriteriaBuilder.php b/Filter/CriteriaBuilder.php new file mode 100644 index 00000000..8c131f2d --- /dev/null +++ b/Filter/CriteriaBuilder.php @@ -0,0 +1,95 @@ +filterBuilder = $filterBuilder; + $this->criteria = $criteria; + } + + public function build() + { + $this->buildPriority(); + $this->buildLife(); + $this->buildLimit(); + $this->buildOrder(); + + return $this->filterBuilder; + } + + public function buildPriority() + { + if (!isset($this->criteria['priority'])) { + return; + } + + $priority = $this->criteria['priority']; + + if (!is_array($priority)) { + $priority = array('min' => $priority); + } + + $min = isset($priority['min']) ? $priority['min'] : null; + $max = isset($priority['max']) ? $priority['max'] : null; + + $this->filterBuilder->andWhere(new PrioritySpecification($min, $max)); + } + + public function buildLife() + { + if (!isset($this->criteria['life'])) { + return; + } + + $life = $this->criteria['life']; + + if (!is_array($life)) { + $life = array('min' => $life); + } + + $min = isset($life['min']) ? $life['min'] : null; + $max = isset($life['max']) ? $life['max'] : null; + + $this->filterBuilder->andWhere(new LifeSpecification($min, $max)); + } + + public function buildLimit() + { + if (!isset($this->criteria['limit'])) { + return; + } + + $this->filterBuilder->setMaxResults($this->criteria['limit']); + } + + public function buildOrder() + { + if (!isset($this->criteria['order_by'])) { + return; + } + + $orderings = $this->criteria['order_by']; + + if (!is_array($orderings)) { + $orderings = array($orderings => FilterBuilder::ASC); + } + + $this->filterBuilder->orderBy($orderings); + } +} diff --git a/Filter/DefaultFilter.php b/Filter/DefaultFilter.php new file mode 100644 index 00000000..b72d3416 --- /dev/null +++ b/Filter/DefaultFilter.php @@ -0,0 +1,18 @@ +filterBuilder = $filterBuilder; + } + + public function filter($envelopes, $criteria = array()) + { + return $this->filterBuilder->withCriteria($criteria)->filter($envelopes); + } +} diff --git a/Filter/FilterBuilder.php b/Filter/FilterBuilder.php new file mode 100644 index 00000000..a26ddc30 --- /dev/null +++ b/Filter/FilterBuilder.php @@ -0,0 +1,176 @@ + + */ + private $orderings = array(); + + /** + * @var int|null + */ + private $maxResults; + + public function orderBy(array $orderings) + { + $this->orderings = array_map( + static function ($ordering) { + return strtoupper($ordering) === FilterBuilder::ASC ? FilterBuilder::ASC : FilterBuilder::DESC; + }, + $orderings + ); + + return $this; + } + + /** + * @return array + */ + public function getOrderings() + { + return $this->orderings; + } + + public function withCriteria($criteria) + { + $criteriaBuilder = new CriteriaBuilder($this, $criteria); + $criteriaBuilder->build(); + + return $this; + } + + public function filter(array $envelopes) + { + $specification = $this->getSpecification(); + + if (null !== $specification) { + $envelopes = array_filter( + $envelopes, + static function (Envelope $envelope) use ($specification) { + return $specification->isSatisfiedBy($envelope); + } + ); + } + + $orderings = $this->getOrderings(); + + if (null !== $orderings) { + foreach ($orderings as $field => $ordering) { + usort( + $envelopes, + static function (Envelope $a, Envelope $b) use ($field, $ordering) { + if (FilterBuilder::ASC === $ordering) { + list($a, $b) = array($b, $a); + } + + $stampA = $a->get($field); + $stampB = $b->get($field); + + if (!$stampA instanceof OrderableStampInterface) { + return 0; + } + + return $stampA->compare($stampB); + } + ); + } + } + + $length = $this->getMaxResults(); + + if (null !== $length) { + $envelopes = array_slice($envelopes, 0, $length, true); + } + + return $envelopes; + } + + /** + * @return \Flasher\Prime\TestsFilter\Specification\SpecificationInterface + */ + public function getSpecification() + { + return $this->specification; + } + + /** + * @return int|null + */ + public function getMaxResults() + { + return $this->maxResults; + } + + /** + * @param int $maxResults + * + * @return $this + */ + public function setMaxResults($maxResults) + { + $this->maxResults = $maxResults; + + return $this; + } + + /** + * @param \Flasher\Prime\TestsFilter\Specification\SpecificationInterface $specification + * + * @return $this + */ + public function andWhere(SpecificationInterface $specification) + { + if ($this->specification === null) { + return $this->where($specification); + } + + $this->specification = new AndSpecification($this->specification, $specification); + + return $this; + } + + /** + * @param \Flasher\Prime\TestsFilter\Specification\SpecificationInterface $specification + * + * @return $this + */ + public function where(SpecificationInterface $specification) + { + $this->specification = $specification; + + return $this; + } + + /** + * @param \Flasher\Prime\TestsFilter\Specification\SpecificationInterface $specification + * + * @return $this + */ + public function orWhere(SpecificationInterface $specification) + { + if ($this->specification === null) { + return $this->where($specification); + } + + $this->specification = new OrSpecification($this->specification, $specification); + + return $this; + } +} diff --git a/Filter/FilterInterface.php b/Filter/FilterInterface.php new file mode 100644 index 00000000..f609de71 --- /dev/null +++ b/Filter/FilterInterface.php @@ -0,0 +1,7 @@ +config->get('default_filter', 'default'); + } +} diff --git a/Filter/Specification/AndSpecification.php b/Filter/Specification/AndSpecification.php new file mode 100644 index 00000000..e592f737 --- /dev/null +++ b/Filter/Specification/AndSpecification.php @@ -0,0 +1,37 @@ +specifications = $specifications; + } + + /** + * @inheritDoc + */ + public function isSatisfiedBy(Envelope $envelope) + { + foreach ($this->specifications as $specification) { + if (!$specification->isSatisfiedBy($envelope)) { + return false; + } + } + + return true; + } +} diff --git a/Filter/Specification/LifeSpecification.php b/Filter/Specification/LifeSpecification.php new file mode 100644 index 00000000..76791f6b --- /dev/null +++ b/Filter/Specification/LifeSpecification.php @@ -0,0 +1,44 @@ +minLife = $minLife; + $this->maxLife = $maxLife; + } + + /** + * @param \Notify\Envelope $envelope + * + * @return bool + */ + public function isSatisfiedBy(Envelope $envelope) + { + $stamp = $envelope->get('Flasher\Prime\TestsStamp\ReplayStamp'); + + if (null === $stamp) { + return false; + } + + if (null !== $this->maxLife && $stamp->getLife() > $this->maxLife) { + return false; + } + + return $stamp->getLife() >= $this->minLife; + } +} diff --git a/Filter/Specification/NotSpecification.php b/Filter/Specification/NotSpecification.php new file mode 100644 index 00000000..f6c62506 --- /dev/null +++ b/Filter/Specification/NotSpecification.php @@ -0,0 +1,26 @@ +specification = $specification; + } + + /** + * @inheritDoc + */ + public function isSatisfiedBy(Envelope $envelope) + { + return !$this->specification->isSatisfiedBy($envelope); + } +} diff --git a/Filter/Specification/OrSpecification.php b/Filter/Specification/OrSpecification.php new file mode 100644 index 00000000..72946578 --- /dev/null +++ b/Filter/Specification/OrSpecification.php @@ -0,0 +1,37 @@ +specifications = $specifications; + } + + /** + * @inheritDoc + */ + public function isSatisfiedBy(Envelope $envelope) + { + foreach ($this->specifications as $specification) { + if ($specification->isSatisfiedBy($envelope)) { + return true; + } + } + + return false; + } +} diff --git a/Filter/Specification/PrioritySpecification.php b/Filter/Specification/PrioritySpecification.php new file mode 100644 index 00000000..892926e0 --- /dev/null +++ b/Filter/Specification/PrioritySpecification.php @@ -0,0 +1,44 @@ +minPriority = $minPriority; + $this->maxPriority = $maxPriority; + } + + /** + * @param \Notify\Envelope $envelope + * + * @return bool + */ + public function isSatisfiedBy(Envelope $envelope) + { + $stamp = $envelope->get('Flasher\Prime\TestsStamp\PriorityStamp'); + + if (null === $stamp) { + return false; + } + + if (null !== $this->maxPriority && $stamp->getPriority() > $this->maxPriority) { + return false; + } + + return $stamp->getPriority() >= $this->minPriority; + } +} diff --git a/Filter/Specification/SpecificationInterface.php b/Filter/Specification/SpecificationInterface.php new file mode 100644 index 00000000..fccee585 --- /dev/null +++ b/Filter/Specification/SpecificationInterface.php @@ -0,0 +1,15 @@ +minTime = $minTime; + $this->maxTime = $maxTime; + } + + /** + * @param \Notify\Envelope $envelope + * + * @return bool + */ + public function isSatisfiedBy(Envelope $envelope) + { + $stamp = $envelope->get('Flasher\Prime\TestsStamp\CreatedAtStamp'); + + if (null === $stamp) { + return false; + } + + if (null !== $this->maxTime && $stamp->getCreatedAt() > $this->maxTime) { + return false; + } + + return $stamp->getCreatedAt() >= $this->minTime; + } +} diff --git a/Flasher.php b/Flasher.php new file mode 100644 index 00000000..e8d5b333 --- /dev/null +++ b/Flasher.php @@ -0,0 +1,27 @@ +config->get('default'); + } +} diff --git a/FlasherInterface.php b/FlasherInterface.php new file mode 100644 index 00000000..6a49f13e --- /dev/null +++ b/FlasherInterface.php @@ -0,0 +1,27 @@ + + */ + protected $drivers = array(); + + /** + * @var ConfigInterface + */ + protected $config; + + /** + * @param ConfigInterface $config + */ + public function __construct(ConfigInterface $config) + { + $this->config = $config; + } + + /** + * Get a driver instance. + * + * @param string|null $name + * @param array $context + * + * @return object + * + * @throws \InvalidArgumentException + */ + public function make($name = null, array $context = array()) + { + $name = $name ?: $this->getDefaultDriver(); + + if (is_array($name)) { + $context = $name; + $name = null; + } + + foreach ($this->drivers as $driver) { + if ($driver->supports($name, $context)) { + return $driver; + } + } + + throw new InvalidArgumentException(sprintf('Driver [%s] not supported.', $name)); + } + + /** + * Register a custom driver creator. + * + * @param \Closure|object $driver + * + * @return $this + */ + public function addDriver($driver) + { + $this->drivers[] = $driver; + + return $this; + } + + /** + * @return ConfigInterface + */ + public function getConfig() + { + return $this->config; + } + + /** + * 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->make(), $method), $parameters); + } + + /** + * @return string|null + */ + protected function getDefaultDriver() + { + return null; + } +} diff --git a/Manager/ManagerInterface.php b/Manager/ManagerInterface.php new file mode 100644 index 00000000..4fdcd898 --- /dev/null +++ b/Manager/ManagerInterface.php @@ -0,0 +1,27 @@ +get('Flasher\Prime\TestsStamp\CreatedAtStamp')) { + $envelope->withStamp(new CreatedAtStamp()); + } + + return $next($envelope); + } +} diff --git a/Middleware/AddPriorityStampMiddleware.php b/Middleware/AddPriorityStampMiddleware.php new file mode 100644 index 00000000..e887dd3e --- /dev/null +++ b/Middleware/AddPriorityStampMiddleware.php @@ -0,0 +1,18 @@ +get('Flasher\Prime\TestsStamp\PriorityStamp')) { + $envelope->withStamp(new PriorityStamp(0)); + } + + return $next($envelope); + } +} diff --git a/Middleware/AddRenderedAtStampMiddleware.php b/Middleware/AddRenderedAtStampMiddleware.php new file mode 100644 index 00000000..f5370673 --- /dev/null +++ b/Middleware/AddRenderedAtStampMiddleware.php @@ -0,0 +1,18 @@ +get('Flasher\Prime\TestsStamp\RenderedAtStamp')) { + $envelope->withStamp(new RenderedAtStamp()); + } + + return $next($envelope); + } +} diff --git a/Middleware/AddReplayStampMiddleware.php b/Middleware/AddReplayStampMiddleware.php new file mode 100644 index 00000000..f7433f18 --- /dev/null +++ b/Middleware/AddReplayStampMiddleware.php @@ -0,0 +1,18 @@ +get('Flasher\Prime\TestsStamp\ReplayStamp')) { + $envelope->withStamp(new ReplayStamp(1)); + } + + return $next($envelope); + } +} diff --git a/Middleware/MiddlewareInterface.php b/Middleware/MiddlewareInterface.php new file mode 100644 index 00000000..40050678 --- /dev/null +++ b/Middleware/MiddlewareInterface.php @@ -0,0 +1,16 @@ +createExecutionChain(); + + $middlewareChain($envelope); + + return $envelope; + } + + /** + * @param \Flasher\Prime\TestsMiddleware\MiddlewareInterface $middleware + * + * @return $this + */ + public function addMiddleware(MiddlewareInterface $middleware) + { + $this->middlewares[] = $middleware; + + return $this; + } + + /** + * @return callable + */ + private function createExecutionChain() + { + $lastCallable = static function () { + // the final callable is a no-op + }; + + $middlewares = $this->middlewares; + + while ($middleware = array_pop($middlewares)) { + $lastCallable = static function ($command) use ($middleware, $lastCallable) { + return $middleware->handle($command, $lastCallable); + }; + } + + return $lastCallable; + } +} diff --git a/Notification/Notification.php b/Notification/Notification.php new file mode 100644 index 00000000..0e8f8271 --- /dev/null +++ b/Notification/Notification.php @@ -0,0 +1,109 @@ + + */ + protected $options = array(); + + /** + * @param string|null $message + * @param string|null $type + * @param array $options + */ + public function __construct($message = null, $type = self::TYPE_SUCCESS, array $options = array()) + { + $this->message = $message; + $this->type = $type; + $this->options = $options; + } + + /** + * @inheritDoc + */ + public function getType() + { + return $this->type; + } + + /** + * @inheritDoc + */ + public function setType($type) + { + $this->type = $type; + } + + /** + * @inheritDoc + */ + public function getMessage() + { + return $this->message; + } + + /** + * @inheritDoc + */ + public function setMessage($message) + { + $this->message = $message; + } + + /** + * @inheritDoc + */ + public function getOptions() + { + return $this->options; + } + + /** + * @inheritDoc + */ + public function setOptions(array $options) + { + $this->options = $options; + } + + /** + * @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; + } + + /** + * @inheritDoc + */ + public function unsetOption($name) + { + unset($this->options[$name]); + } +} diff --git a/Notification/NotificationBuilder.php b/Notification/NotificationBuilder.php new file mode 100644 index 00000000..01f9bca5 --- /dev/null +++ b/Notification/NotificationBuilder.php @@ -0,0 +1,111 @@ +notification = $notification ?: new Notification(); + } + + /** + * @inheritDoc + */ + public function type($type, $message = null, array $options = array()) + { + $this->notification->setType($type); + + if (null !== $message) { + $this->message($message); + } + + if (array() !== $options) { + $this->options($options, false); + } + + return $this; + } + + /** + * @inheritDoc + */ + public function message($message) + { + $this->notification->setMessage($message); + + return $this; + } + + /** + * @inheritDoc + */ + public function options($options, $merge = true) + { + if (true === $merge) { + $options = array_merge($this->notification->getOptions(), $options); + } + + $this->notification->setOptions($options); + + return $this; + } + + /** + * @inheritDoc + */ + public function option($name, $value) + { + $this->notification->setOption($name, $value); + + return $this; + } + + /** + * @inheritDoc + */ + public function getNotification() + { + return $this->notification; + } + + /** + * @inheritDoc + */ + public function success($message = null, array $options = array()) + { + return $this->type(NotificationInterface::TYPE_SUCCESS, $message, $options); + } + + /** + * @inheritDoc + */ + public function error($message = null, array $options = array()) + { + return $this->type(NotificationInterface::TYPE_ERROR, $message, $options); + } + + /** + * @inheritDoc + */ + public function info($message = null, array $options = array()) + { + return $this->type(NotificationInterface::TYPE_INFO, $message, $options); + } + + /** + * @inheritDoc + */ + public function warning($message = null, array $options = array()) + { + return $this->type(NotificationInterface::TYPE_WARNING, $message, $options); + } +} diff --git a/Notification/NotificationBuilderInterface.php b/Notification/NotificationBuilderInterface.php new file mode 100644 index 00000000..95e9a993 --- /dev/null +++ b/Notification/NotificationBuilderInterface.php @@ -0,0 +1,76 @@ + $options + * @param bool $merge + * + * @return \Flasher\Prime\TestsNotification\NotificationBuilder + */ + public function options($options, $merge = true); + + /** + * @param string $name + * @param mixed $value + * + * @return \Flasher\Prime\TestsNotification\NotificationBuilder + */ + public function option($name, $value); + + /** + * @return \Flasher\Prime\TestsNotification\NotificationInterface + */ + public function getNotification(); + + /** + * @param string|null $message + * @param array $options + * + * @return self + */ + public function success($message = null, array $options = array()); + + /** + * @param string|null $message + * @param array $options + * + * @return self + */ + public function error($message = null, array $options = array()); + + + /** + * @param string|null $message + * @param array $options + * + * @return self + */ + public function info($message = null, array $options = array()); + + /** + * @param string|null $message + * @param array $options + * + * @return self + */ + public function warning($message = null, array $options = array()); +} diff --git a/Notification/NotificationInterface.php b/Notification/NotificationInterface.php new file mode 100644 index 00000000..4ffbbe8e --- /dev/null +++ b/Notification/NotificationInterface.php @@ -0,0 +1,62 @@ + + */ + public function getOptions(); + + /** + * @param array $options + */ + 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 mixed + */ + public function setOption($name, $value); + + /** + * @param string $name + */ + public function unsetOption($name); +} diff --git a/Presenter/AbstractPresenter.php b/Presenter/AbstractPresenter.php new file mode 100644 index 00000000..96b708e3 --- /dev/null +++ b/Presenter/AbstractPresenter.php @@ -0,0 +1,162 @@ +config = $config; + $this->storage = $storage; + $this->filterManager = $filterManager; + $this->rendererManager = $rendererManager; + } + + /** + * @inheritDoc + */ + public function supports($name = null, array $context = array()) + { + return get_class($this) === $name; + } + + protected function getEnvelopes($filterName, $criteria = array()) + { + $filter = $this->filterManager->make($filterName); + $envelopes = $filter->filter($this->storage->get(), $criteria); + + return array_filter( + $envelopes, + static function (Envelope $envelope) { + $lifeStamp = $envelope->get('Flasher\Prime\TestsStamp\ReplayStamp'); + + return $lifeStamp->getLife() > 0; + } + ); + } + + /** + * @param Envelope[] $envelopes + * + * @return string[] + */ + protected function getStyles($envelopes) + { + $files = $this->config->get('styles', array()); + $renderers = array(); + + foreach ($envelopes as $envelope) { + $rendererStamp = $envelope->get('Flasher\Prime\TestsStamp\HandlerStamp'); + if (in_array($rendererStamp->getHandler(), $renderers)) { + continue; + } + + $renderer = $this->rendererManager->make($rendererStamp->getHandler()); + if (!$renderer instanceof HasStylesInterface) { + continue; + } + + $files = array_merge($files, $renderer->getStyles()); + $renderers[] = $rendererStamp->getHandler(); + } + + return array_values(array_filter(array_unique($files))); + } + + /** + * @param Envelope[] $envelopes + * + * @return string[] + */ + protected function getScripts($envelopes) + { + $files = $this->config->get('scripts', array()); + $renderers = array(); + + foreach ($envelopes as $envelope) { + $rendererStamp = $envelope->get('Flasher\Prime\TestsStamp\HandlerStamp'); + if (in_array($rendererStamp->getHandler(), $renderers)) { + continue; + } + + $renderer = $this->rendererManager->make($rendererStamp->getHandler()); + if (!$renderer instanceof HasScriptsInterface) { + continue; + } + + $files = array_merge($files, $renderer->getScripts()); + $renderers[] = $rendererStamp->getHandler(); + } + + return array_values(array_filter(array_unique($files))); + } + + /** + * @param Envelope[] $envelopes + * + * @return string[] + */ + protected function getOptions($envelopes) + { + $options = array(); + $renderers = array(); + + foreach ($envelopes as $envelope) { + $rendererStamp = $envelope->get('Flasher\Prime\TestsStamp\HandlerStamp'); + if (in_array($rendererStamp->getHandler(), $renderers)) { + continue; + } + + $renderer = $this->rendererManager->make($rendererStamp->getHandler()); + if (!$renderer instanceof HasOptionsInterface) { + continue; + } + + $options[] = $renderer->renderOptions(); + $renderers[] = $rendererStamp->getHandler(); + } + + return array_values(array_filter(array_unique($options))); + } +} diff --git a/Presenter/Adapter/HtmlPresenter.php b/Presenter/Adapter/HtmlPresenter.php new file mode 100644 index 00000000..45245f61 --- /dev/null +++ b/Presenter/Adapter/HtmlPresenter.php @@ -0,0 +1,105 @@ +getEnvelopes($filterName, $criteria); + + if (empty($envelopes)) { + return ''; + } + + $scripts = $this->renderScripts($envelopes); + $styles = json_encode($this->getStyles($envelopes)); + $options = $this->renderOptions($envelopes); + $notifications = $this->renderEnvelopes($envelopes); + + $html = << +var renderPHPNotifyNotifications = function () { + {$options} + {$notifications} +} + +if ("undefined" !== typeof PHPNotify) { + PHPNotify.addStyles({$styles}, renderPHPNotifyNotifications); +} else { + renderPHPNotifyNotifications(); +} + +HTML; + + $this->storage->flush($envelopes); + + return $html; + } + + /** + * @param \Notify\Envelope[] $envelopes + * + * @return string + */ + public function renderEnvelopes($envelopes) + { + $html = ''; + + foreach ($envelopes as $envelope) { + $rendererStamp = $envelope->get('Flasher\Prime\TestsStamp\HandlerStamp'); + $renderer = $this->rendererManager->make($rendererStamp->getHandler()); + + $html .= $renderer->render($envelope).PHP_EOL; + } + + return $html; + } + + /** + * @param \Notify\Envelope[] $envelopes + * + * @return string + */ + public function renderOptions($envelopes) + { + $html = ''; + + foreach ($this->getOptions($envelopes) as $option) { + $html .= $option.PHP_EOL; + } + + return $html; + } + + /** + * @param \Notify\Envelope[] $envelopes + * + * @return string + */ + public function renderScripts($envelopes) + { + $html = ''; + + foreach ($this->getScripts($envelopes) as $file) { + $html .= sprintf('', $file).PHP_EOL; + } + + return $html; + } +} diff --git a/Presenter/Adapter/JsonPresenter.php b/Presenter/Adapter/JsonPresenter.php new file mode 100644 index 00000000..bdb77d42 --- /dev/null +++ b/Presenter/Adapter/JsonPresenter.php @@ -0,0 +1,62 @@ +getEnvelopes($filterName, $criteria); + + if (empty($envelopes)) { + return array(); + } + + $response = array( + 'scripts' => $this->getScripts($envelopes), + 'styles' => $this->getStyles($envelopes), + 'options' => $this->getOptions($envelopes), + 'notifications' => $this->renderEnvelopes($envelopes), + ); + + $this->storage->flush($envelopes); + + return $response; + } + + /** + * @param \Notify\Envelope[] $envelopes + * + * @return array + */ + private function renderEnvelopes($envelopes) + { + $notifications = array(); + + foreach ($envelopes as $envelope) { + $rendererStamp = $envelope->get('Flasher\Prime\TestsStamp\HandlerStamp'); + $renderer = $this->rendererManager->make($rendererStamp->getHandler()); + + $notifications[] = array( + 'code' => $renderer->render($envelope), + 'adapter' => $rendererStamp->getHandler() + ); + } + + return $notifications; + } +} diff --git a/Presenter/PresenterInterface.php b/Presenter/PresenterInterface.php new file mode 100644 index 00000000..43c69c2c --- /dev/null +++ b/Presenter/PresenterInterface.php @@ -0,0 +1,21 @@ +flasher

+ +

Easy flash notifications for PHP, Laravel, Symfony, Lumen

+ +

:eyes: PHP Flasher library helps you to add flash notifications to your projects. This library was developed with the idea that you should be able to add flash notification to your application with ease and with few lines of code. No application-wide rewrites and no big investments upfront.

+ +

+ + + + + + + + + + + + + + + +

+ +## Introduction + +PHP Flasher library helps you to add flash notifications to your projects. This library was developed with the idea that you should be able to add flash notification to your application with ease and with few lines of code. No application-wide rewrites and no big investments upfront. + +# Why use PHP Flasher ? + +The PHP Flasher project supports a variety of notification libraries : __toastr.js__, __sweet alert 2__, __pflasher__ and __notyf__ +and its highly extendable so you can add custom adapters. + +This library is designed, so you can take full control when creating you notifications : + +> * Display multiple notifications +> * Sort and filter notifications +> * Render notification from JSON response with Ajax or Websockets +> * Limit the number of displayed notifications +> * Show notifications from different adapters at the same time +> * implementations for popular frameworks : Symfony and Laravel +> * ...and more + + +## Official Documentation + +Documentation for Valet can be found on the [PHP Flasher website](https://php-flasher.github.io/). + +## License + +PHP Flasher is open-sourced software licensed under the [MIT license](https://opensource.org/licenses/MIT). diff --git a/Renderer/HasOptionsInterface.php b/Renderer/HasOptionsInterface.php new file mode 100644 index 00000000..f6d6ffcf --- /dev/null +++ b/Renderer/HasOptionsInterface.php @@ -0,0 +1,11 @@ +createdAt = $createdAt ?: new \DateTime('now', new \DateTimeZone('Africa/Casablanca')); + } + + /** + * @return \DateTime + */ + public function getCreatedAt() + { + return $this->createdAt; + } + + /** + * @param \Flasher\Prime\TestsStamp\OrderableStampInterface $orderable + * + * @return int + */ + public function compare($orderable) + { + if (!$orderable instanceof CreatedAtStamp) { + return 0; + } + + return $this->createdAt > $orderable->createdAt; + } +} diff --git a/Stamp/HandlerStamp.php b/Stamp/HandlerStamp.php new file mode 100644 index 00000000..7e2252bd --- /dev/null +++ b/Stamp/HandlerStamp.php @@ -0,0 +1,27 @@ +handler = $handler; + } + + /** + * @return string + */ + public function getHandler() + { + return $this->handler; + } +} diff --git a/Stamp/OrderableStampInterface.php b/Stamp/OrderableStampInterface.php new file mode 100644 index 00000000..ccbfa670 --- /dev/null +++ b/Stamp/OrderableStampInterface.php @@ -0,0 +1,13 @@ +priority = $priority; + } + + /** + * @return int + */ + public function getPriority() + { + return $this->priority; + } + + /** + * @param \Flasher\Prime\TestsStamp\OrderableStampInterface $orderable + * + * @return int + */ + public function compare($orderable) + { + if (!$orderable instanceof PriorityStamp) { + return 0; + } + + return $this->priority > $orderable->priority; + } +} diff --git a/Stamp/RenderedAtStamp.php b/Stamp/RenderedAtStamp.php new file mode 100644 index 00000000..049f090e --- /dev/null +++ b/Stamp/RenderedAtStamp.php @@ -0,0 +1,29 @@ +renderedAt = $renderedAt ?: new \DateTime('now', new \DateTimeZone('Africa/Casablanca')); + } + + /** + * @return \DateTime + */ + public function getRenderedAt() + { + return $this->renderedAt; + } +} diff --git a/Stamp/ReplayStamp.php b/Stamp/ReplayStamp.php new file mode 100644 index 00000000..41848252 --- /dev/null +++ b/Stamp/ReplayStamp.php @@ -0,0 +1,27 @@ +count = $count; + } + + /** + * @return int + */ + public function getCount() + { + return $this->count; + } +} diff --git a/Stamp/StampInterface.php b/Stamp/StampInterface.php new file mode 100644 index 00000000..e87df488 --- /dev/null +++ b/Stamp/StampInterface.php @@ -0,0 +1,7 @@ +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 \Notify\Envelope|\Notify\Envelope[] $envelopes + * + * @return array + */ + public static function indexWithUuid($envelopes) + { + $envelopes = is_array($envelopes) ? $envelopes : func_get_args(); + + $map = array(); + + foreach ($envelopes as $envelope) { + $uuid = $envelope->get('Flasher\Prime\TestsStamp\UuidStamp')->getUuid(); + + $map[$uuid] = $envelope; + } + + return $map; + } + + /** + * @return string + */ + public function getUuid() + { + return $this->uuid; + } +} diff --git a/Storage/ArrayStorage.php b/Storage/ArrayStorage.php new file mode 100644 index 00000000..8c51fde3 --- /dev/null +++ b/Storage/ArrayStorage.php @@ -0,0 +1,65 @@ +envelopes; + } + + /** + * @inheritDoc + */ + public function add($envelopes) + { + $envelopes = is_array($envelopes) ? $envelopes : func_get_args(); + + foreach ($envelopes as $envelope) { + if (null === $envelope->get('Flasher\Prime\TestsStamp\UuidStamp')) { + $envelope->withStamp(new UuidStamp()); + } + + $this->envelopes[] = $envelope; + } + } + + /** + * @param \Notify\Envelope[] $envelopes + */ + public function remove($envelopes) + { + $envelopes = is_array($envelopes) ? $envelopes : func_get_args(); + + $map = UuidStamp::indexWithUuid($envelopes); + + $this->envelopes = array_filter( + $this->envelopes, + function (Envelope $envelope) use ($map) { + $uuid = $envelope->get('Flasher\Prime\TestsStamp\UuidStamp')->getUuid(); + + return !isset($map[$uuid]); + } + ); + } + + /** + * @inheritDoc + */ + public function clear() + { + $this->envelopes = array(); + } +} diff --git a/Storage/StorageInterface.php b/Storage/StorageInterface.php new file mode 100644 index 00000000..349f6b68 --- /dev/null +++ b/Storage/StorageInterface.php @@ -0,0 +1,26 @@ +storage = $storage; + } + + /** + * @inheritDoc + */ + public function flush($envelopes) + { + $envelopes = is_array($envelopes) ? $envelopes : func_get_args(); + + $this->storage->remove($envelopes); + + foreach ($envelopes as $envelope) { + $replayStamp = $envelope->get('Flasher\Prime\TestsStamp\ReplayStamp'); + $replayCount = null === $replayStamp ? 0 : $replayStamp->getCount() - 1; + + if (1 > $replayCount) { + continue; + } + + $envelope->with(new ReplayStamp($replayCount)); + $this->storage->add($envelope); + } + } + + /** + * @inheritDoc + */ + public function all() + { + return $this->storage->all(); + } + + /** + * @inheritDoc + */ + public function add(Envelope $envelope) + { + $this->storage->add($envelope); + } + + /** + * @inheritDoc + */ + public function remove($envelopes) + { + $this->storage->remove($envelopes); + } + + /** + * @inheritDoc + */ + public function clear() + { + $this->storage->clear(); + } +} diff --git a/Storage/StorageManagerInterface.php b/Storage/StorageManagerInterface.php new file mode 100644 index 00000000..62acb8cd --- /dev/null +++ b/Storage/StorageManagerInterface.php @@ -0,0 +1,33 @@ + 'notify', + 'drivers' => array( + 'notify' => array( + 'scripts' => array('script.js'), + 'styles' => array('styles.css'), + 'options' => array() + ) + ), + ) + ); + + $this->assertEquals('notify', $config->get('default')); + $this->assertEquals( + array( + 'scripts' => array('script.js'), + 'styles' => array('styles.css'), + 'options' => array() + ), + $config->get('drivers.notify') + ); + $this->assertEquals(array('styles.css'), $config->get('drivers.notify.styles')); + $this->assertEquals(array(), $config->get('drivers.notify.options')); + $this->assertEquals(null, $config->get('drivers.not_exists.options')); + $this->assertEquals('now_it_exists', $config->get('drivers.not_exists.options', 'now_it_exists')); + } +} diff --git a/Tests/Envelope/EnvelopeTest.php b/Tests/Envelope/EnvelopeTest.php new file mode 100644 index 00000000..a51a17db --- /dev/null +++ b/Tests/Envelope/EnvelopeTest.php @@ -0,0 +1,81 @@ +getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(); + $stamp = $this->getMockBuilder('Flasher\Prime\TestsStamp\StampInterface')->getMock(); + + $envelope = new Envelope($notification, array($stamp)); + + $this->assertSame($notification, $envelope->getNotification()); + $this->assertSame(array(get_class($stamp) => $stamp), $envelope->all()); + } + + public function testWith() + { + $notification = $this->getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(); + $stamp1 = $this->getMockBuilder('Flasher\Prime\TestsStamp\StampInterface')->getMock(); + $stamp2 = $this->getMockBuilder('Flasher\Prime\TestsStamp\StampInterface')->getMock(); + + $envelope = new Envelope($notification); + $envelope->with($stamp1, $stamp2); + + $this->assertSame($notification, $envelope->getNotification()); + $this->assertSame(array(get_class($stamp1) => $stamp1, get_class($stamp2) => $stamp2), $envelope->all()); + } + + public function testWrap() + { + $notification = $this->getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(); + $stamp = $this->getMockBuilder('Flasher\Prime\TestsStamp\StampInterface')->getMock(); + + $envelope = Envelope::wrap($notification, array($stamp)); + + $this->assertSame($notification, $envelope->getNotification()); + $this->assertSame(array(get_class($stamp) => $stamp), $envelope->all()); + } + + public function testAll() + { + $notification = $this->getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(); + $stamps = array( + $this->getMockBuilder('Flasher\Prime\TestsStamp\StampInterface')->getMock(), + $this->getMockBuilder('Flasher\Prime\TestsStamp\StampInterface')->getMock(), + $this->getMockBuilder('Flasher\Prime\TestsStamp\StampInterface')->getMock(), + $this->getMockBuilder('Flasher\Prime\TestsStamp\StampInterface')->getMock(), + ); + + $envelope = new Envelope($notification, $stamps); + + $this->assertSame($notification, $envelope->getNotification()); + $this->assertSame(array(get_class($stamps[0]) => $stamps[3]), $envelope->all()); + } + + public function testGet() + { + $notification = $this->getMockBuilder('\Flasher\Prime\TestsNotification\NotificationInterface')->getMock(); + $stamps = array( + $this->getMockBuilder('Flasher\Prime\TestsStamp\StampInterface')->getMock(), + $this->getMockBuilder('Flasher\Prime\TestsStamp\StampInterface')->getMock(), + $this->getMockBuilder('Flasher\Prime\TestsStamp\StampInterface')->getMock(), + ); + + $envelope = new \Notify\Envelope($notification, $stamps); + + $this->assertSame($notification, $envelope->getNotification()); + + $last = $envelope->get(get_class($stamps[0])); + + $this->assertSame($stamps[2], $last); + $this->assertSame($last, $envelope->get(get_class($stamps[0]))); + + $this->assertNull($envelope->get('NotFoundStamp')); + } +} diff --git a/Tests/Envelope/Stamp/CreatedAtStampTest.php b/Tests/Envelope/Stamp/CreatedAtStampTest.php new file mode 100644 index 00000000..e1eb5b92 --- /dev/null +++ b/Tests/Envelope/Stamp/CreatedAtStampTest.php @@ -0,0 +1,31 @@ +getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(); + $stamp = new CreatedAtStamp(); + + $envelop = new Envelope($notification, array($stamp)); + + $this->assertSame($stamp, $envelop->get('Flasher\Prime\TestsStamp\CreatedAtStamp')); + $this->assertInstanceOf('Flasher\Prime\TestsStamp\StampInterface', $stamp); + } + + public function testCompare() + { + $createdAt1 = new \Flasher\Prime\TestsStamp\CreatedAtStamp(new \DateTime('+2 h')); + $createdAt2 = new \Flasher\Prime\TestsStamp\CreatedAtStamp(new \DateTime('+1 h')); + + $this->assertFalse($createdAt1->compare($createdAt2)); + $this->assertSame(0, $createdAt1->compare(new ReplayStamp(1))); + } +} diff --git a/Tests/Envelope/Stamp/LifeStampTest.php b/Tests/Envelope/Stamp/LifeStampTest.php new file mode 100644 index 00000000..13ae149a --- /dev/null +++ b/Tests/Envelope/Stamp/LifeStampTest.php @@ -0,0 +1,21 @@ +getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(); + $stamp = new \Flasher\Prime\TestsStamp\ReplayStamp(5); + + $envelop = new Envelope($notification, array($stamp)); + + $this->assertSame($stamp, $envelop->get('Flasher\Prime\TestsStamp\ReplayStamp')); + $this->assertInstanceOf('Flasher\Prime\TestsStamp\ReplayStamp', $stamp); + $this->assertSame(5, $stamp->getCount()); + } +} diff --git a/Tests/Envelope/Stamp/PriorityStampTest.php b/Tests/Envelope/Stamp/PriorityStampTest.php new file mode 100644 index 00000000..bc73f7e7 --- /dev/null +++ b/Tests/Envelope/Stamp/PriorityStampTest.php @@ -0,0 +1,31 @@ +getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(); + $stamp = new PriorityStamp(5); + + $envelop = new Envelope($notification, array($stamp)); + + $this->assertSame($stamp, $envelop->get('Flasher\Prime\TestsStamp\PriorityStamp')); + $this->assertInstanceOf('Flasher\Prime\TestsStamp\StampInterface', $stamp); + $this->assertSame(5, $stamp->getPriority()); + } + + public function testCompare() + { + $stamp1 = new PriorityStamp(1); + $stamp2 = new \Flasher\Prime\TestsStamp\PriorityStamp(2); + + $this->assertFalse($stamp1->compare($stamp2)); + $this->assertSame(0, $stamp1->compare(new \Flasher\Prime\TestsStamp\ReplayStamp(1))); + } +} diff --git a/Tests/Envelope/Stamp/RendererStampTest.php b/Tests/Envelope/Stamp/RendererStampTest.php new file mode 100644 index 00000000..712d47cc --- /dev/null +++ b/Tests/Envelope/Stamp/RendererStampTest.php @@ -0,0 +1,21 @@ +getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(); + $stamp = new \Flasher\Prime\TestsStamp\HandlerStamp('toastr'); + + $envelop = new Envelope($notification, array($stamp)); + + $this->assertSame($stamp, $envelop->get('Flasher\Prime\TestsStamp\HandlerStamp')); + $this->assertInstanceOf('Flasher\Prime\TestsStamp\HandlerStamp', $stamp); + $this->assertSame('toastr', $stamp->getHandler()); + } +} diff --git a/Tests/Envelope/Stamp/UuidStampTest.php b/Tests/Envelope/Stamp/UuidStampTest.php new file mode 100644 index 00000000..f96cda32 --- /dev/null +++ b/Tests/Envelope/Stamp/UuidStampTest.php @@ -0,0 +1,21 @@ +getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(); + $stamp = new \Flasher\Prime\TestsStamp\UuidStamp(); + + $envelop = new Envelope($notification, array($stamp)); + + $this->assertSame($stamp, $envelop->get('Flasher\Prime\TestsStamp\UuidStamp')); + $this->assertInstanceOf('Flasher\Prime\TestsStamp\UuidStamp', $stamp); + $this->assertNotEmpty($stamp->getUuid()); + } +} diff --git a/Tests/Filter/CriteriaBuilderTest.php b/Tests/Filter/CriteriaBuilderTest.php new file mode 100644 index 00000000..9cc5f07a --- /dev/null +++ b/Tests/Filter/CriteriaBuilderTest.php @@ -0,0 +1,33 @@ + 1, + 'life' => 2, + 'limit' => 2, + 'order_by' => 'Flasher\Prime\TestsStamp\ReplayStamp', + ) + ); + + $this->assertInstanceOf('Flasher\Prime\TestsFilter\FilterBuilder', $criteria->build()); + $this->assertNotEmpty($criteria->build()->getSpecification()); + } + + public function testWithoutPriority() + { + $criteria = new CriteriaBuilder(new FilterBuilder(), array()); + + $this->assertInstanceOf('Flasher\Prime\TestsFilter\FilterBuilder', $criteria->build()); + $this->assertEmpty($criteria->build()->getSpecification()); + } +} diff --git a/Tests/Filter/DefaultFilterTest.php b/Tests/Filter/DefaultFilterTest.php new file mode 100644 index 00000000..f192a292 --- /dev/null +++ b/Tests/Filter/DefaultFilterTest.php @@ -0,0 +1,54 @@ +getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(), + $this->getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(), + $this->getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(), + ); + + $notifications[3] = new Envelope( + $this->getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(), + array(new PriorityStamp(5)) + ); + + $notifications[4] = new Envelope( + $this->getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(), + array(new PriorityStamp(-1)) + ); + + $notifications[5] = new Envelope( + $this->getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(), + array(new PriorityStamp(1)) + ); + + $config = new Config( + array( + 'default' => 'notify', + 'adapters' => array( + 'notify' => array( + 'scripts' => array('script.js'), + 'styles' => array('styles.css'), + 'options' => array() + ) + ), + 'stamps_middlewares' => array( + new AddPriorityStampMiddleware(), + new AddCreatedAtStampMiddleware(), + ) + ) + ); + } +} diff --git a/Tests/Filter/FilterManagerTest.php b/Tests/Filter/FilterManagerTest.php new file mode 100644 index 00000000..6d5004c2 --- /dev/null +++ b/Tests/Filter/FilterManagerTest.php @@ -0,0 +1,105 @@ +getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(), + $this->getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(), + $this->getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(), + ); + + $notifications[3] = new Envelope( + $this->getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(), + array(new PriorityStamp(5)) + ); + + $notifications[4] = new Envelope( + $this->getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(), + array(new PriorityStamp(-1)) + ); + + $notifications[5] = new Envelope( + $this->getMockBuilder('Flasher\Prime\TestsNotification\NotificationInterface')->getMock(), + array(new PriorityStamp(1)) + ); + + $config = new Config( + array( + 'default' => 'notify', + 'adapters' => array( + 'notify' => array( + 'scripts' => array('script.js'), + 'styles' => array('styles.css'), + 'options' => array() + ) + ), + 'stamps_middlewares' => array( + new AddPriorityStampMiddleware(), + new AddCreatedAtStampMiddleware(), + ) + ) + ); + + $middleware = new NotifyBus($config); + + $envelopes = array(); + foreach ($notifications as $notification) { + $envelopes[] = $middleware->dispatch($notification); + } + + $builder = new FilterBuilder(); + + $envelopes = $builder + ->andWhere(new PrioritySpecification(1)) + ->andWhere(new PrioritySpecification(1, 5)) + ->orderBy( + array( + 'Flasher\Prime\TestsStamp\PriorityStamp' => 'ASC' + ) + ) + ->setMaxResults(2) + ->filter($envelopes); + + $this->assertNotEmpty($envelopes); + + $builder = new FilterBuilder(); + + $envelopes = $builder + ->orWhere(new PrioritySpecification(1)) + ->orWhere(new PrioritySpecification(1, 5)) + ->orderBy( + array( + 'Flasher\Prime\TestsStamp\PriorityStamp' => 'ASC', + 'Notify\Envelope\Stamp\NotExists' => 'ASC', + ) + ) + ->setMaxResults(2) + ->filter($envelopes); + + $this->assertNotEmpty($envelopes); + + $builder = new FilterBuilder(); + $builder->withCriteria( + array( + 'priority' => '1' + ) + ); + + $envelopes = $builder->filter($envelopes); + $this->assertNotEmpty($envelopes); + } +} diff --git a/Tests/Manager/ManagerTest.php b/Tests/Manager/ManagerTest.php new file mode 100644 index 00000000..97eafcd1 --- /dev/null +++ b/Tests/Manager/ManagerTest.php @@ -0,0 +1,53 @@ +getMockBuilder('Notify\Config\ConfigInterface')->getMock(); + $config->method('get') + ->with('default') + ->willReturn('default_notifier'); + + $manager = new Notify($config); + $this->assertEquals('default_notifier', $manager->getDefaultDriver()); + } + + public function testMakeDriver() + { + $config = $this->getMockBuilder('Notify\Config\ConfigInterface')->getMock(); + $config->method('get') + ->with('default') + ->willReturn('default_notifier'); + + $manager = new Notify($config); + + $producer = $this->getMockBuilder('Notify\NotifyFactory')->getMock(); + $producer->method('supports')->willReturn(true); + $manager->addDriver($producer); + + $this->assertSame($producer, $manager->make('fake')); + } + + public function testDriverNotSupported() + { + $this->setExpectedException('InvalidArgumentException', 'Driver [test_driver] not supported.'); + + $config = $this->getMockBuilder('Notify\Config\ConfigInterface')->getMock(); + $config->method('get') + ->with('default') + ->willReturn('default_notifier'); + + $manager = new Notify($config); + + $producer = $this->getMockBuilder('Notify\NotifyFactory')->getMock(); + $manager->addDriver($producer); + + $manager->make('test_driver'); + } +} diff --git a/Tests/Middleware/MiddlewareStackTest.php b/Tests/Middleware/MiddlewareStackTest.php new file mode 100644 index 00000000..c7a40056 --- /dev/null +++ b/Tests/Middleware/MiddlewareStackTest.php @@ -0,0 +1,86 @@ + 'notify', + 'adapters' => array( + 'notify' => array( + 'scripts' => array('script.js'), + 'styles' => array('styles.css'), + 'options' => array() + ) + ), + 'stamps_middlewares' => array( + new AddPriorityStampMiddleware(), + new AddCreatedAtStampMiddleware(), + ) + )); + + $stack = new MiddlewareManager($config); + + $notification = $this->getMockBuilder('Flasher\Prime\Notification\NotificationInterface')->getMock(); + $envelope = new Envelope($notification); + + $stack->handle($envelope); + + $this->assertSame($notification, $envelope->getNotification()); + $this->assertCount(3, $envelope->all()); + + $priorityStamp = $envelope->get('Flasher\Prime\Stamp\PriorityStamp'); + $this->assertInstanceOf('Flasher\Prime\Stamp\PriorityStamp', $priorityStamp); +// $this->assertEquals(0, $priorityStamp->getPriority()); + + $timeStamp = $envelope->get('Flasher\Prime\Stamp\CreatedAtStamp'); + $this->assertInstanceOf('Flasher\Prime\Stamp\CreatedAtStamp', $timeStamp); + + $this->assertEquals(time(), $timeStamp->getCreatedAt()->getTimestamp()); + } + + public function testHandleWithExistingStamps() + { + $config = new Config(array( + 'default' => 'notify', + 'adapters' => array( + 'notify' => array( + 'scripts' => array('script.js'), + 'styles' => array('styles.css'), + 'options' => array() + ) + ), + 'stamps_middlewares' => array( + new AddPriorityStampMiddleware(), + new AddCreatedAtStampMiddleware(), + ) + )); + + $stack = new MiddlewareManager($config); + + $notification = $this->getMockBuilder('Flasher\Prime\Notification\NotificationInterface')->getMock(); + $stamps = array( + new PriorityStamp(1), + ); + $envelope = new Envelope($notification, $stamps); + + $stack->handle($envelope); + + $this->assertSame($notification, $envelope->getNotification()); + $this->assertCount(3, $envelope->all()); + + $priorityStamp = $envelope->get('Flasher\Prime\Stamp\PriorityStamp'); + $this->assertInstanceOf('Flasher\Prime\Stamp\PriorityStamp', $priorityStamp); +// $this->assertEquals(1, $priorityStamp->getPriority()); + } +} diff --git a/Tests/Notification/NotificationTest.php b/Tests/Notification/NotificationTest.php new file mode 100644 index 00000000..bdbfdbe9 --- /dev/null +++ b/Tests/Notification/NotificationTest.php @@ -0,0 +1,30 @@ + 5000)); + + $this->assertSame('type', $notification->getType()); + $this->assertSame('message', $notification->getMessage()); + $this->assertSame(array('timer' => 5000), $notification->getOptions()); + } + + public function testAddOption() + { + $notification = new Notification('message', 'type', array('timer' => 5000)); + $notification->setOption('toast', true); + + $this->assertSame(array('timer' => 5000, 'toast' => true), $notification->getOptions()); + + $notification->unsetOption('timer'); + + $this->assertSame(array('toast' => true), $notification->getOptions()); + } +} diff --git a/Tests/Producer/ProducerManagerTest.php b/Tests/Producer/ProducerManagerTest.php new file mode 100644 index 00000000..7ce0382e --- /dev/null +++ b/Tests/Producer/ProducerManagerTest.php @@ -0,0 +1,57 @@ +getMockBuilder('Notify\Config\ConfigInterface')->getMock(); + $manager = new \Notify\Notify($config); + + $producer = $this->getMockBuilder('Notify\NotifyFactory')->getMock(); + $producer->method('supports')->willReturn(true); + $manager->addDriver($producer); + + $reflection = new ReflectionClass(get_class($manager)); + $extensions = $reflection->getProperty('drivers'); + $extensions->setAccessible(true); + + $drivers = $extensions->getValue($manager); + $this->assertCount(1, $drivers); + + $producer1 = $manager->make('producer_1'); + $this->assertSame($producer, $producer1); + } + + public function testNullDriver() + { + $this->setExpectedException('InvalidArgumentException', 'Driver [] not supported.'); + + $config = $this->getMockBuilder('Notify\Config\ConfigInterface')->getMock(); + $config->method('get')->willReturn(null); + + $manager = new \Notify\Notify($config); + + $producer = $this->getMockBuilder('Notify\NotifyFactory')->getMock(); + $manager->addDriver($producer); + + $this->assertSame($producer, $manager->make()); + } + + public function testNotSupportedDriver() + { + $this->setExpectedException('InvalidArgumentException', 'Driver [not_supported] not supported.'); + + $config = $this->getMockBuilder('Notify\Config\ConfigInterface')->getMock(); + $manager = new \Notify\Notify($config); + + $producer = $this->getMockBuilder('Notify\NotifyFactory')->getMock(); + $manager->addDriver($producer); + + $this->assertSame($producer, $manager->make('not_supported')); + } +} diff --git a/Tests/Storage/ArrayStorageTest.php b/Tests/Storage/ArrayStorageTest.php new file mode 100644 index 00000000..54896f2d --- /dev/null +++ b/Tests/Storage/ArrayStorageTest.php @@ -0,0 +1,71 @@ +add($envelopes[$index]); + } + + $this->assertCount(5, $storage->all()); + } + + public function testAddNotificationWithUuidStamp() + { + $storage = new ArrayStorage(); + $storage->add(new Envelope(new Notification('success'))); + + $envelopes = $storage->all(); + + $this->assertCount(1, $envelopes); + + $uuid = $envelopes[0]->get('Flasher\Prime\TestsStamp\UuidStamp'); + $this->assertNotNull($uuid); + } + + public function testClear() + { + $storage = new ArrayStorage(); + $envelopes = array(); + + foreach (range(0, 4) as $index) { + $envelopes[$index] = new Envelope(new Notification('success', 'success message')); + $storage->add($envelopes[$index]); + } + + $storage->clear(); + + $this->assertSame(array(), $storage->all()); + } + + public function testRemove() + { + $storage = new ArrayStorage(); + $envelopes = array(); + + foreach (range(0, 4) as $index) { + $envelopes[$index] = new Envelope(new Notification('success', 'success message'), new UuidStamp()); + $storage->add($envelopes[$index]); + } + + $storage->remove($envelopes[0], $envelopes[2]); + + $actual = UuidStamp::indexWithUuid($storage->all()); + $expected = UuidStamp::indexWithUuid($envelopes[1], $envelopes[3], $envelopes[4]); + + $this->assertSame(array(), array_diff_key($actual, $expected)); + } +} diff --git a/Tests/Storage/StorageManagerTest.php b/Tests/Storage/StorageManagerTest.php new file mode 100644 index 00000000..b3dddd65 --- /dev/null +++ b/Tests/Storage/StorageManagerTest.php @@ -0,0 +1,78 @@ +add($envelopes[$index]); + } + + $this->assertCount(5, $storageManager->all()); + } + + public function testClear() + { + $storageManager = new StorageManager(new ArrayStorage()); + $envelopes = array(); + + foreach (range(0, 4) as $index) { + $envelopes[$index] = new Envelope(new Notification('success', 'success message')); + $storageManager->add($envelopes[$index]); + } + + $storageManager->clear(); + + $this->assertSame(array(), $storageManager->all()); + } + + public function testAdd() + { + $storageManager = new StorageManager(new ArrayStorage()); + $storageManager->add(new Envelope(new Notification('success'))); + + $envelopes = $storageManager->all(); + + $this->assertCount(1, $envelopes); + + $uuid = $envelopes[0]->get('Flasher\Prime\TestsStamp\UuidStamp'); + $this->assertNotNull($uuid); + } + + public function testFlush() + { + $storageManager = new StorageManager(new ArrayStorage()); + + $envelope = new Envelope( + new Notification('error message', 'error'), + new ReplayStamp(2), + new UuidStamp('fake-uuid') + ); + $storageManager->add($envelope); + + $envelopes = array(); + foreach (range(0, 2) as $index) { + $envelopes[$index] = new Envelope(new Notification('success message', 'success')); + $storageManager->add($envelopes[$index]); + } + $envelopes[] = $envelope; + + $storageManager->flush($envelopes); + + $this->assertSame(array('fake-uuid'), array_keys(UuidStamp::indexWithUuid($storageManager->all()))); + } +} diff --git a/Tests/Stubs/Producer/FakeProducer.php b/Tests/Stubs/Producer/FakeProducer.php new file mode 100644 index 00000000..230f41b9 --- /dev/null +++ b/Tests/Stubs/Producer/FakeProducer.php @@ -0,0 +1,13 @@ +getType(), + $envelope->getMessage(), + $envelope->getTitle() + ); + } +} diff --git a/Tests/TestCase.php b/Tests/TestCase.php new file mode 100644 index 00000000..ed5e10f4 --- /dev/null +++ b/Tests/TestCase.php @@ -0,0 +1,40 @@ +expectException($exceptionName); + $this->expectExceptionMessage($exceptionMessage); + } else { + parent::setExpectedException($exceptionName, $exceptionMessage, $exceptionCode); + } + } + + /** + * Call protected/private method of a class. + * + * @param object $object Instantiated object that we will run method on. + * @param string $methodName Method name to call. + * @param array|mixed $parameters array of parameters to pass into method. + * + * @return mixed method return + * + * @throws \ReflectionException + */ + protected function callMethod(&$object, $methodName, $parameters = array()) + { + $reflection = new ReflectionClass(get_class($object)); + $method = $reflection->getMethod($methodName); + $method->setAccessible(true); + + $parameters = is_array($parameters) ? $parameters : array_slice(func_get_args(), 2); + + return $method->invokeArgs($object, $parameters); + } +} diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 00000000..e69de29b diff --git a/composer.json b/composer.json new file mode 100644 index 00000000..24522f01 --- /dev/null +++ b/composer.json @@ -0,0 +1,49 @@ +{ + "name": "php-flasher/flasher", + "description": "a flash notifications library for PHP", + "keywords": [ + "notify", + "flash", + "php", + "laravel", + "symfony", + "Lumen", + "notifications", + "messages", + "alerts", + "pnotify", + "toastr " + ], + "homepage": "https://github.com/php-flasher/flasher", + "authors": [ + { + "name": "Younes Khoubza", + "email": "younes.khoubza@gmail.com", + "homepage": "https://github.com/yoeunes", + "role": "Developer" + } + ], + "license": "MIT", + "require": { + "php": ">=5.3" + }, + "require-dev": { + "phpunit/phpunit": ">=4.8.36" + }, + "autoload": { + "psr-4": { + "Flasher\\Prime\\": "", + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "files": [ + "helpers.php" + ] + }, + "config": { + "sort-packages": true + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/phpunit.xml.dist b/phpunit.xml.dist new file mode 100644 index 00000000..8b8227e4 --- /dev/null +++ b/phpunit.xml.dist @@ -0,0 +1,22 @@ + + + + + Tests + + + + + src/ + + +