From 4556a50f584843ccf9b063da77d3735c00ddbfe5 Mon Sep 17 00:00:00 2001 From: Aldarien Date: Tue, 30 Mar 2021 16:32:39 -0300 Subject: [PATCH] Events WebSocket --- common/Alias/Event/Body.php | 23 ++++++++++++ common/Alias/Event/Message.php | 46 +++++++++++++++++++++++ common/Alias/Event/Request.php | 35 ++++++++++++++++++ common/Alias/Event/Response.php | 27 ++++++++++++++ common/Alias/Server/App.php | 20 ++++++++++ common/Define/Event/Body.php | 7 ++++ common/Define/Event/Request.php | 13 +++++++ common/Define/Event/Response.php | 9 +++++ common/Factory/Event/Listener.php | 57 +++++++++++++++++++++++++++++ common/Factory/Event/Request.php | 19 ++++++++++ common/Factory/Event/Response.php | 15 ++++++++ common/Service/Event/Dispatcher.php | 29 +++++++++++++++ 12 files changed, 300 insertions(+) create mode 100644 common/Alias/Event/Body.php create mode 100644 common/Alias/Event/Message.php create mode 100644 common/Alias/Event/Request.php create mode 100644 common/Alias/Event/Response.php create mode 100644 common/Alias/Server/App.php create mode 100644 common/Define/Event/Body.php create mode 100644 common/Define/Event/Request.php create mode 100644 common/Define/Event/Response.php create mode 100644 common/Factory/Event/Listener.php create mode 100644 common/Factory/Event/Request.php create mode 100644 common/Factory/Event/Response.php create mode 100644 common/Service/Event/Dispatcher.php 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); + } +}