]> git.sur5r.net Git - bacula/bacula/blob - gui/baculum/framework/Web/UI/WebControls/TRepeater.php
a563a12df67fd59b0a3e87e0d9062cbc648d1e7d
[bacula/bacula] / gui / baculum / framework / Web / UI / WebControls / TRepeater.php
1 <?php
2 /**
3  * TRepeater class file
4  *
5  * @author Qiang Xue <qiang.xue@gmail.com>
6  * @link http://www.pradosoft.com/
7  * @copyright Copyright &copy; 2005-2014 PradoSoft
8  * @license http://www.pradosoft.com/license/
9  * @package System.Web.UI.WebControls
10  */
11
12 /**
13  * Using TDataBoundControl and TDataFieldAccessor cass
14  */
15 Prado::using('System.Web.UI.WebControls.TDataBoundControl');
16 Prado::using('System.Util.TDataFieldAccessor');
17
18 /**
19  * TRepeater class.
20  *
21  * TRepeater displays its content repeatedly based on the data fetched from
22  * {@link setDataSource DataSource}.
23  * The repeated contents in TRepeater are called items, which are controls and
24  * can be accessed through {@link getItems Items}. When {@link dataBind()} is invoked,
25  * TRepeater creates an item for each row of data and binds the data row to the item.
26  * Optionally, a repeater can have a header, a footer and/or separators between items.
27  *
28  * The layout of the repeated contents are specified by inline templates.
29  * Repeater items, header, footer, etc. are being instantiated with the corresponding
30  * templates when data is being bound to the repeater.
31  *
32  * Since v3.1.0, the layout can also be specified by renderers. A renderer is a control class
33  * that can be instantiated as repeater items, header, etc. A renderer can thus be viewed
34  * as an external template (in fact, it can also be non-templated controls).
35  *
36  * A renderer can be any control class.
37  * - If the class implements {@link IDataRenderer}, the <b>Data</b>
38  * property will be set as the data row during databinding. Many PRADO controls
39  * implement this interface, such as {@link TLabel}, {@link TTextBox}, etc.
40  * - If the class implements {@link IItemDataRenderer}, the <b>ItemIndex</b> property will be set
41  * as the zero-based index of the item in the repeater item collection, and
42  * the <b>ItemType</b> property as the item's type (such as TListItemType::Item).
43  * {@link TRepeaterItemRenderer} may be used as the convenient base class which
44  * already implements {@link IDataItemRenderer}.
45  *
46  * The following properties are used to specify different types of template and renderer
47  * for a repeater:
48  * - {@link setItemTemplate ItemTemplate}, {@link setItemRenderer ItemRenderer}:
49  * for each repeated row of data
50  * - {@link setAlternatingItemTemplate AlternatingItemTemplate}, {@link setAlternatingItemRenderer AlternatingItemRenderer}:
51  * for each alternating row of data. If not set, {@link setItemTemplate ItemTemplate} or {@link setItemRenderer ItemRenderer}
52  * will be used instead.
53  * - {@link setHeaderTemplate HeaderTemplate}, {@link setHeaderRenderer HeaderRenderer}:
54  * for the repeater header.
55  * - {@link setFooterTemplate FooterTemplate}, {@link setFooterRenderer FooterRenderer}:
56  * for the repeater footer.
57  * - {@link setSeparatorTemplate SeparatorTemplate}, {@link setSeparatorRenderer SeparatorRenderer}:
58  * for content to be displayed between items.
59  * - {@link setEmptyTemplate EmptyTemplate}, {@link setEmptyRenderer EmptyRenderer}:
60  * used when data bound to the repeater is empty.
61  *
62  * If a content type is defined with both a template and a renderer, the latter takes precedence.
63  *
64  * When {@link dataBind()} is being called, TRepeater undergoes the following lifecycles for each row of data:
65  * - create item based on templates or renderers
66  * - set the row of data to the item
67  * - raise {@link onItemCreated OnItemCreated}:
68  * - add the item as a child control
69  * - call dataBind() of the item
70  * - raise {@link onItemDataBound OnItemDataBound}:
71  *
72  * TRepeater raises an {@link onItemCommand OnItemCommand} whenever a button control
73  * within some repeater item raises a <b>OnCommand</b> event. Therefore,
74  * you can handle all sorts of <b>OnCommand</b> event in a central place by
75  * writing an event handler for {@link onItemCommand OnItemCommand}.
76  *
77  * When a page containing a repeater is post back, the repeater will restore automatically
78  * all its contents, including items, header, footer and separators.
79  * However, the data row associated with each item will not be recovered and become null.
80  * To access the data, use one of the following ways:
81  * - Use {@link getDataKeys DataKeys} to obtain the data key associated with
82  * the specified repeater item and use the key to fetch the corresponding data
83  * from some persistent storage such as DB.
84  * - Save the whole dataset in viewstate, which will restore the dataset automatically upon postback.
85  * Be aware though, if the size of your dataset is big, your page size will become big. Some
86  * complex data may also have serializing problem if saved in viewstate.
87  *
88  * @author Qiang Xue <qiang.xue@gmail.com>
89  * @package System.Web.UI.WebControls
90  * @since 3.0
91  */
92 class TRepeater extends TDataBoundControl implements INamingContainer
93 {
94         /**
95          * Repeater item types
96          * @deprecated deprecated since version 3.0.4. Use TListItemType constants instead.
97          */
98         const IT_HEADER='Header';
99         const IT_FOOTER='Footer';
100         const IT_ITEM='Item';
101         const IT_SEPARATOR='Separator';
102         const IT_ALTERNATINGITEM='AlternatingItem';
103
104         /**
105          * @var ITemplate template for repeater items
106          */
107         private $_itemTemplate=null;
108         /**
109          * @var ITemplate template for each alternating item
110          */
111         private $_alternatingItemTemplate=null;
112         /**
113          * @var ITemplate template for header
114          */
115         private $_headerTemplate=null;
116         /**
117          * @var ITemplate template for footer
118          */
119         private $_footerTemplate=null;
120         /**
121          * @var ITemplate template used for repeater when no data is bound
122          */
123         private $_emptyTemplate=null;
124         /**
125          * @var ITemplate template for separator
126          */
127         private $_separatorTemplate=null;
128         /**
129          * @var TRepeaterItemCollection list of repeater items
130          */
131         private $_items=null;
132         /**
133          * @var TControl header item
134          */
135         private $_header=null;
136         /**
137          * @var TControl footer item
138          */
139         private $_footer=null;
140
141
142         /**
143          * @return string the class name for repeater items. Defaults to empty, meaning not set.
144          * @since 3.1.0
145          */
146         public function getItemRenderer()
147         {
148                 return $this->getViewState('ItemRenderer','');
149         }
150
151         /**
152          * Sets the item renderer class.
153          *
154          * If not empty, the class will be used to instantiate as repeater items.
155          * This property takes precedence over {@link getItemTemplate ItemTemplate}.
156          *
157          * @param string the renderer class name in namespace format.
158          * @see setItemTemplate
159          * @since 3.1.0
160          */
161         public function setItemRenderer($value)
162         {
163                 $this->setViewState('ItemRenderer',$value,'');
164         }
165
166         /**
167          * @return string the class name for alternative repeater items. Defaults to empty, meaning not set.
168          * @since 3.1.0
169          */
170         public function getAlternatingItemRenderer()
171         {
172                 return $this->getViewState('AlternatingItemRenderer','');
173         }
174
175         /**
176          * Sets the alternative item renderer class.
177          *
178          * If not empty, the class will be used to instantiate as alternative repeater items.
179          * This property takes precedence over {@link getAlternatingItemTemplate AlternatingItemTemplate}.
180          *
181          * @param string the renderer class name in namespace format.
182          * @see setAlternatingItemTemplate
183          * @since 3.1.0
184          */
185         public function setAlternatingItemRenderer($value)
186         {
187                 $this->setViewState('AlternatingItemRenderer',$value,'');
188         }
189
190         /**
191          * @return string the class name for repeater item separators. Defaults to empty, meaning not set.
192          * @since 3.1.0
193          */
194         public function getSeparatorRenderer()
195         {
196                 return $this->getViewState('SeparatorRenderer','');
197         }
198
199         /**
200          * Sets the repeater item separator renderer class.
201          *
202          * If not empty, the class will be used to instantiate as repeater item separators.
203          * This property takes precedence over {@link getSeparatorTemplate SeparatorTemplate}.
204          *
205          * @param string the renderer class name in namespace format.
206          * @see setSeparatorTemplate
207          * @since 3.1.0
208          */
209         public function setSeparatorRenderer($value)
210         {
211                 $this->setViewState('SeparatorRenderer',$value,'');
212         }
213
214         /**
215          * @return string the class name for repeater header item. Defaults to empty, meaning not set.
216          * @since 3.1.0
217          */
218         public function getHeaderRenderer()
219         {
220                 return $this->getViewState('HeaderRenderer','');
221         }
222
223         /**
224          * Sets the repeater header renderer class.
225          *
226          * If not empty, the class will be used to instantiate as repeater header item.
227          * This property takes precedence over {@link getHeaderTemplate HeaderTemplate}.
228          *
229          * @param string the renderer class name in namespace format.
230          * @see setHeaderTemplate
231          * @since 3.1.0
232          */
233         public function setHeaderRenderer($value)
234         {
235                 $this->setViewState('HeaderRenderer',$value,'');
236         }
237
238         /**
239          * @return string the class name for repeater footer item. Defaults to empty, meaning not set.
240          * @since 3.1.0
241          */
242         public function getFooterRenderer()
243         {
244                 return $this->getViewState('FooterRenderer','');
245         }
246
247         /**
248          * Sets the repeater footer renderer class.
249          *
250          * If not empty, the class will be used to instantiate as repeater footer item.
251          * This property takes precedence over {@link getFooterTemplate FooterTemplate}.
252          *
253          * @param string the renderer class name in namespace format.
254          * @see setFooterTemplate
255          * @since 3.1.0
256          */
257         public function setFooterRenderer($value)
258         {
259                 $this->setViewState('FooterRenderer',$value,'');
260         }
261
262         /**
263          * @return string the class name for empty repeater item. Defaults to empty, meaning not set.
264          * @since 3.1.0
265          */
266         public function getEmptyRenderer()
267         {
268                 return $this->getViewState('EmptyRenderer','');
269         }
270
271         /**
272          * Sets the repeater empty renderer class.
273          *
274          * The empty renderer is created as the child of the repeater
275          * if data bound to the repeater is empty.
276          * This property takes precedence over {@link getEmptyTemplate EmptyTemplate}.
277          *
278          * @param string the renderer class name in namespace format.
279          * @see setEmptyTemplate
280          * @since 3.1.0
281          */
282         public function setEmptyRenderer($value)
283         {
284                 $this->setViewState('EmptyRenderer',$value,'');
285         }
286
287         /**
288          * @return ITemplate the template for repeater items
289          */
290         public function getItemTemplate()
291         {
292                 return $this->_itemTemplate;
293         }
294
295         /**
296          * @param ITemplate the template for repeater items
297          * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
298          */
299         public function setItemTemplate($value)
300         {
301                 if($value instanceof ITemplate || $value===null)
302                         $this->_itemTemplate=$value;
303                 else
304                         throw new TInvalidDataTypeException('repeater_template_required','ItemTemplate');
305         }
306
307         /**
308          * @return ITemplate the alternative template string for the item
309          */
310         public function getAlternatingItemTemplate()
311         {
312                 return $this->_alternatingItemTemplate;
313         }
314
315         /**
316          * @param ITemplate the alternative item template
317          * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
318          */
319         public function setAlternatingItemTemplate($value)
320         {
321                 if($value instanceof ITemplate || $value===null)
322                         $this->_alternatingItemTemplate=$value;
323                 else
324                         throw new TInvalidDataTypeException('repeater_template_required','AlternatingItemTemplate');
325         }
326
327         /**
328          * @return ITemplate the header template
329          */
330         public function getHeaderTemplate()
331         {
332                 return $this->_headerTemplate;
333         }
334
335         /**
336          * @param ITemplate the header template
337          * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
338          */
339         public function setHeaderTemplate($value)
340         {
341                 if($value instanceof ITemplate || $value===null)
342                         $this->_headerTemplate=$value;
343                 else
344                         throw new TInvalidDataTypeException('repeater_template_required','HeaderTemplate');
345         }
346
347         /**
348          * @return ITemplate the footer template
349          */
350         public function getFooterTemplate()
351         {
352                 return $this->_footerTemplate;
353         }
354
355         /**
356          * @param ITemplate the footer template
357          * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
358          */
359         public function setFooterTemplate($value)
360         {
361                 if($value instanceof ITemplate || $value===null)
362                         $this->_footerTemplate=$value;
363                 else
364                         throw new TInvalidDataTypeException('repeater_template_required','FooterTemplate');
365         }
366
367         /**
368          * @return ITemplate the template applied when no data is bound to the repeater
369          */
370         public function getEmptyTemplate()
371         {
372                 return $this->_emptyTemplate;
373         }
374
375         /**
376          * @param ITemplate the template applied when no data is bound to the repeater
377          * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
378          */
379         public function setEmptyTemplate($value)
380         {
381                 if($value instanceof ITemplate || $value===null)
382                         $this->_emptyTemplate=$value;
383                 else
384                         throw new TInvalidDataTypeException('repeater_template_required','EmptyTemplate');
385         }
386
387         /**
388          * @return ITemplate the separator template
389          */
390         public function getSeparatorTemplate()
391         {
392                 return $this->_separatorTemplate;
393         }
394
395         /**
396          * @param ITemplate the separator template
397          * @throws TInvalidDataTypeException if the input is not an {@link ITemplate} or not null.
398          */
399         public function setSeparatorTemplate($value)
400         {
401                 if($value instanceof ITemplate || $value===null)
402                         $this->_separatorTemplate=$value;
403                 else
404                         throw new TInvalidDataTypeException('repeater_template_required','SeparatorTemplate');
405         }
406
407         /**
408          * @return TControl the header item
409          */
410         public function getHeader()
411         {
412                 return $this->_header;
413         }
414
415         /**
416          * @return TControl the footer item
417          */
418         public function getFooter()
419         {
420                 return $this->_footer;
421         }
422
423         /**
424          * @return TRepeaterItemCollection list of repeater item controls
425          */
426         public function getItems()
427         {
428                 if(!$this->_items)
429                         $this->_items=new TRepeaterItemCollection;
430                 return $this->_items;
431         }
432
433         /**
434          * @return string the field of the data source that provides the keys of the list items.
435          */
436         public function getDataKeyField()
437         {
438                 return $this->getViewState('DataKeyField','');
439         }
440
441         /**
442          * @param string the field of the data source that provides the keys of the list items.
443          */
444         public function setDataKeyField($value)
445         {
446                 $this->setViewState('DataKeyField',$value,'');
447         }
448
449         /**
450          * @return TList the keys used in the data listing control.
451          */
452         public function getDataKeys()
453         {
454                 if(($dataKeys=$this->getViewState('DataKeys',null))===null)
455                 {
456                         $dataKeys=new TList;
457                         $this->setViewState('DataKeys',$dataKeys,null);
458                 }
459                 return $dataKeys;
460         }
461
462         /**
463          * Creates a repeater item.
464          * This method invokes {@link createItem} to create a new repeater item.
465          * @param integer zero-based item index.
466          * @param TListItemType item type
467          * @return TControl the created item, null if item is not created
468          */
469         private function createItemInternal($itemIndex,$itemType)
470         {
471                 if(($item=$this->createItem($itemIndex,$itemType))!==null)
472                 {
473                         $param=new TRepeaterItemEventParameter($item);
474                         $this->onItemCreated($param);
475                         $this->getControls()->add($item);
476                         return $item;
477                 }
478                 else
479                         return null;
480         }
481
482         /**
483          * Creates a repeater item and performs databinding.
484          * This method invokes {@link createItem} to create a new repeater item.
485          * @param integer zero-based item index.
486          * @param TListItemType item type
487          * @param mixed data to be associated with the item
488          * @return TControl the created item, null if item is not created
489          */
490         private function createItemWithDataInternal($itemIndex,$itemType,$dataItem)
491         {
492                 if(($item=$this->createItem($itemIndex,$itemType))!==null)
493                 {
494                         $param=new TRepeaterItemEventParameter($item);
495                         if($item instanceof IDataRenderer)
496                                 $item->setData($dataItem);
497                         $this->onItemCreated($param);
498                         $this->getControls()->add($item);
499                         $item->dataBind();
500                         $this->onItemDataBound($param);
501                         return $item;
502                 }
503                 else
504                         return null;
505         }
506
507         /**
508          * Creates a repeater item instance based on the item type and index.
509          * @param integer zero-based item index
510          * @param TListItemType item type
511          * @return TControl created repeater item
512          */
513         protected function createItem($itemIndex,$itemType)
514         {
515                 $template=null;
516                 $classPath=null;
517                 switch($itemType)
518                 {
519                         case TListItemType::Item :
520                                 $classPath=$this->getItemRenderer();
521                                 $template=$this->_itemTemplate;
522                                 break;
523                         case TListItemType::AlternatingItem :
524                                 if(($classPath=$this->getAlternatingItemRenderer())==='' && ($template=$this->_alternatingItemTemplate)===null)
525                                 {
526                                         $classPath=$this->getItemRenderer();
527                                         $template=$this->_itemTemplate;
528                                 }
529                                 break;
530                         case TListItemType::Header :
531                                 $classPath=$this->getHeaderRenderer();
532                                 $template=$this->_headerTemplate;
533                                 break;
534                         case TListItemType::Footer :
535                                 $classPath=$this->getFooterRenderer();
536                                 $template=$this->_footerTemplate;
537                                 break;
538                         case TListItemType::Separator :
539                                 $classPath=$this->getSeparatorRenderer();
540                                 $template=$this->_separatorTemplate;
541                                 break;
542                         default:
543                                 throw new TInvalidDataValueException('repeater_itemtype_unknown',$itemType);
544                 }
545                 if($classPath!=='')
546                 {
547                         $item=Prado::createComponent($classPath);
548                         if($item instanceof IItemDataRenderer)
549                         {
550                                 $item->setItemIndex($itemIndex);
551                                 $item->setItemType($itemType);
552                         }
553                 }
554                 else if($template!==null)
555                 {
556                         $item=new TRepeaterItem;
557                         $item->setItemIndex($itemIndex);
558                         $item->setItemType($itemType);
559                         $template->instantiateIn($item);
560                 }
561                 else
562                         $item=null;
563
564                 return $item;
565         }
566
567         /**
568          * Creates empty repeater content.
569          */
570         protected function createEmptyContent()
571         {
572                 if(($classPath=$this->getEmptyRenderer())!=='')
573                         $this->getControls()->add(Prado::createComponent($classPath));
574                 else if($this->_emptyTemplate!==null)
575                         $this->_emptyTemplate->instantiateIn($this);
576         }
577
578         /**
579          * Renders the repeater.
580          * This method overrides the parent implementation by rendering the body
581          * content as the whole presentation of the repeater. Outer tag is not rendered.
582          * @param THtmlWriter writer
583          */
584         public function render($writer)
585         {
586                 if($this->_items && $this->_items->getCount() || $this->_emptyTemplate!==null || $this->getEmptyRenderer()!=='')
587                         $this->renderContents($writer);
588         }
589
590         /**
591          * Saves item count in viewstate.
592          * This method is invoked right before control state is to be saved.
593          */
594         public function saveState()
595         {
596                 parent::saveState();
597                 if($this->_items)
598                         $this->setViewState('ItemCount',$this->_items->getCount(),0);
599                 else
600                         $this->clearViewState('ItemCount');
601         }
602
603         /**
604          * Loads item count information from viewstate.
605          * This method is invoked right after control state is loaded.
606          */
607         public function loadState()
608         {
609                 parent::loadState();
610                 if(!$this->getIsDataBound())
611                         $this->restoreItemsFromViewState();
612                 $this->clearViewState('ItemCount');
613         }
614
615         /**
616          * Clears up all items in the repeater.
617          */
618         public function reset()
619         {
620                 $this->getControls()->clear();
621                 $this->getItems()->clear();
622                 $this->_header=null;
623                 $this->_footer=null;
624         }
625
626         /**
627          * Creates repeater items based on viewstate information.
628          */
629         protected function restoreItemsFromViewState()
630         {
631                 $this->reset();
632                 if(($itemCount=$this->getViewState('ItemCount',0))>0)
633                 {
634                         $items=$this->getItems();
635                         $hasSeparator=$this->_separatorTemplate!==null || $this->getSeparatorRenderer()!=='';
636                         $this->_header=$this->createItemInternal(-1,TListItemType::Header);
637                         for($i=0;$i<$itemCount;++$i)
638                         {
639                                 if($hasSeparator && $i>0)
640                                         $this->createItemInternal($i-1,TListItemType::Separator);
641                                 $itemType=$i%2==0?TListItemType::Item : TListItemType::AlternatingItem;
642                                 $items->add($this->createItemInternal($i,$itemType,false,null));
643                         }
644                         $this->_footer=$this->createItemInternal(-1,TListItemType::Footer);
645                 }
646                 else
647                         $this->createEmptyContent();
648                 $this->clearChildState();
649         }
650
651         /**
652          * Performs databinding to populate repeater items from data source.
653          * This method is invoked by dataBind().
654          * You may override this function to provide your own way of data population.
655          * @param Traversable the data
656          */
657         protected function performDataBinding($data)
658         {
659                 $this->reset();
660
661                 $keys=$this->getDataKeys();
662                 $keys->clear();
663                 $keyField=$this->getDataKeyField();
664
665                 $items=$this->getItems();
666                 $itemIndex=0;
667                 $hasSeparator=$this->_separatorTemplate!==null || $this->getSeparatorRenderer()!=='';
668                 foreach($data as $key=>$dataItem)
669                 {
670                         if($keyField!=='')
671                                 $keys->add($this->getDataFieldValue($dataItem,$keyField));
672                         else
673                                 $keys->add($key);
674                         if($itemIndex===0)
675                                 $this->_header=$this->createItemWithDataInternal(-1,TListItemType::Header,null);
676                         if($hasSeparator && $itemIndex>0)
677                                 $this->createItemWithDataInternal($itemIndex-1,TListItemType::Separator,null);
678                         $itemType=$itemIndex%2==0?TListItemType::Item : TListItemType::AlternatingItem;
679                         $items->add($this->createItemWithDataInternal($itemIndex,$itemType,$dataItem));
680                         $itemIndex++;
681                 }
682                 if($itemIndex>0)
683                         $this->_footer=$this->createItemWithDataInternal(-1,TListItemType::Footer,null);
684                 else
685                 {
686                         $this->createEmptyContent();
687                         $this->dataBindChildren();
688                 }
689                 $this->setViewState('ItemCount',$itemIndex,0);
690         }
691
692         /**
693          * This method overrides parent's implementation to handle
694          * {@link onItemCommand OnItemCommand} event which is bubbled from
695          * repeater items and their child controls.
696          * This method should only be used by control developers.
697          * @param TControl the sender of the event
698          * @param TEventParameter event parameter
699          * @return boolean whether the event bubbling should stop here.
700          */
701         public function bubbleEvent($sender,$param)
702         {
703                 if($param instanceof TRepeaterCommandEventParameter)
704                 {
705                         $this->onItemCommand($param);
706                         return true;
707                 }
708                 else
709                         return false;
710         }
711
712         /**
713          * Raises <b>OnItemCreated</b> event.
714          * This method is invoked after a repeater item is created and instantiated with
715          * template, but before added to the page hierarchy.
716          * The repeater item control responsible for the event
717          * can be determined from the event parameter.
718          * If you override this method, be sure to call parent's implementation
719          * so that event handlers have chance to respond to the event.
720          * @param TRepeaterItemEventParameter event parameter
721          */
722         public function onItemCreated($param)
723         {
724                 $this->raiseEvent('OnItemCreated',$this,$param);
725         }
726
727         /**
728          * Raises <b>OnItemDataBound</b> event.
729          * This method is invoked right after an item is data bound.
730          * The repeater item control responsible for the event
731          * can be determined from the event parameter.
732          * If you override this method, be sure to call parent's implementation
733          * so that event handlers have chance to respond to the event.
734          * @param TRepeaterItemEventParameter event parameter
735          */
736         public function onItemDataBound($param)
737         {
738                 $this->raiseEvent('OnItemDataBound',$this,$param);
739         }
740
741         /**
742          * Raises <b>OnItemCommand</b> event.
743          * This method is invoked after a button control in
744          * a template raises <b>OnCommand</b> event.
745          * The repeater control responsible for the event
746          * can be determined from the event parameter.
747          * The event parameter also contains the information about
748          * the initial sender of the <b>OnCommand</b> event, command name
749          * and command parameter.
750          * You may override this method to provide customized event handling.
751          * Be sure to call parent's implementation so that
752          * event handlers have chance to respond to the event.
753          * @param TRepeaterCommandEventParameter event parameter
754          */
755         public function onItemCommand($param)
756         {
757                 $this->raiseEvent('OnItemCommand',$this,$param);
758         }
759
760         /**
761          * Returns the value of the data at the specified field.
762          * If data is an array, TMap or TList, the value will be returned at the index
763          * of the specified field. If the data is a component with a property named
764          * as the field name, the property value will be returned.
765          * Otherwise, an exception will be raised.
766          * @param mixed data item
767          * @param mixed field name
768          * @return mixed data value at the specified field
769          * @throws TInvalidDataValueException if the data is invalid
770          */
771         protected function getDataFieldValue($data,$field)
772         {
773                 return TDataFieldAccessor::getDataFieldValue($data,$field);
774         }
775 }
776
777 /**
778  * TRepeaterItemEventParameter class
779  *
780  * TRepeaterItemEventParameter encapsulates the parameter data for
781  * {@link TRepeater::onItemCreated ItemCreated} event of {@link TRepeater} controls.
782  * The {@link getItem Item} property indicates the repeater item related with the event.
783  *
784  * @author Qiang Xue <qiang.xue@gmail.com>
785  * @package System.Web.UI.WebControls
786  * @since 3.0
787  */
788 class TRepeaterItemEventParameter extends TEventParameter
789 {
790         /**
791          * The repeater item control responsible for the event.
792          * @var TControl
793          */
794         private $_item=null;
795
796         /**
797          * Constructor.
798          * @param TControl repeater item related with the corresponding event
799          */
800         public function __construct($item)
801         {
802                 $this->_item=$item;
803         }
804
805         /**
806          * @return TControl repeater item related with the corresponding event
807          */
808         public function getItem()
809         {
810                 return $this->_item;
811         }
812 }
813
814 /**
815  * TRepeaterCommandEventParameter class
816  *
817  * TRepeaterCommandEventParameter encapsulates the parameter data for
818  * {@link TRepeater::onItemCommand ItemCommand} event of {@link TRepeater} controls.
819  *
820  * The {@link getItem Item} property indicates the repeater item related with the event.
821  * The {@link getCommandSource CommandSource} refers to the control that originally
822  * raises the Command event.
823  *
824  * @author Qiang Xue <qiang.xue@gmail.com>
825  * @package System.Web.UI.WebControls
826  * @since 3.0
827  */
828 class TRepeaterCommandEventParameter extends TCommandEventParameter
829 {
830         /**
831          * @var TControl the repeater item control responsible for the event.
832          */
833         private $_item=null;
834         /**
835          * @var TControl the control originally raises the <b>OnCommand</b> event.
836          */
837         private $_source=null;
838
839         /**
840          * Constructor.
841          * @param TControl repeater item responsible for the event
842          * @param TControl original event sender
843          * @param TCommandEventParameter original event parameter
844          */
845         public function __construct($item,$source,TCommandEventParameter $param)
846         {
847                 $this->_item=$item;
848                 $this->_source=$source;
849                 parent::__construct($param->getCommandName(),$param->getCommandParameter());
850         }
851
852         /**
853          * @return TControl the repeater item control responsible for the event.
854          */
855         public function getItem()
856         {
857                 return $this->_item;
858         }
859
860         /**
861          * @return TControl the control originally raises the <b>OnCommand</b> event.
862          */
863         public function getCommandSource()
864         {
865                 return $this->_source;
866         }
867 }
868
869 /**
870  * TRepeaterItem class
871  *
872  * A TRepeaterItem control represents an item in the {@link TRepeater} control,
873  * such as heading section, footer section, or a data item.
874  * The index and data value of the item can be accessed via {@link getItemIndex ItemIndex}>
875  * and {@link getDataItem DataItem} properties, respectively. The type of the item
876  * is given by {@link getItemType ItemType} property.
877  *
878  * @author Qiang Xue <qiang.xue@gmail.com>
879  * @package System.Web.UI.WebControls
880  * @since 3.0
881  */
882 class TRepeaterItem extends TControl implements INamingContainer, IItemDataRenderer
883 {
884         /**
885          * index of the data item in the Items collection of repeater
886          */
887         private $_itemIndex;
888         /**
889          * type of the TRepeaterItem
890          * @var TListItemType
891          */
892         private $_itemType;
893         /**
894          * data associated with this item
895          * @var mixed
896          */
897         private $_data;
898
899         /**
900          * @return TListItemType item type
901          */
902         public function getItemType()
903         {
904                 return $this->_itemType;
905         }
906
907         /**
908          * @param TListItemType item type.
909          */
910         public function setItemType($value)
911         {
912                 $this->_itemType=TPropertyValue::ensureEnum($value,'TListItemType');
913         }
914
915         /**
916          * Returns a value indicating the zero-based index of the item in the corresponding data control's item collection.
917          * If the item is not in the collection (e.g. it is a header item), it returns -1.
918          * @return integer zero-based index of the item.
919          */
920         public function getItemIndex()
921         {
922                 return $this->_itemIndex;
923         }
924
925         /**
926          * Sets the zero-based index for the item.
927          * If the item is not in the item collection (e.g. it is a header item), -1 should be used.
928          * @param integer zero-based index of the item.
929          */
930         public function setItemIndex($value)
931         {
932                 $this->_itemIndex=TPropertyValue::ensureInteger($value);
933         }
934
935         /**
936          * @return mixed data associated with the item
937          * @since 3.1.0
938          */
939         public function getData()
940         {
941                 return $this->_data;
942         }
943
944         /**
945          * @param mixed data to be associated with the item
946          * @since 3.1.0
947          */
948         public function setData($value)
949         {
950                 $this->_data=$value;
951         }
952
953         /**
954          * This property is deprecated since v3.1.0.
955          * @return mixed data associated with the item
956          * @deprecated deprecated since v3.1.0. Use {@link getData} instead.
957          */
958         public function getDataItem()
959         {
960                 return $this->getData();
961         }
962
963         /**
964          * This property is deprecated since v3.1.0.
965          * @param mixed data to be associated with the item
966          * @deprecated deprecated since version 3.1.0. Use {@link setData} instead.
967          */
968         public function setDataItem($value)
969         {
970                 return $this->setData($value);
971         }
972
973         /**
974          * This method overrides parent's implementation by wrapping event parameter
975          * for <b>OnCommand</b> event with item information.
976          * @param TControl the sender of the event
977          * @param TEventParameter event parameter
978          * @return boolean whether the event bubbling should stop here.
979          */
980         public function bubbleEvent($sender,$param)
981         {
982                 if($param instanceof TCommandEventParameter)
983                 {
984                         $this->raiseBubbleEvent($this,new TRepeaterCommandEventParameter($this,$sender,$param));
985                         return true;
986                 }
987                 else
988                         return false;
989         }
990 }
991
992
993 /**
994  * TRepeaterItemCollection class.
995  *
996  * TRepeaterItemCollection represents a collection of repeater items.
997  *
998  * @author Qiang Xue <qiang.xue@gmail.com>
999  * @package System.Web.UI.WebControls
1000  * @since 3.0
1001  */
1002 class TRepeaterItemCollection extends TList
1003 {
1004         /**
1005          * Inserts an item at the specified position.
1006          * This overrides the parent implementation by inserting only objects that are descendant of {@link TControl}.
1007          * @param integer the speicified position.
1008          * @param TControl new item
1009          * @throws TInvalidDataTypeException if the item to be inserted is not a control.
1010          */
1011         public function insertAt($index,$item)
1012         {
1013                 if($item instanceof TControl)
1014                         parent::insertAt($index,$item);
1015                 else
1016                         throw new TInvalidDataTypeException('repeateritemcollection_item_invalid');
1017         }
1018 }
1019