Packages

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
      • Adapters
      • Extensions
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Diagnostics
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
      • PhpGenerator
  • NetteModule
  • None
  • PHP

Classes

  • Component
  • ComponentContainer

Interfaces

  • IComponent
  • IComponentContainer
  • Overview
  • Package
  • Class
  • Tree
  • Deprecated
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (http://nette.org)
  5:  *
  6:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  7:  *
  8:  * For the full copyright and license information, please view
  9:  * the file license.txt that was distributed with this source code.
 10:  * @package Nette\ComponentModel
 11:  */
 12: 
 13: 
 14: 
 15: /**
 16:  * ComponentContainer is default implementation of IContainer.
 17:  *
 18:  * @author     David Grudl
 19:  *
 20:  * @property-read ArrayIterator $components
 21:  * @package Nette\ComponentModel
 22:  */
 23: class ComponentContainer extends Component implements IComponentContainer
 24: {
 25:     /** @var IComponent[] */
 26:     private $components = array();
 27: 
 28:     /** @var IComponent|NULL */
 29:     private $cloning;
 30: 
 31: 
 32:     /********************* interface IContainer ****************d*g**/
 33: 
 34: 
 35:     /**
 36:      * Adds the specified component to the IContainer.
 37:      * @param  IComponent
 38:      * @param  string
 39:      * @param  string
 40:      * @return self
 41:      * @throws InvalidStateException
 42:      */
 43:     public function addComponent(IComponent $component, $name, $insertBefore = NULL)
 44:     {
 45:         if ($name === NULL) {
 46:             $name = $component->getName();
 47:         }
 48: 
 49:         if (is_int($name)) {
 50:             $name = (string) $name;
 51: 
 52:         } elseif (!is_string($name)) {
 53:             throw new InvalidArgumentException("Component name must be integer or string, " . gettype($name) . " given.");
 54: 
 55:         } elseif (!preg_match('#^[a-zA-Z0-9_]+\z#', $name)) {
 56:             throw new InvalidArgumentException("Component name must be non-empty alphanumeric string, '$name' given.");
 57:         }
 58: 
 59:         if (isset($this->components[$name])) {
 60:             throw new InvalidStateException("Component with name '$name' already exists.");
 61:         }
 62: 
 63:         // check circular reference
 64:         $obj = $this;
 65:         do {
 66:             if ($obj === $component) {
 67:                 throw new InvalidStateException("Circular reference detected while adding component '$name'.");
 68:             }
 69:             $obj = $obj->getParent();
 70:         } while ($obj !== NULL);
 71: 
 72:         // user checking
 73:         $this->validateChildComponent($component);
 74: 
 75:         try {
 76:             if (isset($this->components[$insertBefore])) {
 77:                 $tmp = array();
 78:                 foreach ($this->components as $k => $v) {
 79:                     if ($k === $insertBefore) {
 80:                         $tmp[$name] = $component;
 81:                     }
 82:                     $tmp[$k] = $v;
 83:                 }
 84:                 $this->components = $tmp;
 85:             } else {
 86:                 $this->components[$name] = $component;
 87:             }
 88:             $component->setParent($this, $name);
 89: 
 90:         } catch (Exception $e) {
 91:             unset($this->components[$name]); // undo
 92:             throw $e;
 93:         }
 94:         return $this;
 95:     }
 96: 
 97: 
 98:     /**
 99:      * Removes a component from the IContainer.
100:      * @return void
101:      */
102:     public function removeComponent(IComponent $component)
103:     {
104:         $name = $component->getName();
105:         if (!isset($this->components[$name]) || $this->components[$name] !== $component) {
106:             throw new InvalidArgumentException("Component named '$name' is not located in this container.");
107:         }
108: 
109:         unset($this->components[$name]);
110:         $component->setParent(NULL);
111:     }
112: 
113: 
114:     /**
115:      * Returns component specified by name or path.
116:      * @param  string
117:      * @param  bool   throw exception if component doesn't exist?
118:      * @return IComponent|NULL
119:      */
120:     final public function getComponent($name, $need = TRUE)
121:     {
122:         if (is_int($name)) {
123:             $name = (string) $name;
124: 
125:         } elseif (!is_string($name)) {
126:             throw new InvalidArgumentException("Component name must be integer or string, " . gettype($name) . " given.");
127: 
128:         } else {
129:             $a = strpos($name, self::NAME_SEPARATOR);
130:             if ($a !== FALSE) {
131:                 $ext = (string) substr($name, $a + 1);
132:                 $name = substr($name, 0, $a);
133:             }
134: 
135:             if ($name === '') {
136:                 throw new InvalidArgumentException("Component or subcomponent name must not be empty string.");
137:             }
138:         }
139: 
140:         if (!isset($this->components[$name])) {
141:             $component = $this->createComponent($name);
142:             if ($component instanceof IComponent && $component->getParent() === NULL) {
143:                 $this->addComponent($component, $name);
144:             }
145:         }
146: 
147:         if (isset($this->components[$name])) {
148:             if (!isset($ext)) {
149:                 return $this->components[$name];
150: 
151:             } elseif ($this->components[$name] instanceof IComponentContainer) {
152:                 return $this->components[$name]->getComponent($ext, $need);
153: 
154:             } elseif ($need) {
155:                 throw new InvalidArgumentException("Component with name '$name' is not container and cannot have '$ext' component.");
156:             }
157: 
158:         } elseif ($need) {
159:             throw new InvalidArgumentException("Component with name '$name' does not exist.");
160:         }
161:     }
162: 
163: 
164:     /**
165:      * Component factory. Delegates the creation of components to a createComponent<Name> method.
166:      * @param  string      component name
167:      * @return IComponent  the created component (optionally)
168:      */
169:     protected function createComponent($name)
170:     {
171:         $ucname = ucfirst($name);
172:         $method = 'createComponent' . $ucname;
173:         if ($ucname !== $name && method_exists($this, $method) && $this->getReflection()->getMethod($method)->getName() === $method) {
174:             $component = $this->$method($name);
175:             if (!$component instanceof IComponent && !isset($this->components[$name])) {
176:                 $class = get_class($this);
177:                 throw new UnexpectedValueException("Method $class::$method() did not return or create the desired component.");
178:             }
179:             return $component;
180:         }
181:     }
182: 
183: 
184:     /**
185:      * Iterates over a components.
186:      * @param  bool    recursive?
187:      * @param  string  class types filter
188:      * @return ArrayIterator
189:      */
190:     final public function getComponents($deep = FALSE, $filterType = NULL)
191:     {
192:         $iterator = new RecursiveComponentIterator($this->components);
193:         if ($deep) {
194:             $deep = $deep > 0 ? RecursiveIteratorIterator::SELF_FIRST : RecursiveIteratorIterator::CHILD_FIRST;
195:             $iterator = new RecursiveIteratorIterator($iterator, $deep);
196:         }
197:         if ($filterType) {
198:             $iterator = new InstanceFilterIterator($iterator, $filterType);
199:         }
200:         return $iterator;
201:     }
202: 
203: 
204:     /**
205:      * Descendant can override this method to disallow insert a child by throwing an InvalidStateException.
206:      * @return void
207:      * @throws InvalidStateException
208:      */
209:     protected function validateChildComponent(IComponent $child)
210:     {
211:     }
212: 
213: 
214:     /********************* cloneable, serializable ****************d*g**/
215: 
216: 
217:     /**
218:      * Object cloning.
219:      */
220:     public function __clone()
221:     {
222:         if ($this->components) {
223:             $oldMyself = reset($this->components)->getParent();
224:             $oldMyself->cloning = $this;
225:             foreach ($this->components as $name => $component) {
226:                 $this->components[$name] = clone $component;
227:             }
228:             $oldMyself->cloning = NULL;
229:         }
230:         parent::__clone();
231:     }
232: 
233: 
234:     /**
235:      * Is container cloning now?
236:      * @return NULL|IComponent
237:      * @internal
238:      */
239:     public function _isCloning()
240:     {
241:         return $this->cloning;
242:     }
243: 
244: }
245: 
Nette Framework 2.0.12 (for PHP 5.2, un-prefixed) API API documentation generated by ApiGen 2.8.0