1  <?php
  2  /* Copyright (c) 2013, Geert Bergman (geert@scrivo.nl)
  3   * All rights reserved.
  4   *
  5   * Redistribution and use in source and binary forms, with or without
  6   * modification, are permitted provided that the following conditions are met:
  7   *
  8   * 1. Redistributions of source code must retain the above copyright notice,
  9   *    this list of conditions and the following disclaimer.
 10   * 2. Redistributions in binary form must reproduce the above copyright notice,
 11   *    this list of conditions and the following disclaimer in the documentation
 12   *    and/or other materials provided with the distribution.
 13   * 3. Neither the name of "Scrivo" nor the names of its contributors may be
 14   *    used to endorse or promote products derived from this software without
 15   *    specific prior written permission.
 16   *
 17   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 18   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 19   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 20   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 21   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 22   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 23   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 24   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 25   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 26   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 27   * POSSIBILITY OF SUCH DAMAGE.
 28   *
 29   * $Id: AssetSet.php 841 2013-08-19 22:19:47Z geert $
 30   */
 31  
 32  /**
 33   * Implementation of the \Scrivo\AssetSet class.
 34   */
 35  
 36  namespace Scrivo;
 37  
 38  /**
 39   * A Scrivo Asset set is a group of Scrivo assets with a common parent id. A
 40   * asset set is actually a simple array of (child) assets but it does a
 41   * couple of things extra:
 42   *
 43   * - When serialized only the ids are stored.
 44   * - When iteratering, counting or getting assets from the array only the
 45   *   readable assets in the array will be taken into account.
 46   *
 47   * Asset sets are a part of a Scrivo asset and are used to retrieve and iterate
 48   * through the child assets (or path) of an asset.
 49   */
 50  class AssetSet implements \ArrayAccess, \Iterator, \Countable {
 51  
 52      /**
 53       * The array containing the assets or asset ids.
 54       * @var \Scrivo\Asset[id]|int[id]
 55       */
 56      private $items = array();
 57  
 58      /**
 59       * The parent asset of the set.
 60       * @var \Scrivo\Asset
 61       */
 62      private $asset null;
 63  
 64      /**
 65       * An array containing the keys of the items array, used when serializing.
 66       * @var int[id]
 67       */
 68      private $ids null;
 69  
 70      /**
 71       * When reading the items array always check of the actual entry is an
 72       * instantiated Scrivo asset. If not, get that asset and store it in the
 73       * items array.
 74       *
 75       * @param int $id The asset id of the entry to check.
 76       */
 77      private function check($id) {
 78          if (is_int($this->items[$id])) {
 79              $this->items[$id] =
 80                  \Scrivo\Asset::fetch($this->asset->context$this->items[$id]);
 81          }
 82          return $this->items[$id];
 83      }
 84  
 85      /**
 86       * Construct an asset set.
 87       *
 88       * @param \Scrivo\Asset $asset The parent asset of the asset set.
 89       */
 90      public function __construct(\Scrivo\Asset $asset) {
 91          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(null));
 92  
 93          $this->items = array();
 94          $this->asset $asset;
 95      }
 96  
 97      /**
 98       * Set an asset in the asset set.
 99       *
100       * @param int $id A Scrivo asset id.
101       * @param \Scrivo\Asset $asset The parent asset of the asset set.
102       */
103      public function offsetSet($id$asset) {
104          $this->items[$id] = $asset;
105      }
106  
107      /**
108       * Add an asset to the beginning of the set.
109       *
110       * @param \Scrivo\Asset $asset The parent asset of the asset set.
111       */
112      public function prepend($asset) {
113          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(null));
114  
115          $this->items = array($asset->id => $asset) + $this->items;
116      }
117  
118      /**
119       * Test if asset is set in the asset set.
120       *
121       * @param int $id A Scrivo asset id to test.
122       *
123       * @return boolean True of the asset with the given id exists in the set.
124       */
125      public function offsetExists($id) {
126          return (isset($this->items[$id]) &&
127              $this->check($id)->roles->canRead($this->asset->context->principal));
128      }
129  
130      /**
131       * It is not possible to unset assets in an asset set. Calling this method
132       * will raise a system exception.
133       *
134       * @param int $id A Scrivo asset id to unset.
135       */
136      public function offsetUnset($id) {
137          throw new \Scrivo\SystemException("Illegal method");
138      }
139  
140      /**
141       * Get an asset with a specific id from the asset set.
142       *
143       * @param int $id A Scrivo asset id to test.
144       *
145       * @return \Scrivo\Asset The asset with the given id.
146       */
147      public function offsetGet($id) {
148          if (!$this->offsetExists($id)) {
149              throw new \Scrivo\SystemException("Not set");
150          }
151          return $this->items[$id];
152      }
153  
154      /**
155       * Rewind the asset set so that iterating will start at the beginning.
156       */
157      function rewind() {
158          reset($this->items);
159      }
160  
161      /**
162       * Get the current asset from the asset set when iterating.
163       *
164       * @return \Scrivo\Asset The current asset in the asset set.
165       */
166      function current() {
167          return current($this->items);
168      }
169  
170      /**
171       * Get the key(id) of the current asset from the asset set when iterating.
172       *
173       * @return \Scrivo\Asset The key (id) of the current asset in the asset set.
174       */
175      function key() {
176          return key($this->items);
177      }
178  
179      /**
180       * Get the current asset from the asset set and move the internal pointer
181       * to the next asset in the set.
182       *
183       * @return \Scrivo\Asset The current asset in the asset set.
184       */
185      function next() {
186          return next($this->items);
187      }
188  
189      /**
190       * Test if the current asset is valid.
191       *
192       * @return boolean True if the current asset is valid.
193       */
194      function valid() {
195  
196          $k key($this->items);
197          $pr $this->asset->context->principal;
198  
199          // Get the current asset ...
200          if (isset($this->items[$k]) && $c $this->check($k)) {
201              // ... and check if it is readable ...
202              if ($c->roles->canRead($pr)) {
203                  return true;
204              }
205              // ... and if not move to the next until a readable asset is found.
206              while (next($this->items)) {
207                  if ($this->check(key($this->items))->roles->canRead($pr)) {
208                      return true;
209                  }
210              }
211          }
212  
213          return false;
214      }
215  
216      /**
217       * The asset count of assets in the set. Note that returned asset count
218       * depends on whether the assets are readable for the user defined in the
219       * Scrivo context. So the returned count is always equeal or less that the
220       * actual count of assets in the items array.
221       *
222       * @return int The number of assets in the set that are readable for the
223       *    users defined in the Scrivo context.
224       */
225      public function count() {
226          // Start counting
227          $count 0;
228          foreach($this as $i) {
229              if ($i->roles->canRead($this->asset->context->principal)) {
230                  $count++;
231              }
232          }
233          return $count;
234      }
235  
236      /**
237       * When serializing retrieve the don't store the items array but just the
238       * keys.
239       *
240       * return array An array with the names of the serializable members.
241       */
242      public function __sleep() {
243  
244          $this->ids array_keys($this->items);
245  
246          // Note that asset sets always will be serialized as a part of the
247          // parent asset. Therefore the asset member will be serialized as a
248          // reference value.
249          return array("ids""asset");
250      }
251  
252      /**
253       * When unserializing restore the items array only the id.
254       */
255      public function __wakeup() {
256          $this->items array_combine($this->ids$this->ids);
257          unset($this->ids);
258      }
259  
260  }
261  
262  ?>

Documentation generated by phpDocumentor 2.0.0a12 and ScrivoDocumentor on August 29, 2013