KeyPrefixPreprocessor.php 6.3 KB

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