diff --git a/lib/hooks/basicemitter.php b/lib/hooks/basicemitter.php index e615a58cfe846c3fde3d4aaf1d6ffdaf2b8a65c9..9ffe1af23144f6aae36841e3fbc3c689f5c272a9 100644 --- a/lib/hooks/basicemitter.php +++ b/lib/hooks/basicemitter.php @@ -13,7 +13,7 @@ abstract class BasicEmitter implements Emitter { /** * @var (callable[])[] $listeners */ - private $listeners = array(); + protected $listeners = array(); /** * @param string $scope diff --git a/lib/hooks/forwardingemitter.php b/lib/hooks/forwardingemitter.php new file mode 100644 index 0000000000000000000000000000000000000000..1aacc4012e0014cb933af81f56a2d5f5e88da362 --- /dev/null +++ b/lib/hooks/forwardingemitter.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace OC\Hooks; + +/** + * Class ForwardingEmitter + * + * allows forwarding all listen calls to other emitters + * + * @package OC\Hooks + */ +abstract class ForwardingEmitter extends BasicEmitter { + /** + * @var \OC\Hooks\Emitter[] array + */ + private $forwardEmitters = array(); + + /** + * @param string $scope + * @param string $method + * @param callable $callback + */ + public function listen($scope, $method, $callback) { + parent::listen($scope, $method, $callback); + foreach ($this->forwardEmitters as $emitter) { + $emitter->listen($scope, $method, $callback); + } + } + + /** + * @param \OC\Hooks\Emitter $emitter + */ + protected function forward($emitter) { + $this->forwardEmitters[] = $emitter; + + //forward all previously connected hooks + foreach ($this->listeners as $key => $listeners) { + list($scope, $method) = explode('::', $key, 2); + foreach ($listeners as $listener) { + $emitter->listen($scope, $method, $listener); + } + } + } +} diff --git a/tests/lib/hooks/forwardingemitter.php b/tests/lib/hooks/forwardingemitter.php new file mode 100644 index 0000000000000000000000000000000000000000..decf6bb354cae24f0bf1afc7572cd5dee7e10bf7 --- /dev/null +++ b/tests/lib/hooks/forwardingemitter.php @@ -0,0 +1,74 @@ +<?php +/** + * Copyright (c) 2013 Robin Appelman <icewind@owncloud.com> + * This file is licensed under the Affero General Public License version 3 or + * later. + * See the COPYING-README file. + */ + +namespace Test\Hooks; +use OC\Hooks\PublicEmitter; + +class DummyForwardingEmitter extends \OC\Hooks\ForwardingEmitter { + public function emitEvent($scope, $method, $arguments = array()) { + $this->emit($scope, $method, $arguments); + } + + /** + * @param \OC\Hooks\Emitter $emitter + */ + public function forward($emitter) { + parent::forward($emitter); + } +} + +/** + * Class ForwardingEmitter + * + * allows forwarding all listen calls to other emitters + * + * @package OC\Hooks + */ +class ForwardingEmitter extends BasicEmitter { + public function testSingleForward() { + $baseEmitter = new PublicEmitter(); + $forwardingEmitter = new DummyForwardingEmitter(); + $forwardingEmitter->forward($baseEmitter); + $hookCalled = false; + $forwardingEmitter->listen('Test', 'test', function () use (&$hookCalled) { + $hookCalled = true; + }); + $baseEmitter->emit('Test', 'test'); + $this->assertTrue($hookCalled); + } + + public function testMultipleForwards() { + $baseEmitter1 = new PublicEmitter(); + $baseEmitter2 = new PublicEmitter(); + $forwardingEmitter = new DummyForwardingEmitter(); + $forwardingEmitter->forward($baseEmitter1); + $forwardingEmitter->forward($baseEmitter2); + $hookCalled = 0; + $forwardingEmitter->listen('Test', 'test1', function () use (&$hookCalled) { + $hookCalled++; + }); + $forwardingEmitter->listen('Test', 'test2', function () use (&$hookCalled) { + $hookCalled++; + }); + $baseEmitter1->emit('Test', 'test1'); + $baseEmitter1->emit('Test', 'test2'); + $this->assertEquals(2, $hookCalled); + } + + public function testForwardExistingHooks() { + $baseEmitter = new PublicEmitter(); + $forwardingEmitter = new DummyForwardingEmitter(); + $hookCalled = false; + $forwardingEmitter->listen('Test', 'test', function () use (&$hookCalled) { + $hookCalled = true; + }); + $forwardingEmitter->forward($baseEmitter); + $baseEmitter->emit('Test', 'test'); + $this->assertTrue($hookCalled); + } +}