/ARedisSet.php

https://github.com/phpnode/YiiRedis · PHP · 358 lines · 222 code · 16 blank · 120 comment · 37 complexity · 9ec7cf65209aa12f1204a73e7313c6c3 MD5 · raw file

  1. <?php
  2. /**
  3. * Represents a redis set.
  4. * Redis Sets are an unordered collection of Strings. It is possible to add, remove, and test for existence of members in O(1) (constant time regardless of the number of elements contained inside the Set).
  5. *
  6. * <pre>
  7. * $set = new ARedisSet("mySet");
  8. * $set->add(1);
  9. * $set->add(2);
  10. * $set->add(3);
  11. *
  12. * $otherSet = new ARedisSet("myOtherSet");
  13. * $otherSet->add(2);
  14. *
  15. * print_r($set->diff($otherSet)); // the difference between the sets
  16. * </pre>
  17. *
  18. *
  19. * @author Charles Pick
  20. * @package packages.redis
  21. */
  22. class ARedisSet extends ARedisIterableEntity {
  23. /**
  24. * Adds an item to the set
  25. * @param mixed $item the item to add
  26. * @return boolean true if the item was added, otherwise false
  27. */
  28. public function add($item) {
  29. if (!$this->getConnection()->getClient()->sadd($this->name,$item)) {
  30. return false;
  31. }
  32. $this->_data = null;
  33. $this->_count = null;
  34. return true;
  35. }
  36. /**
  37. * Removes an item from the set
  38. * @param mixed $item the item to remove
  39. * @return boolean true if the item was removed, otherwise false
  40. */
  41. public function remove($item) {
  42. if (!$this->getConnection()->getClient()->srem($this->name,$item)) {
  43. return false;
  44. }
  45. $this->_data = null;
  46. $this->_count = null;
  47. return true;
  48. }
  49. /**
  50. * Removes and returns a random item from the set
  51. * @return mixed the item that was removed from the set
  52. */
  53. public function pop() {
  54. $member = $this->getConnection()->getClient()->spop($this->name);
  55. $this->_data = null;
  56. $this->_count = null;
  57. return $member;
  58. }
  59. /**
  60. * Gets a random member of the set
  61. * @return mixed a random member of the set
  62. */
  63. public function random() {
  64. return $this->getConnection()->getClient()->srandmember($this->name);
  65. }
  66. /**
  67. * Gets the difference between this set and the given set(s) and returns it
  68. * @param mixed $set, $set2 The sets to compare to, either ARedisSet instances or their names
  69. * @return array the difference between this set and the given sets
  70. */
  71. public function diff($set) {
  72. if (is_array($set)) {
  73. $parameters = $set;
  74. }
  75. else {
  76. $parameters = func_get_args();
  77. }
  78. foreach($parameters as $n => $set) {
  79. if ($set instanceof ARedisSet) {
  80. $parameters[$n] = $set->name;
  81. }
  82. }
  83. array_unshift($parameters,$this->name);
  84. return call_user_func_array(array(
  85. $this->getConnection()->getClient(),
  86. "sdiff"
  87. ),$parameters);
  88. }
  89. /**
  90. * Gets the difference between this set and the given set(s), stores it in a new set and returns it
  91. * @param ARedisSet|string $destination the destination to store the result in
  92. * @param mixed $set, $set2 The sets to compare to, either ARedisSet instances or their names
  93. * @return ARedisSet a set that contains the difference between this set and the given sets
  94. */
  95. public function diffStore($destination, $set) {
  96. if ($destination instanceof ARedisSet) {
  97. $destination->_count = null;
  98. $destination->_data = null;
  99. }
  100. else {
  101. $destination = new ARedisSet($destination,$this->getConnection());
  102. }
  103. if (is_array($set)) {
  104. $parameters = $set;
  105. }
  106. else {
  107. $parameters = func_get_args();
  108. array_shift($parameters);
  109. }
  110. foreach($parameters as $n => $set) {
  111. if ($set instanceof ARedisSet) {
  112. $parameters[$n] = $set->name;
  113. }
  114. }
  115. array_unshift($parameters,$this->name);
  116. array_unshift($parameters, $destination->name);
  117. call_user_func_array(array(
  118. $this->getConnection()->getClient(),
  119. "sdiffstore"
  120. ),$parameters);
  121. return $destination;
  122. }
  123. /**
  124. * Gets the intersection between this set and the given set(s) and returns it
  125. * @param mixed $set, $set2 The sets to compare to, either ARedisSet instances or their names
  126. * @return array the intersection between this set and the given sets
  127. */
  128. public function inter($set) {
  129. if (is_array($set)) {
  130. $parameters = $set;
  131. }
  132. else {
  133. $parameters = func_get_args();
  134. }
  135. foreach($parameters as $n => $set) {
  136. if ($set instanceof ARedisSet) {
  137. $parameters[$n] = $set->name;
  138. }
  139. }
  140. array_unshift($parameters,$this->name);
  141. return call_user_func_array(array(
  142. $this->getConnection()->getClient(),
  143. "sinter"
  144. ),$parameters);
  145. }
  146. /**
  147. * Gets the intersection between this set and the given set(s), stores it in a new set and returns it
  148. * @param ARedisSet|string $destination the destination to store the result in
  149. * @param mixed $set, $set2 The sets to compare to, either ARedisSet instances or their names
  150. * @return ARedisSet a set that contains the intersection between this set and the given sets
  151. */
  152. public function interStore($destination, $set) {
  153. if ($destination instanceof ARedisSet) {
  154. $destination->_count = null;
  155. $destination->_data = null;
  156. }
  157. else {
  158. $destination = new ARedisSet($destination,$this->getConnection());
  159. }
  160. if (is_array($set)) {
  161. $parameters = $set;
  162. }
  163. else {
  164. $parameters = func_get_args();
  165. array_shift($parameters);
  166. }
  167. foreach($parameters as $n => $set) {
  168. if ($set instanceof ARedisSet) {
  169. $parameters[$n] = $set->name;
  170. }
  171. }
  172. array_unshift($parameters,$this->name);
  173. array_unshift($parameters, $destination->name);
  174. call_user_func_array(array(
  175. $this->getConnection()->getClient(),
  176. "sinterstore"
  177. ),$parameters);
  178. return $destination;
  179. }
  180. /**
  181. * Gets the union of this set and the given set(s) and returns it
  182. * @param mixed $set, $set2 The sets to compare to, either ARedisSet instances or their names
  183. * @return array the union of this set and the given sets
  184. */
  185. public function union($set) {
  186. if (is_array($set)) {
  187. $parameters = $set;
  188. }
  189. else {
  190. $parameters = func_get_args();
  191. }
  192. foreach($parameters as $n => $set) {
  193. if ($set instanceof ARedisSet) {
  194. $parameters[$n] = $set->name;
  195. }
  196. }
  197. array_unshift($parameters,$this->name);
  198. return call_user_func_array(array(
  199. $this->getConnection()->getClient(),
  200. "sunion"
  201. ),$parameters);
  202. }
  203. /**
  204. * Gets the union of this set and the given set(s), stores it in a new set and returns it
  205. * @param ARedisSet|string $destination the destination to store the result in
  206. * @param mixed $set, $set2 The sets to compare to, either ARedisSet instances or their names
  207. * @return ARedisSet a set that contains the union of this set and the given sets
  208. */
  209. public function unionStore($destination, $set) {
  210. if ($destination instanceof ARedisSet) {
  211. $destination->_count = null;
  212. $destination->_data = null;
  213. }
  214. else {
  215. $destination = new ARedisSet($destination,$this->getConnection());
  216. }
  217. if (is_array($set)) {
  218. $parameters = $set;
  219. }
  220. else {
  221. $parameters = func_get_args();
  222. array_shift($parameters);
  223. }
  224. foreach($parameters as $n => $set) {
  225. if ($set instanceof ARedisSet) {
  226. $parameters[$n] = $set->name;
  227. }
  228. }
  229. array_unshift($parameters,$this->name);
  230. array_unshift($parameters, $destination->name);
  231. call_user_func_array(array(
  232. $this->getConnection()->getClient(),
  233. "sunionstore"
  234. ),$parameters);
  235. return $destination;
  236. }
  237. /**
  238. * Moves an item from this redis set to another
  239. * @param ARedisSet|string $destination the set to move the item to
  240. * @param mixed $item the item to move
  241. * @return boolean true if the item was moved successfully
  242. */
  243. public function move($destination, $item) {
  244. if ($destination instanceof ARedisSet) {
  245. $destination->_count = null;
  246. $destination->_data = null;
  247. $destination = $destination->name;
  248. }
  249. $this->_count = null;
  250. $this->_data = null;
  251. return $this->getConnection()->getClient()->smove($this->name, $destination, $item);
  252. }
  253. /**
  254. * Gets the number of items in the set
  255. * @return integer the number of items in the set
  256. */
  257. public function getCount() {
  258. if ($this->_count === null) {
  259. $this->_count = $this->getConnection()->getClient()->scard($this->name);
  260. }
  261. return $this->_count;
  262. }
  263. /**
  264. * Gets all the members in the set
  265. * @param boolean $forceRefresh whether to force a refresh or not
  266. * @return array the members in the set
  267. */
  268. public function getData($forceRefresh = false) {
  269. if ($forceRefresh || $this->_data === null) {
  270. $this->_data = $this->getConnection()->getClient()->smembers($this->name);
  271. }
  272. return $this->_data;
  273. }
  274. /**
  275. * Copies iterable data into the list.
  276. * Note, existing data in the list will be cleared first.
  277. * @param mixed $data the data to be copied from, must be an array or object implementing Traversable
  278. * @throws CException If data is neither an array nor a Traversable.
  279. */
  280. public function copyFrom($data)
  281. {
  282. if(is_array($data) || ($data instanceof Traversable))
  283. {
  284. if($this->_count>0)
  285. $this->clear();
  286. if($data instanceof CList)
  287. $data=$data->_data;
  288. foreach($data as $item) {
  289. $this->add($item);
  290. }
  291. }
  292. else if($data!==null)
  293. throw new CException(Yii::t('yii','List data must be an array or an object implementing Traversable.'));
  294. }
  295. /**
  296. * Determines whether the item is contained in the entity
  297. * @param mixed $item the item to check for
  298. * @return boolean true if the item exists in the entity, otherwise false
  299. */
  300. public function contains($item) {
  301. return $this->getConnection()->getClient()->sismember($this->name, $item);
  302. }
  303. /**
  304. * Returns whether there is an item at the specified offset.
  305. * This method is required by the interface ArrayAccess.
  306. * @param integer $offset the offset to check on
  307. * @return boolean
  308. */
  309. public function offsetExists($offset)
  310. {
  311. return ($offset>=0 && $offset<$this->getCount());
  312. }
  313. /**
  314. * Returns the item at the specified offset.
  315. * This method is required by the interface ArrayAccess.
  316. * @param integer $offset the offset to retrieve item.
  317. * @return mixed the item at the offset
  318. */
  319. public function offsetGet($offset)
  320. {
  321. return $this->_data[$offset];
  322. }
  323. /**
  324. * Sets the item at the specified offset.
  325. * This method is required by the interface ArrayAccess.
  326. * @param integer $offset the offset to set item
  327. * @param mixed $item the item value
  328. */
  329. public function offsetSet($offset,$item)
  330. {
  331. $this->add($item);
  332. }
  333. /**
  334. * Unsets the item at the specified offset.
  335. * This method is required by the interface ArrayAccess.
  336. * @param integer $offset the offset to unset item
  337. */
  338. public function offsetUnset($offset)
  339. {
  340. $this->remove($this->_data[$offset]);
  341. }
  342. }