Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ytake committed Jul 19, 2020
0 parents commit 52ac080
Show file tree
Hide file tree
Showing 15 changed files with 298 additions and 0 deletions.
9 changes: 9 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.gitattributes export-ignore
.gitignore export-ignore
.travis.yml export-ignore
.travis.sh export-ignore
composer.lock export-ignore
tests/ export-ignore
.hhconfig export-ignore
hhast-lint.json export-ignore
*.hack linguist-language=Hack
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
composer.phar
composer.lock
vendor/
docker/
docker-compose.yml
.vscode
*.hhast.parser-cache
13 changes: 13 additions & 0 deletions .hhconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
assume_php = false
enable_experimental_tc_features = no_fallback_in_namespaces
ignored_paths = [ "vendor/.+/tests/.+", "vendor/bin/.*"]
disallow_assign_by_ref = false
unsafe_rx = false
disable_static_local_variables = true
disable_instanceof_refinement = true
disallow_array_literal = false
disable_lval_as_an_expression = true
new_inference_lambda = true
error_php_lambdas = true
allowed_decl_fixme_codes=2053,4045,4047
allowed_fixme_codes_strict=2011,2049,2050,2053,2083,3004,3084,4027,4045,4047,4053,4104,4107,4106,4108,4110,4119,4128,4135,4188,4223,4240,4248,4323,4200
20 changes: 20 additions & 0 deletions .travis.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash
set -ex
apt update -y
DEBIAN_FRONTEND=noninteractive apt install -y php-cli zip unzip
hhvm --version
php --version

(
cd $(mktemp -d)
curl https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
)

if (hhvm --version | grep -q -- -dev); then
# Doesn't exist in master, but keep it here so that we can test release
# branches on nightlies too
rm -f composer.lock
fi
composer install
hh_client
./vendor/bin/hacktest.hack tests/
17 changes: 17 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
sudo: required
language: generic
services:
- docker
env:
matrix:
- HHVM_VERSION=4.62.0
- HHVM_VERSION=4.64.0
- HHVM_VERSION=4.65.0
- HHVM_VERSION=latest
install:
- docker pull hhvm/hhvm-proxygen:$HHVM_VERSION
script:
- docker run --rm -w /var/source -v $(pwd):/var/source hhvm/hhvm:$HHVM_VERSION ./.travis.sh
notifications:
slack:
secure: iOveDi8HmYUL5yiAXSnRBmUoIJOjxPq/tAgmAHYnScZAqEyh9ST8zoixscmenRMdU26X0XZaU6o1bKti/fvA/jPgkt39gxjZl7Z87HFncXU1bTFNC7+v8j4Ri2WmBoFQAnWun0pXOEPt3YZ5u3vRs0ZpRrBCtyRFzt8S+obw7ZzUAz6egmShYzieUiohCy3jzhPxfZeBPfdnrdh7Y1+2h7JC/m60gWn9CZE0Gn62TeJecz1td7xwUgcZQ5ZdXzSeA6jKrSYIrNa3Mn2w+PF8rbiOGrNDvbCwGBaw+P2BTYZ0GQrUv1I8jXETsWTs6R1qZTgv0ZlcsXP2icx1lE3rBeIpcyjj5CpK/fnlFGCV4Pi0RA8OPBvSYJ8KIUJ8f6jOdXLpz8iko1WQCnEEky2oLZLBFaK4uRV7t/fzJ87hINZ/V0NQV/m/6oeerpaM816DBX937TPoonkwjqHvzXb6HvQ/gpq53XyhFi/77rU2fl/KHuCEB9jL6WxBBbrINttlc+jlc7hpG72JUfcU0WlzQg2+KPHa30Lu6SRnSk6bk/IHrSTgeirIXi1kykA3e5UsKr+H+R/cQV6SibOo1sN2TaCebBBJW//kHYFZXqzX5l2kRSPXHwoFQpDhElOKMbbNuBySq2vXFexoadl1q6GOXTh1rhwf36HfrRdAnowwVTo=
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
The MIT License (MIT)

Copyright (c) 2017-2020 Yuuki Takezawa

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.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# event-dispatcher

