diff --git a/common/Alias/Event/Body.php b/common/Alias/Event/Body.php new file mode 100644 index 0000000..1cad4c0 --- /dev/null +++ b/common/Alias/Event/Body.php @@ -0,0 +1,23 @@ +write((array) $data); + } + if (!is_array($data)) { + $this->body []= $data; + return; + } + foreach ($data as $key => $line) { + $this->body[$key] = $line; + } + } + public function read() { + return $this->body; + } +} diff --git a/common/Alias/Event/Message.php b/common/Alias/Event/Message.php new file mode 100644 index 0000000..c17e9f8 --- /dev/null +++ b/common/Alias/Event/Message.php @@ -0,0 +1,46 @@ +clients = $storage; + } + protected $dispatcher; + public function setDispatcher(Dispatcher $dispatcher) { + $this->dispatcher = $dispatcher; + return $this; + } + protected $request_builder; + public function setRequestBuilder(RequestBuilder $builder) { + $this->request_builder = $builder; + return $this; + } + + public function onOpen(Connection $conn) { + $this->clients->attach($conn); + } + public function onMessage(Connection $from, $msg) { + foreach ($this->clients as $client) { + if ($client != $from) { + continue; + } + $request = $this->request_builder->build($msg); + $response = $this->dispatcher->dispatch($request); + $from->send($response); + } + } + public function onClose(Connection $conn) { + $this->clients->detach($conn); + } + public function onError(Connection $conn, \Exception $e) { + $conn->send(json_encode($e)); + $conn->close(); + } +} diff --git a/common/Alias/Event/Request.php b/common/Alias/Event/Request.php new file mode 100644 index 0000000..fef382b --- /dev/null +++ b/common/Alias/Event/Request.php @@ -0,0 +1,35 @@ +action = $action; + } + protected $method; + public function setMethod(string $method) { + $this->method = $method; + } + protected $body; + public function setBody(Body $body) { + $this->body = $body; + } + public function getAction(): string { + return $this->action; + } + public function getMethod(): string { + return $this->method; + } + public function getBody(): Body { + return $this->body; + } + public function jsonSerialize() { + return [ + 'action' => $this->action, + 'method' => $this->method, + 'body' => $this->body->read() + ]; + } +} diff --git a/common/Alias/Event/Response.php b/common/Alias/Event/Response.php new file mode 100644 index 0000000..9d3bcd2 --- /dev/null +++ b/common/Alias/Event/Response.php @@ -0,0 +1,27 @@ +request = $request; + } + protected $body; + public function setBody(Body $body) { + $this->body = $body; + } + public function getRequest(): Request { + return $this->request; + } + public function getBody(): Body { + return $this->body; + } + public function jsonSerialize() { + return [ + 'request' => $this->request->jsonSerialize(), + 'body' => $this->body->read() + ]; + } +} diff --git a/common/Alias/Server/App.php b/common/Alias/Server/App.php new file mode 100644 index 0000000..9946012 --- /dev/null +++ b/common/Alias/Server/App.php @@ -0,0 +1,20 @@ +container = $container; + } + public function getContainer(): Container { + return $this->container; + } + + public function add(string $action, callable $call) { + $this->container->get(Dispatcher::class)->register($action, $call); + } +} diff --git a/common/Define/Event/Body.php b/common/Define/Event/Body.php new file mode 100644 index 0000000..0ed9379 --- /dev/null +++ b/common/Define/Event/Body.php @@ -0,0 +1,7 @@ +container = $container; + } + public function build(callable $call, Request $request, Response $response) { + $function = false; + $object = null; + if (is_string($call)) { + $ref = new ReflectionFunction($call); + $params = $ref->getParameters(); + $function = true; + } + if (is_object($call)) { + $ref = new ReflectionObject($call); + $ref = $ref->getMethod('__invoke'); + $params = $ref->getParameters(); + $object = $call; + } + if (is_array($call)) { + $ref = new ReflectionObject($call[0]); + $ref = $ref->getMethod($call[1]); + $params = $ref->getParameters(); + $object = $call[0]; + } + $invoke_params = [$request, $response]; + foreach ($params as $param) { + if ($param->getName() == 'request' or $param->getName() == 'response') { + continue; + } + if ($param->getType() and $this->container->has($param->getType()->getName())) { + $invoke_params []= $this->container->get($param->getType()->getName()); + continue; + } + if ($param->getType() and class_exists($param->getType()->getName())) { + $class = $param->getType()->getName(); + $invoke_params []= new $class(); + continue; + } + if ($param->isDefaultValueAvailable()) { + $invoke_params []= $param->getDefaultValue(); + continue; + } + } + if ($function) { + return json_encode($ref->invokeArgs($invoke_params)); + } + return json_encode($ref->invokeArgs(new $object(), $invoke_params)); + } +} diff --git a/common/Factory/Event/Request.php b/common/Factory/Event/Request.php new file mode 100644 index 0000000..0590d60 --- /dev/null +++ b/common/Factory/Event/Request.php @@ -0,0 +1,19 @@ +setAction($data->action); + $request->setMethod($data->method ?? 'GET'); + $body = new Body(); + $body->write($data->data ?? []); + $request->setBody($body); + return $request; + } +} diff --git a/common/Factory/Event/Response.php b/common/Factory/Event/Response.php new file mode 100644 index 0000000..383f703 --- /dev/null +++ b/common/Factory/Event/Response.php @@ -0,0 +1,15 @@ +setRequest($request); + $body = new Body(); + $response->setBody($body); + return $response; + } +} diff --git a/common/Service/Event/Dispatcher.php b/common/Service/Event/Dispatcher.php new file mode 100644 index 0000000..a419def --- /dev/null +++ b/common/Service/Event/Dispatcher.php @@ -0,0 +1,29 @@ +container = $container; + } + protected $listeners; + public function register(string $action, callable $listener) { + $this->listeners[$action] = $listener; + } + public function dispatch(object $event) { + if (!is_a($event, Request::class)) { + throw new \InvalidArgumentException('Argument passed for dispatch NEEDS to be a ' . Request::class); + } + $action = $event->getAction(); + if (!isset($this->listeners[$action])) { + throw new \InvalidArgumentException($action . ' not set.'); + } + $response = $this->container->get(ResponseBuilder::class)->build($event); + return $this->container->get(Listener::class)->build($this->listeners[$action], $event, $response); + } +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..52bce30 --- /dev/null +++ b/composer.json @@ -0,0 +1,25 @@ +{ + "name": "provm/events", + "description": "Event handler for WebSocket", + "type": "project", + "require": { + "cboden/ratchet": "^0.4.3", + "psr/event-dispatcher": "^1.0" + }, + "require-dev": { + "phpunit/phpunit": "^9.5", + "kint-php/kint": "^3.3" + }, + "license": "MIT", + "authors": [ + { + "name": "Aldarien", + "email": "aldarien85@gmail.com" + } + ], + "autoload": { + "psr-4": { + "ProVM\\Common\\": "./common" + } + } +}