1: <?php
2: /**
3: * QListItemManagerager.trait.php contains the QListItemManager trait
4: * @package Controls
5: */
6:
7: /**
8: * This is a trait that presents an interface for managing an item list. It is used by the QListControl, QHListControl,
9: * and the QHListItem classes, the latter because a QHListItem can itself contain a list of other items.
10: *
11: * Note that some abstract methods are declared here that must be implemented by the using class:
12: * GetId() - returns the id
13: * MarkAsModified() - marks the object as modified. Optional.
14: *
15: * @package Controls
16: */
17: trait QListItemManager {
18: ///////////////////////////
19: // Private Member Variables
20: ///////////////////////////
21: /** @var QListItemBase[] an array of subitems if this is a recursive item. */
22: protected $objListItemArray;
23:
24: /**
25: * Add a base list item to the list.
26: *
27: * @param QListItemBase $objListItem
28: */
29: public function AddListItem(QListItemBase $objListItem) {
30: if ($strControlId = $this->GetId()) {
31: $objListItem->SetId($strControlId . '_' . count($this->objListItemArray)); // auto assign the id based on parent id
32: $objListItem->Reindex();
33: }
34: $this->objListItemArray[] = $objListItem;
35: $this->MarkAsModified();
36: }
37:
38:
39: /**
40: * Allows you to add a ListItem at a certain index
41: * Unlike AddItem, this will insert the ListItem at whatever index is passed to the function. Additionally,
42: * only a ListItem object can be passed (as opposed to an object or strings)
43: *
44: * @param integer $intIndex index at which the item should be inserted
45: * @param QListItemBase $objListItem the ListItem which shall be inserted
46: *
47: * @throws QIndexOutOfRangeException
48: * @throws Exception|QInvalidCastException
49: */
50: public function AddItemAt($intIndex, QListItemBase $objListItem) {
51: try {
52: $intIndex = QType::Cast($intIndex, QType::Integer);
53: } catch (QInvalidCastException $objExc) {
54: $objExc->IncrementOffset();
55: throw $objExc;
56: }
57: if ($intIndex >= 0 &&
58: (!$this->objListItemArray && $intIndex == 0 ||
59: $intIndex <= count($this->objListItemArray))) {
60: for ($intCount = count($this->objListItemArray); $intCount > $intIndex; $intCount--) {
61: $this->objListItemArray[$intCount] = $this->objListItemArray[$intCount - 1];
62: }
63: } else {
64: throw new QIndexOutOfRangeException($intIndex, "AddItemAt()");
65: }
66:
67: $this->objListItemArray[$intIndex] = $objListItem;
68: $this->Reindex();
69: }
70:
71: /**
72: * Reindex the ids of the items based on the current item. We manage all the ids in the list internally
73: * to be able to get to an item in the list quickly, and to make sure the ids are unique.
74: */
75: public function Reindex() {
76: if ($this->GetId() && $this->objListItemArray) for ($i = 0; $i < $this->GetItemCount(); $i++) {
77: $this->objListItemArray[$i]->SetId($this->GetId() . '_' . $i); // assign the id based on parent id
78: $this->objListItemArray[$i]->Reindex();
79: }
80: }
81:
82: /**
83: * Stub function. The including function needs to implement this.
84: */
85: abstract public function MarkAsModified();
86:
87: /**
88: * Returns the id of the item, however the item stores it.
89: * @return string
90: */
91: abstract public function GetId();
92:
93: /**
94: * Adds an array of items,
95: *
96: * @param QListItemBase[] $objListItemArray Array of QListItems or key=>val pairs.
97: *
98: * @throws Exception|QInvalidCastException
99: */
100: public function AddListItems(array $objListItemArray) {
101: try {
102: $objListItemArray = QType::Cast($objListItemArray, QType::ArrayType);
103: if ($objListItemArray) {
104: if (!reset($objListItemArray) instanceof QListItemBase) {
105: throw new QCallerException ('Not an array of QListItemBase types');
106: }
107: }
108: } catch (QInvalidCastException $objExc) {
109: $objExc->IncrementOffset();
110: throw $objExc;
111: }
112:
113: if ($this->objListItemArray) {
114: $this->objListItemArray = array_merge ($this->objListItemArray, $objListItemArray);
115: } else {
116: $this->objListItemArray = $objListItemArray;
117: }
118: $this->Reindex();
119: $this->MarkAsModified();
120: }
121:
122: /**
123: * Retrieve the ListItem at the specified index location
124: *
125: * @param integer $intIndex
126: *
127: * @throws QIndexOutOfRangeException
128: * @throws Exception|QInvalidCastException
129: * @return QListItem
130: */
131: public function GetItem($intIndex) {
132: try {
133: $intIndex = QType::Cast($intIndex, QType::Integer);
134: } catch (QInvalidCastException $objExc) {
135: $objExc->IncrementOffset();
136: throw $objExc;
137: }
138: if (($intIndex < 0) ||
139: ($intIndex >= count($this->objListItemArray)))
140: throw new QIndexOutOfRangeException($intIndex, "GetItem()");
141:
142: return $this->objListItemArray[$intIndex];
143: }
144:
145: /**
146: * This will return an array of ALL the QListItems associated with this QListControl.
147: * Please note that while each individual item can be altered, altering the array, itself,
148: * will not affect any change on the QListControl. So existing QListItems may be modified,
149: * but to add / remove items from the QListControl, you should use AddItem() and RemoveItem().
150: * @return QListItem[]
151: */
152: public function GetAllItems() {
153: return $this->objListItemArray;
154: }
155:
156: /**
157: * Removes all the items in objListItemArray
158: */
159: public function RemoveAllItems() {
160: $this->MarkAsModified();
161: $this->objListItemArray = null;
162: }
163:
164: /**
165: * Removes a ListItem at the specified index location
166: *
167: * @param integer $intIndex
168: *
169: * @throws QIndexOutOfRangeException
170: * @throws Exception|QInvalidCastException
171: */
172: public function RemoveItem($intIndex) {
173: try {
174: $intIndex = QType::Cast($intIndex, QType::Integer);
175: } catch (QInvalidCastException $objExc) {
176: $objExc->IncrementOffset();
177: throw $objExc;
178: }
179: if (($intIndex < 0) ||
180: ($intIndex > (count($this->objListItemArray) - 1)))
181: throw new QIndexOutOfRangeException($intIndex, "RemoveItem()");
182: for ($intCount = $intIndex; $intCount < count($this->objListItemArray) - 1; $intCount++) {
183: $this->objListItemArray[$intCount] = $this->objListItemArray[$intCount + 1];
184: }
185:
186: $this->objListItemArray[$intCount] = null;
187: unset($this->objListItemArray[$intCount]);
188: $this->MarkAsModified();
189: $this->Reindex();
190: }
191:
192: /**
193: * Replaces a QListItem at $intIndex. This combines the RemoveItem() and AddItemAt() operations.
194: *
195: * @param integer $intIndex
196: * @param QListItem $objListItem
197: *
198: * @throws Exception|QInvalidCastException
199: */
200: public function ReplaceItem($intIndex, QListItem $objListItem) {
201: try {
202: $intIndex = QType::Cast($intIndex, QType::Integer);
203: } catch (QInvalidCastException $objExc) {
204: $objExc->IncrementOffset();
205: throw $objExc;
206: }
207: $objListItem->SetId($this->GetId() . '_' . $intIndex);
208: $this->objListItemArray[$intIndex] = $objListItem;
209: $objListItem->Reindex();
210: $this->MarkAsModified();
211: }
212:
213: /**
214: * Return the count of the items.
215: *
216: * @return int
217: */
218: public function GetItemCount() {
219: $count = 0;
220: if ($this->objListItemArray) {
221: $count = count($this->objListItemArray);
222: }
223: return $count;
224: }
225:
226: /**
227: * Finds the item by id recursively. Makes use of the fact that we maintain the ids in order to efficiently
228: * find the item.
229: *
230: * @param string $strId If this is a sub-item, it will be an id fragment
231: * @return null|QListItem
232: */
233: public function FindItem($strId) {
234: if (!$this->objListItemArray) return null;
235: $objFoundItem = null;
236: $a = explode ('_', $strId, 3);
237: if (isset($a[1]) &&
238: $a[1] < count ($this->objListItemArray)) { // just in case
239: $objFoundItem = $this->objListItemArray[$a[1]];
240: }
241: if (isset($a[2])) { // a recursive list
242: $objFoundItem = $objFoundItem->FindItem ($a[1] . '_' . $a[2]);
243: }
244:
245: return $objFoundItem;
246: }
247:
248: /**
249: * Returns the first tiem found with the given value.
250: *
251: * @param $strValue
252: * @return null|QListItemBase
253: */
254: public function FindItemByValue($strValue) {
255: if (!$this->objListItemArray) return null;
256: foreach ($this->objListItemArray as $objItem) {
257: if ($objItem->Value == $strValue) {
258: return $objItem;
259: }
260: }
261: return null;
262: }
263: }
264: