KeyPrefixProcessor.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <?php
  2. namespace Predis\Commands\Processors;
  3. use Predis\ClientException;
  4. use Predis\Profiles\IServerProfile;
  5. class KeyPrefixProcessor implements ICommandProcessor {
  6. private $_prefix;
  7. private $_strategies;
  8. public function __construct($prefix, IServerProfile $profile = null) {
  9. if (isset($profile)) {
  10. $this->checkProfile($profile);
  11. }
  12. $this->_prefix = $prefix;
  13. $this->_strategies = $this->getPrefixStrategies();
  14. }
  15. protected function checkProfile(IServerProfile $profile) {
  16. if (!in_array($profile, $this->getSupportedProfiles())) {
  17. throw new ClientException("Unsupported profile: $profile");
  18. }
  19. }
  20. protected function getSupportedProfiles() {
  21. return array('1.2', '2.0', '2.2');
  22. }
  23. protected function getPrefixStrategies() {
  24. $skipLast = function(&$arguments, $prefix) {
  25. $length = count($arguments);
  26. for ($i = 0; $i < $length - 1; $i++) {
  27. $arguments[$i] = "$prefix{$arguments[$i]}";
  28. }
  29. };
  30. $interleavedKeys = function(&$arguments, $prefix) {
  31. $length = count($arguments);
  32. if ($length === 1 && is_array($arguments[0])) {
  33. $oldKvs = &$arguments[0];
  34. $newKvs = array();
  35. foreach ($oldKvs as $key => $value) {
  36. $newKvs["$prefix$key"] = $value;
  37. unset($oldKvs[$key]);
  38. }
  39. $arguments[0] = $newKvs;
  40. }
  41. else {
  42. for ($i = 0; $i < $length; $i += 2) {
  43. $arguments[$i] = "$prefix{$arguments[$i]}";
  44. }
  45. }
  46. };
  47. $zunionstore = function(&$arguments, $prefix) {
  48. $arguments[0] = "$prefix{$arguments[0]}";
  49. if (is_array($arguments[1])) {
  50. foreach ($arguments[1] as &$destinationKey) {
  51. $destinationKey = "$prefix$destinationKey";
  52. }
  53. $args = &$arguments[1];
  54. $length = count($args);
  55. for ($i = 0; $i < $length; $i++) {
  56. $arguments[1][$i] = "$prefix{$args[$i]}";
  57. }
  58. }
  59. else {
  60. $length = (int)$arguments[1];
  61. for ($i = 2; $i < $length; $i++) {
  62. $arguments[$i] = "$prefix{$arguments[$i]}";
  63. }
  64. }
  65. };
  66. $sort = function(&$arguments, $prefix) {
  67. $arguments[0] = "$prefix{$arguments[0]}";
  68. if (count($arguments) === 1) {
  69. return;
  70. }
  71. foreach ($arguments[1] as $modifier => &$value) {
  72. switch (strtoupper($modifier)) {
  73. case 'BY':
  74. case 'STORE':
  75. $value = "$prefix$value";
  76. break;
  77. case 'GET':
  78. if (is_array($value)) {
  79. foreach ($value as &$getItem) {
  80. $getItem = "$prefix$getItem";
  81. }
  82. }
  83. else {
  84. $value = "$prefix$value";
  85. }
  86. break;
  87. }
  88. }
  89. };
  90. $debug = function(&$arguments, $prefix) {
  91. if (count($arguments) === 3 && strtoupper($arguments[1]) == 'OBJECT') {
  92. $arguments[2] = "$prefix{$arguments[2]}";
  93. }
  94. };
  95. $cmdSingleKey = array(
  96. 'type', 'exists', 'move', 'expire', 'persist', 'sort', 'expireat', 'ttl', 'append',
  97. 'getrange', 'setnx', 'decr', 'getset', 'setrange', 'decrby', 'incr', 'set', 'strlen',
  98. 'get', 'incrby', 'setbit', 'getbit', 'setex', 'hdel', 'hgetall', 'hlen', 'hset',
  99. 'hexists', 'hincrby', 'hmget', 'hsetnx', 'hget', 'hkeys', 'hmset', 'hvals', 'lindex',
  100. 'linsert', 'llen', 'lpop', 'lpush', 'lpushx', 'rpushx', 'lrange', 'lrem', 'lset',
  101. 'ltrim', 'rpop', 'rpush', 'rpushx', 'sadd', 'scard', 'sismember', 'smembers', 'spop',
  102. 'srandmember', 'srem', 'zadd', 'zcard', 'zcount', 'zincrby', 'zrange', 'zrangebyscore',
  103. 'zrank', 'zrem', 'zremrangebyrank', 'zremrangebyscore', 'zrevrange', 'zrevrangebyscore',
  104. 'zrevrank', 'zscore', 'publish', 'keys',
  105. );
  106. $cmdMultiKeys = array(
  107. 'del', 'rename', 'renamenx', 'mget', 'rpoplpush', 'sdiff', 'sdiffstore', 'sinter',
  108. 'sinterstore', 'sunion', 'sunionstore', 'subscribe', 'punsubscribe', 'subscribe',
  109. 'unsubscribe', 'watch',
  110. );
  111. return array_merge(
  112. array_fill_keys($cmdSingleKey, $this->getSingleKeyStrategy()),
  113. array_fill_keys($cmdMultiKeys, $this->getMultipleKeysStrategy()),
  114. array(
  115. 'blpop' => $skipLast, 'brpop' => $skipLast, 'brpoplpush' => $skipLast, 'smove' => $skipLast,
  116. 'mset' => $interleavedKeys, 'msetnx' => $interleavedKeys,
  117. 'zinterstore' => $zunionstore, 'zunionstore' => $zunionstore,
  118. 'sort' => $sort, 'debug' => $debug
  119. )
  120. );
  121. }
  122. public function setPrefixStrategy($command, $strategy) {
  123. if (!is_callable($callable)) {
  124. throw new \InvalidArgumentException(
  125. 'The command preprocessor strategy must be a callable object'
  126. );
  127. }
  128. $this->_strategies[$command] = $strategy;
  129. }
  130. public function getSingleKeyStrategy() {
  131. return function(&$arguments, $prefix) {
  132. $arguments[0] = "$prefix{$arguments[0]}";
  133. };
  134. }
  135. public function getMultipleKeysStrategy() {
  136. return function(&$arguments, $prefix) {
  137. if (count($arguments) === 1 && is_array($arguments[0])) {
  138. $arguments = &$arguments[0];
  139. }
  140. foreach ($arguments as &$key) {
  141. $key = "$prefix$key";
  142. }
  143. };
  144. }
  145. public function getPrefixStrategy($command) {
  146. if (isset($this->_strategies[$command])) {
  147. return $this->_strategies[$command];
  148. }
  149. }
  150. public function setPrefix($prefix) {
  151. $this->_prefix = $prefix;
  152. }
  153. public function getPrefix() {
  154. return $this->_prefix;
  155. }
  156. public function process($method, &$arguments) {
  157. if (isset($this->_strategies[$method])) {
  158. $this->_strategies[$method]($arguments, $this->_prefix);
  159. }
  160. }
  161. }