public function subscribe($name, $id = null, $callback = null, $timeout = null, $failswitch = false)
{
$self = $this;
if (!is_string($name)) {
throw new TypeError('topic name must be a string');
}
if (is_callable($id) && !is_callable($callback)) {
$timeout = $callback;
$callback = $id;
$id = null;
}
if (!is_callable($callback)) {
throw new TypeError('callback must be a function.');
}
if (!isset($this->topics[$name])) {
$this->topics[$name] = array();
}
if ($id === null) {
if ($this->id == null) {
$this->id = $this->autoId();
}
$this->id->then(function ($id) use($self, $name, $callback, $timeout, $failswitch) {
$self->subscribe($name, $id, $callback, $timeout, $failswitch);
});
return;
}
if (!is_int($timeout)) {
$timeout = $this->timeout;
}
$topic = $this->getTopic($name, $id);
if ($topic === null) {
$topic = new stdClass();
$settings = new InvokeSettings(array('idempotent' => true, 'failswitch' => $failswitch, 'timeout' => $timeout));
$cb = function () use($self, &$cb, $topic, $name, $id, $settings) {
$args = array($id);
$self->invoke($name, $args, $settings)->then($topic->handler, $cb);
};
$topic->handler = function ($result) use($self, $name, $id, $cb) {
$topic = $self->getTopic($name, $id);
if ($topic !== null) {
if ($result !== null) {
$callbacks = $topic->callbacks;
foreach ($callbacks as $callback) {
try {
call_user_func($callback, $result);
} catch (Exception $ex) {
} catch (Throwable $ex) {
}
}
}
if ($self->getTopic($name, $id) !== null) {
$cb();
}
}
};
$topic->callbacks = array($callback);
$this->topics[$name][$id] = $topic;
$cb();
} elseif (array_search($callback, $topic->callbacks, true) === false) {
$topic->callbacks[] = $callback;
}
}