Skip to content

Commit

Permalink
First commit
Browse files Browse the repository at this point in the history
  • Loading branch information
oanhnn committed Dec 30, 2015
0 parents commit d1edeaf
Show file tree
Hide file tree
Showing 13 changed files with 541 additions and 0 deletions.
44 changes: 44 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Define the line ending behavior of the different file extensions
# Set default behaviour, in case users don't have core.autocrlf set.
* text=auto
* text eol=lf

# Explicitly declare text files we want to always be normalized and converted
# to native line endings on checkout.
*.php text
*.default text
*.ctp text
*.sql text
*.md text
*.po text
*.js text
*.css text
*.ini text
*.properties text
*.txt text
*.xml text
*.yml text
.htaccess text

# Declare files that will always have CRLF line endings on checkout.
*.bat eol=crlf

# Declare files that will always have LF line endings on checkout.
*.pem eol=lf

# Denote all files that are truly binary and should not be modified.
*.png binary
*.jpg binary
*.gif binary
*.ico binary
*.mo binary
*.pdf binary
*.phar binary

# Exclude unused files
/tests export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
/.travis.yml export-ignore
/phpunit.xml export-ignore
/CHANGELOG.md export-ignore
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/composer.lock
/vendor
23 changes: 23 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
Change log
===
All Notable changes to project will be documented in this file

v1.0.0 - YYYY-MM-DD
---
#### Added
- Nothing

#### Deprecated
- Nothing

#### Fixed
- Nothing

#### Removed
- Nothing


v0.1.0 - 2015-12-30
---
#### Added
- Initialize project
21 changes: 21 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright © 2015-2016 LemonPHP Team

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
lemonphp/event
===
A simple event dispatcher

Usage
---
```
use Lemonphp\Event\Event;
use Lemonphp\Event\Dispatcher;
$dispatcher = new Dispatcher();
$dispatcher->on('event.name', function(Event $event) {
echo $event->getName() . ' is fired';
});
$dispatcher->trigger('event.name');
```

Changelog
---
See [CHANGELOG.md](https://github.com/lemonphp/event/blob/master/CHANGELOG.md)

Contributing
---
Please report any bugs or add pull requests on [Github Issues](https://github.com/lemonphp/event/issues).

License
---
This project is released under the MIT License.
29 changes: 29 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"name": "lemonphp/event",
"version": "1.0.0",
"description": "Simple event dispatcher",
"keywords": ["event", "event-dispatcher"],
"license": "MIT",
"homepage": "https://github.com/lemonphp/event",
"support": {
"issues": "https://github.com/lemonphp/event/issues",
"source": "https://github.com/lemonphp/event"
},
"authors": [
{
"name": "Oanh Nguyen",
"email": "[email protected]"
}
],
"autoload": {
"psr-4": {
"Lemon\\Event\\": "src/"
}
},
"require": {
"php": ">=5.4.0"
},
"require-dev": {
"phpunit/phpunit": "~4.5"
}
}
33 changes: 33 additions & 0 deletions phpunit.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<phpunit
colors="true"
processIsolation="false"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
stopOnError="false"
stopOnFailure="false"
syntaxCheck="true"
verbose="true"
bootstrap="tests/bootstrap.php"
>
<php>
<ini name="memory_limit" value="-1"/>
<ini name="apc.enable_cli" value="1"/>
</php>

<!-- Add any additional test suites you want to run here -->
<testsuites>
<testsuite name="Test Source">
<directory>./tests</directory>
</testsuite>
</testsuites>

<!-- Ignore vendor tests in code coverage reports -->
<filter>
<blacklist>
<directory suffix=".php">./vendor/</directory>
<directory>bin/</directory>
</blacklist>
</filter>
</phpunit>
145 changes: 145 additions & 0 deletions src/Dispatcher.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php

namespace Lemon\Event;

class Dispatcher implements DispatcherInterface
{
/**
* @var array
*/
protected $listeners = [];

/**
* @var array
*/
protected $sorted = [];

/**
* {@inheritdoc}
*/
public function trigger($eventName, Event $event = null)
{
if (null === $event) {
$event = new Event($eventName);
}

if ($listeners = $this->getListeners($eventName)) {
$this->doDispatch($listeners, $eventName, $event);
}

return $event;
}

/**
* {@inheritdoc}
*/
public function on($eventName, $listener, $priority = 0)
{
$this->listeners[$eventName][$priority][] = $listener;
unset($this->sorted[$eventName]);
}

/**
* {@inheritdoc}
*/
public function off($eventName, $listener = null)
{
if (!isset($this->listeners[$eventName])) {
return;
}

foreach ($this->listeners[$eventName] as $priority => $listeners) {
if (false !== ($key = array_search($listener, $listeners, true))) {
unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]);
}
}
}

