Code Coverage  | 
     ||||||||||
Classes and Traits  | 
      Functions and Methods  | 
      Lines  | 
     ||||||||
| Total |         | 
      100.00%  | 
      1 / 1  | 
              | 
      100.00%  | 
      13 / 13  | 
      CRAP |         | 
      100.00%  | 
      124 / 124  | 
     
| PageDefinitionHints |         | 
      100.00%  | 
      1 / 1  | 
              | 
      100.00%  | 
      13 / 13  | 
      34 |         | 
      100.00%  | 
      124 / 124  | 
     
| __construct( \Scrivo\Context $context, $pageDefinitionId, $listType) |         | 
      100.00%  | 
      1 / 1  | 
      4 |         | 
      100.00%  | 
      13 / 13  | 
     |||
| offsetGet($key) |         | 
      100.00%  | 
      1 / 1  | 
      2 |         | 
      100.00%  | 
      4 / 4  | 
     |||
| offsetSet($key, $value) |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      2 / 2  | 
     |||
| offsetExists($key) |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      1 / 1  | 
     |||
| offsetUnset($key) |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      2 / 2  | 
     |||
| rewind() |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      2 / 2  | 
     |||
| current() |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      1 / 1  | 
     |||
| key() |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      1 / 1  | 
     |||
| next() |         | 
      100.00%  | 
      1 / 1  | 
      1 |         | 
      100.00%  | 
      2 / 2  | 
     |||
| valid() |         | 
      100.00%  | 
      1 / 1  | 
      2 |         | 
      100.00%  | 
      1 / 1  | 
     |||
| load($children=false) |         | 
      100.00%  | 
      1 / 1  | 
      6 |         | 
      100.00%  | 
      34 / 34  | 
     |||
| loadCorrected($parentId) |         | 
      100.00%  | 
      1 / 1  | 
      8 |         | 
      100.00%  | 
      35 / 35  | 
     |||
| update() |         | 
      100.00%  | 
      1 / 1  | 
      5 |         | 
      100.00%  | 
      26 / 26  | 
     |||
