Files
predis/lib/Predis/PubSub/DispatcherLoop.php
T
Eloi Poch 6cd124cc59 Fix DispatcherLoop error with client prefix keys
DispatcherLoop works properly if a client have configured a
prefix for the keys or not
2013-04-20 13:02:17 +02:00

168 lines
4.2 KiB
PHP

<?php
/*
* This file is part of the Predis package.
*
* (c) Daniele Alessandri <suppakilla@gmail.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Predis\PubSub;
use Predis\ClientInterface;
/**
* Method-dispatcher loop built around the client-side abstraction of a Redis
* Publish / Subscribe context.
*
* @author Daniele Alessandri <suppakilla@gmail.com>
*/
class DispatcherLoop
{
private $client;
private $pubSubContext;
private $callbacks;
private $defaultCallback;
private $subscriptionCallback;
/**
* @param ClientInterface Client instance used by the context.
*/
public function __construct(ClientInterface $client)
{
$this->callbacks = array();
$this->client = $client;
$this->pubSubContext = $client->pubSub();
}
/**
* Checks if the passed argument is a valid callback.
*
* @param mixed A callback.
*/
protected function validateCallback($callable)
{
if (!is_callable($callable)) {
throw new \InvalidArgumentException("A valid callable object must be provided");
}
}
/**
* Returns the underlying Publish / Subscribe context.
*
* @return PubSubContext
*/
public function getPubSubContext()
{
return $this->pubSubContext;
}
/**
* Sets a callback that gets invoked upon new subscriptions.
*
* @param mixed $callable A callback.
*/
public function subscriptionCallback($callable = null)
{
if (isset($callable)) {
$this->validateCallback($callable);
}
$this->subscriptionCallback = $callable;
}
/**
* Sets a callback that gets invoked when a message is received on a
* channel that does not have an associated callback.
*
* @param mixed $callable A callback.
*/
public function defaultCallback($callable = null)
{
if (isset($callable)) {
$this->validateCallback($callable);
}
$this->subscriptionCallback = $callable;
}
/**
* Binds a callback to a channel.
*
* @param string $channel Channel name.
* @param Callable $callback A callback.
*/
public function attachCallback($channel, $callback)
{
$callbackName = $this->getPrefixKeys() . $channel;
$this->validateCallback($callback);
$this->callbacks[$callbackName] = $callback;
$this->pubSubContext->subscribe($channel);
}
/**
* Stops listening to a channel and removes the associated callback.
*
* @param string $channel Redis channel.
*/
public function detachCallback($channel)
{
$callbackName = $this->getPrefixKeys() . $channel;
if (isset($this->callbacks[$callbackName])) {
unset($this->callbacks[$callbackName]);
$this->pubSubContext->unsubscribe($channel);
}
}
/**
* Starts the dispatcher loop.
*/
public function run()
{
foreach ($this->pubSubContext as $message) {
$kind = $message->kind;
if ($kind !== PubSubContext::MESSAGE && $kind !== PubSubContext::PMESSAGE) {
if (isset($this->subscriptionCallback)) {
$callback = $this->subscriptionCallback;
call_user_func($callback, $message);
}
continue;
}
if (isset($this->callbacks[$message->channel])) {
$callback = $this->callbacks[$message->channel];
call_user_func($callback, $message->payload);
} else if (isset($this->defaultCallback)) {
$callback = $this->defaultCallback;
call_user_func($callback, $message);
}
}
}
/**
* Terminates the dispatcher loop.
*/
public function stop()
{
$this->pubSubContext->closeContext();
}
/**
* Return the prefix of the keys
*
* @return string
*/
protected function getPrefixKeys()
{
$prefix = $this->client->getOptions()->prefix;
return $prefix ? $prefix->getPrefix() : '';
}
}