Redis.php 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. <?php
  2. namespace OAuth\Common\Storage;
  3. use OAuth\Common\Token\TokenInterface;
  4. use OAuth\Common\Storage\Exception\TokenNotFoundException;
  5. use OAuth\Common\Storage\Exception\AuthorizationStateNotFoundException;
  6. use Predis\Client as Predis;
  7. /*
  8. * Stores a token in a Redis server. Requires the Predis library available at https://github.com/nrk/predis
  9. */
  10. class Redis implements TokenStorageInterface
  11. {
  12. /**
  13. * @var string
  14. */
  15. protected $key;
  16. protected $stateKey;
  17. /**
  18. * @var object|\Redis
  19. */
  20. protected $redis;
  21. /**
  22. * @var object|TokenInterface
  23. */
  24. protected $cachedTokens;
  25. /**
  26. * @var object
  27. */
  28. protected $cachedStates;
  29. /**
  30. * @param Predis $redis An instantiated and connected redis client
  31. * @param string $key The key to store the token under in redis
  32. * @param string $stateKey The key to store the state under in redis.
  33. */
  34. public function __construct(Predis $redis, $key, $stateKey)
  35. {
  36. $this->redis = $redis;
  37. $this->key = $key;
  38. $this->stateKey = $stateKey;
  39. $this->cachedTokens = array();
  40. $this->cachedStates = array();
  41. }
  42. /**
  43. * {@inheritDoc}
  44. */
  45. public function retrieveAccessToken($service)
  46. {
  47. if (!$this->hasAccessToken($service)) {
  48. throw new TokenNotFoundException('Token not found in redis');
  49. }
  50. if (isset($this->cachedTokens[$service])) {
  51. return $this->cachedTokens[$service];
  52. }
  53. $val = $this->redis->hget($this->key, $service);
  54. return $this->cachedTokens[$service] = unserialize($val);
  55. }
  56. /**
  57. * {@inheritDoc}
  58. */
  59. public function storeAccessToken($service, TokenInterface $token)
  60. {
  61. // (over)write the token
  62. $this->redis->hset($this->key, $service, serialize($token));
  63. $this->cachedTokens[$service] = $token;
  64. // allow chaining
  65. return $this;
  66. }
  67. /**
  68. * {@inheritDoc}
  69. */
  70. public function hasAccessToken($service)
  71. {
  72. if (isset($this->cachedTokens[$service])
  73. && $this->cachedTokens[$service] instanceof TokenInterface
  74. ) {
  75. return true;
  76. }
  77. return $this->redis->hexists($this->key, $service);
  78. }
  79. /**
  80. * {@inheritDoc}
  81. */
  82. public function clearToken($service)
  83. {
  84. $this->redis->hdel($this->key, $service);
  85. unset($this->cachedTokens[$service]);
  86. // allow chaining
  87. return $this;
  88. }
  89. /**
  90. * {@inheritDoc}
  91. */
  92. public function clearAllTokens()
  93. {
  94. // memory
  95. $this->cachedTokens = array();
  96. // redis
  97. $keys = $this->redis->hkeys($this->key);
  98. $me = $this; // 5.3 compat
  99. // pipeline for performance
  100. $this->redis->pipeline(
  101. function ($pipe) use ($keys, $me) {
  102. foreach ($keys as $k) {
  103. $pipe->hdel($me->getKey(), $k);
  104. }
  105. }
  106. );
  107. // allow chaining
  108. return $this;
  109. }
  110. /**
  111. * {@inheritDoc}
  112. */
  113. public function retrieveAuthorizationState($service)
  114. {
  115. if (!$this->hasAuthorizationState($service)) {
  116. throw new AuthorizationStateNotFoundException('State not found in redis');
  117. }
  118. if (isset($this->cachedStates[$service])) {
  119. return $this->cachedStates[$service];
  120. }
  121. $val = $this->redis->hget($this->stateKey, $service);
  122. return $this->cachedStates[$service] = $val;
  123. }
  124. /**
  125. * {@inheritDoc}
  126. */
  127. public function storeAuthorizationState($service, $state)
  128. {
  129. // (over)write the token
  130. $this->redis->hset($this->stateKey, $service, $state);
  131. $this->cachedStates[$service] = $state;
  132. // allow chaining
  133. return $this;
  134. }
  135. /**
  136. * {@inheritDoc}
  137. */
  138. public function hasAuthorizationState($service)
  139. {
  140. if (isset($this->cachedStates[$service])
  141. && null !== $this->cachedStates[$service]
  142. ) {
  143. return true;
  144. }
  145. return $this->redis->hexists($this->stateKey, $service);
  146. }
  147. /**
  148. * {@inheritDoc}
  149. */
  150. public function clearAuthorizationState($service)
  151. {
  152. $this->redis->hdel($this->stateKey, $service);
  153. unset($this->cachedStates[$service]);
  154. // allow chaining
  155. return $this;
  156. }
  157. /**
  158. * {@inheritDoc}
  159. */
  160. public function clearAllAuthorizationStates()
  161. {
  162. // memory
  163. $this->cachedStates = array();
  164. // redis
  165. $keys = $this->redis->hkeys($this->stateKey);
  166. $me = $this; // 5.3 compat
  167. // pipeline for performance
  168. $this->redis->pipeline(
  169. function ($pipe) use ($keys, $me) {
  170. foreach ($keys as $k) {
  171. $pipe->hdel($me->getKey(), $k);
  172. }
  173. }
  174. );
  175. // allow chaining
  176. return $this;
  177. }
  178. /**
  179. * @return Predis $redis
  180. */
  181. public function getRedis()
  182. {
  183. return $this->redis;
  184. }
  185. /**
  186. * @return string $key
  187. */
  188. public function getKey()
  189. {
  190. return $this->key;
  191. }
  192. }