File indexing completed on 2024-12-29 05:28:09

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_Tool
0017  * @subpackage Framework
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  * @version    $Id$
0021  */
0022 
0023 /**
0024  * @see Zend_Tool_Project_Profile_Resource_SearchConstraints
0025  */
0026 // require_once 'Zend/Tool/Project/Profile/Resource/SearchConstraints.php';
0027 
0028 /**
0029  * This class is an iterator that will iterate only over enabled resources
0030  *
0031  * @category   Zend
0032  * @package    Zend_Tool
0033  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0034  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0035  */
0036 class Zend_Tool_Project_Profile_Resource_Container implements RecursiveIterator, Countable
0037 {
0038 
0039     /**
0040      * @var array
0041      */
0042     protected $_subResources = array();
0043 
0044     /**
0045      * @var int
0046      */
0047     protected $_position = 0;
0048 
0049     /**
0050      * @var bool
0051      */
0052     protected $_appendable = true;
0053 
0054     /**
0055      * @var array
0056      */
0057     protected $_attributes = array();
0058 
0059     /**
0060      * Finder method to be able to find resources by context name
0061      * and attributes.  Example usage:
0062      *
0063      * <code>
0064      *
0065      * </code>
0066      *
0067      * @param Zend_Tool_Project_Profile_Resource_SearchConstraints|string|array $searchParameters
0068      * @return Zend_Tool_Project_Profile_Resource
0069      */
0070     public function search($matchSearchConstraints, $nonMatchSearchConstraints = null)
0071     {
0072         if (!$matchSearchConstraints instanceof Zend_Tool_Project_Profile_Resource_SearchConstraints) {
0073             $matchSearchConstraints = new Zend_Tool_Project_Profile_Resource_SearchConstraints($matchSearchConstraints);
0074         }
0075 
0076         $this->rewind();
0077 
0078         /**
0079          * @todo This should be re-written with better support for a filter iterator, its the way to go
0080          */
0081 
0082         if ($nonMatchSearchConstraints) {
0083             $filterIterator = new Zend_Tool_Project_Profile_Iterator_ContextFilter($this, array('denyNames' => $nonMatchSearchConstraints));
0084             $riIterator = new RecursiveIteratorIterator($filterIterator, RecursiveIteratorIterator::SELF_FIRST);
0085         } else {
0086             $riIterator = new RecursiveIteratorIterator($this, RecursiveIteratorIterator::SELF_FIRST);
0087         }
0088 
0089         $foundResource     = false;
0090         $currentConstraint = $matchSearchConstraints->getConstraint();
0091         $foundDepth        = 0;
0092 
0093         foreach ($riIterator as $currentResource) {
0094 
0095             // if current depth is less than found depth, end
0096             if ($riIterator->getDepth() < $foundDepth) {
0097                 break;
0098             }
0099 
0100             if (strtolower($currentResource->getName()) == strtolower($currentConstraint->name)) {
0101 
0102                 $paramsMatch = true;
0103 
0104                 // @todo check to ensure params match (perhaps)
0105                 if (count($currentConstraint->params) > 0) {
0106                     $currentResourceAttributes = $currentResource->getAttributes();
0107                     if (!is_array($currentConstraint->params)) {
0108                         // require_once 'Zend/Tool/Project/Profile/Exception.php';
0109                         throw new Zend_Tool_Project_Profile_Exception('Search parameter specifics must be in the form of an array for key "'
0110                             . $currentConstraint->name .'"');
0111                     }
0112                     foreach ($currentConstraint->params as $paramName => $paramValue) {
0113                         if (!isset($currentResourceAttributes[$paramName]) || $currentResourceAttributes[$paramName] != $paramValue) {
0114                             $paramsMatch = false;
0115                             break;
0116                         }
0117                     }
0118                 }
0119 
0120                 if ($paramsMatch) {
0121                     $foundDepth = $riIterator->getDepth();
0122 
0123                     if (($currentConstraint = $matchSearchConstraints->getConstraint()) == null) {
0124                         $foundResource = $currentResource;
0125                         break;
0126                     }
0127                 }
0128 
0129             }
0130 
0131         }
0132 
0133         return $foundResource;
0134     }
0135 
0136     /**
0137      * createResourceAt()
0138      *
0139      * @param array|Zend_Tool_Project_Profile_Resource_SearchConstraints $appendResourceOrSearchConstraints
0140      * @param string $context
0141      * @param array $attributes
0142      * @return Zend_Tool_Project_Profile_Resource
0143      */
0144     public function createResourceAt($appendResourceOrSearchConstraints, $context, Array $attributes = array())
0145     {
0146         if (!$appendResourceOrSearchConstraints instanceof Zend_Tool_Project_Profile_Resource_Container) {
0147             if (($parentResource = $this->search($appendResourceOrSearchConstraints)) == false) {
0148                 // require_once 'Zend/Tool/Project/Profile/Exception.php';
0149                 throw new Zend_Tool_Project_Profile_Exception('No node was found to append to.');
0150             }
0151         } else {
0152             $parentResource = $appendResourceOrSearchConstraints;
0153         }
0154 
0155         return $parentResource->createResource($context, $attributes);
0156     }
0157 
0158     /**
0159      * createResource()
0160      *
0161      * Method to create a resource with a given context with specific attributes
0162      *
0163      * @param string $context
0164      * @param array $attributes
0165      * @return Zend_Tool_Project_Profile_Resource
0166      */
0167     public function createResource($context, Array $attributes = array())
0168     {
0169         if (is_string($context)) {
0170             $contextRegistry = Zend_Tool_Project_Context_Repository::getInstance();
0171             if ($contextRegistry->hasContext($context)) {
0172                 $context = $contextRegistry->getContext($context);
0173             } else {
0174                 // require_once 'Zend/Tool/Project/Profile/Exception.php';
0175                 throw new Zend_Tool_Project_Profile_Exception('Context by name ' . $context . ' was not found in the context registry.');
0176             }
0177         } elseif (!$context instanceof Zend_Tool_Project_Context_Interface) {
0178             // require_once 'Zend/Tool/Project/Profile/Exception.php';
0179             throw new Zend_Tool_Project_Profile_Exception('Context must be of type string or Zend_Tool_Project_Context_Interface.');
0180         }
0181 
0182         $newResource = new Zend_Tool_Project_Profile_Resource($context);
0183 
0184         if ($attributes) {
0185             $newResource->setAttributes($attributes);
0186         }
0187 
0188         /**
0189          * Interesting logic here:
0190          *
0191          * First set the parentResource (this will also be done inside append).  This will allow
0192          * the initialization routine to change the appendability of the parent resource.  This
0193          * is important to allow specific resources to be appendable by very specific sub-resources.
0194          */
0195         $newResource->setParentResource($this);
0196         $newResource->initializeContext();
0197         $this->append($newResource);
0198 
0199         return $newResource;
0200     }
0201 
0202     /**
0203      * setAttributes()
0204      *
0205      * persist the attributes if the resource will accept them
0206      *
0207      * @param array $attributes
0208      * @return Zend_Tool_Project_Profile_Resource_Container
0209      */
0210     public function setAttributes(Array $attributes)
0211     {
0212         foreach ($attributes as $attrName => $attrValue) {
0213             $setMethod = 'set' . $attrName;
0214             if (method_exists($this, $setMethod)) {
0215                 $this->{$setMethod}($attrValue);
0216             } else {
0217                 $this->setAttribute($attrName, $attrValue);
0218             }
0219         }
0220         return $this;
0221     }
0222 
0223     /**
0224      * getAttributes()
0225      *
0226      * @return array
0227      */
0228     public function getAttributes()
0229     {
0230         return $this->_attributes;
0231     }
0232 
0233     /**
0234      * setAttribute()
0235      *
0236      * @param string $name
0237      * @param mixed $value
0238      * @return Zend_Tool_Project_Profile_Resource_Container
0239      */
0240     public function setAttribute($name, $value)
0241     {
0242         $this->_attributes[$name] = $value;
0243         return $this;
0244     }
0245 
0246     /**
0247      * getAttribute()
0248      *
0249      * @param string $name
0250      * @return Zend_Tool_Project_Profile_Resource_Container
0251      */
0252     public function getAttribute($name)
0253     {
0254         return (array_key_exists($name, $this->_attributes)) ? $this->_attributes[$name] : null;
0255     }
0256 
0257     /**
0258      * hasAttribute()
0259      *
0260      * @param string $name
0261      * @return bool
0262      */
0263     public function hasAttribute($name)
0264     {
0265         return array_key_exists($name, $this->_attributes);
0266     }
0267 
0268     /**
0269      * setAppendable()
0270      *
0271      * @param bool $appendable
0272      * @return Zend_Tool_Project_Profile_Resource_Container
0273      */
0274     public function setAppendable($appendable)
0275     {
0276         $this->_appendable = (bool) $appendable;
0277         return $this;
0278     }
0279 
0280     /**
0281      * isAppendable()
0282      *
0283      * @return bool
0284      */
0285     public function isAppendable()
0286     {
0287         return $this->_appendable;
0288     }
0289 
0290     /**
0291      * setParentResource()
0292      *
0293      * @param Zend_Tool_Project_Profile_Resource_Container $parentResource
0294      * @return Zend_Tool_Project_Profile_Resource_Container
0295      */
0296     public function setParentResource(Zend_Tool_Project_Profile_Resource_Container $parentResource)
0297     {
0298         $this->_parentResource = $parentResource;
0299         return $this;
0300     }
0301 
0302     /**
0303      * getParentResource()
0304      *
0305      * @return Zend_Tool_Project_Profile_Resource_Container
0306      */
0307     public function getParentResource()
0308     {
0309         return $this->_parentResource;
0310     }
0311 
0312     /**
0313      * append()
0314      *
0315      * @param Zend_Tool_Project_Profile_Resource_Container $resource
0316      * @return Zend_Tool_Project_Profile_Resource_Container
0317      */
0318     public function append(Zend_Tool_Project_Profile_Resource_Container $resource)
0319     {
0320         if (!$this->isAppendable()) {
0321             throw new Exception('Resource by name ' . (string) $this . ' is not appendable');
0322         }
0323         array_push($this->_subResources, $resource);
0324         $resource->setParentResource($this);
0325 
0326         return $this;
0327     }
0328 
0329     /**
0330      * current() - required by RecursiveIterator
0331      *
0332      * @return Zend_Tool_Project_Profile_Resource
0333      */
0334     public function current()
0335     {
0336         return current($this->_subResources);
0337     }
0338 
0339     /**
0340      * key() - required by RecursiveIterator
0341      *
0342      * @return int
0343      */
0344     public function key()
0345     {
0346         return key($this->_subResources);
0347     }
0348 
0349     /**
0350      * next() - required by RecursiveIterator
0351      *
0352      * @return bool
0353      */
0354     public function next()
0355     {
0356         return next($this->_subResources);
0357     }
0358 
0359     /**
0360      * rewind() - required by RecursiveIterator
0361      *
0362      * @return bool
0363      */
0364     public function rewind()
0365     {
0366         return reset($this->_subResources);
0367     }
0368 
0369     /**
0370      * valid() - - required by RecursiveIterator
0371      *
0372      * @return bool
0373      */
0374     public function valid()
0375     {
0376         return (bool) $this->current();
0377     }
0378 
0379     /**
0380      * hasChildren()
0381      *
0382      * @return bool
0383      */
0384     public function hasChildren()
0385     {
0386         return (count($this->_subResources > 0)) ? true : false;
0387     }
0388 
0389     /**
0390      * getChildren()
0391      *
0392      * @return array
0393      */
0394     public function getChildren()
0395     {
0396         return $this->current();
0397     }
0398 
0399     /**
0400      * count()
0401      *
0402      * @return int
0403      */
0404     public function count()
0405     {
0406         return count($this->_subResources);
0407     }
0408 
0409     /**
0410      * __clone()
0411      *
0412      */
0413     public function __clone()
0414     {
0415         $this->rewind();
0416         foreach ($this->_subResources as $index => $resource) {
0417             $this->_subResources[$index] = clone $resource;
0418         }
0419     }
0420 
0421 }