File indexing completed on 2024-05-12 06:02:48

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category  Zend
0016  * @package   Zend_Navigation
0017  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0018  * @license   http://framework.zend.com/license/new-bsd     New BSD License
0019  * @version    $Id$
0020  */
0021 
0022 /**
0023  * @see Zend_Navigation_Container
0024  */
0025 // require_once 'Zend/Navigation/Container.php';
0026 
0027 /**
0028  * Base class for Zend_Navigation_Page pages
0029  *
0030  * @category  Zend
0031  * @package   Zend_Navigation
0032  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0033  * @license   http://framework.zend.com/license/new-bsd     New BSD License
0034  */
0035 abstract class Zend_Navigation_Page extends Zend_Navigation_Container
0036 {
0037     /**
0038      * Page label
0039      *
0040      * @var string|null
0041      */
0042     protected $_label;
0043 
0044     /**
0045      * Fragment identifier (anchor identifier)
0046      * 
0047      * The fragment identifier (anchor identifier) pointing to an anchor within 
0048      * a resource that is subordinate to another, primary resource.
0049      * The fragment identifier introduced by a hash mark "#".
0050      * Example: http://www.example.org/foo.html#bar ("bar" is the fragment identifier)
0051      * 
0052      * @link http://www.w3.org/TR/html401/intro/intro.html#fragment-uri
0053      * 
0054      * @var string|null
0055      */
0056     protected $_fragment;
0057 
0058     /**
0059      * Page id
0060      *
0061      * @var string|null
0062      */
0063     protected $_id;
0064 
0065     /**
0066      * Style class for this page (CSS)
0067      *
0068      * @var string|null
0069      */
0070     protected $_class;
0071 
0072     /**
0073      * A more descriptive title for this page
0074      *
0075      * @var string|null
0076      */
0077     protected $_title;
0078 
0079     /**
0080      * This page's target
0081      *
0082      * @var string|null
0083      */
0084     protected $_target;
0085 
0086     /**
0087      * Accessibility key character
0088      *
0089      * This attribute assigns an access key to an element. An access key is a
0090      * single character from the document character set.
0091      *
0092      * @link http://www.w3.org/TR/html401/interact/forms.html#access-keys
0093      *
0094      * @var string|null
0095      */
0096     protected $_accesskey;
0097 
0098     /**
0099      * Forward links to other pages
0100      *
0101      * @link http://www.w3.org/TR/html4/struct/links.html#h-12.3.1
0102      *
0103      * @var array
0104      */
0105     protected $_rel = array();
0106 
0107     /**
0108      * Reverse links to other pages
0109      *
0110      * @link http://www.w3.org/TR/html4/struct/links.html#h-12.3.1
0111      *
0112      * @var array
0113      */
0114     protected $_rev = array();
0115 
0116     /**
0117      * Page order used by parent container
0118      *
0119      * @var int|null
0120      */
0121     protected $_order;
0122 
0123     /**
0124      * ACL resource associated with this page
0125      *
0126      * @var string|Zend_Acl_Resource_Interface|null
0127      */
0128     protected $_resource;
0129 
0130     /**
0131      * ACL privilege associated with this page
0132      *
0133      * @var string|null
0134      */
0135     protected $_privilege;
0136 
0137     /**
0138      * Whether this page should be considered active
0139      *
0140      * @var bool
0141      */
0142     protected $_active = false;
0143 
0144     /**
0145      * Whether this page should be considered visible
0146      *
0147      * @var bool
0148      */
0149     protected $_visible = true;
0150 
0151     /**
0152      * Parent container
0153      *
0154      * @var Zend_Navigation_Container|null
0155      */
0156     protected $_parent;
0157 
0158     /**
0159      * Custom page properties, used by __set(), __get() and __isset()
0160      *
0161      * @var array
0162      */
0163     protected $_properties = array();
0164 
0165     /**
0166      * Custom HTML attributes
0167      *
0168      * @var array
0169      */
0170     protected $_customHtmlAttribs = array();
0171 
0172     /**
0173      * The type of page to use when it wasn't set
0174      *
0175      * @var string
0176      */
0177     protected static $_defaultPageType;
0178 
0179     // Initialization:
0180 
0181     /**
0182      * Factory for Zend_Navigation_Page classes
0183      *
0184      * A specific type to construct can be specified by specifying the key
0185      * 'type' in $options. If type is 'uri' or 'mvc', the type will be resolved
0186      * to Zend_Navigation_Page_Uri or Zend_Navigation_Page_Mvc. Any other value
0187      * for 'type' will be considered the full name of the class to construct.
0188      * A valid custom page class must extend Zend_Navigation_Page.
0189      *
0190      * If 'type' is not given, the type of page to construct will be determined
0191      * by the following rules:
0192      * - If $options contains either of the keys 'action', 'controller',
0193      *   'module', or 'route', a Zend_Navigation_Page_Mvc page will be created.
0194      * - If $options contains the key 'uri', a Zend_Navigation_Page_Uri page
0195      *   will be created.
0196      *
0197      * @param  array|Zend_Config $options  options used for creating page
0198      * @return Zend_Navigation_Page        a page instance
0199      * @throws Zend_Navigation_Exception   if $options is not array/Zend_Config
0200      * @throws Zend_Exception              if 'type' is specified and
0201      *                                     Zend_Loader is unable to load the
0202      *                                     class
0203      * @throws Zend_Navigation_Exception   if something goes wrong during
0204      *                                     instantiation of the page
0205      * @throws Zend_Navigation_Exception   if 'type' is given, and the specified
0206      *                                     type does not extend this class
0207      * @throws Zend_Navigation_Exception   if unable to determine which class
0208      *                                     to instantiate
0209      */
0210     public static function factory($options)
0211     {
0212         if ($options instanceof Zend_Config) {
0213             $options = $options->toArray();
0214         }
0215 
0216         if (!is_array($options)) {
0217             // require_once 'Zend/Navigation/Exception.php';
0218             throw new Zend_Navigation_Exception(
0219                 'Invalid argument: $options must be an array or Zend_Config');
0220         }
0221 
0222         if (isset($options['type'])) {
0223             $type = $options['type'];
0224         } elseif(self::getDefaultPageType()!= null) {
0225             $type = self::getDefaultPageType();
0226         }
0227 
0228         if(isset($type)) {
0229             if (is_string($type) && !empty($type)) {
0230                 switch (strtolower($type)) {
0231                     case 'mvc':
0232                         $type = 'Zend_Navigation_Page_Mvc';
0233                         break;
0234                     case 'uri':
0235                         $type = 'Zend_Navigation_Page_Uri';
0236                         break;
0237                 }
0238 
0239                 if (!class_exists($type)) {
0240                     // require_once 'Zend/Loader.php';
0241                     @Zend_Loader::loadClass($type);
0242                 }
0243 
0244                 $page = new $type($options);
0245                 if (!$page instanceof Zend_Navigation_Page) {
0246                     // require_once 'Zend/Navigation/Exception.php';
0247                     throw new Zend_Navigation_Exception(sprintf(
0248                             'Invalid argument: Detected type "%s", which ' .
0249                             'is not an instance of Zend_Navigation_Page',
0250                             $type));
0251                 }
0252                 return $page;
0253             }
0254         }
0255 
0256         $hasUri = isset($options['uri']);
0257         $hasMvc = isset($options['action']) || isset($options['controller']) ||
0258                   isset($options['module']) || isset($options['route']) ||
0259                   isset($options['params']);
0260 
0261         if ($hasMvc) {
0262             // require_once 'Zend/Navigation/Page/Mvc.php';
0263             return new Zend_Navigation_Page_Mvc($options);
0264         } elseif ($hasUri) {
0265             // require_once 'Zend/Navigation/Page/Uri.php';
0266             return new Zend_Navigation_Page_Uri($options);
0267         } else {
0268             // require_once 'Zend/Navigation/Exception.php';
0269             
0270             $message = 'Invalid argument: Unable to determine class to instantiate';
0271             if (isset($options['label'])) {
0272                 $message .= ' (Page label: ' . $options['label'] . ')';
0273         }
0274             
0275             throw new Zend_Navigation_Exception($message);
0276     }
0277     }
0278 
0279     /**
0280      * Page constructor
0281      *
0282      * @param  array|Zend_Config $options   [optional] page options. Default is
0283      *                                      null, which should set defaults.
0284      * @throws Zend_Navigation_Exception    if invalid options are given
0285      */
0286     public function __construct($options = null)
0287     {
0288         if (is_array($options)) {
0289             $this->setOptions($options);
0290         } elseif ($options instanceof Zend_Config) {
0291             $this->setConfig($options);
0292         }
0293 
0294         // do custom initialization
0295         $this->_init();
0296     }
0297 
0298     /**
0299      * Initializes page (used by subclasses)
0300      *
0301      * @return void
0302      */
0303     protected function _init()
0304     {
0305     }
0306 
0307     /**
0308      * Sets page properties using a Zend_Config object
0309      *
0310      * @param  Zend_Config $config        config object to get properties from
0311      * @return Zend_Navigation_Page       fluent interface, returns self
0312      * @throws Zend_Navigation_Exception  if invalid options are given
0313      */
0314     public function setConfig(Zend_Config $config)
0315     {
0316         return $this->setOptions($config->toArray());
0317     }
0318 
0319     /**
0320      * Sets page properties using options from an associative array
0321      *
0322      * Each key in the array corresponds to the according set*() method, and
0323      * each word is separated by underscores, e.g. the option 'target'
0324      * corresponds to setTarget(), and the option 'reset_params' corresponds to
0325      * the method setResetParams().
0326      *
0327      * @param  array $options             associative array of options to set
0328      * @return Zend_Navigation_Page       fluent interface, returns self
0329      * @throws Zend_Navigation_Exception  if invalid options are given
0330      */
0331     public function setOptions(array $options)
0332     {
0333         foreach ($options as $key => $value) {
0334             $this->set($key, $value);
0335         }
0336 
0337         return $this;
0338     }
0339 
0340     // Accessors:
0341 
0342     /**
0343      * Sets page label
0344      *
0345      * @param  string $label              new page label
0346      * @return Zend_Navigation_Page       fluent interface, returns self
0347      * @throws Zend_Navigation_Exception  if empty/no string is given
0348      */
0349     public function setLabel($label)
0350     {
0351         if (null !== $label && !is_string($label)) {
0352             // require_once 'Zend/Navigation/Exception.php';
0353             throw new Zend_Navigation_Exception(
0354                     'Invalid argument: $label must be a string or null');
0355         }
0356 
0357         $this->_label = $label;
0358         return $this;
0359     }
0360 
0361     /**
0362      * Returns page label
0363      *
0364      * @return string  page label or null
0365      */
0366     public function getLabel()
0367     {
0368         return $this->_label;
0369     }
0370 
0371     /**
0372      * Sets a fragment identifier
0373      *
0374      * @param  string $fragment   new fragment identifier
0375      * @return Zend_Navigation_Page         fluent interface, returns self
0376      * @throws Zend_Navigation_Exception    if empty/no string is given
0377      */
0378     public function setFragment($fragment)
0379     {
0380         if (null !== $fragment && !is_string($fragment)) {
0381             // require_once 'Zend/Navigation/Exception.php';
0382             throw new Zend_Navigation_Exception(
0383                     'Invalid argument: $fragment must be a string or null');
0384         }
0385  
0386         $this->_fragment = $fragment;
0387         return $this;
0388     }
0389     
0390      /**
0391      * Returns fragment identifier
0392      *
0393      * @return string|null  fragment identifier
0394      */
0395     public function getFragment()
0396     {
0397         return $this->_fragment;
0398     }
0399 
0400     /**
0401      * Sets page id
0402      *
0403      * @param  string|null $id            [optional] id to set. Default is null,
0404      *                                    which sets no id.
0405      * @return Zend_Navigation_Page       fluent interface, returns self
0406      * @throws Zend_Navigation_Exception  if not given string or null
0407      */
0408     public function setId($id = null)
0409     {
0410         if (null !== $id && !is_string($id) && !is_numeric($id)) {
0411             // require_once 'Zend/Navigation/Exception.php';
0412             throw new Zend_Navigation_Exception(
0413                     'Invalid argument: $id must be a string, number or null');
0414         }
0415 
0416         $this->_id = null === $id ? $id : (string) $id;
0417 
0418         return $this;
0419     }
0420 
0421     /**
0422      * Returns page id
0423      *
0424      * @return string|null  page id or null
0425      */
0426     public function getId()
0427     {
0428         return $this->_id;
0429     }
0430 
0431     /**
0432      * Sets page CSS class
0433      *
0434      * @param  string|null $class         [optional] CSS class to set. Default
0435      *                                    is null, which sets no CSS class.
0436      * @return Zend_Navigation_Page       fluent interface, returns self
0437      * @throws Zend_Navigation_Exception  if not given string or null
0438      */
0439     public function setClass($class = null)
0440     {
0441         if (null !== $class && !is_string($class)) {
0442             // require_once 'Zend/Navigation/Exception.php';
0443             throw new Zend_Navigation_Exception(
0444                     'Invalid argument: $class must be a string or null');
0445         }
0446 
0447         $this->_class = $class;
0448         return $this;
0449     }
0450 
0451     /**
0452      * Returns page class (CSS)
0453      *
0454      * @return string|null  page's CSS class or null
0455      */
0456     public function getClass()
0457     {
0458         return $this->_class;
0459     }
0460 
0461     /**
0462      * Sets page title
0463      *
0464      * @param  string $title              [optional] page title. Default is
0465      *                                    null, which sets no title.
0466      * @return Zend_Navigation_Page       fluent interface, returns self
0467      * @throws Zend_Navigation_Exception  if not given string or null
0468      */
0469     public function setTitle($title = null)
0470     {
0471         if (null !== $title && !is_string($title)) {
0472             // require_once 'Zend/Navigation/Exception.php';
0473             throw new Zend_Navigation_Exception(
0474                     'Invalid argument: $title must be a non-empty string');
0475         }
0476 
0477         $this->_title = $title;
0478         return $this;
0479     }
0480 
0481     /**
0482      * Returns page title
0483      *
0484      * @return string|null  page title or null
0485      */
0486     public function getTitle()
0487     {
0488         return $this->_title;
0489     }
0490 
0491     /**
0492      * Sets page target
0493      *
0494      * @param  string|null $target        [optional] target to set. Default is
0495      *                                    null, which sets no target.
0496      * @return Zend_Navigation_Page       fluent interface, returns self
0497      * @throws Zend_Navigation_Exception  if target is not string or null
0498      */
0499     public function setTarget($target = null)
0500     {
0501         if (null !== $target && !is_string($target)) {
0502             // require_once 'Zend/Navigation/Exception.php';
0503             throw new Zend_Navigation_Exception(
0504                     'Invalid argument: $target must be a string or null');
0505         }
0506 
0507         $this->_target = $target;
0508         return $this;
0509     }
0510 
0511     /**
0512      * Returns page target
0513      *
0514      * @return string|null  page target or null
0515      */
0516     public function getTarget()
0517     {
0518         return $this->_target;
0519     }
0520 
0521     /**
0522      * Sets access key for this page
0523      *
0524      * @param  string|null $character     [optional] access key to set. Default
0525      *                                    is null, which sets no access key.
0526      * @return Zend_Navigation_Page       fluent interface, returns self
0527      * @throws Zend_Navigation_Exception  if access key is not string or null or
0528      *                                    if the string length not equal to one
0529      */
0530     public function setAccesskey($character = null)
0531     {
0532         if (null !== $character
0533             && (!is_string($character) || 1 != strlen($character)))
0534         {
0535             // require_once 'Zend/Navigation/Exception.php';
0536             throw new Zend_Navigation_Exception(
0537                 'Invalid argument: $character must be a single character or null'
0538             );
0539         }
0540  
0541         $this->_accesskey = $character;
0542         return $this;
0543     }
0544 
0545      /**
0546      * Returns page access key
0547      *
0548      * @return string|null  page access key or null
0549      */
0550     public function getAccesskey()
0551     {
0552         return $this->_accesskey;
0553     }
0554 
0555     /**
0556      * Sets the page's forward links to other pages
0557      *
0558      * This method expects an associative array of forward links to other pages,
0559      * where each element's key is the name of the relation (e.g. alternate,
0560      * prev, next, help, etc), and the value is a mixed value that could somehow
0561      * be considered a page.
0562      *
0563      * @param  array|Zend_Config $relations  [optional] an associative array of
0564      *                                       forward links to other pages
0565      * @return Zend_Navigation_Page          fluent interface, returns self
0566      */
0567     public function setRel($relations = null)
0568     {
0569         $this->_rel = array();
0570 
0571         if (null !== $relations) {
0572             if ($relations instanceof Zend_Config) {
0573                 $relations = $relations->toArray();
0574             }
0575 
0576             if (!is_array($relations)) {
0577                 // require_once 'Zend/Navigation/Exception.php';
0578                 throw new Zend_Navigation_Exception(
0579                         'Invalid argument: $relations must be an ' .
0580                         'array or an instance of Zend_Config');
0581             }
0582 
0583             foreach ($relations as $name => $relation) {
0584                 if (is_string($name)) {
0585                     $this->_rel[$name] = $relation;
0586                 }
0587             }
0588         }
0589 
0590         return $this;
0591     }
0592 
0593     /**
0594      * Returns the page's forward links to other pages
0595      *
0596      * This method returns an associative array of forward links to other pages,
0597      * where each element's key is the name of the relation (e.g. alternate,
0598      * prev, next, help, etc), and the value is a mixed value that could somehow
0599      * be considered a page.
0600      *
0601      * @param  string $relation  [optional] name of relation to return. If not
0602      *                           given, all relations will be returned.
0603      * @return array             an array of relations. If $relation is not
0604      *                           specified, all relations will be returned in
0605      *                           an associative array.
0606      */
0607     public function getRel($relation = null)
0608     {
0609         if (null !== $relation) {
0610             return isset($this->_rel[$relation]) ?
0611                    $this->_rel[$relation] :
0612                    null;
0613         }
0614 
0615         return $this->_rel;
0616     }
0617 
0618     /**
0619      * Sets the page's reverse links to other pages
0620      *
0621      * This method expects an associative array of reverse links to other pages,
0622      * where each element's key is the name of the relation (e.g. alternate,
0623      * prev, next, help, etc), and the value is a mixed value that could somehow
0624      * be considered a page.
0625      *
0626      * @param  array|Zend_Config $relations  [optional] an associative array of
0627      *                                       reverse links to other pages
0628      * @return Zend_Navigation_Page          fluent interface, returns self
0629      */
0630     public function setRev($relations = null)
0631     {
0632         $this->_rev = array();
0633 
0634         if (null !== $relations) {
0635             if ($relations instanceof Zend_Config) {
0636                 $relations = $relations->toArray();
0637             }
0638 
0639             if (!is_array($relations)) {
0640                 // require_once 'Zend/Navigation/Exception.php';
0641                 throw new Zend_Navigation_Exception(
0642                         'Invalid argument: $relations must be an ' .
0643                         'array or an instance of Zend_Config');
0644             }
0645 
0646             foreach ($relations as $name => $relation) {
0647                 if (is_string($name)) {
0648                     $this->_rev[$name] = $relation;
0649                 }
0650             }
0651         }
0652 
0653         return $this;
0654     }
0655 
0656     /**
0657      * Returns the page's reverse links to other pages
0658      *
0659      * This method returns an associative array of forward links to other pages,
0660      * where each element's key is the name of the relation (e.g. alternate,
0661      * prev, next, help, etc), and the value is a mixed value that could somehow
0662      * be considered a page.
0663      *
0664      * @param  string $relation  [optional] name of relation to return. If not
0665      *                           given, all relations will be returned.
0666      * @return array             an array of relations. If $relation is not
0667      *                           specified, all relations will be returned in
0668      *                           an associative array.
0669      */
0670     public function getRev($relation = null)
0671     {
0672         if (null !== $relation) {
0673             return isset($this->_rev[$relation]) ?
0674                    $this->_rev[$relation] :
0675                    null;
0676         }
0677 
0678         return $this->_rev;
0679     }
0680 
0681     /**
0682      * Sets a single custom HTML attribute
0683      *
0684      * @param  string      $name            name of the HTML attribute
0685      * @param  string|null $value           value for the HTML attribute
0686      * @return Zend_Navigation_Page         fluent interface, returns self
0687      * @throws Zend_Navigation_Exception    if name is not string or value is
0688      *                                      not null or a string
0689      */
0690     public function setCustomHtmlAttrib($name, $value)
0691     {
0692         if (!is_string($name)) {
0693             // require_once 'Zend/Navigation/Exception.php';
0694             throw new Zend_Navigation_Exception(
0695                 'Invalid argument: $name must be a string'
0696             );
0697         }
0698 
0699         if (null !== $value && !is_string($value)) {
0700             // require_once 'Zend/Navigation/Exception.php';
0701             throw new Zend_Navigation_Exception(
0702                 'Invalid argument: $value must be a string or null'
0703             );
0704         }
0705 
0706         if (null === $value && isset($this->_customHtmlAttribs[$name])) {
0707             unset($this->_customHtmlAttribs[$name]);
0708         } else {
0709             $this->_customHtmlAttribs[$name] = $value;
0710         }
0711 
0712         return $this;
0713     }
0714 
0715     /**
0716      * Returns a single custom HTML attributes by name
0717      *
0718      * @param  string $name                 name of the HTML attribute
0719      * @return string|null                  value for the HTML attribute or null
0720      * @throws Zend_Navigation_Exception    if name is not string
0721      */
0722     public function getCustomHtmlAttrib($name)
0723     {
0724         if (!is_string($name)) {
0725             // require_once 'Zend/Navigation/Exception.php';
0726             throw new Zend_Navigation_Exception(
0727                 'Invalid argument: $name must be a string'
0728             );
0729         }
0730 
0731         if (isset($this->_customHtmlAttribs[$name])) {
0732             return $this->_customHtmlAttribs[$name];
0733         }
0734 
0735         return null;
0736     }
0737 
0738     /**
0739      * Sets multiple custom HTML attributes at once
0740      *
0741      * @param array $attribs        an associative array of html attributes
0742      * @return Zend_Navigation_Page fluent interface, returns self
0743      */
0744     public function setCustomHtmlAttribs(array $attribs)
0745     {
0746         foreach ($attribs as $key => $value) {
0747             $this->setCustomHtmlAttrib($key, $value);
0748         }
0749         return $this;
0750     }
0751 
0752     /**
0753      * Returns all custom HTML attributes as an array
0754      *
0755      * @return array    an array containing custom HTML attributes
0756      */
0757     public function getCustomHtmlAttribs()
0758     {
0759         return $this->_customHtmlAttribs;
0760     }
0761 
0762     /**
0763      * Removes a custom HTML attribute from the page
0764      *
0765      * @param  string $name          name of the custom HTML attribute
0766      * @return Zend_Navigation_Page  fluent interface, returns self
0767      */
0768     public function removeCustomHtmlAttrib($name)
0769     {
0770         if (!is_string($name)) {
0771             // require_once 'Zend/Navigation/Exception.php';
0772             throw new Zend_Navigation_Exception(
0773                 'Invalid argument: $name must be a string'
0774             );
0775         }
0776 
0777         if (isset($this->_customHtmlAttribs[$name])) {
0778             unset($this->_customHtmlAttribs[$name]);
0779         }
0780     }
0781 
0782     /**
0783      * Clear all custom HTML attributes
0784      *
0785      * @return Zend_Navigation_Page fluent interface, returns self
0786      */
0787     public function clearCustomHtmlAttribs()
0788     {
0789         $this->_customHtmlAttribs = array();
0790 
0791         return $this;
0792     }
0793 
0794     /**
0795      * Sets page order to use in parent container
0796      *
0797      * @param  int $order                 [optional] page order in container.
0798      *                                    Default is null, which sets no
0799      *                                    specific order.
0800      * @return Zend_Navigation_Page       fluent interface, returns self
0801      * @throws Zend_Navigation_Exception  if order is not integer or null
0802      */
0803     public function setOrder($order = null)
0804     {
0805         if (is_string($order)) {
0806             $temp = (int) $order;
0807             if ($temp < 0 || $temp > 0 || $order == '0') {
0808                 $order = $temp;
0809             }
0810         }
0811 
0812         if (null !== $order && !is_int($order)) {
0813             // require_once 'Zend/Navigation/Exception.php';
0814             throw new Zend_Navigation_Exception(
0815                     'Invalid argument: $order must be an integer or null, ' .
0816                     'or a string that casts to an integer');
0817         }
0818 
0819         $this->_order = $order;
0820 
0821         // notify parent, if any
0822         if (isset($this->_parent)) {
0823             $this->_parent->notifyOrderUpdated();
0824         }
0825 
0826         return $this;
0827     }
0828 
0829     /**
0830      * Returns page order used in parent container
0831      *
0832      * @return int|null  page order or null
0833      */
0834     public function getOrder()
0835     {
0836         return $this->_order;
0837     }
0838 
0839     /**
0840      * Sets ACL resource assoicated with this page
0841      *
0842      * @param  string|Zend_Acl_Resource_Interface $resource  [optional] resource
0843      *                                                       to associate with
0844      *                                                       page. Default is
0845      *                                                       null, which sets no
0846      *                                                       resource.
0847      * @throws Zend_Navigation_Exception                     if $resource if
0848      *                                                       invalid
0849      * @return Zend_Navigation_Page                          fluent interface,
0850      *                                                       returns self
0851      */
0852     public function setResource($resource = null)
0853     {
0854         if (null === $resource || is_string($resource) ||
0855             $resource instanceof Zend_Acl_Resource_Interface) {
0856             $this->_resource = $resource;
0857         } else {
0858             // require_once 'Zend/Navigation/Exception.php';
0859             throw new Zend_Navigation_Exception(
0860                     'Invalid argument: $resource must be null, a string, ' .
0861                     ' or an instance of Zend_Acl_Resource_Interface');
0862         }
0863 
0864         return $this;
0865     }
0866 
0867     /**
0868      * Returns ACL resource assoicated with this page
0869      *
0870      * @return string|Zend_Acl_Resource_Interface|null  ACL resource or null
0871      */
0872     public function getResource()
0873     {
0874         return $this->_resource;
0875     }
0876 
0877     /**
0878      * Sets ACL privilege associated with this page
0879      *
0880      * @param  string|null $privilege  [optional] ACL privilege to associate
0881      *                                 with this page. Default is null, which
0882      *                                 sets no privilege.
0883      * @return Zend_Navigation_Page    fluent interface, returns self
0884      */
0885     public function setPrivilege($privilege = null)
0886     {
0887         $this->_privilege = is_string($privilege) ? $privilege : null;
0888         return $this;
0889     }
0890 
0891     /**
0892      * Returns ACL privilege associated with this page
0893      *
0894      * @return string|null  ACL privilege or null
0895      */
0896     public function getPrivilege()
0897     {
0898         return $this->_privilege;
0899     }
0900 
0901     /**
0902      * Sets whether page should be considered active or not
0903      *
0904      * @param  bool $active          [optional] whether page should be
0905      *                               considered active or not. Default is true.
0906      * @return Zend_Navigation_Page  fluent interface, returns self
0907      */
0908     public function setActive($active = true)
0909     {
0910         $this->_active = (bool) $active;
0911         return $this;
0912     }
0913 
0914     /**
0915      * Returns whether page should be considered active or not
0916      *
0917      * @param  bool $recursive  [optional] whether page should be considered
0918      *                          active if any child pages are active. Default is
0919      *                          false.
0920      * @return bool             whether page should be considered active
0921      */
0922     public function isActive($recursive = false)
0923     {
0924         if (!$this->_active && $recursive) {
0925             foreach ($this->_pages as $page) {
0926                 if ($page->isActive(true)) {
0927                     return true;
0928                 }
0929             }
0930             return false;
0931         }
0932 
0933         return $this->_active;
0934     }
0935 
0936     /**
0937      * Proxy to isActive()
0938      *
0939      * @param  bool $recursive  [optional] whether page should be considered
0940      *                          active if any child pages are active. Default
0941      *                          is false.
0942      * @return bool             whether page should be considered active
0943      */
0944     public function getActive($recursive = false)
0945     {
0946         return $this->isActive($recursive);
0947     }
0948 
0949     /**
0950      * Sets whether the page should be visible or not
0951      *
0952      * @param  bool $visible         [optional] whether page should be
0953      *                               considered visible or not. Default is true.
0954      * @return Zend_Navigation_Page  fluent interface, returns self
0955      */
0956     public function setVisible($visible = true)
0957     {
0958         if (is_string($visible) && 'false' == strtolower($visible)) {
0959             $visible = false;
0960         }
0961         $this->_visible = (bool) $visible;
0962         return $this;
0963     }
0964 
0965     /**
0966      * Returns a boolean value indicating whether the page is visible
0967      *
0968      * @param  bool $recursive  [optional] whether page should be considered
0969      *                          invisible if parent is invisible. Default is
0970      *                          false.
0971      * @return bool             whether page should be considered visible
0972      */
0973     public function isVisible($recursive = false)
0974     {
0975         if ($recursive && isset($this->_parent) &&
0976             $this->_parent instanceof Zend_Navigation_Page) {
0977             if (!$this->_parent->isVisible(true)) {
0978                 return false;
0979             }
0980         }
0981 
0982         return $this->_visible;
0983     }
0984 
0985     /**
0986      * Proxy to isVisible()
0987      *
0988      * Returns a boolean value indicating whether the page is visible
0989      *
0990      * @param  bool $recursive  [optional] whether page should be considered
0991      *                          invisible if parent is invisible. Default is
0992      *                          false.
0993      * @return bool             whether page should be considered visible
0994      */
0995     public function getVisible($recursive = false)
0996     {
0997         return $this->isVisible($recursive);
0998     }
0999 
1000     /**
1001      * Sets parent container
1002      *
1003      * @param  Zend_Navigation_Container $parent  [optional] new parent to set.
1004      *                                            Default is null which will set
1005      *                                            no parent.
1006      * @return Zend_Navigation_Page               fluent interface, returns self
1007      */
1008     public function setParent(Zend_Navigation_Container $parent = null)
1009     {
1010         if ($parent === $this) {
1011             // require_once 'Zend/Navigation/Exception.php';
1012             throw new Zend_Navigation_Exception(
1013                 'A page cannot have itself as a parent');
1014         }
1015 
1016         // return if the given parent already is parent
1017         if ($parent === $this->_parent) {
1018             return $this;
1019         }
1020 
1021         // remove from old parent
1022         if (null !== $this->_parent) {
1023             $this->_parent->removePage($this);
1024         }
1025 
1026         // set new parent
1027         $this->_parent = $parent;
1028 
1029         // add to parent if page and not already a child
1030         if (null !== $this->_parent && !$this->_parent->hasPage($this, false)) {
1031             $this->_parent->addPage($this);
1032         }
1033 
1034         return $this;
1035     }
1036 
1037     /**
1038      * Returns parent container
1039      *
1040      * @return Zend_Navigation_Container|null  parent container or null
1041      */
1042     public function getParent()
1043     {
1044         return $this->_parent;
1045     }
1046 
1047     /**
1048      * Sets the given property
1049      *
1050      * If the given property is native (id, class, title, etc), the matching
1051      * set method will be used. Otherwise, it will be set as a custom property.
1052      *
1053      * @param  string $property           property name
1054      * @param  mixed  $value              value to set
1055      * @return Zend_Navigation_Page       fluent interface, returns self
1056      * @throws Zend_Navigation_Exception  if property name is invalid
1057      */
1058     public function set($property, $value)
1059     {
1060         if (!is_string($property) || empty($property)) {
1061             // require_once 'Zend/Navigation/Exception.php';
1062             throw new Zend_Navigation_Exception(
1063                     'Invalid argument: $property must be a non-empty string');
1064         }
1065 
1066         $method = 'set' . self::_normalizePropertyName($property);
1067 
1068         if ($method != 'setOptions' && $method != 'setConfig' &&
1069             method_exists($this, $method)) {
1070             $this->$method($value);
1071         } else {
1072             $this->_properties[$property] = $value;
1073         }
1074 
1075         return $this;
1076     }
1077 
1078     /**
1079      * Returns the value of the given property
1080      *
1081      * If the given property is native (id, class, title, etc), the matching
1082      * get method will be used. Otherwise, it will return the matching custom
1083      * property, or null if not found.
1084      *
1085      * @param  string $property           property name
1086      * @return mixed                      the property's value or null
1087      * @throws Zend_Navigation_Exception  if property name is invalid
1088      */
1089     public function get($property)
1090     {
1091         if (!is_string($property) || empty($property)) {
1092             // require_once 'Zend/Navigation/Exception.php';
1093             throw new Zend_Navigation_Exception(
1094                     'Invalid argument: $property must be a non-empty string');
1095         }
1096 
1097         $method = 'get' . self::_normalizePropertyName($property);
1098 
1099         if (method_exists($this, $method)) {
1100             return $this->$method();
1101         } elseif (isset($this->_properties[$property])) {
1102             return $this->_properties[$property];
1103         }
1104 
1105         return null;
1106     }
1107 
1108     // Magic overloads:
1109 
1110     /**
1111      * Sets a custom property
1112      *
1113      * Magic overload for enabling <code>$page->propname = $value</code>.
1114      *
1115      * @param  string $name               property name
1116      * @param  mixed  $value              value to set
1117      * @return void
1118      * @throws Zend_Navigation_Exception  if property name is invalid
1119      */
1120     public function __set($name, $value)
1121     {
1122         $this->set($name, $value);
1123     }
1124 
1125     /**
1126      * Returns a property, or null if it doesn't exist
1127      *
1128      * Magic overload for enabling <code>$page->propname</code>.
1129      *
1130      * @param  string $name               property name
1131      * @return mixed                      property value or null
1132      * @throws Zend_Navigation_Exception  if property name is invalid
1133      */
1134     public function __get($name)
1135     {
1136         return $this->get($name);
1137     }
1138 
1139     /**
1140      * Checks if a property is set
1141      *
1142      * Magic overload for enabling <code>isset($page->propname)</code>.
1143      *
1144      * Returns true if the property is native (id, class, title, etc), and
1145      * true or false if it's a custom property (depending on whether the
1146      * property actually is set).
1147      *
1148      * @param  string $name  property name
1149      * @return bool          whether the given property exists
1150      */
1151     public function __isset($name)
1152     {
1153         $method = 'get' . self::_normalizePropertyName($name);
1154         if (method_exists($this, $method)) {
1155             return true;
1156         }
1157 
1158         return isset($this->_properties[$name]);
1159     }
1160 
1161     /**
1162      * Unsets the given custom property
1163      *
1164      * Magic overload for enabling <code>unset($page->propname)</code>.
1165      *
1166      * @param  string $name               property name
1167      * @return void
1168      * @throws Zend_Navigation_Exception  if the property is native
1169      */
1170     public function __unset($name)
1171     {
1172         $method = 'set' . self::_normalizePropertyName($name);
1173         if (method_exists($this, $method)) {
1174             // require_once 'Zend/Navigation/Exception.php';
1175             throw new Zend_Navigation_Exception(sprintf(
1176                     'Unsetting native property "%s" is not allowed',
1177                     $name));
1178         }
1179 
1180         if (isset($this->_properties[$name])) {
1181             unset($this->_properties[$name]);
1182         }
1183     }
1184 
1185     /**
1186      * Returns page label
1187      *
1188      * Magic overload for enabling <code>echo $page</code>.
1189      *
1190      * @return string  page label
1191      */
1192     public function __toString()
1193     {
1194         return $this->_label;
1195     }
1196 
1197     // Public methods:
1198 
1199     /**
1200      * Adds a forward relation to the page
1201      *
1202      * @param  string $relation      relation name (e.g. alternate, glossary,
1203      *                               canonical, etc)
1204      * @param  mixed  $value         value to set for relation
1205      * @return Zend_Navigation_Page  fluent interface, returns self
1206      */
1207     public function addRel($relation, $value)
1208     {
1209         if (is_string($relation)) {
1210             $this->_rel[$relation] = $value;
1211         }
1212         return $this;
1213     }
1214 
1215     /**
1216      * Adds a reverse relation to the page
1217      *
1218      * @param  string $relation      relation name (e.g. alternate, glossary,
1219      *                               canonical, etc)
1220      * @param  mixed  $value         value to set for relation
1221      * @return Zend_Navigation_Page  fluent interface, returns self
1222      */
1223     public function addRev($relation, $value)
1224     {
1225         if (is_string($relation)) {
1226             $this->_rev[$relation] = $value;
1227         }
1228         return $this;
1229     }
1230 
1231     /**
1232      * Removes a forward relation from the page
1233      *
1234      * @param  string $relation      name of relation to remove
1235      * @return Zend_Navigation_Page  fluent interface, returns self
1236      */
1237     public function removeRel($relation)
1238     {
1239         if (isset($this->_rel[$relation])) {
1240             unset($this->_rel[$relation]);
1241         }
1242 
1243         return $this;
1244     }
1245 
1246     /**
1247      * Removes a reverse relation from the page
1248      *
1249      * @param  string $relation      name of relation to remove
1250      * @return Zend_Navigation_Page  fluent interface, returns self
1251      */
1252     public function removeRev($relation)
1253     {
1254         if (isset($this->_rev[$relation])) {
1255             unset($this->_rev[$relation]);
1256         }
1257 
1258         return $this;
1259     }
1260 
1261     /**
1262      * Returns an array containing the defined forward relations
1263      *
1264      * @return array  defined forward relations
1265      */
1266     public function getDefinedRel()
1267     {
1268         return array_keys($this->_rel);
1269     }
1270 
1271     /**
1272      * Returns an array containing the defined reverse relations
1273      *
1274      * @return array  defined reverse relations
1275      */
1276     public function getDefinedRev()
1277     {
1278         return array_keys($this->_rev);
1279     }
1280 
1281     /**
1282      * Returns custom properties as an array
1283      *
1284      * @return array  an array containing custom properties
1285      */
1286     public function getCustomProperties()
1287     {
1288         return $this->_properties;
1289     }
1290 
1291     /**
1292      * Returns a hash code value for the page
1293      *
1294      * @return string  a hash code value for this page
1295      */
1296     public final function hashCode()
1297     {
1298         return spl_object_hash($this);
1299     }
1300 
1301     /**
1302      * Returns an array representation of the page
1303      *
1304      * @return array  associative array containing all page properties
1305      */
1306     public function toArray()
1307     {
1308         return array_merge(
1309             $this->getCustomProperties(),
1310             array(
1311                 'label'             => $this->getlabel(),
1312                 'fragment'          => $this->getFragment(),
1313                 'id'                => $this->getId(),
1314                 'class'             => $this->getClass(),
1315                 'title'             => $this->getTitle(),
1316                 'target'            => $this->getTarget(),
1317                 'accesskey'         => $this->getAccesskey(),
1318                 'rel'               => $this->getRel(),
1319                 'rev'               => $this->getRev(),
1320                 'customHtmlAttribs' => $this->getCustomHtmlAttribs(),
1321                 'order'             => $this->getOrder(),
1322                 'resource'          => $this->getResource(),
1323                 'privilege'         => $this->getPrivilege(),
1324                 'active'            => $this->isActive(),
1325                 'visible'           => $this->isVisible(),
1326                 'type'              => get_class($this),
1327                 'pages'             => parent::toArray()
1328             )
1329         );
1330     }
1331 
1332     // Internal methods:
1333 
1334     /**
1335      * Normalizes a property name
1336      *
1337      * @param  string $property  property name to normalize
1338      * @return string            normalized property name
1339      */
1340     protected static function _normalizePropertyName($property)
1341     {
1342         return str_replace(' ', '', ucwords(str_replace('_', ' ', $property)));
1343     }
1344 
1345     public static function setDefaultPageType($type = null) {
1346         if($type !== null && !is_string($type)) {
1347             throw new Zend_Navigation_Exception(
1348                 'Cannot set default page type: type is no string but should be'
1349             );
1350         }
1351 
1352         self::$_defaultPageType = $type;
1353     }
1354 
1355     public static function getDefaultPageType() {
1356         return self::$_defaultPageType;
1357     }
1358 
1359     // Abstract methods:
1360 
1361     /**
1362      * Returns href for this page
1363      *
1364      * @return string  the page's href
1365      */
1366     abstract public function getHref();
1367 }