Command Refactoring
Refactored Command namespace; reusing more code, standardized interfaces WebSocket handles wrapping messages better/properly now
This commit is contained in:
parent
c45962c7b4
commit
1d14119bb5
@ -1,25 +1,15 @@
|
||||
<?php
|
||||
namespace Ratchet\Command\Action;
|
||||
use Ratchet\Command\ActionInterface;
|
||||
use Ratchet\SocketInterface;
|
||||
use Ratchet\Command\ActionTemplate;
|
||||
use Ratchet\SocketObserver;
|
||||
|
||||
/**
|
||||
* Close the connection to the sockets passed in the constructor
|
||||
*/
|
||||
class CloseConnection implements ActionInterface {
|
||||
/**
|
||||
* @var SocketInterface
|
||||
*/
|
||||
protected $_socket;
|
||||
|
||||
public function __construct(SocketInterface $socket) {
|
||||
$this->_socket = $socket;
|
||||
}
|
||||
|
||||
class CloseConnection extends ActionTemplate {
|
||||
function execute(SocketObserver $scope = null) {
|
||||
$ret = $scope->onClose($this->_socket);
|
||||
$this->_socket->close();
|
||||
$ret = $scope->onClose($this->getSocket());
|
||||
$this->getSocket()->close();
|
||||
|
||||
return $ret;
|
||||
}
|
||||
|
@ -1,16 +1,12 @@
|
||||
<?php
|
||||
namespace Ratchet\Command\Action;
|
||||
use Ratchet\Command\ActionInterface;
|
||||
use Ratchet\SocketInterface;
|
||||
use Ratchet\Command\ActionTemplate;
|
||||
use Ratchet\SocketObserver;
|
||||
|
||||
/**
|
||||
* Null pattern - execution does nothing, something needs to be passed back though
|
||||
*/
|
||||
class Null implements ActionInterface {
|
||||
public function __construct(SocketInterface $socket) {
|
||||
}
|
||||
|
||||
class Null extends ActionTemplate {
|
||||
public function execute(SocketObserver $scope = null) {
|
||||
}
|
||||
}
|
@ -1,26 +1,16 @@
|
||||
<?php
|
||||
namespace Ratchet\Command\Action;
|
||||
use Ratchet\Command\ActionInterface;
|
||||
use Ratchet\SocketInterface;
|
||||
use Ratchet\Command\ActionTemplate;
|
||||
use Ratchet\SocketObserver;
|
||||
|
||||
class Runtime implements ActionInterface {
|
||||
/**
|
||||
* @var SocketInterface
|
||||
*/
|
||||
protected $_socket;
|
||||
|
||||
class Runtime extends ActionTemplate {
|
||||
/**
|
||||
* @var Closure
|
||||
*/
|
||||
protected $_command = null;
|
||||
|
||||
public function __construct(SocketInterface $socket) {
|
||||
$this->_socket = $socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* Your closure should accept a single \Ratchet\Socket parameter
|
||||
* Your closure should accept a single \Ratchet\SocketInterface parameter and return a CommandInterface or NULL
|
||||
* @param Closure Your closure/lambda to execute when the time comes
|
||||
*/
|
||||
public function setCommand(\Closure $callback) {
|
||||
@ -28,6 +18,6 @@ class Runtime implements ActionInterface {
|
||||
}
|
||||
|
||||
public function execute(SocketObserver $scope = null) {
|
||||
return call_user_func($this->_command, $socket);
|
||||
return call_user_func($this->_command, $this->getSocket());
|
||||
}
|
||||
}
|
@ -1,27 +1,17 @@
|
||||
<?php
|
||||
namespace Ratchet\Command\Action;
|
||||
use Ratchet\Command\ActionInterface;
|
||||
use Ratchet\SocketInterface;
|
||||
use Ratchet\Command\ActionTemplate;
|
||||
use Ratchet\SocketObserver;
|
||||
|
||||
/**
|
||||
* Send text back to the client end of the socket(s)
|
||||
*/
|
||||
class SendMessage implements ActionInterface {
|
||||
/**
|
||||
* @var SocketInterface
|
||||
*/
|
||||
public $_socket;
|
||||
|
||||
class SendMessage extends ActionTemplate {
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
protected $_message = '';
|
||||
|
||||
public function __construct(SocketInterface $socket) {
|
||||
$this->_socket = $socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* The message to send to the socket(s)
|
||||
* @param string
|
||||
@ -48,6 +38,6 @@ class SendMessage implements ActionInterface {
|
||||
throw new \UnexpectedValueException("Message is empty");
|
||||
}
|
||||
|
||||
$this->_socket->write($this->_message, strlen($this->_message));
|
||||
$this->getSocket()->write($this->_message, strlen($this->_message));
|
||||
}
|
||||
}
|
@ -8,4 +8,9 @@ interface ActionInterface extends CommandInterface {
|
||||
* @param Ratchet\SocketInterface
|
||||
*/
|
||||
function __construct(SocketInterface $socket);
|
||||
|
||||
/**
|
||||
* @return Ratchet\SocketInterface
|
||||
*/
|
||||
function getSocket();
|
||||
}
|
18
lib/Ratchet/Command/ActionTemplate.php
Normal file
18
lib/Ratchet/Command/ActionTemplate.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
namespace Ratchet\Command;
|
||||
use Ratchet\SocketInterface;
|
||||
|
||||
abstract class ActionTemplate implements ActionInterface {
|
||||
/**
|
||||
* @var Ratchet\SocketInterface
|
||||
*/
|
||||
protected $_socket;
|
||||
|
||||
public function __construct(SocketInterface $socket) {
|
||||
$this->_socket = $socket;
|
||||
}
|
||||
|
||||
public function getSocket() {
|
||||
return $this->_socket;
|
||||
}
|
||||
}
|
@ -9,6 +9,8 @@ use Ratchet\SocketObserver;
|
||||
interface CommandInterface {
|
||||
/**
|
||||
* The Server class will call the execution
|
||||
* @param Ratchet\SocketObserver Scope to execute the command under
|
||||
* @return CommandInterface|NULL
|
||||
*/
|
||||
function execute(SocketObserver $scope = null);
|
||||
}
|
@ -3,8 +3,13 @@ namespace Ratchet\Command;
|
||||
use Ratchet\SocketObserver;
|
||||
|
||||
class Composite extends \SplQueue implements CommandInterface {
|
||||
public function enqueue(CommandInterface $command) {
|
||||
if ($command instanceof Composite) {
|
||||
/**
|
||||
* Add another Command to the stack
|
||||
* Unlike a true composite the enqueue flattens a composite parameter into leafs
|
||||
* @param CommandInterface
|
||||
*/
|
||||
public function enqueue(CommandInterface $command = null) {
|
||||
if ($command instanceof self) {
|
||||
foreach ($command as $cmd) {
|
||||
$this->enqueue($cmd);
|
||||
}
|
||||
@ -12,7 +17,9 @@ class Composite extends \SplQueue implements CommandInterface {
|
||||
return;
|
||||
}
|
||||
|
||||
parent::enqueue($command);
|
||||
if (null !== $command) {
|
||||
parent::enqueue($command);
|
||||
}
|
||||
}
|
||||
|
||||
public function execute(SocketObserver $scope = null) {
|
||||
@ -21,11 +28,7 @@ class Composite extends \SplQueue implements CommandInterface {
|
||||
$recursive = new self;
|
||||
|
||||
foreach ($this as $command) {
|
||||
$ret = $command->execute($scope);
|
||||
|
||||
if ($ret instanceof CommandInterface) {
|
||||
$recursive->enqueue($ret);
|
||||
}
|
||||
$recursive->enqueue($command->execute($scope));
|
||||
}
|
||||
|
||||
if (count($recursive) > 0) {
|
||||
|
@ -4,9 +4,9 @@ use Ratchet\Protocol\WebSocket\Client;
|
||||
use Ratchet\Protocol\WebSocket\VersionInterface;
|
||||
use Ratchet\SocketInterface;
|
||||
use Ratchet\SocketObserver;
|
||||
use Ratchet\Command\Factory;
|
||||
use Ratchet\Command\CommandInterface;
|
||||
use Ratchet\Command\Action\SendMessage;
|
||||
use Ratchet\Command\Composite;
|
||||
use Ratchet\Protocol\WebSocket\Util\HTTP;
|
||||
|
||||
/**
|
||||
@ -15,8 +15,14 @@ use Ratchet\Protocol\WebSocket\Util\HTTP;
|
||||
* @link http://ca.php.net/manual/en/ref.http.php
|
||||
* @todo Make sure this works both ways (client/server) as stack needs to exist on client for framing
|
||||
* @todo Make sure all SendMessage Commands are framed, not just ones received from onRecv
|
||||
* @todo Learn about closing the socket. A message has to be sent prior to closing - does the message get sent onClose event or CloseConnection command?
|
||||
*/
|
||||
class WebSocket implements ProtocolInterface {
|
||||
/**
|
||||
* @var Ratchet\Command\Factory
|
||||
*/
|
||||
protected $_factory;
|
||||
|
||||
/**
|
||||
* Lookup for connected clients
|
||||
* @type SplObjectStorage
|
||||
@ -40,6 +46,7 @@ class WebSocket implements ProtocolInterface {
|
||||
public function __construct(SocketObserver $application) {
|
||||
$this->_clients = new \SplObjectStorage;
|
||||
$this->_app = $application;
|
||||
$this->_factory = new Factory;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -83,12 +90,8 @@ class WebSocket implements ProtocolInterface {
|
||||
$header = $response;
|
||||
}
|
||||
|
||||
$cmds = new Composite;
|
||||
$mess = new SendMessage($from);
|
||||
$mess->setMessage($header);
|
||||
$cmds->enqueue($mess);
|
||||
|
||||
return $cmds;
|
||||
// here, need to send headers/handshake to application, let it have the cookies, etc
|
||||
return $this->_factory->newCommand('SendMessage', $from)->setMessage($header);
|
||||
}
|
||||
|
||||
try {
|
||||
@ -97,26 +100,11 @@ class WebSocket implements ProtocolInterface {
|
||||
$msg = $msg['payload'];
|
||||
}
|
||||
} catch (\UnexpectedValueException $e) {
|
||||
$cmd = new Composite;
|
||||
$close = new \Ratchet\Command\Action\CloseConnection($from); // This is to change to Disconnect (proper protocol close)
|
||||
$cmd->enqueue($close);
|
||||
|
||||
return $cmd;
|
||||
return $this->_factory->newCommand('CloseConnection', $from);
|
||||
}
|
||||
|
||||
$cmds = $this->_app->onRecv($from, $msg);
|
||||
if ($cmds instanceof Composite) {
|
||||
foreach ($cmds as $cmd) {
|
||||
if ($cmd instanceof SendMessage) {
|
||||
$sock = $cmd->_socket; // bad
|
||||
$clnt = $this->_clients[$sock];
|
||||
|
||||
$cmd->setMessage($clnt->getVersion()->frame($cmd->getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $cmds;
|
||||
return $this->prepareCommand($cmds);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,16 +123,23 @@ class WebSocket implements ProtocolInterface {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \Ratchet\Command\CommandInterface
|
||||
* @param Version\VersionInterface
|
||||
* @return \Ratchet\Command\CommandInterface
|
||||
* Checks if a return Command from your application is a message, if so encode it/them
|
||||
* @param Ratchet\Command\CommandInterface|NULL
|
||||
* @return Ratchet\Command\CommandInterface|NULL
|
||||
*/
|
||||
protected function prepareCommand(CommandInterface $cmd, VersionInterface $version) {
|
||||
if ($cmd instanceof SendMessage) {
|
||||
$cmd->setMessage($version->frame($cmd->getMessage()));
|
||||
protected function prepareCommand(CommandInterface $command = null) {
|
||||
if ($command instanceof SendMessage) {
|
||||
$version = $this->_clients[$command->getSocket()]->getVersion();
|
||||
return $command->setMessage($version->frame($command->getMessage()));
|
||||
}
|
||||
|
||||
return $cmd;
|
||||
if ($command instanceof \Traversable) {
|
||||
foreach ($command as $cmd) {
|
||||
$cmd = $this->prepareCommand($cmd);
|
||||
}
|
||||
}
|
||||
|
||||
return $command;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user