Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationLatte
      • ApplicationTracy
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsLatte
      • Framework
      • HttpTracy
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Drivers
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Templating
    • Utils
  • NetteModule
  • none
  • Tracy

Classes

  • Component
  • Container

Interfaces

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