From 86baa700bc409e2846702c2de6de6966cdef917e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20Kr=C3=A4mer?= Date: Wed, 18 May 2016 00:30:29 +0200 Subject: [PATCH] Implementing decorators for event callables. First commit, proof of concept like, tests will follow. --- src/Event/Decorator/EventDecorator.php | 78 +++++++++++++++++++++++++ src/Event/Decorator/FilterDecorator.php | 63 ++++++++++++++++++++ src/Event/EventManager.php | 5 +- 3 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 src/Event/Decorator/EventDecorator.php create mode 100644 src/Event/Decorator/FilterDecorator.php diff --git a/src/Event/Decorator/EventDecorator.php b/src/Event/Decorator/EventDecorator.php new file mode 100644 index 00000000000..3939ba6a235 --- /dev/null +++ b/src/Event/Decorator/EventDecorator.php @@ -0,0 +1,78 @@ +_callable = $callable; + $this->_options = $options; + } + + /** + * Invoke + * + * @link http://php.net/manual/en/language.oop5.magic.php#object.invoke + * @return mixed + */ + public function __invoke() + { + return $this->call($this->_callable, func_get_args()); + } + + /** + * Calls a callable with the passed arguments. + * + * @param $callable The callable. + * @param array $args Arguments for the callable. + * @return mixed + */ + public function call(callable $callable, $args) + { + switch (count($args)) { + case 0: + return $callable(); + case 1: + return $callable($args[0]); + case 2: + return $callable($args[0], $args[1]); + case 3: + return $callable($args[0], $args[1], $args[2]); + default: + return call_user_func_array($callable, $args); + } + } +} diff --git a/src/Event/Decorator/FilterDecorator.php b/src/Event/Decorator/FilterDecorator.php new file mode 100644 index 00000000000..95f57cda0fd --- /dev/null +++ b/src/Event/Decorator/FilterDecorator.php @@ -0,0 +1,63 @@ +canTrigger($args[0])) { + return false; + } + return call_user_func_array('parent::__invoke', $args); + } + + /** + * Checks if the event is triggered for this listener. + * + * @param \Cake\Event\Event $event Event object. + * @return bool + */ + public function canTrigger(Event $event) + { + $if = $this->_evaluateCondition('if', $event); + $unless = $this->_evaluateCondition('unless', $event); + + return $if && !$unless; + } + + /** + * Evaluates the filter conditions + * + * @param string $condition Condition type + * @param \Cake\Event\Event $event Event objekt + * @return bool + */ + protected function _evaluateCondition($condition, Event $event) + { + if (!isset($this->_options[$condition])) { + return true; + } + if (!is_callable($this->_options[$condition])) { + throw new RuntimeException('Is not a callable!'); + } + return $this->_options[$condition]($event); + } +} diff --git a/src/Event/EventManager.php b/src/Event/EventManager.php index c61e33d4313..3ec2bdfd815 100644 --- a/src/Event/EventManager.php +++ b/src/Event/EventManager.php @@ -14,6 +14,7 @@ */ namespace Cake\Event; +use Cake\Event\Decorator\FilterDecorator; use InvalidArgumentException; /** @@ -157,14 +158,14 @@ public function on($eventKey = null, $options = [], $callable = null) $argCount = func_num_args(); if ($argCount === 2) { $this->_listeners[$eventKey][static::$defaultPriority][] = [ - 'callable' => $options + 'callable' => new FilterDecorator($options), ]; return; } if ($argCount === 3) { $priority = isset($options['priority']) ? $options['priority'] : static::$defaultPriority; $this->_listeners[$eventKey][$priority][] = [ - 'callable' => $callable + 'callable' => new FilterDecorator($callable, $options) ]; return; }