TRepeater::getDataFieldValue()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 2
dl 0
loc 3
ccs 0
cts 3
cp 0
crap 2
rs 10
1
<?php
2
3
/**
4
 * TRepeater class file
5
 *
6
 * @author Qiang Xue <[email protected]>
7
 * @link https://github.com/pradosoft/prado
8
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
9
 */
10
11
namespace Prado\Web\UI\WebControls;
12
13
use Prado\Exceptions\TInvalidDataTypeException;
14
use Prado\Exceptions\TInvalidDataValueException;
15
use Prado\Collections\TMap;
16
use Prado\Collections\TList;
17
use Prado\Prado;
18
use Prado\Util\TDataFieldAccessor;
19
use Prado\Web\UI\ITemplate;
20
21
/**
22
 * TRepeater class.
23
 *
24
 * TRepeater displays its content repeatedly based on the data fetched from
25
 * {@see setDataSource DataSource}.
26
 * The repeated contents in TRepeater are called items, which are controls and
27
 * can be accessed through {@see getItems Items}. When {@see dataBind()} is invoked,
28
 * TRepeater creates an item for each row of data and binds the data row to the item.
29
 * Optionally, a repeater can have a header, a footer and/or separators between items.
30
 *
31
 * The layout of the repeated contents are specified by inline templates.
32
 * Repeater items, header, footer, etc. are being instantiated with the corresponding
33
 * templates when data is being bound to the repeater.
34
 *
35
 * Since v3.1.0, the layout can also be specified by renderers. A renderer is a control class
36
 * that can be instantiated as repeater items, header, etc. A renderer can thus be viewed
37
 * as an external template (in fact, it can also be non-templated controls).
38
 *
39
 * A renderer can be any control class.
40
 * - If the class implements {@see \Prado\IDataRenderer}, the <b>Data</b>
41
 * property will be set as the data row during databinding. Many PRADO controls
42
 * implement this interface, such as {@see \Prado\Web\UI\WebControls\TLabel}, {@see \Prado\Web\UI\WebControls\TTextBox}, etc.
43
 * - If the class implements {@see \Prado\Web\UI\WebControls\IItemDataRenderer}, the <b>ItemIndex</b> property will be set
44
 * as the zero-based index of the item in the repeater item collection, and
45
 * the <b>ItemType</b> property as the item's type (such as TListItemType::Item).
46
 * {@see \Prado\Web\UI\WebControls\TRepeaterItemRenderer} may be used as the convenient base class which
47
 * already implements {@see IDataItemRenderer}.
48
 *
49
 * The following properties are used to specify different types of template and renderer
50
 * for a repeater:
51
 * - {@see setItemTemplate ItemTemplate}, {@see setItemRenderer ItemRenderer}:
52
 * for each repeated row of data
53
 * - {@see setAlternatingItemTemplate AlternatingItemTemplate}, {@see setAlternatingItemRenderer AlternatingItemRenderer}:
54
 * for each alternating row of data. If not set, {@see setItemTemplate ItemTemplate} or {@see setItemRenderer ItemRenderer}
55
 * will be used instead.
56
 * - {@see setHeaderTemplate HeaderTemplate}, {@see setHeaderRenderer HeaderRenderer}:
57
 * for the repeater header.
58
 * - {@see setFooterTemplate FooterTemplate}, {@see setFooterRenderer FooterRenderer}:
59
 * for the repeater footer.
60
 * - {@see setSeparatorTemplate SeparatorTemplate}, {@see setSeparatorRenderer SeparatorRenderer}:
61
 * for content to be displayed between items.
62
 * - {@see setEmptyTemplate EmptyTemplate}, {@see setEmptyRenderer EmptyRenderer}:
63
 * used when data bound to the repeater is empty.
64
 *
65
 * If a content type is defined with both a template and a renderer, the latter takes precedence.
66
 *
67
 * When {@see dataBind()} is being called, TRepeater undergoes the following lifecycles for each row of data:
68
 * - create item based on templates or renderers
69
 * - set the row of data to the item
70
 * - raise {@see onItemCreated OnItemCreated}:
71
 * - add the item as a child control
72
 * - call dataBind() of the item
73
 * - raise {@see onItemDataBound OnItemDataBound}:
74
 *
75
 * TRepeater raises an {@see onItemCommand OnItemCommand} whenever a button control
76
 * within some repeater item raises a <b>OnCommand</b> event. Therefore,
77
 * you can handle all sorts of <b>OnCommand</b> event in a central place by
78
 * writing an event handler for {@see onItemCommand OnItemCommand}.
79
 *
80
 * When a page containing a repeater is post back, the repeater will restore automatically
81
 * all its contents, including items, header, footer and separators.
82
 * However, the data row associated with each item will not be recovered and become null.
83
 * To access the data, use one of the following ways:
84
 * - Use {@see getDataKeys DataKeys} to obtain the data key associated with
85
 * the specified repeater item and use the key to fetch the corresponding data
86
 * from some persistent storage such as DB.
87
 * - Save the whole dataset in viewstate, which will restore the dataset automatically upon postback.
88
 * Be aware though, if the size of your dataset is big, your page size will become big. Some
89
 * complex data may also have serializing problem if saved in viewstate.
90
 *
91
 * @author Qiang Xue <[email protected]>
92
 * @since 3.0
93
 */
