/** * Shared between increment/decrement: both have mostly the same logic * (decrement just increments a negative value), but need their validation * & use of non-ttl native methods split up. * * @param string $key * @param int $offset * @param int $initial * @param int $expire * * @return int|bool */ protected function doIncrement($key, $offset, $initial, $expire) { $ttl = $this->ttl($expire); $this->client->watch($key); $value = $this->client->get($key); if ($value === false) { /* * Negative ttl behavior isn't properly documented & doesn't always * appear to treat the value as non-existing. Let's play safe and not * even create the value (also saving a request) */ if ($ttl < 0) { return true; } // value is not yet set, store initial value! $this->client->multi(); $this->client->set($key, $initial, $ttl); /** @var bool[] $return */ $return = (array) $this->client->exec(); return !in_array(false, $return) ? $initial : false; } // can't increment if a non-numeric value is set if (!is_numeric($value) || $value < 0) { /* * HHVM Redis only got unwatch recently. * @see https://github.com/asgrim/hhvm/commit/bf5a259cece5df8a7617133c85043608d1ad5316 */ if (method_exists($this->client, 'unwatch')) { $this->client->unwatch(); } else { // this should also kill the watch... $this->client->multi()->discard(); } return false; } $value += $offset; // value can never be lower than 0 $value = max(0, $value); $this->client->multi(); /* * Negative ttl behavior isn't properly documented & doesn't always * appear to treat the value as non-existing. Let's play safe and just * delete it right away! */ if ($ttl < 0) { $this->client->del($key); } else { $this->client->set($key, $value, $ttl); } /** @var bool[] $return */ $return = (array) $this->client->exec(); return !in_array(false, $return) ? $value : false; }