Subversion-Projekte lars-tiefland.prado

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

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