/**
* {@inheritdoc}
*/
public function getListeners($eventName = null)
{
if (null !== $eventName) {
if (!isset($this->listeners[$eventName])) {
return [];
}

if (!isset($this->sorted[$eventName])) {
$this->sortListeners($eventName);
}

return $this->sorted[$eventName];
}

foreach ($this->listeners as $eventName => $eventListeners) {
if (!isset($this->sorted[$eventName])) {
$this->sortListeners($eventName);
}
}

return array_filter($this->sorted);
}

/**
* {@inheritdoc}
*/
public function hasListeners($eventName = null)
{
return (bool) count($this->getListeners($eventName));
}

/**
* Gets the listener priority for a specific event.
*
* Returns null if the event or the listener does not exist.
*
* @param string $eventName The name of the event
* @param callable $listener The listener
*
* @return int|null The event listener priority
*/
public function getListenerPriority($eventName, $listener)
{
if (!isset($this->listeners[$eventName])) {
return;
}

foreach ($this->listeners[$eventName] as $priority => $listeners) {
if (false !== ($key = array_search($listener, $listeners, true))) {
return $priority;
}
}
}

/**
* Triggers the listeners of an event.
*
* This method can be overridden to add functionality that is executed
* for each listener.
*
* @param callable[] $listeners The event listeners.
* @param string $eventName The name of the event to dispatch.
* @param Event $event The event object to pass to the event handlers/listeners.
*/
protected function doDispatch($listeners, $eventName, Event $event)
{
foreach ($listeners as $listener) {
call_user_func($listener, $event, $eventName, $this);
if ($event->isPropagationStopped()) {
break;
}
}
}

/**
* Sorts the internal list of listeners for the given event by priority.
*
* @param string $eventName The name of the event.
*/
protected function sortListeners($eventName)
{
krsort($this->listeners[$eventName]);
$this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]);
}
}
55 changes: 55 additions & 0 deletions src/DispatcherInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

namespace Lemon\Event;

interface DispatcherInterface
{

/**
* Dispatches an event to all registered listeners.
*
* @param string $eventName The name of the event to dispatch. The name of
* the event is the name of the method that is
* invoked on listeners.
* @param Event $event The event to pass to the event handlers/listeners.
* If not supplied, an empty Event instance is created.
* @return Event
*/
public function trigger($eventName, Event $event = null);

/**
* Adds an event listener that listens on the specified events.
*
* @param string $eventName The event to listen on
* @param callable $listener The listener
* @param int $priority The higher this value, the earlier an event
* listener will be triggered in the chain (defaults to 0)
*/
public function on($eventName, $listener, $priority = 0);

/**
* Removes an event listener from the specified events.
*
* @param string $eventName The event to remove a listener from
* @param callable $listener The listener to remove
*/
public function off($eventName, $listener = null);

/**
* Gets the listeners of a specific event or all listeners sorted by descending priority.
*
* @param string $eventName The name of the event
*
* @return array The event listeners for the specified event, or all event listeners by event name
*/
public function getListeners($eventName = null);

/**
* Checks whether an event has any registered listeners.
*
* @param string $eventName The name of the event
*
* @return bool true if the specified event has any listeners, false otherwise
*/
public function hasListeners($eventName = null);
}
Loading

0 comments on commit d1edeaf

Please sign in to comment.