[BUGFIX] Fix grouping of file references in FlexForms of workspaces
[Packages/TYPO3.CMS.git] / typo3 / sysext / version / Classes / Dependency / ElementEntity.php
1 <?php
2 namespace TYPO3\CMS\Version\Dependency;
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 /**
18 * Object to hold information on a dependent database element in abstract.
19 */
20 class ElementEntity {
21
22 const REFERENCES_ChildOf = 'childOf';
23 const REFERENCES_ParentOf = 'parentOf';
24 const EVENT_Construct = 'TYPO3\\CMS\\Version\\Dependency\\ElementEntity::construct';
25 const EVENT_CreateChildReference = 'TYPO3\\CMS\\Version\\Dependency\\ElementEntity::createChildReference';
26 const EVENT_CreateParentReference = 'TYPO3\\CMS\\Version\\Dependency\\ElementEntity::createParentReference';
27 const RESPONSE_Skip = 'TYPO3\\CMS\\Version\\Dependency\\ElementEntity->skip';
28
29 /**
30 * @var bool
31 */
32 protected $invalid = FALSE;
33
34 /**
35 * @var string
36 */
37 protected $table;
38
39 /**
40 * @var int
41 */
42 protected $id;
43
44 /**
45 * @var array
46 */
47 protected $data;
48
49 /**
50 * @var array
51 */
52 protected $record;
53
54 /**
55 * @var \TYPO3\CMS\Version\Dependency\DependencyResolver
56 */
57 protected $dependency;
58
59 /**
60 * @var array
61 */
62 protected $children;
63
64 /**
65 * @var array
66 */
67 protected $parents;
68
69 /**
70 * @var bool
71 */
72 protected $traversingParents = FALSE;
73
74 /**
75 * @var \TYPO3\CMS\Version\Dependency\ElementEntity
76 */
77 protected $outerMostParent;
78
79 /**
80 * @var array
81 */
82 protected $nestedChildren;
83
84 /**
85 * Creates this object.
86 *
87 * @param string $table
88 * @param int $id
89 * @param array $data (optional)
90 * @param \TYPO3\CMS\Version\Dependency\DependencyResolver $dependency
91 */
92 public function __construct($table, $id, array $data = array(), \TYPO3\CMS\Version\Dependency\DependencyResolver $dependency) {
93 $this->table = $table;
94 $this->id = (int)$id;
95 $this->data = $data;
96 $this->dependency = $dependency;
97 $this->dependency->executeEventCallback(self::EVENT_Construct, $this);
98 }
99
100 /**
101 * @param bool $invalid
102 */
103 public function setInvalid($invalid) {
104 $this->invalid = (bool)$invalid;
105 }
106
107 /**
108 * @return bool
109 */
110 public function isInvalid() {
111 return $this->invalid;
112 }
113
114 /**
115 * Gets the table.
116 *
117 * @return string
118 */
119 public function getTable() {
120 return $this->table;
121 }
122
123 /**
124 * Gets the id.
125 *
126 * @return int
127 */
128 public function getId() {
129 return $this->id;
130 }
131
132 /**
133 * Sets the id.
134 *
135 * @param int $id
136 */
137 public function setId($id) {
138 $this->id = (int)$id;
139 }
140
141 /**
142 * Gets the data.
143 *
144 * @return array
145 */
146 public function getData() {
147 return $this->data;
148 }
149
150 /**
151 * Gets a value for a particular key from the data.
152 *
153 * @param string $key
154 * @return mixed
155 */
156 public function getDataValue($key) {
157 $result = NULL;
158 if ($this->hasDataValue($key)) {
159 $result = $this->data[$key];
160 }
161 return $result;
162 }
163
164 /**
165 * Sets a value for a particular key in the data.
166 *
167 * @param string $key
168 * @param mixed $value
169 * @return void
170 */
171 public function setDataValue($key, $value) {
172 $this->data[$key] = $value;
173 }
174
175 /**
176 * Determines whether a particular key holds data.
177 *
178 * @param string $key
179 * @return bool
180 */
181 public function hasDataValue($key) {
182 return isset($this->data[$key]);
183 }
184
185 /**
186 * Converts this object for string representation.
187 *
188 * @return string
189 */
190 public function __toString() {
191 return self::getIdentifier($this->table, $this->id);
192 }
193
194 /**
195 * Gets the parent dependency object.
196 *
197 * @return \TYPO3\CMS\Version\Dependency\DependencyResolver
198 */
199 public function getDependency() {
200 return $this->dependency;
201 }
202
203 /**
204 * Gets all child references.
205 *
206 * @return array|ReferenceEntity[]
207 */
208 public function getChildren() {
209 if (!isset($this->children)) {
210 $this->children = array();
211 $where = 'tablename=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($this->table, 'sys_refindex') . ' AND recuid='
212 . $this->id . ' AND workspace=' . $this->dependency->getWorkspace();
213 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'sys_refindex', $where, '', 'sorting');
214 if (is_array($rows)) {
215 foreach ($rows as $row) {
216 $arguments = array('table' => $row['ref_table'], 'id' => $row['ref_uid'], 'field' => $row['field'], 'scope' => self::REFERENCES_ChildOf);
217 $callbackResponse = $this->dependency->executeEventCallback(self::EVENT_CreateChildReference, $this, $arguments);
218 if ($callbackResponse !== self::RESPONSE_Skip) {
219 $this->children[] = $this->getDependency()->getFactory()->getReferencedElement(
220 $row['ref_table'],
221 $row['ref_uid'],
222 $row['field'],
223 array(),
224 $this->getDependency()
225 );
226 }
227 }
228 }
229 }
230 return $this->children;
231 }
232
233 /**
234 * Gets all parent references.
235 *
236 * @return array|ReferenceEntity[]
237 */
238 public function getParents() {
239 if (!isset($this->parents)) {
240 $this->parents = array();
241 $where = 'ref_table=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($this->table, 'sys_refindex')
242 . ' AND deleted=0 AND ref_uid=' . $this->id . ' AND workspace=' . $this->dependency->getWorkspace();
243 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'sys_refindex', $where, '', 'sorting');
244 if (is_array($rows)) {
245 foreach ($rows as $row) {
246 $arguments = array('table' => $row['tablename'], 'id' => $row['recuid'], 'field' => $row['field'], 'scope' => self::REFERENCES_ParentOf);
247 $callbackResponse = $this->dependency->executeEventCallback(self::EVENT_CreateParentReference, $this, $arguments);
248 if ($callbackResponse !== self::RESPONSE_Skip) {
249 $this->parents[] = $this->getDependency()->getFactory()->getReferencedElement(
250 $row['tablename'],
251 $row['recuid'],
252 $row['field'],
253 array(),
254 $this->getDependency()
255 );
256 }
257 }
258 }
259 }
260 return $this->parents;
261 }
262
263 /**
264 * Determines whether there are child or parent references.
265 *
266 * @return bool
267 */
268 public function hasReferences() {
269 return count($this->getChildren()) > 0 || count($this->getParents()) > 0;
270 }
271
272 /**
273 * Gets the outermost parent element.
274 *
275 * @return ElementEntity
276 */
277 public function getOuterMostParent() {
278 if (!isset($this->outerMostParent)) {
279 $parents = $this->getParents();
280 if (count($parents) === 0) {
281 $this->outerMostParent = $this;
282 } else {
283 $this->outerMostParent = FALSE;
284 /** @var $parent \TYPO3\CMS\Version\Dependency\ReferenceEntity */
285 foreach ($parents as $parent) {
286 $outerMostParent = $parent->getElement()->getOuterMostParent();
287 if ($outerMostParent instanceof \TYPO3\CMS\Version\Dependency\ElementEntity) {
288 $this->outerMostParent = $outerMostParent;
289 break;
290 } elseif ($outerMostParent === FALSE) {
291 break;
292 }
293 }
294 }
295 }
296 return $this->outerMostParent;
297 }
298
299 /**
300 * Gets nested children accumulated.
301 *
302 * @return array|ReferenceEntity[]
303 */
304 public function getNestedChildren() {
305 if (!isset($this->nestedChildren)) {
306 $this->nestedChildren = array();
307 $children = $this->getChildren();
308 /** @var $child \TYPO3\CMS\Version\Dependency\ReferenceEntity */
309 foreach ($children as $child) {
310 $this->nestedChildren = array_merge($this->nestedChildren, array($child->getElement()->__toString() => $child->getElement()), $child->getElement()->getNestedChildren());
311 }
312 }
313 return $this->nestedChildren;
314 }
315
316 /**
317 * Converts the object for string representation.
318 *
319 * @param string $table
320 * @param int $id
321 * @return string
322 */
323 static public function getIdentifier($table, $id) {
324 return $table . ':' . $id;
325 }
326
327 /**
328 * Gets the database record of this element.
329 *
330 * @return array
331 */
332 public function getRecord() {
333 if (empty($this->record['uid']) || (int)$this->record['uid'] !== $this->getId()) {
334 $this->record = array();
335 $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('uid,pid,t3ver_wsid,t3ver_state,t3ver_oid', $this->getTable(), 'uid=' . $this->getId());
336 if (is_array($row)) {
337 $this->record = $row;
338 }
339 }
340 return $this->record;
341 }
342
343 }