1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21:
22:
23: namespace picon;
24:
25: 26: 27: 28: 29: 30: 31:
32: class MarkupContainer extends Component
33: {
34: private $children = array();
35:
36: public function add(&$object)
37: {
38: if($object instanceof Component)
39: {
40: $this->addComponent($object);
41: return;
42: }
43: parent::add($object);
44: }
45:
46: public function addOrReplace(Component &$component)
47: {
48: if($component->added)
49: {
50: throw new \RuntimeException(sprintf("Component %s has been added already.", $component->getId()));
51: }
52: if($this->childExists($component->getId()))
53: {
54: $old = &$this->children;
55: $old[$component->getId()] = $component;
56: $this->onComponentAdded($component);
57: }
58: else
59: {
60: $this->addComponent($component);
61: }
62: }
63:
64: protected final function remove(Component &$component)
65: {
66: if($this->childExists($component->getId()))
67: {
68: unset($this->children[$component->getId()]);
69: }
70: }
71:
72: protected final function addComponent(Component &$component)
73: {
74: if($this->childExists($component->getId()))
75: {
76: throw new \RuntimeException(sprintf("Component %s already has a child with id %s", $this->getId(), $component->getId()));
77: }
78:
79: if($component->added)
80: {
81: throw new \RuntimeException(sprintf("Component %s has already been added to another",$component->getId()));
82: }
83:
84: if($component==$this)
85: {
86: throw new \RuntimeException(sprintf("Component %s cannot be added to itself.",$component->getId()));
87: }
88:
89: $this->children[$component->getId()] = $component;
90:
91: $this->onComponentAdded($component);
92: }
93:
94: public function internalInitialize()
95: {
96: parent::internalInitialize();
97: $callback = function(&$component)
98: {
99: $component->internalInitialize();
100: return Component::VISITOR_CONTINUE_TRAVERSAL;
101: };
102: $this->visitChildren(Component::getIdentifier(), $callback);
103: }
104:
105: public function beforePageRender()
106: {
107: parent::beforePageRender();
108: foreach($this->children as $child)
109: {
110: $child->beforePageRender();
111: }
112: }
113:
114: public function afterPageRender()
115: {
116: parent::afterPageRender();
117: foreach($this->children as $child)
118: {
119: $child->afterPageRender();
120: }
121: }
122:
123: protected function onComponentAdded(Component &$component)
124: {
125: $component->setParent($this);
126: $page = $this->getPage();
127:
128: if($page!=null)
129: {
130: if($page->isInitialized())
131: {
132: $component->internalInitialize();
133: }
134: }
135:
136: if($this->isBeforePageRender())
137: {
138: $component->beforePageRender();
139: }
140: }
141:
142: public function getChildren()
143: {
144: return $this->children;
145: }
146:
147: 148: 149: 150:
151: protected function onComponentTagBody(ComponentTag $tag)
152: {
153: parent::onComponentTagBody($tag);
154: if($tag->hasChildren())
155: {
156: $this->renderAll($tag->getChildren());
157: }
158: }
159:
160: public function get($id)
161: {
162: if(empty($id))
163: {
164: return $this;
165: }
166: if(substr($id, strlen($id)-1, strlen($id))!=self::PATH_SEPERATOR)
167: {
168: $id = $id.self::PATH_SEPERATOR;
169: }
170: $nodes = explode(self::PATH_SEPERATOR, $id);
171: $child = $nodes[0];
172:
173: if($this->childExists($child))
174: {
175: $childComponent = $this->children[$child];
176: return $childComponent->get(substr($id, strlen($child.self::PATH_SEPERATOR)));
177: }
178: return null;
179: }
180:
181: protected function childExists($id)
182: {
183: return array_key_exists($id, $this->children);
184: }
185:
186: public function hasChildren()
187: {
188: return count($this->children)>0;
189: }
190:
191: 192: 193: 194: 195: 196:
197: public function visitChildren(Identifier $identifier, $callback)
198: {
199: Args::callBackArgs($callback, 1, 'callback');
200: $this->internalVisitChildren($identifier, $this->getChildren(), $callback);
201: }
202:
203: private function internalVisitChildren(Identifier $identifier, $components, $callback)
204: {
205: foreach($components as $component)
206: {
207: $response = self::VISITOR_CONTINUE_TRAVERSAL;
208: if($component::getIdentifier()->of($identifier))
209: {
210: $response = $callback($component);
211: }
212: if($response==self::VISITOR_CONTINUE_TRAVERSAL && $component instanceof MarkupContainer)
213: {
214: $this->internalVisitChildren($identifier, $component->getChildren(), $callback);
215: }
216: else if($response==self::VISITOR_STOP_TRAVERSAL)
217: {
218: break;
219: }
220: }
221: }
222:
223: 224: 225: 226: 227:
228: public function loadAssociatedMarkup()
229: {
230: return MarkupLoader::get()->loadMarkup($this);
231: }
232:
233: protected function onRender()
234: {
235: $this->internalRenderComponent();
236: }
237:
238: 239: 240: 241:
242: public function getMarkupForChild(Component $child)
243: {
244: return $this->getMarkUpSource()->getMarkup($this, $child);
245: }
246:
247: public function detach()
248: {
249: foreach($this->getChildren() as $child)
250: {
251: if($child->isAuto())
252: {
253: $this->remove($child);
254: }
255: }
256: }
257: }
258:
259: ?>
260: