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: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44:
45: abstract class Component implements InjectOnWakeup, Identifiable, Detachable
46: {
47: const TYPE_STRING = 'string';
48: const TYPE_FLOAT = 'float';
49: const TYPE_BOOL = 'boolean';
50: const TYPE_DOUBLE = 'double';
51: const TYPE_INT = 'integer';
52: const TYPE_ARRAY = 'array';
53:
54:
55: const VISITOR_CONTINUE_TRAVERSAL = 1;
56: const VISITOR_STOP_TRAVERSAL = 2;
57: const VISITOR_CONTINUE_TRAVERSAL_NO_DEEPER = 3;
58:
59: 60: 61:
62: private $id;
63:
64: 65: 66:
67: private $parent;
68:
69: 70: 71:
72: private $behaviours = array();
73:
74: 75: 76:
77: private $markup;
78:
79: 80: 81:
82: private $rendered = false;
83:
84: 85: 86:
87: private $initialized = false;
88:
89: 90: 91: 92:
93: private $flagInitializeParentCall = false;
94:
95:
96: private $beforePageRendered = false;
97:
98: private $model;
99:
100: 101: 102:
103: private $renderBodyOnly;
104:
105: 106: 107:
108: protected $added = false;
109:
110: private $markupSource = null;
111:
112: private $markupId;
113:
114: private $outputMarkupId = false;
115:
116: private $visible = true;
117:
118: private static $nextId = 0;
119:
120: 121: 122:
123: private $auto = false;
124:
125: private $beforePageRenderCallback;
126: private $afterPageRenderCallback;
127: private $beforeComponentRenderCallback;
128: private $afterComponentRenderCallback;
129: private $onComponentTagCallback;
130: private $onComponentTagBodyCallback;
131: private $renderHeadCallback;
132:
133: const PATH_SEPERATOR = ':';
134:
135: 136: 137: 138:
139: public function __construct($id, Model $model = null)
140: {
141: Args::isString($id, 'id');
142: $this->id = $id;
143: $this->model = $model;
144: PiconApplication::get()->getComponentInstantiationListener()->onInstantiate($this);
145: }
146:
147: 148: 149: 150:
151: protected function onInitialize()
152: {
153: $this->flagInitializeParentCall = true;
154:
155: foreach($this->behaviours as $behaviour)
156: {
157: $behaviour->bind($this);
158: }
159:
160: PiconApplication::get()->getComponentInitializationListener()->onInitialize($this);
161: }
162:
163: protected final function fireInitialize()
164: {
165: if($this->isInitialized())
166: {
167: return;
168: }
169: $this->initialized = true;
170: $this->flagInitializeParentCall = false;
171: $this->onInitialize();
172: if(!$this->flagInitializeParentCall)
173: {
174: throw new \IllegalStateException(sprintf("Parent implementation of onInitialize for component %s was not called", $this->id));
175: }
176: }
177:
178: public function internalInitialize()
179: {
180: $this->fireInitialize();
181: }
182:
183: public function add(&$object)
184: {
185: if($object instanceof Behaviour)
186: {
187: $this->addBehaviour($object);
188: }
189: else
190: {
191: throw new \InvalidArgumentException(sprintf("Argument %s was not a valid type for this method", gettype($object)));
192: }
193: }
194:
195: protected final function addBehaviour(Behaviour &$behaviour)
196: {
197: $this->behaviours['behaviour_'.$this->getNextComponentId()] = $behaviour;
198: if($this->isInitialized())
199: {
200: $behaviour->bind($this);
201: }
202: }
203:
204: 205: 206:
207: public function getMarkup()
208: {
209: if($this->markup!=null)
210: {
211: return $this->markup;
212: }
213: else
214: {
215: if($this->parent==null)
216: {
217: if($this instanceof MarkupContainer)
218: {
219: $this->markup = $this->loadAssociatedMarkup();
220: return $this->markup;
221: }
222: else
223: {
224: throw new \MarkupNotFoundException(sprintf("Component %s has no associated markup and no parent to get markup from", $this->id));
225: }
226:
227: }
228: else
229: {
230: $this->markup = $this->parent->getMarkupForChild($this);
231: return $this->markup;
232: }
233: }
234: }
235:
236: 237: 238:
239: public function beforePageRender()
240: {
241: if($this->beforePageRenderCallback!=null)
242: {
243: $callable = $this->beforePageRenderCallback;
244: $callable($this);
245: }
246: $this->beforePageRendered = true;
247: }
248:
249: 250: 251:
252: public function afterPageRender()
253: {
254: if($this->afterPageRenderCallback!=null)
255: {
256: $callable = $this->afterPageRenderCallback;
257: $callable($this);
258: }
259: }
260:
261: 262: 263:
264: public function beforeComponentRender()
265: {
266: PiconApplication::get()->getComponentBeforeRenderListener()->onBeforeRender($this);
267: $this->notifyBehavioursBeforeRender();
268: if($this->beforeComponentRenderCallback!=null)
269: {
270: $callable = $this->beforeComponentRenderCallback;
271: $callable($this);
272: }
273: }
274:
275: public function isInitialized()
276: {
277: return $this->initialized;
278: }
279:
280: public function isBeforePageRender()
281: {
282: return $this->beforePageRendered;
283: }
284:
285: 286: 287:
288: public function afterComponentRender()
289: {
290: if($this->afterComponentRenderCallback!=null)
291: {
292: $callable = $this->afterComponentRender;
293: $callable($this);
294: }
295: $this->rendered = true;
296: PiconApplication::get()->getComponentAfterRenderListenersr()->onAfterRender($this);
297: $this->notifyBehavioursAfterRender();
298:
299: if($this instanceof MarkupContainer && $this->visible)
300: {
301: foreach($this->getChildren() as $child)
302: {
303: 304: 305: 306: 307: 308:
309: if(!$child->rendered)
310: {
311: throw new \RuntimeException(sprintf("Component %s was not rendered because there was no corrisponding picon:id in the markup.", $child->id));
312: }
313: }
314: }
315: }
316:
317: public function render()
318: {
319: $exception = null;
320:
321: try
322: {
323: if($this->getParent()==null)
324: {
325: $this->beforePageRender();
326: }
327: $this->beforeComponentRender();
328: $this->internalRender();
329: }
330: catch(Exception $ex)
331: {
332: $exception = $ex;
333: }
334: try
335: {
336: $this->afterComponentRender();
337: if($this->getParent()==null)
338: {
339: $this->afterPageRender();
340: }
341: }
342: catch(Exception $ex)
343: {
344: if($exception==null)
345: {
346: $exception = $ex;
347: }
348: }
349:
350: if($exception!=null)
351: {
352: throw $exception;
353: }
354: }
355:
356: private function internalRender()
357: {
358: $markup = $this->getMarkup();
359:
360: if($markup==null)
361: {
362: throw new \MarkupNotFoundException(sprintf("Markup not found for component %s.", $this->id));
363: }
364: $this->onRender();
365: }
366:
367: 368: 369:
370: protected final function internalRenderComponent()
371: {
372: $markup = $this->getMarkup();
373:
374: if($markup==null)
375: {
376: throw new \MarkupNotFoundException(sprintf("Markup not found for component %s.", $this->id));
377: }
378: 379: 380: 381:
382: $markup = clone $markup;
383:
384:
385: if(!$this->visible)
386: {
387: return;
388: }
389:
390: if($this->renderBodyOnly)
391: {
392: $this->onComponentTagBody($markup);
393: }
394: else
395: {
396: $this->onComponentTag($markup);
397: $this->renderElementStart($markup);
398: $this->onComponentTagBody($markup);
399: $this->renderElementEnd($markup);
400: }
401: }
402:
403: 404: 405: 406:
407: private final function renderElementStart(MarkupElement $element)
408: {
409: $this->getResponse()->write('<'.$element->getName());
410: $this->renderAttributes($element->getAttributes());
411: if($element->isOpenClose())
412: {
413: $this->getResponse()->write(' /');
414: }
415: $this->getResponse()->write('>');
416: }
417:
418: 419: 420: 421:
422: private final function renderElementEnd(MarkupElement $element)
423: {
424: if($element->isOpen())
425: {
426: $this->getResponse()->write('</'.$element->getName().'>');
427: }
428: }
429:
430: 431: 432: 433:
434: private function renderAttributes($attributes)
435: {
436: foreach($attributes as $name => $value)
437: {
438: $this->getResponse()->write(' '.$name.'="'.$value.'"');
439: }
440: }
441:
442: public function renderElement(MarkupElement $element)
443: {
444: $this->renderElementStart($element);
445: if($element->hasChildren())
446: {
447: $this->renderAll($element->getChildren());
448: }
449: $this->renderElementEnd($element);
450: }
451:
452: 453: 454: 455:
456: protected function renderAll($markup = null)
457: {
458: if($markup==null)
459: {
460: $markup = $this->getMarkup();
461:
462: if($markup==null)
463: {
464: throw new \MarkupNotFoundException(sprintf("Markup not found for component %s.", $this->id));
465: }
466: }
467:
468: foreach($markup as &$element)
469: {
470: if($element instanceof ComponentTag)
471: {
472: if($this instanceof MarkupContainer)
473: {
474: $child = $this->get($element->getComponentTagId());
475:
476: if($child==null)
477: {
478: $child = ComponentResolverHelper::resolve($this, $element);
479:
480: if($child!=null && $child->getParent()==null)
481: {
482: $child->setAuto();
483: $this->addComponent($child);
484: }
485: if($child!=null)
486: {
487: $child->setMarkup($element);
488: }
489: }
490:
491: if($child!=null)
492: {
493: $child->render();
494: }
495: else
496: {
497: throw new \RuntimeException(sprintf("A component was not found for element with picon:id %s. This may be because you have forgotten to create it in your code or the hierarchy is wrong", $element->getComponentTagId()));
498: }
499:
500: }
501: else
502: {
503: throw new \InvalidMarkupException(sprintf("Markup element %s may not contain a child with a picon:id as the component %s cannot not have any child components", $element->getName(), $this->id));
504: }
505: }
506: elseif($element instanceof TextElement)
507: {
508: $this->getResponse()->write($element->getContent());
509: }
510: else
511: {
512: $this->renderElement($element);
513: }
514: }
515: }
516:
517: protected abstract function onRender();
518:
519: 520: 521: 522: 523: 524: 525: 526:
527: protected function onComponentTag(ComponentTag $tag)
528: {
529: if($this->onComponentTagCallback!=null)
530: {
531: $callable = $this->onComponentTagCallback;
532: $callable($this, $tag);
533: }
534: $this->getMarkUpSource()->onComponentTag($this, $tag);
535: if($this instanceof MarkupContainer && $this->hasChildren())
536: {
537: $tag->setTagType(new XmlTagType(XmlTagType::OPEN));
538: }
539:
540: if($this->outputMarkupId)
541: {
542: $tag->put('id', $this->getMarkupId());
543: }
544: $this->notifyBehavioursComponentTag($tag);
545: }
546:
547: 548: 549: 550:
551: public function getMarkupId()
552: {
553: if(!isset($this->markupId))
554: {
555: $this->markupId = $this->id.$this->getNextComponentId();
556: }
557: return $this->markupId;
558: }
559:
560: 561: 562: 563: 564:
565: public function setMarkupId($id)
566: {
567: $this->markupId = $id;
568: }
569:
570: 571: 572: 573:
574: public function setOutputMarkupId($output)
575: {
576: Args::isBoolean($output, 'output');
577: $this->outputMarkupId = $output;
578: }
579:
580: 581: 582: 583:
584: protected function onComponentTagBody(ComponentTag $tag)
585: {
586: if($this->onComponentTagBodyCallback!=null)
587: {
588: $callable = $this->onComponentTagBodyCallback;
589: $callable($this, $tag);
590: }
591: $this->getMarkUpSource()->onComponentTagBody($this, $tag);
592: }
593:
594: 595: 596: 597: 598: 599:
600: protected function checkComponentTag(ComponentTag $tag, $tagName)
601: {
602: if($tag->getName()!=$tagName)
603: {
604: throw new \IllegalStateException(sprintf("An %s component can only be added to the HTML element %s", get_called_class(), $tagName));
605: }
606: }
607:
608: 609: 610: 611: 612: 613: 614:
615: protected function checkComponentTagAttribute(ComponentTag $tag, $attribute, $value)
616: {
617: $attributes = $tag->getAttributes();
618:
619: if(!array_key_exists($attribute, $attributes) || $attributes[$attribute] != $value)
620: {
621: throw new \IllegalStateException(sprintf("An %s component can only be added to a tag with a %s of %s", get_called_class(), $attribute, $value));
622: }
623: }
624:
625: 626: 627: 628: 629: 630:
631: public function visitParents(Identifier $identifier, $callback)
632: {
633: Args::callBackArgs($callback, 1, 'callback');
634: $this->internalVisitParents($identifier, $this->parent, $callback);
635: }
636:
637: private function internalVisitParents(Identifier $identifier, $component, $callback)
638: {
639: if($component!=null)
640: {
641: $response = self::VISITOR_CONTINUE_TRAVERSAL;
642: if($component::getIdentifier()->of($identifier))
643: {
644: $response = $callback($component);
645: }
646: if($response==self::VISITOR_CONTINUE_TRAVERSAL)
647: {
648: $this->internalVisitParents($identifier, $component->parent, $callback);
649: }
650: }
651: }
652:
653: public function getPage()
654: {
655: $current = $this;
656: while($current!=null)
657: {
658: if($current instanceof WebPage)
659: {
660: return $current;
661: }
662: $current = $current->getParent();
663: }
664: return null;
665: }
666:
667: protected function setParent($parent)
668: {
669: $this->parent = $parent;
670: }
671:
672: public final function getApplication()
673: {
674: return $GLOBALS['application'];
675: }
676:
677: public final function getRequestCycle()
678: {
679: return $GLOBALS['requestCycle'];
680: }
681:
682: public final function getRequest()
683: {
684: return $this->getRequestCycle()->getRequest();
685: }
686:
687: public final function getResponse()
688: {
689: return $this->getRequestCycle()->getResponse();
690: }
691:
692: public function getId()
693: {
694: return $this->id;
695: }
696:
697: public static function getIdentifier()
698: {
699: return Identifier::forName(get_called_class());
700: }
701:
702: 703: 704: 705:
706: public function isStateless()
707: {
708: foreach($this->behaviours as $behaviour)
709: {
710: if(!$behaviour->isStateless())
711: {
712: return false;
713: }
714: }
715: return true;
716: }
717:
718: public function get($id)
719: {
720: if(empty($id))
721: {
722: return $this;
723: }
724:
725: throw new \InvalidArgumentException("This component is not a container and does not have any children.");
726: }
727:
728: 729: 730: 731: 732: 733: 734: 735: 736:
737: public function generateUrlFor($for)
738: {
739: if($for instanceof Listener)
740: {
741: return $this->urlForListener($for);
742: }
743: else if($for instanceof Identifier)
744: {
745: return $this->urlForPage($page);
746: }
747: else if($for instanceof WebPage)
748: {
749: return $this->urlForPageInstance($for);
750: }
751: else
752: {
753: throw new \InvalidArgumentException(sprintf("generateUrlFor expected argment of type Identifier or Listener or WebPage, actual %s", get_class($for)));
754: }
755: }
756:
757: 758: 759: 760: 761:
762: public function urlForPage(Identifier $page)
763: {
764: if(is_subclass_of($page->getFullyQualifiedName(), WebPage::getIdentifier()->getFullyQualifiedName()))
765: {
766: return $this->getRequest()->getRootPath().$page->getFullyQualifiedName();
767: }
768: throw new \InvalidArgumentException(sprintf("Expected identifier of a web page, actual %s", $page->getFullyQualifiedName()));
769: }
770:
771:
772: public function urlForPageInstance(WebPage $pageInstance)
773: {
774:
775: }
776:
777: 778: 779: 780: 781:
782: public function urlForListener(Listener $listener)
783: {
784: $target;
785: $page = $this->getPage();
786:
787: $behaviour = null;
788:
789: if($listener instanceof Behaviour)
790: {
791: $behaviour = $listener->getBehaviourId();
792: }
793:
794: if($page->isPageStateless())
795: {
796: $target = new PageRequestWithListenerTarget($page::getIdentifier(), $this->getComponentPath(), $behaviour);
797: }
798: else
799: {
800: $target = new ListenerRequestTarget($this->getPage(), $this->getComponentPath(), $behaviour);
801: }
802: return $this->getRequestCycle()->generateUrl($target);
803: }
804:
805: public function getComponentPath()
806: {
807: $page = $this->getPage();
808: if($page==null)
809: {
810: throw new \IllegalStateException(sprintf("Unable to generate a path for component %s as it has an incomplete hierarchy.", $this->id));
811: }
812:
813: $path = $this->getId();
814:
815: $callback = function($component) use (&$path)
816: {
817: if(!($component instanceof WebPage))
818: {
819: $path = $component->getId().Component::PATH_SEPERATOR.$path;
820: return Component::VISITOR_CONTINUE_TRAVERSAL;
821: }
822: return Component::VISITOR_STOP_TRAVERSAL;
823: };
824: $this->visitParents(Component::getIdentifier(), $callback);
825:
826: return str_replace(self::PATH_SEPERATOR.self::PATH_SEPERATOR, '', $path.self::PATH_SEPERATOR);
827: }
828:
829: protected function newMarkupSource()
830: {
831: return new DefaultMarkupSource();
832: }
833:
834: 835: 836: 837: 838:
839: public function setPage($page)
840: {
841: Args::notNull($page, 'page');
842: if($page instanceof Identifier)
843: {
844: if($page->of(WebPage::getIdentifier()))
845: {
846: $target = new PageRequestTarget($page);
847: }
848: else
849: {
850: throw new \InvalidArgumentException("Expected identifier to be for a web page");
851: }
852: }
853: else if($page instanceof WebPage)
854: {
855: PageMap::get()->addOrUpdate($page);
856: $target = new PageInstanceRequestTarget($page);
857: }
858: else
859: {
860: throw new \InvalidArgumentException(sprintf("setPage expects an identifier for a web page or an instance of a web page and not a %s", get_class($page)));
861: }
862:
863: if($this->getRequestCycle()->containsTarget(ListenerRequestTarget::getIdentifier()))
864: {
865: $url = $this->getRequestCycle()->generateUrl($target);
866: $this->getRequestCycle()->addTarget(new RedirectRequestTarget($url));
867: }
868: else
869: {
870: $this->getRequestCycle()->addTarget($target);
871: }
872: }
873:
874: 875: 876: 877:
878: public function getModel()
879: {
880: if($this->model==null)
881: {
882: $model = null;
883: $current = $this->getParent();
884: while($current!=null)
885: {
886: if($current->model!=null && $current->model instanceof ComponentInheritedModel)
887: {
888: $model = $current->model;
889: break;
890: }
891: $current = $current->getParent();
892: }
893:
894: if($model!=null)
895: {
896: $model = $model->onInherit($this);
897:
898: if($model!=null)
899: {
900: $this->model = $model;
901: $this->model->bind($this);
902: }
903: }
904: }
905: return $this->model;
906: }
907:
908: public function setMarkup(MarkupElement $markup)
909: {
910: $this->markup = $markup;
911: }
912:
913: public function setModel(Model &$model)
914: {
915: $this->model = $model;
916: }
917:
918: protected function getMarkUpSource()
919: {
920: if($this->markupSource==null)
921: {
922: $this->markupSource = $this->newMarkupSource();
923: }
924: return $this->markupSource;
925: }
926:
927: public function getParent()
928: {
929: return $this->parent;
930: }
931:
932: public function setModelObject(&$object)
933: {
934: if($this->getModel()!=null)
935: {
936: $this->getModel()->setModelObject($object);
937: }
938: }
939:
940: public function getModelObject()
941: {
942: if($this->getModel()!=null)
943: {
944: return $this->getModel()->getModelObject();
945: }
946: return null;
947: }
948:
949: private static function getNextComponentId()
950: {
951: self::$nextId++;
952: return dechex(self::$nextId);
953: }
954:
955: 956: 957: 958:
959: public function getModelObjectAsString()
960: {
961: $object = $this->getModelObject();
962: if(is_object($object))
963: {
964: $converter = $this->getApplication()->getConverter(get_class($object));
965:
966: if($converter==null)
967: {
968: throw new \RuntimeException(sprintf("Unable to find converter for type %s", get_class($object)));
969: }
970: $string = $converter->convertToString($object);
971:
972: if(!is_string($string))
973: {
974: throw new \RuntimeException("Convert did not correctly convert to string");
975: }
976: return $string;
977: }
978: else if(is_array($object))
979: {
980: throw new \RuntimeException("getModelObjectAsString() does not support array");
981: }
982: else if(is_bool($object))
983: {
984: return $object ? 'true':'false';
985: }
986: else
987: {
988: settype($object, 'string');
989: return $object;
990: }
991: }
992:
993: public function fatel($message)
994: {
995: FeedbackModel::get()->addMessage(new FeedbackMessage(FeedbackMessage::FEEDBACK_MEESAGE_FATEL, $message, $this));
996: }
997:
998: public function error($message)
999: {
1000: FeedbackModel::get()->addMessage(new FeedbackMessage(FeedbackMessage::FEEDBACK_MEESAGE_ERROR, $message, $this));
1001: }
1002:
1003: public function warning($message)
1004: {
1005: FeedbackModel::get()->addMessage(new FeedbackMessage(FeedbackMessage::FEEDBACK_MEESAGE_WARNING, $message, $this));
1006: }
1007:
1008: public function info($message)
1009: {
1010: FeedbackModel::get()->addMessage(new FeedbackMessage(FeedbackMessage::FEEDBACK_MEESAGE_INFO, $message, $this));
1011: }
1012:
1013: public function success($message)
1014: {
1015: FeedbackModel::get()->addMessage(new FeedbackMessage(FeedbackMessage::FEEDBACK_MEESAGE_SUCCESS, $message, $this));
1016: }
1017:
1018: public function hasMessage($level = null)
1019: {
1020: return FeedbackModel::get()->hasMessages($this, $level);
1021: }
1022:
1023: public function hasErrorMessage()
1024: {
1025: return FeedbackModel::get()->hasMessages($this, FeedbackMessage::FEEDBACK_MEESAGE_ERROR);
1026: }
1027:
1028: private function notifyBehavioursBeforeRender()
1029: {
1030: foreach($this->behaviours as $behaviour)
1031: {
1032: $behaviour->beforeRender($this);
1033: }
1034: }
1035:
1036: private function notifyBehavioursAfterRender()
1037: {
1038: foreach($this->behaviours as $behaviour)
1039: {
1040: $behaviour->afterRender($this);
1041: }
1042: }
1043:
1044: private function notifyBehavioursComponentTag(ComponentTag $tag)
1045: {
1046: foreach($this->behaviours as $behaviour)
1047: {
1048: $behaviour->onComponentTag($this, $tag);
1049: }
1050: }
1051:
1052: 1053: 1054: 1055: 1056:
1057: public final function renderHeadContainer(HeaderContainer $container, HeaderResponse $headerResponse)
1058: {
1059: $this->getMarkUpSource()->renderHead($this, $container, $headerResponse);
1060: $this->renderHead($headerResponse);
1061:
1062: foreach($this->behaviours as $behaviour)
1063: {
1064: $behaviour->renderHead($this, $container, $headerResponse);
1065: }
1066: }
1067:
1068: 1069: 1070: 1071:
1072: public function renderHead(HeaderResponse $headerResponse)
1073: {
1074: if($this->renderHeadCallback!=null)
1075: {
1076: $callable = $this->renderHeadCallback;
1077: $callable($this, $headerResponse);
1078: }
1079: }
1080:
1081: 1082: 1083: 1084: 1085:
1086: public function setRenderBodyOnly($renderBodyOnly)
1087: {
1088: Args::isBoolean($renderBodyOnly, 'renderBodyOnly');
1089: $this->renderBodyOnly = $renderBodyOnly;
1090: }
1091:
1092: public function setVisible($visible)
1093: {
1094: Args::isBoolean($visible, 'visible');
1095: $this->visible = $visible;
1096: }
1097:
1098: public function getBehaviours()
1099: {
1100: return $this->behaviours;
1101: }
1102:
1103: public function getBehaviourById($id)
1104: {
1105: if(array_key_exists($id, $this->behaviours))
1106: {
1107: return $this->behaviours[$id];
1108: }
1109: return null;
1110: }
1111:
1112: private function setAuto()
1113: {
1114: $this->auto = true;
1115: }
1116:
1117:
1118: public function isAuto()
1119: {
1120: return $this->auto;
1121: }
1122:
1123: public function detach()
1124: {
1125:
1126: }
1127:
1128: public function getLocalizer()
1129: {
1130: return Localizer::get($this);
1131: }
1132:
1133: public function getComponentKey($suffix)
1134: {
1135: return sprintf("%s.%s.%s", get_class($this->getPage()), $this->id, $suffix);
1136: }
1137:
1138: public function isRendered()
1139: {
1140: return $this->rendered;
1141: }
1142:
1143: public function setBeforePageRenderCallback($beforePageRenderCallback)
1144: {
1145: Args::callBackArgs($beforePageRenderCallback, 1, 'beforePageRenderCallback');
1146: $this->beforePageRenderCallback = $beforePageRenderCallback;
1147: }
1148:
1149: public function setBeforeComponentRenderCallback($beforeComponentRenderCallback)
1150: {
1151: Args::callBackArgs($beforeComponentRenderCallback, 1, 'beforeComponentRenderCallback');
1152: $this->beforeComponentRenderCallback = $beforeComponentRenderCallback;
1153: }
1154:
1155: public function setAfterPageRenderCallback($afterPageRenderCallback)
1156: {
1157: Args::callBackArgs($afterPageRenderCallback, 1, 'afterPageRenderCallback');
1158: $this->afterPageRenderCallback = $afterPageRenderCallback;
1159: }
1160:
1161: public function setAfterComponentRenderCallback($afterComponentRenderCallback)
1162: {
1163: Args::callBackArgs($afterComponentRenderCallback, 1, 'afterComponentRenderCallback');
1164: $this->afterComponentRenderCallback = $afterComponentRenderCallback;
1165: }
1166:
1167: public function setOnComponentTagCallback($onComponentTagCallback)
1168: {
1169: Args::callBackArgs($onComponentTagCallback, 2, 'onComponentTagCallback');
1170: $this->onComponentTagCallback = $onComponentTagCallback;
1171: }
1172:
1173: public function setOnComponentTagBodyCallback($onComponentTagBodyCallback)
1174: {
1175: Args::callBackArgs($onComponentTagBodyCallback, 2, 'onComponentTagBodyCallback');
1176: $this->onComponentTagBodyCallback = $onComponentTagBodyCallback;
1177: }
1178:
1179: public function setRenderHeadCallback($renderHeadCallback)
1180: {
1181: Args::callBackArgs($renderHeadCallback, 2, 'renderHeadCallback');
1182: $this->renderHeadCallback = $renderHeadCallback;
1183: }
1184: }
1185:
1186: ?>
1187: