diff --git a/lib/Ratchet/Command/Action/CloseConnection.php b/lib/Ratchet/Command/Action/CloseConnection.php index dfbf540..46fed4e 100644 --- a/lib/Ratchet/Command/Action/CloseConnection.php +++ b/lib/Ratchet/Command/Action/CloseConnection.php @@ -1,25 +1,15 @@ _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; } diff --git a/lib/Ratchet/Command/Action/Null.php b/lib/Ratchet/Command/Action/Null.php index cd8f8e0..775641d 100644 --- a/lib/Ratchet/Command/Action/Null.php +++ b/lib/Ratchet/Command/Action/Null.php @@ -1,16 +1,12 @@ _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()); } } \ No newline at end of file diff --git a/lib/Ratchet/Command/Action/SendMessage.php b/lib/Ratchet/Command/Action/SendMessage.php index 9678aac..de02bd7 100644 --- a/lib/Ratchet/Command/Action/SendMessage.php +++ b/lib/Ratchet/Command/Action/SendMessage.php @@ -1,27 +1,17 @@ _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)); } } \ No newline at end of file diff --git a/lib/Ratchet/Command/ActionInterface.php b/lib/Ratchet/Command/ActionInterface.php index 9e5153e..be675c9 100644 --- a/lib/Ratchet/Command/ActionInterface.php +++ b/lib/Ratchet/Command/ActionInterface.php @@ -8,4 +8,9 @@ interface ActionInterface extends CommandInterface { * @param Ratchet\SocketInterface */ function __construct(SocketInterface $socket); + + /** + * @return Ratchet\SocketInterface + */ + function getSocket(); } \ No newline at end of file diff --git a/lib/Ratchet/Command/ActionTemplate.php b/lib/Ratchet/Command/ActionTemplate.php new file mode 100644 index 0000000..3c49019 --- /dev/null +++ b/lib/Ratchet/Command/ActionTemplate.php @@ -0,0 +1,18 @@ +_socket = $socket; + } + + public function getSocket() { + return $this->_socket; + } +} \ No newline at end of file diff --git a/lib/Ratchet/Command/CommandInterface.php b/lib/Ratchet/Command/CommandInterface.php index b1b6524..b29cc96 100644 --- a/lib/Ratchet/Command/CommandInterface.php +++ b/lib/Ratchet/Command/CommandInterface.php @@ -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); } \ No newline at end of file diff --git a/lib/Ratchet/Command/Composite.php b/lib/Ratchet/Command/Composite.php index 670a323..1472719 100644 --- a/lib/Ratchet/Command/Composite.php +++ b/lib/Ratchet/Command/Composite.php @@ -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) { diff --git a/lib/Ratchet/Protocol/WebSocket.php b/lib/Ratchet/Protocol/WebSocket.php index 3445e8a..804ab6b 100644 --- a/lib/Ratchet/Protocol/WebSocket.php +++ b/lib/Ratchet/Protocol/WebSocket.php @@ -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; } /**