/** * Bind event or events * @param string|array $event Event name * @param callable $cb Callback * @return this */ public function bind($event, $cb) { if ($cb !== null) { $cb = CallbackWrapper::wrap($cb); } is_array($event) or $event = [$event]; foreach ($event as $e) { CallbackWrapper::addToArray($this->eventHandlers[$e], $cb); } return $this; }
/** * @TODO * @param string $name * @param array $args * @param callable $cb * @callback $cb ( ) * @return void */ public function command($name, $args, $cb = null) { if ($name === 'MULTI') { $this->acquire(); } elseif (substr($name, -9) === 'SUBSCRIBE') { if (!$this->subscribed) { $this->subscribed = true; $this->pool->servConnSub[$this->url] = $this; $this->acquire(); $this->setTimeouts(86400, 86400); // @TODO: remove timeout } $opcb = null; for ($i = sizeof($args) - 1; $i >= 0; --$i) { $a = $args[$i]; if ((is_array($a) || is_object($a)) && is_callable($a)) { $opcb = $cb; $cb = CallbackWrapper::wrap($a); $args = array_slice($args, 0, $i); break; } elseif ($a !== null) { break; } } } if ($name === 'SUBSCRIBE') { $this->subscribed(); $channels = []; foreach ($args as $arg) { if (!is_array($arg)) { $arg = [$arg]; } foreach ($arg as $chan) { $b = !isset($this->subscribeCb[$chan]); CallbackWrapper::addToArray($this->subscribeCb[$chan], $cb); if ($b) { $channels[] = $chan; } else { if ($opcb !== null) { call_user_func($opcb, $this); } } } } if (sizeof($channels)) { $this->sendCommand($name, $channels, $opcb); } } elseif ($name === 'PSUBSCRIBE') { $this->subscribed(); $channels = []; foreach ($args as $arg) { if (!is_array($arg)) { $arg = [$arg]; } foreach ($arg as $chan) { $b = !isset($this->psubscribeCb[$chan]); CallbackWrapper::addToArray($this->psubscribeCb[$chan], $cb); if ($b) { $channels[] = $chan; } else { if ($opcb !== null) { call_user_func($opcb, $this); } } } } if (sizeof($channels)) { $this->sendCommand($name, $channels, $opcb); } } elseif ($name === 'UNSUBSCRIBE') { $channels = []; foreach ($args as $arg) { if (!is_array($arg)) { $arg = [$arg]; } foreach ($arg as $chan) { if (!isset($this->subscribeCb[$chan])) { if ($opcb !== null) { call_user_func($opcb, $this); } return; } CallbackWrapper::removeFromArray($this->subscribeCb[$chan], $cb); if (sizeof($this->subscribeCb[$chan]) === 0) { $channels[] = $chan; unset($this->subscribeCb[$chan]); } else { if ($opcb !== null) { call_user_func($opcb, $this); } } } } if (sizeof($channels)) { $this->sendCommand($name, $channels, $opcb); } } elseif ($name === 'UNSUBSCRIBEREAL') { /* Race-condition-free UNSUBSCRIBE */ $old = $this->subscribeCb; $this->sendCommand('UNSUBSCRIBE', $args, function ($redis) use($cb, $args, $old) { if (!$redis) { call_user_func($cb, $redis); return; } foreach ($args as $arg) { if (!isset($this->subscribeCb[$arg])) { continue; } foreach ($old[$arg] as $oldcb) { CallbackWrapper::removeFromArray($this->subscribeCb[$arg], $oldcb); } if (!sizeof($this->subscribeCb[$arg])) { unset($this->subscribeCb[$arg]); } } if ($cb !== null) { call_user_func($cb, $this); } }); } elseif ($name === 'PUNSUBSCRIBE') { $channels = []; foreach ($args as $arg) { if (!is_array($arg)) { $arg = [$arg]; } foreach ($arg as $chan) { CallbackWrapper::removeFromArray($this->psubscribeCb[$chan], $cb); if (sizeof($this->psubscribeCb[$chan]) === 0) { $channels[] = $chan; unset($this->psubscribeCb[$chan]); } else { if ($opcb !== null) { call_user_func($opcb, $this); } } } } if (sizeof($channels)) { $this->sendCommand($name, $channels, $opcb); } } elseif ($name === 'PUNSUBSCRIBEREAL') { /* Race-condition-free PUNSUBSCRIBE */ $old = $this->psubscribeCb; $this->sendCommand('PUNSUBSCRIBE', $args, function ($redis) use($cb, $args, $old) { if (!$redis) { call_user_func($cb, $redis); return; } foreach ($args as $arg) { if (!isset($this->psubscribeCb[$arg])) { continue; } foreach ($old[$arg] as $oldcb) { CallbackWrapper::removeFromArray($this->psubscribeCb[$arg], $oldcb); } if (!sizeof($this->psubscribeCb[$arg])) { unset($this->psubscribeCb[$arg]); } } if ($cb !== null) { call_user_func($cb, $this); } }); } else { if ($name === 'MGET') { $this->resultTypeStack->push(static::RESULT_TYPE_ARGSVALS); $this->argsStack->push($args); } elseif ($name === 'HMGET') { $this->resultTypeStack->push(static::RESULT_TYPE_ARGSVALS); $a = $args; array_shift($a); $this->argsStack->push($a); } elseif ($name === 'HGETALL') { $this->resultTypeStack->push(static::RESULT_TYPE_ASSOC); } elseif (($name === 'ZRANGE' || $name === 'ZRANGEBYSCORE' || $name === 'ZREVRANGE' || $name === 'ZREVRANGEBYSCORE') && preg_grep('/WITHSCORES/i', $args)) { $this->resultTypeStack->push(static::RESULT_TYPE_ASSOC); } else { $this->resultTypeStack->push(static::RESULT_TYPE_DEFAULT); } $this->sendCommand($name, $args, $cb); if ($name === 'EXEC' || $name === 'DISCARD') { $this->release(); } } }