b45368dc4c727556b5b7aec7c0455839f2b630c2
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Collection / AbstractRecordCollection.php
1 <?php
2 namespace TYPO3\CMS\Core\Collection;
3
4 /**
5 * This file is part of the TYPO3 CMS project.
6 *
7 * It is free software; you can redistribute it and/or modify it under
8 * the terms of the GNU General Public License, either version 2
9 * of the License, or any later version.
10 *
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
13 *
14 * The TYPO3 project - inspiring people to share!
15 */
16 /**
17 * Abstract implementation of a RecordCollection
18 *
19 * RecordCollection is a collections of TCA-Records.
20 * The collection is meant to be stored in TCA-table sys_collections and is manageable
21 * via TCEforms.
22 *
23 * A RecordCollection might be used to group a set of records (e.g. news, images, contentElements)
24 * for output in frontend
25 *
26 * The AbstractRecordCollection uses SplDoublyLinkedList for internal storage
27 *
28 * @author Steffen Ritter <typo3@steffen-ritter.net>
29 */
30 abstract class AbstractRecordCollection implements \TYPO3\CMS\Core\Collection\RecordCollectionInterface, \TYPO3\CMS\Core\Collection\PersistableCollectionInterface, \TYPO3\CMS\Core\Collection\SortableCollectionInterface {
31
32 /**
33 * The table name collections are stored to
34 *
35 * @var string
36 */
37 static protected $storageTableName = 'sys_collection';
38
39 /**
40 * The table name collections are stored to
41 *
42 * @var string
43 */
44 static protected $storageItemsField = 'items';
45
46 /**
47 * Uid of the storage
48 *
49 * @var int
50 */
51 protected $uid = 0;
52
53 /**
54 * Collection title
55 *
56 * @var string
57 */
58 protected $title;
59
60 /**
61 * Collection description
62 *
63 * @var string
64 */
65 protected $description;
66
67 /**
68 * Table name of the records stored in this collection
69 *
70 * @var string
71 */
72 protected $itemTableName;
73
74 /**
75 * The local storage
76 *
77 * @var SplDoublyLinkedList
78 */
79 protected $storage;
80
81 /**
82 * Creates this object.
83 */
84 public function __construct() {
85 $this->storage = new \SplDoublyLinkedList();
86 }
87
88 /**
89 * (PHP 5 >= 5.1.0)
90 * Return the current element
91 *
92 * @link http://php.net/manual/en/iterator.current.php
93 * @return mixed Can return any type.
94 */
95 public function current() {
96 return $this->storage->current();
97 }
98
99 /**
100 * (PHP 5 >= 5.1.0)
101 * Move forward to next element
102 *
103 * @link http://php.net/manual/en/iterator.next.php
104 * @return void Any returned value is ignored.
105 */
106 public function next() {
107 $this->storage->next();
108 }
109
110 /**
111 * (PHP 5 >= 5.1.0)
112 * Return the key of the current element
113 *
114 * @link http://php.net/manual/en/iterator.key.php
115 * @return int 0 on failure.
116 */
117 public function key() {
118 $currentRecord = $this->storage->current();
119 return $currentRecord['uid'];
120 }
121
122 /**
123 * (PHP 5 >= 5.1.0)
124 * Checks if current position is valid
125 *
126 * @link http://php.net/manual/en/iterator.valid.php
127 * @return bool The return value will be casted to boolean and then evaluated.
128 */
129 public function valid() {
130 return $this->storage->valid();
131 }
132
133 /**
134 * (PHP 5 >= 5.1.0)
135 * Rewind the Iterator to the first element
136 *
137 * @link http://php.net/manual/en/iterator.rewind.php
138 * @return void Any returned value is ignored.
139 */
140 public function rewind() {
141 $this->storage->rewind();
142 }
143
144 /**
145 * (PHP 5 >= 5.1.0)
146 * String representation of object
147 *
148 * @link http://php.net/manual/en/serializable.serialize.php
149 * @return string the string representation of the object or &null;
150 */
151 public function serialize() {
152 $data = array(
153 'uid' => $this->getIdentifier()
154 );
155 return serialize($data);
156 }
157
158 /**
159 * (PHP 5 >= 5.1.0)
160 * Constructs the object
161 *
162 * @link http://php.net/manual/en/serializable.unserialize.php
163 * @param string $serialized The string representation of the object
164 * @return mixed the original value unserialized.
165 */
166 public function unserialize($serialized) {
167 $data = unserialize($serialized);
168 return self::load($data['uid']);
169 }
170
171 /**
172 * (PHP 5 >= 5.1.0)
173 * Count elements of an object
174 *
175 * @link http://php.net/manual/en/countable.count.php
176 * @return int The custom count as an integer.
177 */
178 public function count() {
179 return $this->storage->count();
180 }
181
182 /**
183 * Getter for the title
184 *
185 * @return string
186 */
187 public function getTitle() {
188 return $this->title;
189 }
190
191 /**
192 * Getter for the UID
193 *
194 * @return int
195 */
196 public function getUid() {
197 return $this->uid;
198 }
199
200 /**
201 * Getter for the description
202 *
203 * @return string
204 */
205 public function getDescription() {
206 return $this->description;
207 }
208
209 /**
210 * Setter for the title
211 *
212 * @param string $title
213 * @return void
214 */
215 public function setTitle($title) {
216 $this->title = $title;
217 }
218
219 /**
220 * Setter for the description
221 *
222 * @param string $desc
223 * @return void
224 */
225 public function setDescription($desc) {
226 $this->description = $desc;
227 }
228
229 /**
230 * Setter for the name of the data-source table
231 *
232 * @return string
233 */
234 public function getItemTableName() {
235 return $this->itemTableName;
236 }
237
238 /**
239 * Setter for the name of the data-source table
240 *
241 * @param string $tableName
242 * @return void
243 */
244 public function setItemTableName($tableName) {
245 $this->itemTableName = $tableName;
246 }
247
248 /**
249 * Sorts collection via given callBackFunction
250 *
251 * The comparison function given as must return an integer less than, equal to, or greater than
252 * zero if the first argument is considered to be respectively less than, equal to, or greater than the second.
253 *
254 * @param $callbackFunction
255 * @see http://www.php.net/manual/en/function.usort.php
256 * @return void
257 */
258 public function usort($callbackFunction) {
259 // TODO: Implement usort() method with TCEforms in mind
260 throw new \RuntimeException('This method is not yet supported.', 1322545589);
261 }
262
263 /**
264 * Moves the item within the collection
265 *
266 * the item at $currentPosition will be moved to
267 * $newPosition. Omiting $newPosition will move to top.
268 *
269 * @param int $currentPosition
270 * @param int $newPosition
271 * @return void
272 */
273 public function moveItemAt($currentPosition, $newPosition = 0) {
274 // TODO: Implement usort() method with TCEforms in mind
275 throw new \RuntimeException('This method is not yet supported.', 1322545626);
276 }
277
278 /**
279 * Returns the uid of the collection
280 *
281 * @return int
282 */
283 public function getIdentifier() {
284 return $this->uid;
285 }
286
287 /**
288 * Sets the identifier of the collection
289 *
290 * @param int $id
291 * @return void
292 */
293 public function setIdentifier($id) {
294 $this->uid = (int)$id;
295 }
296
297 /**
298 * Loads the collections with the given id from persistence
299 *
300 * For memory reasons, per default only f.e. title, database-table,
301 * identifier (what ever static data is defined) is loaded.
302 * Entries can be load on first access.
303 *
304 * @param int $id Id of database record to be loaded
305 * @param bool $fillItems Populates the entries directly on load, might be bad for memory on large collections
306 * @return \TYPO3\CMS\Core\Collection\CollectionInterface
307 */
308 static public function load($id, $fillItems = FALSE) {
309 $collectionRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', static::$storageTableName, 'uid=' . (int)$id . \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause(static::$storageTableName));
310 return self::create($collectionRecord, $fillItems);
311 }
312
313 /**
314 * Creates a new collection objects and reconstitutes the
315 * given database record to the new object.
316 *
317 * @param array $collectionRecord Database record
318 * @param bool $fillItems Populates the entries directly on load, might be bad for memory on large collections
319 * @return \TYPO3\CMS\Core\Collection\CollectionInterface
320 */
321 static public function create(array $collectionRecord, $fillItems = FALSE) {
322 $collection = new static();
323 $collection->fromArray($collectionRecord);
324 if ($fillItems) {
325 $collection->loadContents();
326 }
327 return $collection;
328 }
329
330 /**
331 * Persists current collection state to underlying storage
332 *
333 * @return void
334 */
335 public function persist() {
336 $uid = $this->getIdentifier() == 0 ? 'NEW' . rand(100000, 999999) : $this->getIdentifier();
337 $data = array(
338 trim(static::$storageTableName) => array(
339 $uid => $this->getPersistableDataArray()
340 )
341 );
342 // New records always must have a pid
343 if ($this->getIdentifier() == 0) {
344 $data[trim(static::$storageTableName)][$uid]['pid'] = 0;
345 }
346 /** @var \TYPO3\CMS\Core\DataHandling\DataHandler $tce */
347 $tce = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\DataHandling\\DataHandler');
348 $tce->stripslashes_values = 0;
349 $tce->start($data, array());
350 $tce->process_datamap();
351 }
352
353 /**
354 * Returns an array of the persistable properties and contents
355 * which are processable by TCEmain.
356 *
357 * For internal usage in persist only.
358 *
359 * @return array
360 */
361 abstract protected function getPersistableDataArray();
362
363 /**
364 * Generates comma-separated list of entry uids for usage in TCEmain
365 *
366 * also allow to add table name, if it might be needed by TCEmain for
367 * storing the relation
368 *
369 * @param bool $includeTableName
370 * @return string
371 */
372 protected function getItemUidList($includeTableName = TRUE) {
373 $list = array();
374 foreach ($this->storage as $entry) {
375 $list[] = ($includeTableName ? $this->getItemTableName() . '_' : '') . $entry['uid'];
376 }
377 return implode(',', $list);
378 }
379
380 /**
381 * Builds an array representation of this collection
382 *
383 * @return array
384 */
385 public function toArray() {
386 $itemArray = array();
387 foreach ($this->storage as $item) {
388 $itemArray[] = $item;
389 }
390 return array(
391 'uid' => $this->getIdentifier(),
392 'title' => $this->getTitle(),
393 'description' => $this->getDescription(),
394 'table_name' => $this->getItemTableName(),
395 'items' => $itemArray
396 );
397 }
398
399 /**
400 * Loads the properties of this collection from an array
401 *
402 * @param array $array
403 * @return void
404 */
405 public function fromArray(array $array) {
406 $this->uid = $array['uid'];
407 $this->title = $array['title'];
408 $this->description = $array['description'];
409 $this->itemTableName = $array['table_name'];
410 }
411
412 }