94
class TRepeater extends TDataBoundControl implements \Prado\Web\UI\INamingContainer
95
{
96
	/**
97
	 * @var ITemplate template for repeater items
98
	 */
99
	private $_itemTemplate;
100
	/**
101
	 * @var ITemplate template for each alternating item
102
	 */
103
	private $_alternatingItemTemplate;
104
	/**
105
	 * @var ITemplate template for header
106
	 */
107
	private $_headerTemplate;
108
	/**
109
	 * @var ITemplate template for footer
110
	 */
111
	private $_footerTemplate;
112
	/**
113
	 * @var ITemplate template used for repeater when no data is bound
114
	 */
115
	private $_emptyTemplate;
116
	/**
117
	 * @var ITemplate template for separator
118
	 */
119
	private $_separatorTemplate;
120
	/**
121
	 * @var TRepeaterItemCollection list of repeater items
122
	 */
123
	private $_items;
124
	/**
125
	 * @var \Prado\Web\UI\TControl header item
126
	 */
127
	private $_header;
128
	/**
129
	 * @var \Prado\Web\UI\TControl footer item
130
	 */
131
	private $_footer;
132
133
134
	/**
135
	 * @return string the class name for repeater items. Defaults to empty, meaning not set.
136
	 * @since 3.1.0
137
	 */
138
	public function getItemRenderer()
139
	{
140
		return $this->getViewState('ItemRenderer', '');
141
	}
142
143
	/**
144
	 * Sets the item renderer class.
145
	 *
146
	 * If not empty, the class will be used to instantiate as repeater items.
147
	 * This property takes precedence over {@see getItemTemplate ItemTemplate}.
148
	 *
149
	 * @param string $value the renderer class name in namespace format.
150
	 * @see setItemTemplate
151
	 * @since 3.1.0
152
	 */
153
	public function setItemRenderer($value)
154
	{
155
		$this->setViewState('ItemRenderer', $value, '');
156
	}
157
158
	/**
159
	 * @return string the class name for alternative repeater items. Defaults to empty, meaning not set.
160
	 * @since 3.1.0
161
	 */
162
	public function getAlternatingItemRenderer()
163
	{
164
		return $this->getViewState('AlternatingItemRenderer', '');
165
	}
166
167
	/**
168
	 * Sets the alternative item renderer class.
169
	 *
170
	 * If not empty, the class will be used to instantiate as alternative repeater items.
171
	 * This property takes precedence over {@see getAlternatingItemTemplate AlternatingItemTemplate}.
172
	 *
173
	 * @param string $value the renderer class name in namespace format.
174
	 * @see setAlternatingItemTemplate
175
	 * @since 3.1.0
176
	 */
177
	public function setAlternatingItemRenderer($value)
178
	{
179
		$this->setViewState('AlternatingItemRenderer', $value, '');
180
	}
181
182
	/**
183
	 * @return string the class name for repeater item separators. Defaults to empty, meaning not set.
184
	 * @since 3.1.0
185
	 */
186
	public function getSeparatorRenderer()
187
	{
188
		return $this->getViewState('SeparatorRenderer', '');
189
	}
190
191
	/**
192
	 * Sets the repeater item separator renderer class.
193
	 *
194
	 * If not empty, the class will be used to instantiate as repeater item separators.
195
	 * This property takes precedence over {@see getSeparatorTemplate SeparatorTemplate}.
196
	 *
197
	 * @param string $value the renderer class name in namespace format.
198
	 * @see setSeparatorTemplate
199
	 * @since 3.1.0
200
	 */
201
	public function setSeparatorRenderer($value)
202
	{
203
		$this->setViewState('SeparatorRenderer', $value, '');
204
	}
205
206
	/**
207
	 * @return string the class name for repeater header item. Defaults to empty, meaning not set.
208
	 * @since 3.1.0
209
	 */
210
	public function getHeaderRenderer()
211
	{
212
		return $this->getViewState('HeaderRenderer', '');
213
	}
214
215
	/**
216
	 * Sets the repeater header renderer class.
217
	 *
218
	 * If not empty, the class will be used to instantiate as repeater header item.
219
	 * This property takes precedence over {@see getHeaderTemplate HeaderTemplate}.
220
	 *
221
	 * @param string $value the renderer class name in namespace format.
222
	 * @see setHeaderTemplate
223
	 * @since 3.1.0
224
	 */
225
	public function setHeaderRenderer($value)
226
	{
227
		$this->setViewState('HeaderRenderer', $value, '');
228
	}
229
230
	/**
231
	 * @return string the class name for repeater footer item. Defaults to empty, meaning not set.
232
	 * @since 3.1.0
233
	 */
234
	public function getFooterRenderer()
235
	{
236
		return $this->getViewState('FooterRenderer', '');
237
	}
238
239
	/**
240
	 * Sets the repeater footer renderer class.
241
	 *
242
	 * If not empty, the class will be used to instantiate as repeater footer item.
243
	 * This property takes precedence over {@see getFooterTemplate FooterTemplate}.
244
	 *
245
	 * @param string $value the renderer class name in namespace format.
246
	 * @see setFooterTemplate
247
	 * @since 3.1.0
248
	 */
249
	public function setFooterRenderer($value)
250
	{
251
		$this->setViewState('FooterRenderer', $value, '');
252
	}
253
254
	/**
255
	 * @return string the class name for empty repeater item. Defaults to empty, meaning not set.
256
	 * @since 3.1.0
257
	 */
258
	public function getEmptyRenderer()
259
	{
260
		return $this->getViewState('EmptyRenderer', '');
261
	}
262
263
	/**
264
	 * Sets the repeater empty renderer class.
265
	 *
266
	 * The empty renderer is created as the child of the repeater
267
	 * if data bound to the repeater is empty.
268
	 * This property takes precedence over {@see getEmptyTemplate EmptyTemplate}.
269
	 *
270
	 * @param string $value the renderer class name in namespace format.
271
	 * @see setEmptyTemplate
272
	 * @since 3.1.0
273
	 */
274
	public function setEmptyRenderer($value)
275
	{
276
		$this->setViewState('EmptyRenderer', $value, '');
277
	}
278
279
	/**
280
	 * @return \Prado\Web\UI\ITemplate the template for repeater items
281
	 */
282
	public function getItemTemplate()
283
	{
284
		return $this->_itemTemplate;
285
	}
286
287
	/**
288
	 * @param \Prado\Web\UI\ITemplate $value the template for repeater items
289
	 * @throws TInvalidDataTypeException if the input is not an {@see \Prado\Web\UI\ITemplate} or not null.
290
	 */
291
	public function setItemTemplate($value)
292
	{
293
		if ($value instanceof \Prado\Web\UI\ITemplate || $value === null) {
0 ignored issues
show
introduced by
$value is always a sub-type of Prado\Web\UI\ITemplate.
Loading history...
294
			$this->_itemTemplate = $value;
295
		} else {
296
			throw new TInvalidDataTypeException('repeater_template_required', 'ItemTemplate');
297
		}
298
	}
299
300
	/**
301
	 * @return \Prado\Web\UI\ITemplate the alternative template string for the item
302
	 */
303
	public function getAlternatingItemTemplate()
304
	{
305
		return $this->_alternatingItemTemplate;
306
	}
307
308
	/**
309
	 * @param \Prado\Web\UI\ITemplate $value the alternative item template
310
	 * @throws TInvalidDataTypeException if the input is not an {@see \Prado\Web\UI\ITemplate} or not null.
311
	 */
312
	public function setAlternatingItemTemplate($value)
313
	{
314
		if ($value instanceof \Prado\Web\UI\ITemplate || $value === null) {
0 ignored issues
show
introduced by
$value is always a sub-type of Prado\Web\UI\ITemplate.
Loading history...
315
			$this->_alternatingItemTemplate = $value;
316
		} else {
317
			throw new TInvalidDataTypeException('repeater_template_required', 'AlternatingItemTemplate');
318
		}
319
	}
320
321
	/**
322
	 * @return \Prado\Web\UI\ITemplate the header template
323
	 */
324
	public function getHeaderTemplate()
325
	{
326
		return $this->_headerTemplate;
327
	}
328
329
	/**
330
	 * @param \Prado\Web\UI\ITemplate $value the header template
331
	 * @throws TInvalidDataTypeException if the input is not an {@see \Prado\Web\UI\ITemplate} or not null.
332
	 */
333
	public function setHeaderTemplate($value)
334
	{
335
		if ($value instanceof \Prado\Web\UI\ITemplate || $value === null) {
0 ignored issues
show
introduced by
$value is always a sub-type of Prado\Web\UI\ITemplate.
Loading history...
336
			$this->_headerTemplate = $value;
337
		} else {
338
			throw new TInvalidDataTypeException('repeater_template_required', 'HeaderTemplate');
339
		}
340
	}
341
342
	/**
343
	 * @return \Prado\Web\UI\ITemplate the footer template
344
	 */
345
	public function getFooterTemplate()
346
	{
347
		return $this->_footerTemplate;
348
	}
349
350
	/**
351
	 * @param \Prado\Web\UI\ITemplate $value the footer template
352
	 * @throws TInvalidDataTypeException if the input is not an {@see \Prado\Web\UI\ITemplate} or not null.
353
	 */
354
	public function setFooterTemplate($value)
355
	{
356
		if ($value instanceof \Prado\Web\UI\ITemplate || $value === null) {
0 ignored issues
show
introduced by
$value is always a sub-type of Prado\Web\UI\ITemplate.
Loading history...
357
			$this->_footerTemplate = $value;
358
		} else {
359
			throw new TInvalidDataTypeException('repeater_template_required', 'FooterTemplate');
360
		}
361
	}
362
363
	/**
364
	 * @return \Prado\Web\UI\ITemplate the template applied when no data is bound to the repeater
365
	 */
366
	public function getEmptyTemplate()
367
	{
368
		return $this->_emptyTemplate;
369
	}
370
371
	/**
372
	 * @param \Prado\Web\UI\ITemplate $value the template applied when no data is bound to the repeater
373
	 * @throws TInvalidDataTypeException if the input is not an {@see \Prado\Web\UI\ITemplate} or not null.
374
	 */
375
	public function setEmptyTemplate($value)
376
	{
377
		if ($value instanceof \Prado\Web\UI\ITemplate || $value === null) {
0 ignored issues
show
introduced by
$value is always a sub-type of Prado\Web\UI\ITemplate.
Loading history...
378
			$this->_emptyTemplate = $value;
379
		} else {
380
			throw new TInvalidDataTypeException('repeater_template_required', 'EmptyTemplate');
381
		}
382
	}
383
384
	/**
385
	 * @return \Prado\Web\UI\ITemplate the separator template
386
	 */
387
	public function getSeparatorTemplate()
388
	{
389
		return $this->_separatorTemplate;
390
	}
391
392
	/**
393
	 * @param \Prado\Web\UI\ITemplate $value the separator template
394
	 * @throws TInvalidDataTypeException if the input is not an {@see \Prado\Web\UI\ITemplate} or not null.
395
	 */
396
	public function setSeparatorTemplate($value)
397
	{
398
		if ($value instanceof \Prado\Web\UI\ITemplate || $value === null) {
0 ignored issues
show
introduced by
$value is always a sub-type of Prado\Web\UI\ITemplate.
Loading history...
399
			$this->_separatorTemplate = $value;
400
		} else {
401
			throw new TInvalidDataTypeException('repeater_template_required', 'SeparatorTemplate');
402
		}
403
	}
404
405
	/**
406
	 * @return \Prado\Web\UI\TControl the header item
407
	 */
408
	public function getHeader()
409
	{
410
		return $this->_header;
411
	}
412
413
	/**
414
	 * @return \Prado\Web\UI\TControl the footer item
415
	 */
416
	public function getFooter()
417
	{
418
		return $this->_footer;
419
	}
420
421
	/**
422
	 * @return TRepeaterItemCollection list of repeater item controls
423
	 */
424
	public function getItems()
425
	{
426
		if (!$this->_items) {
427
			$this->_items = new TRepeaterItemCollection();
428
		}
429
		return $this->_items;
430
	}
431
432
	/**
433
	 * @return string the field of the data source that provides the keys of the list items.
434
	 */
435
	public function getDataKeyField()
436
	{
437
		return $this->getViewState('DataKeyField', '');
438
	}
439
440
	/**
441
	 * @param string $value the field of the data source that provides the keys of the list items.
442
	 */
443
	public function setDataKeyField($value)
444
	{
445
		$this->setViewState('DataKeyField', $value, '');
446
	}
447
448
	/**
449
	 * @return TList the keys used in the data listing control.
450
	 */
451
	public function getDataKeys()
452
	{
453
		if (($dataKeys = $this->getViewState('DataKeys', null)) === null) {
454
			$dataKeys = new TList();
455
			$this->setViewState('DataKeys', $dataKeys, null);
456
		}
457
		return $dataKeys;
458
	}
459
460
	/**
461
	 * Creates a repeater item.
462
	 * This method invokes {@see createItem} to create a new repeater item.
463
	 * @param int $itemIndex zero-based item index.
464
	 * @param TListItemType $itemType item type
465
	 * @return \Prado\Web\UI\TControl the created item, null if item is not created
466
	 */
467
	private function createItemInternal($itemIndex, $itemType)
468
	{
469
		if (($item = $this->createItem($itemIndex, $itemType)) !== null) {
470
			$param = new TRepeaterItemEventParameter($item);
471
			$this->onItemCreated($param);
472
			$this->getControls()->add($item);
473
			return $item;
474
		} else {
475
			return null;
476
		}
477
	}
478
479
	/**
480
	 * Creates a repeater item and performs databinding.
481
	 * This method invokes {@see createItem} to create a new repeater item.
482
	 * @param int $itemIndex zero-based item index.
483
	 * @param TListItemType $itemType item type
484
	 * @param mixed $dataItem data to be associated with the item
485
	 * @return \Prado\Web\UI\TControl the created item, null if item is not created
486
	 */
487
	private function createItemWithDataInternal($itemIndex, $itemType, $dataItem)
488
	{
489
		if (($item = $this->createItem($itemIndex, $itemType)) !== null) {
490
			$param = new TRepeaterItemEventParameter($item);
491
			if ($item instanceof \Prado\IDataRenderer) {
492
				$item->setData($dataItem);
493
			}
494
			$this->onItemCreated($param);
495
			$this->getControls()->add($item);
496
			$item->dataBind();
497
			$this->onItemDataBound($param);
498
			return $item;
499
		} else {
500
			return null;
501
		}
502
	}
503
504
	/**
505
	 * Creates a repeater item instance based on the item type and index.
506
	 * @param int $itemIndex zero-based item index
507
	 * @param TListItemType $itemType item type
508
	 * @return \Prado\Web\UI\TControl created repeater item
509
	 */
510
	protected function createItem($itemIndex, $itemType)
511
	{
512
		$template = null;
513
		$classPath = null;
514
		switch ($itemType) {
515
			case TListItemType::Item:
516
				$classPath = $this->getItemRenderer();
517
				$template = $this->_itemTemplate;
518
				break;
519
			case TListItemType::AlternatingItem:
520
				if (($classPath = $this->getAlternatingItemRenderer()) === '' && ($template = $this->_alternatingItemTemplate) === null) {
521
					$classPath = $this->getItemRenderer();
522
					$template = $this->_itemTemplate;
523
				}
524
				break;
525
			case TListItemType::Header:
526
				$classPath = $this->getHeaderRenderer();
527
				$template = $this->_headerTemplate;
528
				break;
529
			case TListItemType::Footer:
530
				$classPath = $this->getFooterRenderer();
531
				$template = $this->_footerTemplate;
532
				break;
533
			case TListItemType::Separator:
534
				$classPath = $this->getSeparatorRenderer();
535
				$template = $this->_separatorTemplate;
536
				break;
537
			default:
538
				throw new TInvalidDataValueException('repeater_itemtype_unknown', $itemType);
0 ignored issues
show
Bug introduced by
$itemType of type Prado\Web\UI\WebControls\TListItemType is incompatible with the type string expected by parameter $errorMessage of Prado\Exceptions\TInvali...xception::__construct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

538
				throw new TInvalidDataValueException('repeater_itemtype_unknown', /** @scrutinizer ignore-type */ $itemType);
Loading history...
539
		}
540
		if ($classPath !== '') {
541
			$item = Prado::createComponent($classPath);
542
			if ($item instanceof IItemDataRenderer) {
543
				$item->setItemIndex($itemIndex);
544
				$item->setItemType($itemType);
545
			}
546
		} elseif ($template !== null) {
547
			$item = new TRepeaterItem();
548
			$item->setItemIndex($itemIndex);
549
			$item->setItemType($itemType);
550
			$template->instantiateIn($item);
551
		} else {
552
			$item = null;
553
		}
554
555
		return $item;
556
	}
557
558
	/**
559
	 * Creates empty repeater content.
560
	 */
561
	protected function createEmptyContent()
562
	{
563
		if (($classPath = $this->getEmptyRenderer()) !== '') {
564
			$this->getControls()->add(Prado::createComponent($classPath));
565
		} elseif ($this->_emptyTemplate !== null) {
566
			$this->_emptyTemplate->instantiateIn($this);
567
		}
568
	}
569
570
	/**
571
	 * Renders the repeater.
572
	 * This method overrides the parent implementation by rendering the body
573
	 * content as the whole presentation of the repeater. Outer tag is not rendered.
574
	 * @param \Prado\Web\UI\THtmlWriter $writer writer
575
	 */
576
	public function render($writer)
577
	{
578
		if ($this->_items && $this->_items->getCount() || $this->_emptyTemplate !== null || $this->getEmptyRenderer() !== '') {
579
			$this->renderContents($writer);
580
		}
581
	}
582
583
	/**
584
	 * Saves item count in viewstate.
585
	 * This method is invoked right before control state is to be saved.
586
	 */
587
	public function saveState()
588
	{
589
		parent::saveState();
590
		if ($this->_items) {
591
			$this->setViewState('ItemCount', $this->_items->getCount(), 0);
592
		} else {
593
			$this->clearViewState('ItemCount');
594
		}
595
	}
596
597
	/**
598
	 * Loads item count information from viewstate.
599
	 * This method is invoked right after control state is loaded.
600
	 */
601
	public function loadState()
602
	{
603
		parent::loadState();
604
		if (!$this->getIsDataBound()) {
605
			$this->restoreItemsFromViewState();
606
		}
607
		$this->clearViewState('ItemCount');
608
	}
609
610
	/**
611
	 * Clears up all items in the repeater.
612
	 */
613
	public function reset()
614
	{
615
		$this->getControls()->clear();
616
		$this->getItems()->clear();
617
		$this->_header = null;
618
		$this->_footer = null;
619
	}
620
621
	/**
622
	 * Creates repeater items based on viewstate information.
623
	 */
624
	protected function restoreItemsFromViewState()
625
	{
626
		$this->reset();
627
		if (($itemCount = $this->getViewState('ItemCount', 0)) > 0) {
628
			$items = $this->getItems();
629
			$hasSeparator = $this->_separatorTemplate !== null || $this->getSeparatorRenderer() !== '';
630
			$this->_header = $this->createItemInternal(-1, TListItemType::Header);
0 ignored issues
show
Bug introduced by
Prado\Web\UI\WebControls\TListItemType::Header of type string is incompatible with the type Prado\Web\UI\WebControls\TListItemType expected by parameter $itemType of Prado\Web\UI\WebControls...r::createItemInternal(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

630
			$this->_header = $this->createItemInternal(-1, /** @scrutinizer ignore-type */ TListItemType::Header);
Loading history...
631
			for ($i = 0; $i < $itemCount; ++$i) {
632
				if ($hasSeparator && $i > 0) {
633
					$this->createItemInternal($i - 1, TListItemType::Separator);
634
				}
635
				$itemType = $i % 2 == 0 ? TListItemType::Item : TListItemType::AlternatingItem;
636
				$items->add($this->createItemInternal($i, $itemType));
637
			}
638
			$this->_footer = $this->createItemInternal(-1, TListItemType::Footer);
639
		} else {
640
			$this->createEmptyContent();
641
		}
642
		$this->clearChildState();
643
	}
644
645
	/**
646
	 * Performs databinding to populate repeater items from data source.
647
	 * This method is invoked by dataBind().
648
	 * You may override this function to provide your own way of data population.
649
	 * @param \Traversable $data the data
650
	 */
651
	protected function performDataBinding($data)
652
	{
653
		$this->reset();
654
655
		$keys = $this->getDataKeys();
656
		$keys->clear();
657
		$keyField = $this->getDataKeyField();
658
659
		$items = $this->getItems();
660
		$itemIndex = 0;
661
		$hasSeparator = $this->_separatorTemplate !== null || $this->getSeparatorRenderer() !== '';
662
		foreach ($data as $key => $dataItem) {
663
			if ($keyField !== '') {
664
				$keys->add($this->getDataFieldValue($dataItem, $keyField));
665
			} else {
666
				$keys->add($key);
667
			}
668
			if ($itemIndex === 0) {
669
				$this->_header = $this->createItemWithDataInternal(-1, TListItemType::Header, null);
0 ignored issues
show
Bug introduced by
Prado\Web\UI\WebControls\TListItemType::Header of type string is incompatible with the type Prado\Web\UI\WebControls\TListItemType expected by parameter $itemType of Prado\Web\UI\WebControls...eItemWithDataInternal(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

669
				$this->_header = $this->createItemWithDataInternal(-1, /** @scrutinizer ignore-type */ TListItemType::Header, null);
Loading history...
670
			}
671
			if ($hasSeparator && $itemIndex > 0) {
672
				$this->createItemWithDataInternal($itemIndex - 1, TListItemType::Separator, null);
673
			}
674
			$itemType = $itemIndex % 2 == 0 ? TListItemType::Item : TListItemType::AlternatingItem;
675
			$items->add($this->createItemWithDataInternal($itemIndex, $itemType, $dataItem));
676
			$itemIndex++;
677
		}
678
		if ($itemIndex > 0) {
679
			$this->_footer = $this->createItemWithDataInternal(-1, TListItemType::Footer, null);
680
		} else {
681
			$this->createEmptyContent();
682
			$this->dataBindChildren();
683
		}
684
		$this->setViewState('ItemCount', $itemIndex, 0);
685
	}
686
687
	/**
688
	 * This method overrides parent's implementation to handle
689
	 * {@see onItemCommand OnItemCommand} event which is bubbled from
690
	 * repeater items and their child controls.
691
	 * This method should only be used by control developers.
692
	 * @param \Prado\Web\UI\TControl $sender the sender of the event
693
	 * @param \Prado\TEventParameter $param event parameter
694
	 * @return bool whether the event bubbling should stop here.
695
	 */
696
	public function bubbleEvent($sender, $param)
697
	{
698
		if ($param instanceof TRepeaterCommandEventParameter) {
699
			$this->onItemCommand($param);
700
			return true;
701
		} else {
702
			return false;
703
		}
704
	}
705
706
	/**
707
	 * Raises <b>OnItemCreated</b> event.
708
	 * This method is invoked after a repeater item is created and instantiated with
709
	 * template, but before added to the page hierarchy.
710
	 * The repeater item control responsible for the event
711
	 * can be determined from the event parameter.
712
	 * If you override this method, be sure to call parent's implementation
713
	 * so that event handlers have chance to respond to the event.
714
	 * @param TRepeaterItemEventParameter $param event parameter
715
	 */
716
	public function onItemCreated($param)
717
	{
718
		$this->raiseEvent('OnItemCreated', $this, $param);
719
	}
720
721
	/**
722
	 * Raises <b>OnItemDataBound</b> event.
723
	 * This method is invoked right after an item is data bound.
724
	 * The repeater item control responsible for the event
725
	 * can be determined from the event parameter.
726
	 * If you override this method, be sure to call parent's implementation
727
	 * so that event handlers have chance to respond to the event.
728
	 * @param TRepeaterItemEventParameter $param event parameter
729
	 */
730
	public function onItemDataBound($param)
731
	{
732
		$this->raiseEvent('OnItemDataBound', $this, $param);
733
	}
734
735
	/**
736
	 * Raises <b>OnItemCommand</b> event.
737
	 * This method is invoked after a button control in
738
	 * a template raises <b>OnCommand</b> event.
739
	 * The repeater control responsible for the event
740
	 * can be determined from the event parameter.
741
	 * The event parameter also contains the information about
742
	 * the initial sender of the <b>OnCommand</b> event, command name
743
	 * and command parameter.
744
	 * You may override this method to provide customized event handling.
745
	 * Be sure to call parent's implementation so that
746
	 * event handlers have chance to respond to the event.
747
	 * @param TRepeaterCommandEventParameter $param event parameter
748
	 */
749
	public function onItemCommand($param)
750
	{
751
		$this->raiseEvent('OnItemCommand', $this, $param);
752
	}
753
754
	/**
755
	 * Returns the value of the data at the specified field.
756
	 * If data is an array, TMap or TList, the value will be returned at the index
757
	 * of the specified field. If the data is a component with a property named
758
	 * as the field name, the property value will be returned.
759
	 * Otherwise, an exception will be raised.
760
	 * @param mixed $data data item
761
	 * @param string $field field name
762
	 * @throws TInvalidDataValueException if the data is invalid
763
	 * @return mixed data value at the specified field
764
	 */
765
	protected function getDataFieldValue($data, $field)
766
	{
767
		return TDataFieldAccessor::getDataFieldValue($data, $field);
768
	}
769
}
770