Credis_Client::__call PHP Method

__call() public method

public __call ( $name, $args )
    public function __call($name, $args)
    {
        // Lazy connection
        $this->connect();
        $name = strtolower($name);
        // Send request via native PHP
        if ($this->standalone) {
            switch ($name) {
                case 'eval':
                case 'evalsha':
                    $script = array_shift($args);
                    $keys = (array) array_shift($args);
                    $eArgs = (array) array_shift($args);
                    $args = array($script, count($keys), $keys, $eArgs);
                    break;
                case 'set':
                    // The php redis module has different behaviour with ttl
                    // https://github.com/phpredis/phpredis#set
                    if (count($args) === 3 && is_int($args[2])) {
                        $args = array($args[0], $args[1], array('EX', $args[2]));
                    } elseif (count($args) === 3 && is_array($args[2])) {
                        $tmp_args = $args;
                        $args = array($tmp_args[0], $tmp_args[1]);
                        foreach ($tmp_args[2] as $k => $v) {
                            if (is_string($k)) {
                                $args[] = array($k, $v);
                            } elseif (is_int($k)) {
                                $args[] = $v;
                            }
                        }
                        unset($tmp_args);
                    }
                    break;
                case 'scan':
                    $ref =& $args[0];
                    if (empty($ref)) {
                        $ref = 0;
                    }
                    $eArgs = array($ref);
                    if (!empty($args[1])) {
                        $eArgs[] = 'MATCH';
                        $eArgs[] = $args[1];
                    }
                    if (!empty($args[2])) {
                        $eArgs[] = 'COUNT';
                        $eArgs[] = $args[2];
                    }
                    $args = $eArgs;
                    break;
                case 'sscan':
                case 'zscan':
                case 'hscan':
                    $ref =& $args[1];
                    if (empty($ref)) {
                        $ref = 0;
                    }
                    $eArgs = array($args[0], $ref);
                    if (!empty($args[2])) {
                        $eArgs[] = 'MATCH';
                        $eArgs[] = $args[2];
                    }
                    if (!empty($args[3])) {
                        $eArgs[] = 'COUNT';
                        $eArgs[] = $args[4];
                    }
                    $args = $eArgs;
                    break;
                case 'zrangebyscore':
                case 'zrevrangebyscore':
                case 'zrange':
                case 'zrevrange':
                    if (isset($args[3]) && is_array($args[3])) {
                        // map options
                        $cArgs = array();
                        if (!empty($args[3]['withscores'])) {
                            $cArgs[] = 'withscores';
                        }
                        if (($name == 'zrangebyscore' || $name == 'zrevrangebyscore') && array_key_exists('limit', $args[3])) {
                            $cArgs[] = array('limit' => $args[3]['limit']);
                        }
                        $args[3] = $cArgs;
                    }
                    break;
            }
            // Flatten arguments
            $args = self::_flattenArguments($args);
            // In pipeline mode
            if ($this->usePipeline) {
                if ($name == 'pipeline') {
                    throw new CredisException('A pipeline is already in use and only one pipeline is supported.');
                } else {
                    if ($name == 'exec') {
                        if ($this->isMulti) {
                            $this->commandNames[] = $name;
                            $this->commands .= self::_prepare_command(array($this->getRenamedCommand($name)));
                        }
                        // Write request
                        if ($this->commands) {
                            $this->write_command($this->commands);
                        }
                        $this->commands = NULL;
                        // Read response
                        $response = array();
                        foreach ($this->commandNames as $command) {
                            $response[] = $this->read_reply($command);
                        }
                        $this->commandNames = NULL;
                        if ($this->isMulti) {
                            $response = array_pop($response);
                        }
                        $this->usePipeline = $this->isMulti = FALSE;
                        return $response;
                    } else {
                        if ($name == 'multi') {
                            $this->isMulti = TRUE;
                        }
                        array_unshift($args, $this->getRenamedCommand($name));
                        $this->commandNames[] = $name;
                        $this->commands .= self::_prepare_command($args);
                        return $this;
                    }
                }
            }
            // Start pipeline mode
            if ($name == 'pipeline') {
                $this->usePipeline = TRUE;
                $this->commandNames = array();
                $this->commands = '';
                return $this;
            }
            // If unwatching, allow reconnect with no error thrown
            if ($name == 'unwatch') {
                $this->isWatching = FALSE;
            }
            // Non-pipeline mode
            array_unshift($args, $this->getRenamedCommand($name));
            $command = self::_prepare_command($args);
            $this->write_command($command);
            $response = $this->read_reply($name);
            switch ($name) {
                case 'scan':
                case 'sscan':
                    $ref = array_shift($response);
                    $response = empty($response[0]) ? array() : $response[0];
                    break;
                case 'hscan':
                case 'zscan':
                    $ref = array_shift($response);
                    $response = empty($response[0]) ? array() : $response[0];
                    if (!empty($response) && is_array($response)) {
                        $count = count($response);
                        $out = array();
                        for ($i = 0; $i < $count; $i += 2) {
                            $out[$response[$i]] = $response[$i + 1];
                        }
                        $response = $out;
                    }
                    break;
                case 'zrangebyscore':
                case 'zrevrangebyscore':
                    if (in_array('withscores', $args, true)) {
                        // Map array of values into key=>score list like phpRedis does
                        $item = null;
                        $out = array();
                        foreach ($response as $value) {
                            if ($item == null) {
                                $item = $value;
                            } else {
                                // 2nd value is the score
                                $out[$item] = (double) $value;
                                $item = null;
                            }
                        }
                        $response = $out;
                    }
                    break;
            }
            // Watch mode disables reconnect so error is thrown
            if ($name == 'watch') {
                $this->isWatching = TRUE;
            } else {
                if ($this->isMulti && ($name == 'exec' || $name == 'discard')) {
                    $this->isMulti = FALSE;
                } else {
                    if ($this->isMulti || $name == 'multi') {
                        $this->isMulti = TRUE;
                        $response = $this;
                    }
                }
            }
        } else {
            // Tweak arguments
            switch ($name) {
                case 'get':
                    // optimize common cases
                // optimize common cases
                case 'set':
                case 'hget':
                case 'hset':
                case 'setex':
                case 'mset':
                case 'msetnx':
                case 'hmset':
                case 'hmget':
                case 'del':
                case 'zrangebyscore':
                case 'zrevrangebyscore':
                case 'zrange':
                case 'zrevrange':
                    break;
                case 'mget':
                    if (isset($args[0]) && !is_array($args[0])) {
                        $args = array($args);
                    }
                    break;
                case 'lrem':
                    $args = array($args[0], $args[2], $args[1]);
                    break;
                case 'eval':
                case 'evalsha':
                    if (isset($args[1]) && is_array($args[1])) {
                        $cKeys = $args[1];
                    } elseif (isset($args[1]) && is_string($args[1])) {
                        $cKeys = array($args[1]);
                    } else {
                        $cKeys = array();
                    }
                    if (isset($args[2]) && is_array($args[2])) {
                        $cArgs = $args[2];
                    } elseif (isset($args[2]) && is_string($args[2])) {
                        $cArgs = array($args[2]);
                    } else {
                        $cArgs = array();
                    }
                    $args = array($args[0], array_merge($cKeys, $cArgs), count($cKeys));
                    break;
                case 'subscribe':
                case 'psubscribe':
                    break;
                case 'scan':
                case 'sscan':
                case 'hscan':
                case 'zscan':
                    // allow phpredis to see the caller's reference
                    //$param_ref =& $args[0];
                    break;
                default:
                    // Flatten arguments
                    $args = self::_flattenArguments($args);
            }
            try {
                // Proxy pipeline mode to the phpredis library
                if ($name == 'pipeline' || $name == 'multi') {
                    if ($this->isMulti) {
                        return $this;
                    } else {
                        $this->isMulti = TRUE;
                        $this->redisMulti = call_user_func_array(array($this->redis, $name), $args);
                        return $this;
                    }
                } else {
                    if ($name == 'exec' || $name == 'discard') {
                        $this->isMulti = FALSE;
                        $response = $this->redisMulti->{$name}();
                        $this->redisMulti = NULL;
                        #echo "> $name : ".substr(print_r($response, TRUE),0,100)."\n";
                        return $response;
                    }
                }
                // Use aliases to be compatible with phpredis wrapper
                if (isset($this->wrapperMethods[$name])) {
                    $name = $this->wrapperMethods[$name];
                }
                // Multi and pipeline return self for chaining
                if ($this->isMulti) {
                    call_user_func_array(array($this->redisMulti, $name), $args);
                    return $this;
                }
                // Send request, retry one time when using persistent connections on the first request only
                $this->requests++;
                try {
                    $response = call_user_func_array(array($this->redis, $name), $args);
                } catch (RedisException $e) {
                    if ($this->persistent && $this->requests == 1 && $e->getMessage() == 'read error on connection') {
                        $this->connected = FALSE;
                        $this->connect();
                        $response = call_user_func_array(array($this->redis, $name), $args);
                    } else {
                        throw $e;
                    }
                }
            } catch (RedisException $e) {
                $code = 0;
                if (!($result = $this->redis->IsConnected())) {
                    $this->connected = FALSE;
                    $code = CredisException::CODE_DISCONNECTED;
                }
                throw new CredisException($e->getMessage(), $code, $e);
            }
            #echo "> $name : ".substr(print_r($response, TRUE),0,100)."\n";
            // change return values where it is too difficult to minim in standalone mode
            switch ($name) {
                case 'hmget':
                    $response = array_values($response);
                    break;
                case 'type':
                    $typeMap = array(self::TYPE_NONE, self::TYPE_STRING, self::TYPE_SET, self::TYPE_LIST, self::TYPE_ZSET, self::TYPE_HASH);
                    $response = $typeMap[$response];
                    break;
                    // Handle scripting errors
                // Handle scripting errors
                case 'eval':
                case 'evalsha':
                case 'script':
                    $error = $this->redis->getLastError();
                    $this->redis->clearLastError();
                    if ($error && substr($error, 0, 8) == 'NOSCRIPT') {
                        $response = NULL;
                    } else {
                        if ($error) {
                            throw new CredisException($error);
                        }
                    }
                    break;
                default:
                    $error = $this->redis->getLastError();
                    $this->redis->clearLastError();
                    if ($error) {
                        throw new CredisException($error);
                    }
                    break;
            }
        }
        return $response;
    }