45 changes: 45 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
{
"name": "nazg/event-dispatcher",
"description": "Event Managiment for Hack",
"keywords": [
"hhvm",
"hack",
"event"
],
"license": "MIT",
"authors": [
{
"name": "Yuuki Takezawa",
"email": "[email protected]"
}
],
"require": {
"hhvm": "^4.62",
"hhvm/hsl": "^4.0",
"hhvm/hsl-experimental": "^4.50",
"hhvm/hhvm-autoload": "^3.0"
},
"require-dev": {
"facebook/fbexpect": "^2.6.1",
"hhvm/hhast": "^4.0",
"hhvm/hacktest": "^2.0"
},
"autoload": {
"psr-4": {
"Nazg\\EventDispatcher\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"NazgTest\\": "tests/"
}
},
"scripts": {
"tests": [
"hhvm ./vendor/bin/hacktest.hack tests/"
],
"register": [
"hhvm ./vendor/bin/hh-autoload.hack"
]
}
}
10 changes: 10 additions & 0 deletions hh_autoload.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"roots": [
"src/"
],
"devRoots": [
"tests/"
],
"devFailureHandler": null,
"parser": "ext-factparse"
}
4 changes: 4 additions & 0 deletions hhast-lint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"roots": ["src/", "tests/"],
"builtinLinters": "all"
}
15 changes: 15 additions & 0 deletions src/Event.hack
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Nazg\EventDispatcher;

class Event implements StoppableEventInterface {

private bool $propagationStopped = false;

<<__Rx>>
public function isPropagationStopped(): bool {
return $this->propagationStopped;
}

public function stopPropagation(): void {
$this->propagationStopped = true;
}
}
92 changes: 92 additions & 0 deletions src/EventDispatcher.hack
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
namespace Nazg\EventDispatcher;

use namespace HH\Lib\{Dict, C};
use function array_key_exists;
use function array_filter;

class EventDispatcher {

private dict<string, dict<int, vec<ListenerInterface>>> $listeners = dict[];
private dict<string, dict<int, ListenerInterface>> $sorted = dict[];

public function dispatch(Event $event, string $eventName): Event {
$listeners = $this->getListeners($eventName);
if ($listeners) {
$this->callListeners($listeners, $eventName, $event);
}
return $event;
}

<<__Rx>>
public function hasListeners(
?string $eventName = null
): bool {
if ($eventName is nonnull) {
return !array_key_exists($eventName, $this->listeners);
}
if(C\count($this->listeners)) {
return true;
}
return false;
}

public function addListener(
string $eventName,
ListenerInterface $listener,
int $priority = 0
): void {
$this->listeners[$eventName][$priority][] = $listener;
}

protected function callListeners(
dict<int, ListenerInterface> $listeners,
string $eventName,
Event $event
): void {
foreach ($listeners as $listener) {
if ($event->isPropagationStopped()) {
break;
}
$listener->handle($event, $eventName, $this);
}
}

private function sortListeners(
string $eventName
): void {
Dict\sort_by_key($this->listeners[$eventName]);
$this->sorted[$eventName] = dict[];
foreach ($this->listeners[$eventName] as $listeners) {
foreach ($listeners as $k => $listener) {
$this->sorted[$eventName][] = $listener;
}
}
}

public function getListeners(
?string $eventName = null
): dict<arraykey, ListenerInterface> {
if ($eventName is nonnull) {
if (!C\count($this->listeners[$eventName])) {
return dict[];
}

if (!array_key_exists($eventName, $this->sorted)) {
$this->sortListeners($eventName);
}
return $this->sorted[$eventName];
}
foreach ($this->listeners as $eventName => $eventListeners) {
if (!array_key_exists($eventName, $this->sorted)) {
$this->sortListeners($eventName);
}
}
$sorted = array_filter($this->sorted);
$d = dict[];
foreach ($sorted as $key => $value) {
$d[$key] = $value;
}
/* HH_FIXME[4110] */
return $d;
}
}
10 changes: 10 additions & 0 deletions src/ListenerInterface.hack
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Nazg\EventDispatcher;

interface ListenerInterface {

public function handle(
Event $event,
string $eventName,
EventDispatcher $dispathcher
): void;
}
12 changes: 12 additions & 0 deletions src/StoppableEventInterface.hack
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
namespace Nazg\EventDispatcher;

interface StoppableEventInterface {

/**
* Is propagation stopped?
*
* This will typically only be used by the Dispatcher to determine if the
* previous listener halted propagation.
*/
public function isPropagationStopped() : bool;
}
21 changes: 21 additions & 0 deletions tests/EventDispatcherTest.hack
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use type Nazg\EventDispatcher\{Event, EventDispatcher, ListenerInterface};
use type Facebook\HackTest\HackTest;
use function Facebook\FBExpect\expect;

final class EventDispatcherTest extends HackTest {

public async function testShouldBeEmptyDict(): Awaitable<void> {
$dispatcher = new EventDispatcher();
expect($dispatcher->getListeners())->toBeSame(dict[]);
}
}

class MockListener implements ListenerInterface {
public function handle(
Event $event,
string $eventName,
EventDispatcher $dispathcher
): void {

}
}

0 comments on commit 52ac080

Please sign in to comment.