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

Classes

Interfaces

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