Hoa central
Handler.php
Go to the documentation of this file.
1 <?php
2 
37 namespace Hoa\Socket\Connection;
38 
39 use Hoa\Socket;
40 
51 abstract class Handler
52 {
58  protected $_originalConnection = null;
59 
65  protected $_connection = null;
66 
72  protected $_connections = [];
73 
74 
75 
82  public function __construct(Connection $connection)
83  {
84  $this->_originalConnection = $connection;
85  $this->setConnection($connection);
86 
87  return;
88  }
89 
96  protected function setConnection(Connection $connection)
97  {
98  $old = $this->_connection;
99  $this->_connection = $connection;
100 
101  return $old;
102  }
103 
109  protected function getOriginalConnection()
110  {
112  }
113 
119  public function getConnection()
120  {
121  return $this->_connection;
122  }
123 
136  abstract protected function _run(Socket\Node $node);
137 
143  public function run()
144  {
145  $connection = $this->getConnection();
146 
147  if ($connection instanceof Socket\Server) {
148  $connection->connectAndWait();
149  } else {
150  $connection->connect();
151  }
152 
153  while (true) {
154  foreach ($connection->select() as $node) {
155 
156  // Connection has failed to detect the node, maybe it is a resource
157  // from a merged client in a server.
158  if (false === is_object($node)) {
159  $socket = $node;
160 
161  foreach ($this->_connections as $other) {
162  $otherConnection = $other->getOriginalConnection();
163 
164  if (!($otherConnection instanceof Socket\Client)) {
165  continue;
166  }
167 
168  $node = $otherConnection->getCurrentNode();
169 
170  if ($node->getSocket() === $socket) {
171  $other->_run($node);
172 
173  continue 2;
174  }
175  }
176  }
177 
178  foreach ($this->_connections as $other) {
179  if (true === $connection->is($other->getOriginalConnection())) {
180  $other->_run($node);
181 
182  continue 2;
183  }
184  }
185 
186  $this->_run($node);
187  }
188  }
189 
190  $connection->disconnect();
191 
192  return;
193  }
194 
205  public function merge(self $other)
206  {
207  $thisConnection = $this->getConnection();
208  $otherConnection = $other->getConnection();
209 
210  $thisConnection->consider($otherConnection);
211 
212  if ($otherConnection instanceof Socket\Server) {
213  $other->setConnection($thisConnection);
214  }
215 
216  $this->_connections[] = $other;
217 
218  return $this;
219  }
220 
230  abstract protected function _send($message, Socket\Node $node);
231 
240  public function send($message, Socket\Node $node = null)
241  {
242  if (null === $node) {
243  $node = $this->getConnection()->getCurrentNode();
244  }
245 
246  if (null === $node) {
247  return null;
248  }
249 
250  $old = $this->getConnection()->_setStream($node->getSocket());
251  $send = $this->_send($message, $node);
252 
253  if ($send instanceof \Closure) {
254  $self = $this;
255 
256  return function () use (&$send, &$old, &$self) {
257  $out = call_user_func_array($send, func_get_args());
258  $self->getConnection()->_setStream($old);
259 
260  return $out;
261  };
262  }
263 
264  $this->getConnection()->_setStream($old);
265 
266  return $send;
267  }
268 
277  public function broadcast($message)
278  {
279  $currentNode = $this->getConnection()->getCurrentNode();
280  $arguments = func_get_args();
281  array_unshift(
282  $arguments,
283  function (Socket\Node $node) use ($currentNode) {
284  return $node !== $currentNode;
285  }
286  );
287 
288  return call_user_func_array([$this, 'broadcastIf'], $arguments);
289  }
290 
299  public function broadcastIf(\Closure $predicate, $message)
300  {
301  $connection = $this->getConnection();
302  $currentSocket = $this->getOriginalConnection()->getSocket();
303 
304  if (1 === func_num_args()) {
305  foreach ($connection->getNodes() as $node) {
306  if (true === $predicate($node) &&
307  $node->getConnection()->getSocket() === $currentSocket) {
308  $this->send($message, $node);
309  }
310  }
311 
312  return;
313  }
314 
315  $arguments = array_slice(func_get_args(), 2);
316  array_unshift($arguments, $message, null);
317  $callable = [$this, 'send'];
318 
319  foreach ($connection->getNodes() as $node) {
320  if (true === $predicate($node) &&
321  $node->getConnection()->getSocket() === $currentSocket) {
322  $arguments[1] = $node;
323  call_user_func_array($callable, $arguments);
324  }
325  }
326 
327  return;
328  }
329 }
__construct(Connection $connection)
Definition: Handler.php:82
broadcastIf(\Closure $predicate, $message)
Definition: Handler.php:299
setConnection(Connection $connection)
Definition: Handler.php:96
send($message, Socket\Node $node=null)
Definition: Handler.php:240
_send($message, Socket\Node $node)
_run(Socket\Node $node)