| <?php | |
| /* Copyright (c) 2012, Geert Bergman (geert@scrivo.nl) | |
| * All rights reserved. | |
| * | |
| * Redistribution and use in source and binary forms, with or without | |
| * modification, are permitted provided that the following conditions are met: | |
| * | |
| * 1. Redistributions of source code must retain the above copyright notice, | |
| * this list of conditions and the following disclaimer. | |
| * 2. Redistributions in binary form must reproduce the above copyright notice, | |
| * this list of conditions and the following disclaimer in the documentation | |
| * and/or other materials provided with the distribution. | |
| * 3. Neither the name of "Scrivo" nor the names of its contributors may be | |
| * used to endorse or promote products derived from this software without | |
| * specific prior written permission. | |
| * | |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | |
| * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
| * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE | |
| * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | |
| * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
| * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | |
| * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
| * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | |
| * POSSIBILITY OF SUCH DAMAGE. | |
| * | |
| * $Id: PageDefinitionHints.php 866 2013-08-25 16:22:35Z geert $ | |
| */ | |
| /** | |
| * Implementation of the \Scrivo\PageDefinitionHints class. | |
| */ | |
| namespace Scrivo; | |
| /** | |
| * The PageDefinitionHints class is used to prevent page definition selection | |
| * in the Scrivo user interface. | |
| * | |
| * In principle it is possible to create pages of any page definition | |
| * underneath any other page. But from the viewpoint of the site designer this | |
| * is not always desirable. The site might require specific rules such as that | |
| * there are only 'main menu' pages allowed underneath the home. | |
| * | |
| * Likewise, the site editor will not be facilitated when offered long lists | |
| * of page definitions (with possible many irrelevant entries) each time he or | |
| * she wants to add a page. | |
| * | |
| * To guide the user in page definition selection the PageDefinitionHints class | |
| * lists the number of occurances of pages of a specific page definition that | |
| * is allowed under a page of a given page definition. For these lists it can | |
| * be decided if a page definition is selectable when creating a page. | |
| * | |
| * Suppose we have three page definitions: Home, Standard and Contact. Then a | |
| * likely scenario is that we don't want the the editor the select the 'Home' | |
| * page definition at any time, the 'Standard' page definition for as many | |
| * times as desired but only as a child of a page of page definition 'Home' or | |
| * 'Standard' and the 'Contact' page only once as child of the home page (the | |
| * page of page definition 'Home'). | |
| * | |
| * Again these are merely hints. In the super-interfaces 'admin' and 'config' | |
| * your still allowed to make all combinations you want. These hints are only | |
| * used as a guide in the editor interface. | |
| */ | |
| class PageDefinitionHints implements \Iterator, \ArrayAccess { | |
| /** | |
| * Constant to denote that we want to retrieve the list of how many times | |
| * a page of this page definition may occur underneath pages of other | |
| * page definitions. | |
| */ | |
| const PARENT_PAGE_DEFINITION_COUNT = 1; | |
| /** | |
| * Constant to denote we want to retrieve the list of how many times pages | |
| * of other page definitions (total count) may occur underneath the current | |
| * page. | |
| */ | |
| const CHILD_PAGE_DEFINITION_COUNT = 2; | |
| /** | |
| * Constant to denote we want to retrieve the list of how many times pages | |
| * of other page definitions (remaining count) may occur underneath the | |
| * current page. | |
| */ | |
| const CHILD_PAGE_DEFINITION_REMAINING = 3; | |
| /** | |
| * The id of the page definition to retrieve the list. | |
| * @var int | |
| */ | |
| private $pageDefinitionId = 0; | |
| /** | |
| * The type of the list: | |
| * \Scrivo\PageDefinitionHints::PARENT_PAGE_DEFINITION_COUNT, | |
| * \Scrivo\PageDefinitionHints::CHILD_PAGE_DEFINITION_COUNT or | |
| * \Scrivo\PageDefinitionHints::CHILD_PAGE_DEFINITION_REMAINING. | |
| * @var int | |
| */ | |
| private $type = 0; | |
| /** | |
| * The hints array. | |
| * @var object[] | |
| */ | |
| private $hints = null; | |
| /** | |
| * A Scrivo context | |
| * @var \Scrivo\Context | |
| */ | |
| private $context = null; | |
| /** | |
| * Construct a pageDefinition hints object. Depending on the context where | |
| * you want to use these hints for a number of different lists can be | |
| * constructed. For instance, when defining the user interface one need | |
| * lists that contain the hints as stored in the database | |
| * (PARENT_PAGE_DEFINITION_COUNT or CHILD_PAGE_DEFINITION_COUNT). But in | |
| * the user interface itself you'll want to to use the rules as defined but | |
| * corrected for the pages already created. | |
| * | |
| * Suppose there are three main menus are allowed under the a home page. | |
| * The types PARENT_PAGE_DEFINITION_COUNT or CHILD_PAGE_DEFINITION_COUNT | |
| * will give you that information. But if there are alreay two main menus | |
| * are created under the home CHILD_PAGE_DEFINITION_REMAINING will give | |
| * you the corrected result of just one main menu allowed under the a home | |
| * page. | |
| * * | |
| * @param \Scrivo\Context $context A valid Scrivo context. | |
| * @param int $pageDefinitionId The id of the pageDefinition to create the | |
| * hints for, or the page id in the case of | |
| * CHILD_PAGE_DEFINITION_REMAINING. | |
| * @param int $listType The list type to create: either | |
| * \Scrivo\PageDefinitionHints::PARENT_PAGE_DEFINITION_COUNT, | |
| * \Scrivo\PageDefinitionHints::CHILD_PAGE_DEFINITION_COUNT or | |
| * \Scrivo\PageDefinitionHints::CHILD_PAGE_DEFINITION_REMAINING. | |
| * @param int $listType If the listType parameter was set to | |
| * \Scrivo\PageDefinitionHints::CHILD_PAGE_DEFINITION_REMAINING then the | |
| * id for the page for which to correct the result needs to be supplied. | |
| */ | |
| function __construct( | |
| \Scrivo\Context $context, $pageDefinitionId, $listType) { | |
| $this->context = $context; | |
| $this->type = $listType; | |
| if (self::CHILD_PAGE_DEFINITION_COUNT == $listType) { | |
| $this->pageDefinitionId = $pageDefinitionId; | |
| $this->load(true); | |
| } else if (self::CHILD_PAGE_DEFINITION_REMAINING == $listType) { | |
| $this->loadCorrected($pageDefinitionId); | |
| } else if (self::PARENT_PAGE_DEFINITION_COUNT == $listType) { | |
| $this->pageDefinitionId = $pageDefinitionId; | |
| $this->load(false); | |
| } else { | |
| throw new \Scrivo\SystemException("invalid list type"); | |
| } | |
| } | |
| /** | |
| * Get the page definition hint for a given page definition (id). | |
| * | |
| * @param int $key A page definition id used as key in the hints array. | |
| * | |
| * @return object The hint for the given page definition. The hint has the | |
| * following fields: pageDefinitionId, title and maxNoOfChilds. | |
| * | |
| * @throws \Scrivo\SystemException If the requested offset was out of | |
| * range. | |
| */ | |
| public function offsetGet($key) { | |
| if (!isset($this->hints[$key])) { | |
| throw new \Scrivo\SystemException( | |
| "PageDefinitionHints invalid index"); | |
| } | |
| return $this->hints[$key]; | |
| } | |
| /** | |
| * Part of the implementation of \ArrayAccess. Not applicable for | |
| * PageDefinitionHints. | |
| * | |
| * @param int $key | |
| * @param string $value | |
| * | |
| * @throws \Scrivo\SystemException If this method is called. | |
| */ | |
| public function offsetSet($key, $value) { | |
| throw new \Scrivo\SystemException( | |
| "offsetSet can't be called on PageDefinitionHints objects"); | |
| } | |
| /** | |
| * Test if a hint exists at the requested index location. | |
| * | |
| * @param int $key A page definition id used as key in the hints array. | |
| */ | |
| public function offsetExists($key) { | |
| return isset($this->hints[$key]); | |
| } | |
| /** | |
| * Part of the implementation of \ArrayAccess. Not applicable for | |
| * PageDefinitionHints. | |
| * | |
| * @param int $key | |
| * | |
| * @throws \Exception If this method is called. | |
| */ | |
| public function offsetUnset($key) { | |
| throw new \Scrivo\SystemException( | |
| "offsetUnset can't be called on PageDefinitionHints objects"); | |
| } | |
| /** | |
| * Rewind the hints array so iterating will start at the beginning again. | |
| */ | |
| function rewind() { | |
| reset($this->hints); | |
| } | |
| /** | |
| * Get the current page definition hint when iterating. | |
| */ | |
| function current() { | |
| return current($this->hints); | |
| } | |
| /** | |
| * Get the key of the current page definition hint when iterating. | |
| */ | |
| function key() { | |
| return key($this->hints); | |
| } | |
| /** | |
| * Get the next page definition hint when iterating. | |
| */ | |
| function next() { | |
| next($this->hints); | |
| } | |
| /** | |
| * Check if the current key is valid. | |
| */ | |
| function valid() { | |
| return key($this->hints) ? true : false; | |
| } | |
| /** | |
| * Load the page definition hints as defined in the database. This list | |
| * can be generated from two different viewpoints: | |
| * 1) pages of this page definition can be used x times under pages of | |
| * some other page definition | |
| * ($children==false/PARENT_PAGE_DEFINITION_COUNT), or | |
| * 2) pages of some page definition can occur x times under a page using | |
| * this page definition ($children==true/CHILD_PAGE_DEFINITION_COUNT) | |
| * | |
| * @param boolean $children False (default) if you want to select how | |
| * many times a page using this page definition may occur under pages | |
| * of some other page definition, True if you want to select how many | |
| * times a pages of some other page definition may occur under a page | |
| * using this page definition. | |
| */ | |
| private function load($children=false) { | |
| try { | |
| $this->context->checkPermission(AccessController::READ_ACCESS); | |
| $sth = $this->context->connection->prepare( | |
| "SELECT page_definition_id, title FROM page_definition | |
| WHERE instance_id = :instId ORDER BY title"); | |
| $this->context->connection->bindInstance($sth); | |
| $sth->execute(); | |
| $res = array(); | |
| while ($rd = $sth->fetch(\PDO::FETCH_ASSOC)) { | |
| $k = intval($rd["page_definition_id"]); | |
| $res[$k] = (object)array( | |
| "pageDefinitionId" => $k, | |
| "title" => $rd["title"], | |
| "maxNoOfChildren" => NULL | |
| ); | |
| } | |
| if ($children) { | |
| // CHILD_PAGE_DEFINITION_COUNT | |
| $sth = $this->context->connection->prepare( | |
| "SELECT page_definition_id parent_page_definition_id, max_no_of_children | |
| FROM page_definition_hints WHERE instance_id = :instId AND | |
| parent_page_definition_id = :templId"); | |
| } else { | |
| // PARENT_PAGE_DEFINITION_COUNT | |
| $sth = $this->context->connection->prepare( | |
| "SELECT parent_page_definition_id, max_no_of_children | |
| FROM page_definition_hints WHERE instance_id = :instId AND | |
| page_definition_id = :templId"); | |
| } | |
| $this->context->connection->bindInstance($sth); | |
| $sth->bindValue( | |
| ":templId", $this->pageDefinitionId, \PDO::PARAM_INT); | |
| $sth->execute(); | |
| while ($rd = $sth->fetch(\PDO::FETCH_ASSOC)) { | |
| $k = intval($rd["parent_page_definition_id"]); | |
| if (isset($res[$k])) { | |
| $res[$k]->maxNoOfChildren = | |
| intval($rd["max_no_of_children"]); | |
| } | |
| } | |
| $this->hints = $res; | |
| } catch(\PDOException $e) { | |
| throw new \Scrivo\ResourceException($e); | |
| } | |
| } | |
| /** | |
| * Load the page definition hints as defined in the database, but corrected | |
| * for the currently created pages. This is basically an extion of | |
| * PageDefinitionHints::load(true)/pages of some page definition can occur | |
| * x times under a page using this page | |
| * definition/CHILD_PAGE_DEFINITION_COUNT and a correction for pages that | |
| * are made already. | |
| * | |
| * The parent page is given as an argument, the list generated is a list | |
| * of page definitions and how many times new pages of each page definition | |
| * are still allowed underneath the given page. | |
| * | |
| * @param int $parentId The id of the parent page. | |
| */ | |
| private function loadCorrected($parentId) { | |
| try { | |
| $this->context->checkPermission(AccessController::READ_ACCESS); | |
| $sth = $this->context->connection->prepare( | |
| "SELECT page_definition_id FROM page WHERE instance_id = :instId | |
| AND (has_staging+version) = 0 AND page_id = :docPid"); | |
| $this->context->connection->bindInstance($sth); | |
| $sth->bindValue(":docPid", $parentId, \PDO::PARAM_INT); | |
| $sth->execute(); | |
| if ($sth->rowCount() != 1) { | |
| throw new \Scrivo\SystemException("Failed to load page"); | |
| } | |
| $rd = $sth->fetch(\PDO::FETCH_ASSOC); | |
| $this->pageDefinitionId = $rd["page_definition_id"]; | |
| $this->load(true); | |
| $sth = $this->context->connection->prepare( | |
| "SELECT page_definition_id FROM page WHERE instance_id = :instId | |
| AND (has_staging+version) = 0 AND parent_id = :docPid"); | |
| $this->context->connection->bindInstance($sth); | |
| $sth->bindValue(":docPid", $parentId, \PDO::PARAM_INT); | |
| $sth->execute(); | |
| $res = array(); | |
| while ($rd = $sth->fetch(\PDO::FETCH_ASSOC)) { | |
| $k = intval($rd["page_definition_id"]); | |
| if (!isset($res[$k])) { | |
| $res[$k] = 1; | |
| } else { | |
| $res[$k]++; | |
| } | |
| } | |
| foreach ($res as $used => $count) { | |
| if (isset($this->hints[$used]->maxNoOfChildren)) { | |
| $this->hints[$used]->maxNoOfChildren -= $count; | |
| if ($this->hints[$used]->maxNoOfChildren < 0) { | |
| $this->hints[$used]->maxNoOfChildren = 0; | |
| } | |
| } | |
| } | |
| } catch(\PDOException $e) { | |
| throw new \Scrivo\ResourceException($e); | |
| } | |
| } | |
| /** | |
| * Update a set of page definition hints. Note: It is assumed that you're | |
| * updating a list of type PARENT_PAGE_DEFINITION_COUNT otherwise a | |
| * \Scrivo\SystemException is raised. | |
| */ | |
| public function update() { | |
| try { | |
| if ($this->type != self::PARENT_PAGE_DEFINITION_COUNT) { | |
| throw new \Scrivo\SystemException("Only PageDefinitionHints of". | |
| " type PARENT_PAGE_DEFINITION_COUNT can be updated"); | |
| } | |
| $this->context->checkPermission(AccessController::WRITE_ACCESS); | |
| $sth = $this->context->connection->prepare( | |
| "DELETE FROM page_definition_hints WHERE instance_id = :instId | |
| AND page_definition_id = :templId"); | |
| $this->context->connection->bindInstance($sth); | |
| $sth->bindValue( | |
| ":templId", $this->pageDefinitionId, \PDO::PARAM_INT); | |
| $sth->execute(); | |
| foreach ($this->hints as $k=>$hint) { | |
| if (!is_null($hint->maxNoOfChildren)) { | |
| $sth = $this->context->connection->prepare( | |
| "INSERT INTO page_definition_hints ( | |
| instance_id, parent_page_definition_id, | |
| page_definition_id, max_no_of_children | |
| ) VALUES ( | |
| :instId, :templPid, | |
| :templId, :maxChld | |
| )" | |
| ); | |
| $this->context->connection->bindInstance($sth); | |
| $sth->bindValue(":templPid", $k, \PDO::PARAM_INT); | |
| $sth->bindValue( | |
| ":templId", $this->pageDefinitionId, \PDO::PARAM_INT); | |
| $sth->bindValue( | |
| ":maxChld", $hint->maxNoOfChildren, \PDO::PARAM_INT); | |
| $sth->execute(); | |
| } | |
| } | |
| } catch(\PDOException $e) { | |
| throw new \Scrivo\ResourceException($e); | |
| } | |
| } | |
| } |