pax_global_header00006660000000000000000000000064121722325000014504gustar00rootroot0000000000000052 comment=14f284eede050859e72ac41064df0eac25327190 sabre-event-1.0.0/000077500000000000000000000000001217223250000137155ustar00rootroot00000000000000sabre-event-1.0.0/.gitignore000066400000000000000000000001251217223250000157030ustar00rootroot00000000000000#composer vendor composer.lock #vim lock files .*.swp #development stuff tests/cov sabre-event-1.0.0/.travis.yml000066400000000000000000000001671217223250000160320ustar00rootroot00000000000000language: php php: - 5.4 - 5.5 script: phpunit --configuration tests/phpunit.xml before_script: composer install sabre-event-1.0.0/ChangeLog000066400000000000000000000003011217223250000154610ustar00rootroot000000000000001.0.0-stable (2013-07-19) * Added: removeListener, removeAllListeners * Added: once, to only listen to an event emitting once. * Added README.md. 0.0.1-alpha (2013-06-29) * First version! sabre-event-1.0.0/LICENSE000066400000000000000000000030341217223250000147220ustar00rootroot00000000000000Copyright (C) 2013 fruux GmbH (https://fruux.com/) All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name Sabre nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. sabre-event-1.0.0/README.md000066400000000000000000000103421217223250000151740ustar00rootroot00000000000000sabre/event =========== A lightweight library for event management in PHP. It's design is inspired by Node.js's [EventEmitter][1]. sabre/event requires PHP 5.4. It's distinct from [Événement][2], because I needed a couple of features that were in conflict with it's design goals. Namely: prioritization, and the ability to stop the event chain, like javascript's `preventDefault`. Installation ------------ Make sure you have [composer][3] installed. In your project directory, create, or edit a `composer.json` file, and make sure it contains something like this: ```json { "require" : { "sabre/event" : "~0.0.1@alpha" } } ``` After that, just hit `composer install` and you should be rolling. Usage ----- In an event system there are emitters, and listeners. Emitters trigger an event, at which point a listener is notified. Example: ```php use Sabre\Event\EventEmitter; include 'vendor/autoload.php'; $eventEmitter = new EventEmitter(); // subscribing $eventEmitter->on('create', function() { echo "Something got created, apparently\n" }); $eventEmitter->emit('create'); ``` The name of the event (`create`) can be any free-form string. ### Priorities By supplying a priority, you can make sure that subscribers are handled in a specific order. The default priority is 100. Anything below that will be triggered earlier, anything higher later. If there's two subscribers with the same priority, they will execute in an undefined, but deterministic order. ```php $eventEmitter->on('create', function() { // This event will be handled first. }, 50); ``` ### Callbacks All default PHP callbacks are supported, so closures are not required. ```php $eventEmitter->on('create', 'myFunction'); $eventEmitter->on('create', ['myClass', 'myMethod']); $eventEmitter->on('create', [$myInstance, 'myMethod']); ``` ### Canceling the event handler. If a callback returns `false` the event chain is stopped immidiately. A usecase is to use a listener to check if a user has permission to perform a certain action, and stop execution if they don't. ```php $eventEmitter->on('create', function() { if (!checkPermission()) { return false; } }, 10); ``` `EventEmitter::emit()` will return `false` if the event was cancelled, and true if it wasn't. SabreDAV uses this feature heavily as well. When a HTTP request is received various plugins see if they are capable of handling the request. If they do, they can return false so other plugins will not also attempt to handle the request. Throwing an exception will also stop the chain. ### Passing arguments Arguments can be passed as an array. ```php $eventEmitter->on('create', function($entityId) { echo "An entity with id ", $entityId, " just got created.\n"; }); $entityId = 5; $eventEmitter->emit('create', [$entityId]); ``` Because you cannot really do anything with the return value of a listener, you can pass arguments by reference to communicate between listeners and back to the emitter. ```php $eventEmitter->on('create', function($entityId, &$warnings) { echo "An entity with id ", $entityId, " just got created.\n"; $warnings[] = "Something bad may or may not have happened.\n"; }); $warnings = []; $eventEmitter->emit('create', [$entityId, &$warnings]); print_r($warnings); ``` ### Integration into other objects. To add `EventEmitter` capabilities to any class, you can simply extend it. If you cannot extend, because the class is already part of an existing class hierarchy you can use the supplied trait. ```php use Sabre\Event; class MyNotUneventfulApplication extends AppController implements Event\EventEmitterInterface { use Event\EventEmitterTrait(); } ``` In the preceeding example, `MyNotUneventfulApplication` has all the capabilities of `EventEmitter`. Questions? ---------- Head over to the [sabre/dav mailinglist][4], or you can also just open a ticket on [GitHub][5]. Made at fruux ------------- This library is being developed by [fruux](https://fruux.com/). Drop us a line for commercial services or enterprise support. [1]: http://nodejs.org/api/events.html [2]: https://github.com/igorw/evenement [3]: http://getcomposer.org/ [4]: http://groups.google.com/group/sabredav-discuss [5]: https://github.com/fruux/sabre-event/issues/ sabre-event-1.0.0/composer.json000066400000000000000000000014051217223250000164370ustar00rootroot00000000000000{ "name": "sabre/event", "description" : "The sabre/event library provides utilities for lightweight event-based programming", "keywords" : [ "Events" ], "homepage" : "https://github.com/fruux/sabre-event", "license" : "BSD-3-Clause", "require" : { "php" : ">=5.4.1" }, "authors" : [ { "name" : "Evert Pot", "email" : "evert@rooftopsolutions.nl", "homepage" : "http://evertpot.com/", "role" : "Developer" } ], "support" : { "forum" : "https://groups.google.com/group/sabredav-discuss", "source" : "https://github.com/fruux/sabre-event" }, "autoload" : { "psr-0" : { "Sabre\\Event" : "lib/" } } } sabre-event-1.0.0/lib/000077500000000000000000000000001217223250000144635ustar00rootroot00000000000000sabre-event-1.0.0/lib/Sabre/000077500000000000000000000000001217223250000155175ustar00rootroot00000000000000sabre-event-1.0.0/lib/Sabre/Event/000077500000000000000000000000001217223250000166005ustar00rootroot00000000000000sabre-event-1.0.0/lib/Sabre/Event/EventEmitter.php000066400000000000000000000006351217223250000217300ustar00rootroot00000000000000listeners($eventName); $listeners[] = [$priority, $callBack]; usort($listeners, function($a, $b) { return $a[0]-$b[0]; }); } /** * Subscribe to an event exactly once. * * @param string $eventName * @param callable $callBack * @param int $priority * @return void */ public function once($eventName, callable $callBack, $priority = 100) { $wrapper = null; $wrapper = function() use ($eventName, $callBack, &$wrapper) { $this->removeListener($eventName, $wrapper); $result = call_user_func_array($callBack, func_get_args()); }; $this->on($eventName, $wrapper); } /** * Emits an event. * * This method will return true if 0 or more listeners were succesfully * handled. false is returned if one of the events broke the event chain. * * @param string $eventName * @param array $arguments * @return bool */ public function emit($eventName, array $arguments = []) { foreach($this->listeners($eventName) as $listener) { $result = call_user_func_array($listener[1], $arguments); if ($result === false) { return false; } } return true; } /** * Returns the list of listeners for an event. * * The list is returned as an array. Every item is another array with 2 * elements: priority and the callback. * * The array is returned by reference, and can therefore be used to * manipulate the list of events. * * @param string $eventName * @return array */ public function &listeners($eventName) { if (!isset($this->listeners[$eventName])) { $this->listeners[$eventName] = []; } return $this->listeners[$eventName]; } /** * Removes a specific listener from an event. * * @param string $eventName * @param callable $listener * @return void */ public function removeListener($eventName, callable $listener) { $listeners =& $this->listeners($eventName); foreach($listeners as $index => $check) { if ($check[1]===$listener) { unset($listeners[$index]); break; } } } /** * Removes all listeners from the specified event. * * @param string $eventName * @return void */ public function removeAllListeners($eventName) { $listeners =& $this->listeners($eventName); $listeners = []; } } sabre-event-1.0.0/lib/Sabre/Event/Version.php000066400000000000000000000005641217223250000207430ustar00rootroot00000000000000assertInstanceOf('Sabre\\Event\\EventEmitter', $ee); } /** * @depends testInit */ function testHandleEvent() { $argResult = null; $ee = new EventEmitter(); $ee->on('foo', function($arg) use (&$argResult) { $argResult = $arg; }); $this->assertTrue( $ee->emit('foo', ['bar']) ); $this->assertEquals('bar', $argResult); } /** * @depends testHandleEvent */ function testCancelEvent() { $argResult = 0; $ee = new EventEmitter(); $ee->on('foo', function($arg) use (&$argResult) { $argResult = 1; return false; }); $ee->on('foo', function($arg) use (&$argResult) { $argResult = 2; }); $this->assertFalse( $ee->emit('foo', ['bar']) ); $this->assertEquals(1, $argResult); } /** * @depends testCancelEvent */ function testPriority() { $argResult = 0; $ee = new EventEmitter(); $ee->on('foo', function($arg) use (&$argResult) { $argResult = 1; return false; }); $ee->on('foo', function($arg) use (&$argResult) { $argResult = 2; return false; }, 1); $this->assertFalse( $ee->emit('foo', ['bar']) ); $this->assertEquals(2, $argResult); } /** * @depends testPriority */ function testPriority2() { $result = []; $ee = new EventEmitter(); $ee->on('foo', function() use (&$result) { $result[] = 'a'; }, 200); $ee->on('foo', function() use (&$result) { $result[] = 'b'; }, 50); $ee->on('foo', function() use (&$result) { $result[] = 'c'; }, 300); $ee->on('foo', function() use (&$result) { $result[] = 'd'; }); $ee->emit('foo'); $this->assertEquals(['b','d','a','c'], $result); } function testRemoveListener() { $result = false; $callBack = function() use (&$result) { $result = true; }; $ee = new EventEmitter(); $ee->on('foo', $callBack); $ee->emit('foo'); $this->assertTrue($result); $result = false; $ee->removeListener('foo', $callBack); $ee->emit('foo'); $this->assertFalse($result); } function testRemoveAllListeners() { $result = false; $callBack = function() use (&$result) { $result = true; }; $ee = new EventEmitter(); $ee->on('foo', $callBack); $ee->emit('foo'); $this->assertTrue($result); $result = false; $ee->removeAllListeners('foo'); $ee->emit('foo'); $this->assertFalse($result); } function testOnce() { $result = 0; $callBack = function() use (&$result) { $result++; }; $ee = new EventEmitter(); $ee->once('foo', $callBack); $ee->emit('foo'); $ee->emit('foo'); $this->assertEquals(1, $result); } } sabre-event-1.0.0/tests/bootstrap.php000066400000000000000000000000641217223250000176050ustar00rootroot00000000000000 Sabre/ ../lib/