Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nextcloud/server.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/Common/Collection.php')
-rw-r--r--apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/Common/Collection.php320
1 files changed, 320 insertions, 0 deletions
diff --git a/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/Common/Collection.php b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/Common/Collection.php
new file mode 100644
index 00000000000..e1bf80376e0
--- /dev/null
+++ b/apps/files_external/3rdparty/php-opencloud/lib/OpenCloud/Common/Collection.php
@@ -0,0 +1,320 @@
+<?php
+
+namespace OpenCloud\Common;
+
+/**
+ * Provides an abstraction for working with ordered sets of objects
+ *
+ * Collection objects are used whenever there are multiples; for example,
+ * multiple objects in a container, or multiple servers in a service.
+ *
+ * @since 1.0
+ * @author Glen Campbell <glen.campbell@rackspace.com>
+ * @author Jamie Hannaford <jamie.hannaford@rackspace.com>
+ */
+class Collection extends Base
+{
+
+ private $service;
+ private $itemclass;
+ private $itemlist = array();
+ private $pointer = 0;
+ private $sortkey;
+ private $next_page_class;
+ private $next_page_callback;
+ private $next_page_url;
+
+ /**
+ * A Collection is an array of objects
+ *
+ * Some assumptions:
+ * * The `Collection` class assumes that there exists on its service
+ * a factory method with the same name of the class. For example, if
+ * you create a Collection of class `Foobar`, it will attempt to call
+ * the method `parent::Foobar()` to create instances of that class.
+ * * It assumes that the factory method can take an array of values, and
+ * it passes that to the method.
+ *
+ * @param Service $service - the service associated with the collection
+ * @param string $itemclass - the Class of each item in the collection
+ * (assumed to be the name of the factory method)
+ * @param array $arr - the input array
+ */
+ public function __construct($service, $itemclass, $array)
+ {
+ $this->service = $service;
+
+ $this->getLogger()->info(
+ 'Collection:service={class}, class={itemClass}, array={array}',
+ array(
+ 'class' => get_class($service),
+ 'itemClass' => $itemclass,
+ 'array' => print_r($array, true)
+ )
+ );
+
+ $this->next_page_class = $itemclass;
+
+ if (false !== ($classNamePos = strrpos($itemclass, '\\'))) {
+ $this->itemclass = substr($itemclass, $classNamePos + 1);
+ } else {
+ $this->itemclass = $itemclass;
+ }
+
+ if (!is_array($array)) {
+ throw new Exceptions\CollectionError(
+ Lang::translate('Cannot create a Collection without an array')
+ );
+ }
+
+ // save the array of items
+ $this->setItemList($array);
+ }
+
+ /**
+ * Set the entire data array.
+ *
+ * @param array $array
+ */
+ public function setItemList(array $array)
+ {
+ $this->itemlist = $array;
+ }
+
+ /**
+ * Retrieve the entire data array.
+ *
+ * @return array
+ */
+ public function getItemList()
+ {
+ return $this->itemlist;
+ }
+
+ /**
+ * Returns the number of items in the collection
+ *
+ * For most services, this is the total number of items. If the Collection
+ * is paginated, however, this only returns the count of items in the
+ * current page of data.
+ *
+ * @return int
+ */
+ public function count()
+ {
+ return count($this->itemlist);
+ }
+
+ /**
+ * Pseudonym for count()
+ *
+ * @codeCoverageIgnore
+ */
+ public function size()
+ {
+ return $this->count();
+ }
+
+ /**
+ * Retrieves the service associated with the Collection
+ *
+ * @return Service
+ */
+ public function service()
+ {
+ return $this->service;
+ }
+
+ /**
+ * Resets the pointer to the beginning, but does NOT return the first item
+ *
+ * @api
+ * @return void
+ */
+ public function reset()
+ {
+ $this->pointer = 0;
+ }
+
+ /**
+ * Resets the collection pointer back to the first item in the page
+ * and returns it
+ *
+ * This is useful if you're only interested in the first item in the page.
+ *
+ * @api
+ * @return Base the first item in the set
+ */
+ public function first()
+ {
+ $this->reset();
+ return $this->next();
+ }
+
+ /**
+ * Returns the next item in the page
+ *
+ * @api
+ * @return Base the next item or FALSE if at the end of the page
+ */
+ public function next()
+ {
+ if ($this->pointer >= $this->count()) {
+ return false;
+ }
+
+ $service = $this->service();
+
+ if (method_exists($service, $this->itemclass)) {
+ return $service->{$this->itemclass}($this->itemlist[$this->pointer++]);
+ } elseif (method_exists($service, 'resource')) {
+ return $service->resource($this->itemclass, $this->itemlist[$this->pointer++]);
+ }
+ // @codeCoverageIgnoreStart
+ return false;
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * sorts the collection on a specified key
+ *
+ * Note: only top-level keys can be used as the sort key. Note that this
+ * only sorts the data in the current page of the Collection (for
+ * multi-page data).
+ *
+ * @api
+ * @param string $keyname the name of the field to use as the sort key
+ * @return void
+ */
+ public function sort($keyname = 'id')
+ {
+ $this->sortkey = $keyname;
+ usort($this->itemlist, array($this, 'sortCompare'));
+ }
+
+ /**
+ * selects only specified items from the Collection
+ *
+ * This provides a simple form of filtering on Collections. For each item
+ * in the collection, it calls the callback function, passing it the item.
+ * If the callback returns `TRUE`, then the item is retained; if it returns
+ * `FALSE`, then the item is deleted from the collection.
+ *
+ * Note that this should not supersede server-side filtering; the
+ * `Collection::Select()` method requires that *all* of the data for the
+ * Collection be retrieved from the server before the filtering is
+ * performed; this can be very inefficient, especially for large data
+ * sets. This method is mostly useful on smaller-sized sets.
+ *
+ * Example:
+ * <code>
+ * $services = $connection->ServiceList();
+ * $services->Select(function($item){ return $item->region=='ORD';});
+ * // now the $services Collection only has items from the ORD region
+ * </code>
+ *
+ * `Select()` is *destructive*; that is, it actually removes entries from
+ * the collection. For example, if you use `Select()` to find items with
+ * the ID > 10, then use it again to find items that are <= 10, it will
+ * return an empty list.
+ *
+ * @api
+ * @param callable $testfunc a callback function that is passed each item
+ * in turn. Note that `Select()` performs an explicit test for
+ * `FALSE`, so functions like `strpos()` need to be cast into a
+ * boolean value (and not just return the integer).
+ * @returns void
+ * @throws DomainError if callback doesn't return a boolean value
+ */
+ public function select($testfunc)
+ {
+ foreach ($this->getItemList() as $index => $item) {
+ $test = call_user_func($testfunc, $item);
+ if (!is_bool($test)) {
+ throw new Exceptions\DomainError(
+ Lang::translate('Callback function for Collection::Select() did not return boolean')
+ );
+ }
+ if ($test === false) {
+ unset($this->itemlist[$index]);
+ }
+ }
+ }
+
+ /**
+ * returns the Collection object for the next page of results, or
+ * FALSE if there are no more pages
+ *
+ * Generally, the structure for a multi-page collection will look like
+ * this:
+ *
+ * $coll = $obj->Collection();
+ * do {
+ * while($item = $coll->Next()) {
+ * // do something with the item
+ * }
+ * } while ($coll = $coll->NextPage());
+ *
+ * @api
+ * @return Collection if there are more pages of results, otherwise FALSE
+ */
+ public function nextPage()
+ {
+ if (isset($this->next_page_url)) {
+ return call_user_func(
+ $this->next_page_callback,
+ $this->next_page_class,
+ $this->next_page_url
+ );
+ }
+ // @codeCoverageIgnoreStart
+ return false;
+ // @codeCoverageIgnoreEnd
+ }
+
+ /**
+ * for paginated collection, sets the callback function and URL for
+ * the next page
+ *
+ * The callback function should have the signature:
+ *
+ * function Whatever($class, $url, $parent)
+ *
+ * and the `$url` should be the URL of the next page of results
+ *
+ * @param callable $callback the name of the function (or array of
+ * object, function name)
+ * @param string $url the URL of the next page of results
+ * @return void
+ */
+ public function setNextPageCallback($callback, $url)
+ {
+ $this->next_page_callback = $callback;
+ $this->next_page_url = $url;
+ }
+
+ /**
+ * Compares two values of sort keys
+ */
+ private function sortCompare($a, $b)
+ {
+ $key = $this->sortkey;
+
+ // handle strings with strcmp()
+ if (is_string($a->$key)) {
+ return strcmp($a->$key, $b->$key);
+ }
+
+ // handle others with logical comparisons
+ if ($a->$key == $b->$key) {
+ return 0;
+ }
+
+ if ($a->$key < $b->$key) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+
+}