Events WebSocket
This commit is contained in:
23
common/Alias/Event/Body.php
Normal file
23
common/Alias/Event/Body.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Alias\Event;
|
||||
|
||||
use ProVM\Common\Define\Event\Body as BodyInterface;
|
||||
|
||||
class Body implements BodyInterface {
|
||||
protected $body = [];
|
||||
public function write($data) {
|
||||
if (is_object($data)) {
|
||||
return $this->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;
|
||||
}
|
||||
}
|
46
common/Alias/Event/Message.php
Normal file
46
common/Alias/Event/Message.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Alias\Event;
|
||||
|
||||
use Psr\Container\ContainerInterface as Container;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface as Dispatcher;
|
||||
use Ratchet\MessageComponentInterface as Component;
|
||||
use Ratchet\ConnectionInterface as Connection;
|
||||
use ProVM\Common\Factory\Event\Request as RequestBuilder;
|
||||
|
||||
class Message implements Component {
|
||||
protected $clients;
|
||||
public function __construct($storage) {
|
||||
$this->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();
|
||||
}
|
||||
}
|
35
common/Alias/Event/Request.php
Normal file
35
common/Alias/Event/Request.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Alias\Event;
|
||||
|
||||
use ProVM\Common\Define\Event\{Request as RequestInterface, Body};
|
||||
|
||||
class Request implements RequestInterface {
|
||||
protected $action;
|
||||
public function setAction(string $action) {
|
||||
$this->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()
|
||||
];
|
||||
}
|
||||
}
|
27
common/Alias/Event/Response.php
Normal file
27
common/Alias/Event/Response.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Alias\Event;
|
||||
|
||||
use ProVM\Common\Define\Event\{Response as ResponseInterface, Request, Body};
|
||||
|
||||
class Response implements ResponseInterface {
|
||||
protected $request;
|
||||
public function setRequest(Request $request) {
|
||||
$this->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()
|
||||
];
|
||||
}
|
||||
}
|
20
common/Alias/Server/App.php
Normal file
20
common/Alias/Server/App.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Alias\Server;
|
||||
|
||||
use Psr\Container\ContainerInterface as Container;
|
||||
use Ratchet\Server\IoServer;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface as Dispatcher;
|
||||
|
||||
class App extends IoServer {
|
||||
protected $container;
|
||||
public function setContainer(Container $container) {
|
||||
$this->container = $container;
|
||||
}
|
||||
public function getContainer(): Container {
|
||||
return $this->container;
|
||||
}
|
||||
|
||||
public function add(string $action, callable $call) {
|
||||
$this->container->get(Dispatcher::class)->register($action, $call);
|
||||
}
|
||||
}
|
7
common/Define/Event/Body.php
Normal file
7
common/Define/Event/Body.php
Normal file
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Define\Event;
|
||||
|
||||
interface Body {
|
||||
public function write($data);
|
||||
public function read();
|
||||
}
|
13
common/Define/Event/Request.php
Normal file
13
common/Define/Event/Request.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Define\Event;
|
||||
|
||||
use ProVM\Common\Define\Event\Body;
|
||||
|
||||
interface Request extends \JsonSerializable {
|
||||
public function setAction(string $action);
|
||||
public function setMethod(string $method);
|
||||
public function setBody(Body $body);
|
||||
public function getAction(): string;
|
||||
public function getMethod(): string;
|
||||
public function getBody(): Body;
|
||||
}
|
9
common/Define/Event/Response.php
Normal file
9
common/Define/Event/Response.php
Normal file
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Define\Event;
|
||||
|
||||
interface Response extends \JsonSerializable {
|
||||
public function setRequest(Request $request);
|
||||
public function setBody(Body $body);
|
||||
public function getRequest(): Request;
|
||||
public function getBody(): Body;
|
||||
}
|
57
common/Factory/Event/Listener.php
Normal file
57
common/Factory/Event/Listener.php
Normal file
@ -0,0 +1,57 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Factory\Event;
|
||||
|
||||
use \ReflectionFunction;
|
||||
use \ReflectionObject;
|
||||
use Psr\Container\ContainerInterface as Container;
|
||||
use ProVM\Common\Define\Event\{Request, Response};
|
||||
|
||||
class Listener {
|
||||
public function __construct(Container $container) {
|
||||
$this->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));
|
||||
}
|
||||
}
|
19
common/Factory/Event/Request.php
Normal file
19
common/Factory/Event/Request.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Factory\Event;
|
||||
|
||||
use ProVM\Common\Define\Event\Request as RequestInterface;
|
||||
use ProVM\Common\Alias\Event\Request as RequestClass;
|
||||
use ProVM\Common\Alias\Event\Body;
|
||||
|
||||
class Request {
|
||||
public function build($request_string): RequestInterface {
|
||||
$data = json_decode($request_string);
|
||||
$request = new RequestClass();
|
||||
$request->setAction($data->action);
|
||||
$request->setMethod($data->method ?? 'GET');
|
||||
$body = new Body();
|
||||
$body->write($data->data ?? []);
|
||||
$request->setBody($body);
|
||||
return $request;
|
||||
}
|
||||
}
|
15
common/Factory/Event/Response.php
Normal file
15
common/Factory/Event/Response.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Factory\Event;
|
||||
|
||||
use ProVM\Common\Define\Event\{Request, Response as ResponseInterface};
|
||||
use ProVM\Common\Alias\Event\{Response as ResponseClass, Body};
|
||||
|
||||
class Response {
|
||||
public function build(Request $request): ResponseInterface {
|
||||
$response = new ResponseClass();
|
||||
$response->setRequest($request);
|
||||
$body = new Body();
|
||||
$response->setBody($body);
|
||||
return $response;
|
||||
}
|
||||
}
|
29
common/Service/Event/Dispatcher.php
Normal file
29
common/Service/Event/Dispatcher.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php
|
||||
namespace ProVM\Common\Service\Event;
|
||||
|
||||
use Psr\Container\ContainerInterface as Container;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use ProVM\Common\Define\Event\Request;
|
||||
use ProVM\Common\Factory\Event\{Response as ResponseBuilder, Listener};
|
||||
|
||||
class Dispatcher implements EventDispatcherInterface {
|
||||
protected $container;
|
||||
public function __construct(Container $container) {
|
||||
$this->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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user