PageRenderTime 45ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/184.168.182.1/wp-content/plugins/updraftplus/oc/rs/lib/OpenCloud/Common/Collection.php

https://gitlab.com/endomorphosis/falkenstein
PHP | 408 lines | 272 code | 21 blank | 115 comment | 9 complexity | de4a7092b4d2bb4a1a36a94bda6c5281 MD5 | raw file
  1. <?php
  2. /**
  3. * PHP OpenCloud library.
  4. *
  5. * @copyright 2013 Rackspace Hosting, Inc. See LICENSE for information.
  6. * @license https://www.apache.org/licenses/LICENSE-2.0
  7. * @author Jamie Hannaford <jamie.hannaford@rackspace.com>
  8. */
  9. namespace OpenCloud\Common;
  10. /**
  11. * @deprecated
  12. * @codeCoverageIgnore
  13. */
  14. class Collection extends Base
  15. {
  16. private $service;
  17. private $itemClass;
  18. private $itemList = array();
  19. private $pointer = 0;
  20. private $sortKey;
  21. private $nextPageClass;
  22. private $nextPageCallback;
  23. private $nextPageUrl;
  24. /**
  25. * A Collection is an array of objects
  26. *
  27. * Some assumptions:
  28. * * The `Collection` class assumes that there exists on its service
  29. * a factory method with the same name of the class. For example, if
  30. * you create a Collection of class `Foobar`, it will attempt to call
  31. * the method `parent::Foobar()` to create instances of that class.
  32. * * It assumes that the factory method can take an array of values, and
  33. * it passes that to the method.
  34. *
  35. * @param Service $service - the service associated with the collection
  36. * @param string $itemclass - the Class of each item in the collection
  37. * (assumed to be the name of the factory method)
  38. * @param array $arr - the input array
  39. */
  40. public function __construct($service, $class, array $array = array())
  41. {
  42. $service->getLogger()->deprecated(__METHOD__, 'OpenCloud\Common\Collection\CollectionBuilder');
  43. $this->setService($service);
  44. $this->setNextPageClass($class);
  45. // If they've supplied a FQCN, only get the last part
  46. $class = (false !== ($classNamePos = strrpos($class, '\\')))
  47. ? substr($class, $classNamePos + 1)
  48. : $class;
  49. $this->setItemClass($class);
  50. // Set data
  51. $this->setItemList($array);
  52. }
  53. /**
  54. * Set the entire data array.
  55. *
  56. * @param array $array
  57. */
  58. private function setItemList(array $array)
  59. {
  60. $this->itemList = $array;
  61. return $this;
  62. }
  63. /**
  64. * Retrieve the entire data array.
  65. *
  66. * @return array
  67. */
  68. public function getItemList()
  69. {
  70. return $this->itemList;
  71. }
  72. /**
  73. * Set the service.
  74. *
  75. * @param Service|PersistentObject $service
  76. */
  77. public function setService($service)
  78. {
  79. $this->service = $service;
  80. return $this;
  81. }
  82. /**
  83. * Retrieves the service associated with the Collection
  84. *
  85. * @return Service
  86. */
  87. public function getService()
  88. {
  89. return $this->service;
  90. }
  91. /**
  92. * Set the resource class name.
  93. */
  94. private function setItemClass($itemClass)
  95. {
  96. $this->itemClass = $itemClass;
  97. return $this;
  98. }
  99. /**
  100. * Get item class.
  101. */
  102. private function getItemClass()
  103. {
  104. return $this->itemClass;
  105. }
  106. /**
  107. * Set the key that will be used for sorting.
  108. */
  109. private function setSortKey($sortKey)
  110. {
  111. $this->sortKey = $sortKey;
  112. return $this;
  113. }
  114. /**
  115. * Get the key that will be used for sorting.
  116. */
  117. private function getSortKey()
  118. {
  119. return $this->sortKey;
  120. }
  121. /**
  122. * Set next page class.
  123. */
  124. private function setNextPageClass($nextPageClass)
  125. {
  126. $this->nextPageClass = $nextPageClass;
  127. return $this;
  128. }
  129. /**
  130. * Get next page class.
  131. */
  132. private function getNextPageClass()
  133. {
  134. return $this->nextPageClass;
  135. }
  136. /**
  137. * for paginated collection, sets the callback function and URL for
  138. * the next page
  139. *
  140. * The callback function should have the signature:
  141. *
  142. * function Whatever($class, $url, $parent)
  143. *
  144. * and the `$url` should be the URL of the next page of results
  145. *
  146. * @param callable $callback the name of the function (or array of
  147. * object, function name)
  148. * @param string $url the URL of the next page of results
  149. * @return void
  150. */
  151. public function setNextPageCallback($callback, $url)
  152. {
  153. $this->nextPageCallback = $callback;
  154. $this->nextPageUrl = $url;
  155. return $this;
  156. }
  157. /**
  158. * Get next page callback.
  159. */
  160. private function getNextPageCallback()
  161. {
  162. return $this->nextPageCallback;
  163. }
  164. /**
  165. * Get next page URL.
  166. */
  167. private function getNextPageUrl()
  168. {
  169. return $this->nextPageUrl;
  170. }
  171. /**
  172. * Returns the number of items in the collection
  173. *
  174. * For most services, this is the total number of items. If the Collection
  175. * is paginated, however, this only returns the count of items in the
  176. * current page of data.
  177. *
  178. * @return int
  179. */
  180. public function count()
  181. {
  182. return count($this->getItemList());
  183. }
  184. /**
  185. * Pseudonym for count()
  186. *
  187. * @codeCoverageIgnore
  188. */
  189. public function size()
  190. {
  191. return $this->count();
  192. }
  193. /**
  194. * Resets the pointer to the beginning, but does NOT return the first item
  195. *
  196. * @api
  197. * @return void
  198. */
  199. public function reset()
  200. {
  201. $this->pointer = 0;
  202. }
  203. /**
  204. * Resets the collection pointer back to the first item in the page
  205. * and returns it
  206. *
  207. * This is useful if you're only interested in the first item in the page.
  208. *
  209. * @api
  210. * @return Base the first item in the set
  211. */
  212. public function first()
  213. {
  214. $this->reset();
  215. return $this->next();
  216. }
  217. /**
  218. * Return the item at a particular point of the array.
  219. *
  220. * @param mixed $offset
  221. * @return mixed
  222. */
  223. public function getItem($pointer)
  224. {
  225. return (isset($this->itemList[$pointer])) ? $this->itemList[$pointer] : false;
  226. }
  227. /**
  228. * Add an item to this collection
  229. *
  230. * @param mixed $item
  231. */
  232. public function addItem($item)
  233. {
  234. $this->itemList[] = $item;
  235. }
  236. /**
  237. * Returns the next item in the page
  238. *
  239. * @api
  240. * @return Base the next item or FALSE if at the end of the page
  241. */
  242. public function next()
  243. {
  244. if ($this->pointer >= $this->count()) {
  245. return false;
  246. }
  247. $data = $this->getItem($this->pointer++);
  248. $class = $this->getItemClass();
  249. // Are there specific methods in the parent/service that can be used to
  250. // instantiate the resource? Currently supported: getResource(), resource()
  251. foreach (array($class, 'get' . ucfirst($class)) as $method) {
  252. if (method_exists($this->service, $method)) {
  253. return call_user_func(array($this->service, $method), $data);
  254. }
  255. }
  256. // Backup method
  257. if (method_exists($this->service, 'resource')) {
  258. return $this->service->resource($class, $data);
  259. }
  260. return false;
  261. }
  262. /**
  263. * sorts the collection on a specified key
  264. *
  265. * Note: only top-level keys can be used as the sort key. Note that this
  266. * only sorts the data in the current page of the Collection (for
  267. * multi-page data).
  268. *
  269. * @api
  270. * @param string $keyname the name of the field to use as the sort key
  271. * @return void
  272. */
  273. public function sort($keyname = 'id')
  274. {
  275. $this->setSortKey($keyname);
  276. usort($this->itemList, array($this, 'sortCompare'));
  277. }
  278. /**
  279. * selects only specified items from the Collection
  280. *
  281. * This provides a simple form of filtering on Collections. For each item
  282. * in the collection, it calls the callback function, passing it the item.
  283. * If the callback returns `TRUE`, then the item is retained; if it returns
  284. * `FALSE`, then the item is deleted from the collection.
  285. *
  286. * Note that this should not supersede server-side filtering; the
  287. * `Collection::Select()` method requires that *all* of the data for the
  288. * Collection be retrieved from the server before the filtering is
  289. * performed; this can be very inefficient, especially for large data
  290. * sets. This method is mostly useful on smaller-sized sets.
  291. *
  292. * Example:
  293. * <code>
  294. * $services = $connection->ServiceList();
  295. * $services->Select(function($item){ return $item->region=='ORD';});
  296. * // now the $services Collection only has items from the ORD region
  297. * </code>
  298. *
  299. * `Select()` is *destructive*; that is, it actually removes entries from
  300. * the collection. For example, if you use `Select()` to find items with
  301. * the ID > 10, then use it again to find items that are <= 10, it will
  302. * return an empty list.
  303. *
  304. * @api
  305. * @param callable $testfunc a callback function that is passed each item
  306. * in turn. Note that `Select()` performs an explicit test for
  307. * `FALSE`, so functions like `strpos()` need to be cast into a
  308. * boolean value (and not just return the integer).
  309. * @returns void
  310. * @throws DomainError if callback doesn't return a boolean value
  311. */
  312. public function select($testfunc)
  313. {
  314. foreach ($this->getItemList() as $index => $item) {
  315. $test = call_user_func($testfunc, $item);
  316. if (!is_bool($test)) {
  317. throw new Exceptions\DomainError(
  318. Lang::translate('Callback function for Collection::Select() did not return boolean')
  319. );
  320. }
  321. if ($test === false) {
  322. unset($this->itemList[$index]);
  323. }
  324. }
  325. }
  326. /**
  327. * returns the Collection object for the next page of results, or
  328. * FALSE if there are no more pages
  329. *
  330. * Generally, the structure for a multi-page collection will look like
  331. * this:
  332. *
  333. * $coll = $obj->Collection();
  334. * do {
  335. * while($item = $coll->Next()) {
  336. * // do something with the item
  337. * }
  338. * } while ($coll = $coll->NextPage());
  339. *
  340. * @api
  341. * @return Collection if there are more pages of results, otherwise FALSE
  342. */
  343. public function nextPage()
  344. {
  345. return ($this->getNextPageUrl() !== null)
  346. ? call_user_func($this->getNextPageCallback(), $this->getNextPageClass(), $this->getNextPageUrl())
  347. : false;
  348. }
  349. /**
  350. * Compares two values of sort keys
  351. */
  352. private function sortCompare($a, $b)
  353. {
  354. $key = $this->getSortKey();
  355. // Handle strings
  356. if (is_string($a->$key)) {
  357. return strcmp($a->$key, $b->$key);
  358. }
  359. // Handle others with logical comparisons
  360. if ($a->$key == $b->$key) {
  361. return 0;
  362. } elseif ($a->$key < $b->$key) {
  363. return -1;
  364. } else {
  365. return 1;
  366. }
  367. }
  368. }