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: RoleSet.php 547 2013-03-04 12:06:51Z geert $
 30   */
 31  
 32  /**
 33   * Implementation of the \Scrivo\PageSet class.
 34   */
 35  
 36  namespace Scrivo;
 37  
 38  /**
 39   * A Scrivo Page set is a group of Scrivo pages with a common parent id. A
 40   * page set is actually a simple array of (child) pages but it does a
 41   * couple of things extra:
 42   *
 43   * - When serialized only the ids are stored.
 44   * - When iteratering, counting or getting pages from the array only the
 45   *   readable pages in the array will be taken into account.
 46   *
 47   * Page sets are a part of a Scrivo page and are used to retrieve and iterate
 48   * through the child pages (or path) of a page.
 49   */
 50  class PageSet implements \ArrayAccess, \Iterator, \Countable {
 51  
 52      /**
 53       * The array containing the pages or page ids.
 54       * @var \Scrivo\Page[id]|int[id]
 55       */
 56      private $items = array();
 57  
 58      /**
 59       * The parent page of the set.
 60       * @var \Scrivo\Page
 61       */
 62      private $page 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 page. If not, get that page and store it in the
 73       * items array.
 74       *
 75       * @param int $id The page 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\Page::fetch($this->page->context$this->items[$id]);
 81          }
 82          return $this->items[$id];
 83      }
 84  
 85      /**
 86       * Construct a page set.
 87       *
 88       * @param \Scrivo\Page $page The parent page of the page set.
 89       */
 90      public function __construct(\Scrivo\Page $page) {
 91          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(null));
 92  
 93          $this->items = array();
 94          $this->page $page;
 95      }
 96  
 97      /**
 98       * Set a page in the page set.
 99       *
100       * @param int $id A Scrivo page id.
101       * @param \Scrivo\Page $page The parent page of the page set.
102       */
103      public function offsetSet($id$page) {
104          $this->items[$id] = $page;
105      }
106  
107      /**
108       * Add a page to the beginning of the set.
109       *
110       * @param \Scrivo\Page $page The parent page of the page set.
111       */
112      public function prepend($page) {
113          \Scrivo\ArgumentCheck::assertArgs(func_get_args(), array(null));
114  
115          array_unshift($this->items$page);
116      }
117  
118      /**
119       * Test if page is set in the page set.
120       *
121       * @param int $id A Scrivo page id to test.
122       *
123       * @return boolean True of the page 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->page->context->principal));
128      }
129  
130      /**
131       * It is not possible to unset pages in a page set. Calling this method
132       * will raise a system exception.
133       *
134       * @param int $id A Scrivo page id to unset.
135       */
136      public function offsetUnset($id) {
137          throw new \Scrivo\SystemException("Illegal method");
138      }
139  
140      /**
141       * Get a page with a specific id from the page set.
142       *
143       * @param int $id A Scrivo page id to test.
144       *
145       * @return \Scrivo\Page The page 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 page set so that iterating will start at the beginning.
156       */
157      function rewind() {
158          reset($this->items);
159      }
160  
161      /**
162       * Get the current page from the page set when iterating.
163       *
164       * @return \Scrivo\Page The current page in the page set.
165       */
166      function current() {
167          return current($this->items);
168      }
169  
170      /**
171       * Get the key(id) of the current page from the page set when iterating.
172       *
173       * @return \Scrivo\Page The key (id) of the current page in the page set.
174       */
175      function key() {
176          return key($this->items);
177      }
178  
179      /**
180       * Get the current page from the page set and move the internal pointer
181       * to the next page in the set.
182       *
183       * @return \Scrivo\Page The current page in the page set.
184       */
185      function next() {
186          return next($this->items);
187      }
188  
189      /**
190       * Test if the current page is valid.
191       *
192       * @return boolean True if the current page is valid.
193       */
194      function valid() {
195  
196          $k key($this->items);
197          $pr $this->page->context->principal;
198  
199          // Get the current page ...
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 page 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 page count of pages in the set. Note that returned page count
218       * depends on whether the pages 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 pages in the items array.
221       *
222       * @return int The number of pages 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->page->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 page sets always will be serialized as a part of the
247          // parent page. Therefore the page member will be serialized as a
248          // reference value.
249          return array("ids""page");
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