Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • 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
    • Bridges
      • Nette

Classes

  • Component
  • Container

Interfaces

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