[BUGFIX] Category API does not consider multiple tables
[Packages/TYPO3.CMS.git] / typo3 / sysext / core / Classes / Category / Collection / CategoryCollection.php
1 <?php
2 namespace TYPO3\CMS\Core\Category\Collection;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2012-2013 Fabien Udriot <fabien.udriot@typo3.org>
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29 /**
30 * Category Collection to handle records attached to a category
31 *
32 * @author Fabien Udriot <fabien.udriot@typo3.org>
33 */
34 class CategoryCollection extends \TYPO3\CMS\Core\Collection\AbstractRecordCollection implements \TYPO3\CMS\Core\Collection\EditableCollectionInterface {
35
36 /**
37 * The table name collections are stored to
38 *
39 * @var string
40 */
41 static protected $storageTableName = 'sys_category';
42
43 /**
44 * Creates this object.
45 *
46 * @param string $tableName Name of the table to be working on
47 * @throws \RuntimeException
48 */
49 public function __construct($tableName = NULL) {
50 parent::__construct();
51 if (!empty($tableName)) {
52 $this->setItemTableName($tableName);
53 } elseif (empty($this->itemTableName)) {
54 throw new \RuntimeException('TYPO3\\CMS\\Core\\Category\\Collection\\CategoryCollection needs a valid itemTableName.', 1341826168);
55 }
56 }
57
58 /**
59 * Creates a new collection objects and reconstitutes the
60 * given database record to the new object.
61 *
62 * @param array $collectionRecord Database record
63 * @param boolean $fillItems Populates the entries directly on load, might be bad for memory on large collections
64 * @return \TYPO3\CMS\Core\Category\Collection\CategoryCollection
65 */
66 static public function create(array $collectionRecord, $fillItems = FALSE) {
67 /** @var $collection \TYPO3\CMS\Core\Category\Collection\CategoryCollection */
68 $collection = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Category\\Collection\\CategoryCollection', $collectionRecord['table_name']);
69 $collection->fromArray($collectionRecord);
70 if ($fillItems) {
71 $collection->loadContents();
72 }
73 return $collection;
74 }
75
76 /**
77 * Loads the collections with the given id from persistence
78 * For memory reasons, per default only f.e. title, database-table,
79 * identifier (what ever static data is defined) is loaded.
80 * Entries can be load on first access.
81 *
82 * @param integer $id Id of database record to be loaded
83 * @param boolean $fillItems Populates the entries directly on load, might be bad for memory on large collections
84 * @param string $tableName the table name
85 * @return \TYPO3\CMS\Core\Collection\CollectionInterface
86 */
87 static public function load($id, $fillItems = FALSE, $tableName = '') {
88 $collectionRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', static::$storageTableName, 'uid=' . intval($id) . \TYPO3\CMS\Backend\Utility\BackendUtility::deleteClause(static::$storageTableName));
89 $collectionRecord['table_name'] = $tableName;
90 return self::create($collectionRecord, $fillItems);
91 }
92
93 /**
94 * Gets the collected records in this collection, by
95 * looking up the MM relations of this record to the
96 * table name defined in the local field 'table_name'.
97 *
98 * @return array
99 */
100 protected function getCollectedRecords() {
101 $relatedRecords = array();
102 /** @var $GLOBALS['TYPO3_DB'] \TYPO3\CMS\Core\Database\DatabaseConnection */
103 $resource = $this->getDatabase()->exec_SELECT_mm_query(
104 $this->getItemTableName() . '.*',
105 self::$storageTableName,
106 'sys_category_record_mm',
107 $this->getItemTableName(),
108 'AND ' . self::$storageTableName . '.uid=' . intval($this->getIdentifier())
109 . ' AND sys_category_record_mm.tablenames = "' . $this->getItemTableName() . '"'
110 );
111 if ($resource) {
112 while ($record = $this->getDatabase()->sql_fetch_assoc($resource)) {
113 $relatedRecords[] = $record;
114 }
115 $this->getDatabase()->sql_free_result($resource);
116 }
117 return $relatedRecords;
118 }
119
120 /**
121 * Populates the content-entries of the storage
122 * Queries the underlying storage for entries of the collection
123 * and adds them to the collection data.
124 * If the content entries of the storage had not been loaded on creation
125 * ($fillItems = false) this function is to be used for loading the contents
126 * afterwards.
127 *
128 * @return void
129 */
130 public function loadContents() {
131 $entries = $this->getCollectedRecords();
132 $this->removeAll();
133 foreach ($entries as $entry) {
134 $this->add($entry);
135 }
136 }
137
138 /**
139 * Returns an array of the persistable properties and contents
140 * which are processable by TCEmain.
141 * for internal usage in persist only.
142 *
143 * @return array
144 */
145 protected function getPersistableDataArray() {
146 return array(
147 'title' => $this->getTitle(),
148 'description' => $this->getDescription(),
149 'items' => $this->getItemUidList(TRUE)
150 );
151 }
152
153 /**
154 * Adds on entry to the collection
155 *
156 * @param mixed $data
157 * @return void
158 */
159 public function add($data) {
160 $this->storage->push($data);
161 }
162
163 /**
164 * Adds a set of entries to the collection
165 *
166 * @param \TYPO3\CMS\Core\Collection\CollectionInterface $other
167 * @return void
168 */
169 public function addAll(\TYPO3\CMS\Core\Collection\CollectionInterface $other) {
170 foreach ($other as $value) {
171 $this->add($value);
172 }
173 }
174
175 /**
176 * Removes the given entry from collection
177 * Note: not the given "index"
178 *
179 * @param mixed $data
180 * @return void
181 */
182 public function remove($data) {
183 $offset = 0;
184 foreach ($this->storage as $value) {
185 if ($value == $data) {
186 break;
187 }
188 $offset++;
189 }
190 $this->storage->offsetUnset($offset);
191 }
192
193 /**
194 * Removes all entries from the collection
195 * collection will be empty afterwards
196 *
197 * @return void
198 */
199 public function removeAll() {
200 $this->storage = new \SplDoublyLinkedList();
201 }
202
203 /**
204 * Gets the current available items.
205 *
206 * @return array
207 */
208 public function getItems() {
209 $itemArray = array();
210 /** @var $item \TYPO3\CMS\Core\Resource\File */
211 foreach ($this->storage as $item) {
212 $itemArray[] = $item;
213 }
214 return $itemArray;
215 }
216
217 /**
218 * Getter for the storage table name
219 *
220 * @return string
221 */
222 static public function getStorageTableName() {
223 return self::$storageTableName;
224 }
225
226 /**
227 * Getter for the storage items field
228 *
229 * @return string
230 */
231 static public function getStorageItemsField() {
232 return self::$storageItemsField;
233 }
234
235 /**
236 * Gets the database object.
237 *
238 * @return \TYPO3\CMS\Core\Database\DatabaseConnection
239 */
240 protected function getDatabase() {
241 return $GLOBALS['TYPO3_DB'];
242 }
243
244 }
245
246
247 ?>