[BUGFIX] Respect _FILE/_STRING in versioning
[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 if ($row['ref_table'] !== '_FILE' && $row['ref_table'] !== '_STRING') {
217 $arguments = array(
218 'table' => $row['ref_table'],
219 'id' => $row['ref_uid'],
220 'field' => $row['field'],
221 'scope' => self::REFERENCES_ChildOf
222 );
223
224 $callbackResponse = $this->dependency->executeEventCallback(self::EVENT_CreateChildReference, $this, $arguments);
225 if ($callbackResponse !== self::RESPONSE_Skip) {
226 $this->children[] = $this->getDependency()->getFactory()->getReferencedElement(
227 $row['ref_table'],
228 $row['ref_uid'],
229 $row['field'],
230 array(),
231 $this->getDependency()
232 );
233 }
234 }
235 }
236 }
237 }
238 return $this->children;
239 }
240
241 /**
242 * Gets all parent references.
243 *
244 * @return array|ReferenceEntity[]
245 */
246 public function getParents() {
247 if (!isset($this->parents)) {
248 $this->parents = array();
249 $where = 'ref_table=' . $GLOBALS['TYPO3_DB']->fullQuoteStr($this->table, 'sys_refindex')
250 . ' AND deleted=0 AND ref_uid=' . $this->id . ' AND workspace=' . $this->dependency->getWorkspace();
251 $rows = $GLOBALS['TYPO3_DB']->exec_SELECTgetRows('*', 'sys_refindex', $where, '', 'sorting');
252 if (is_array($rows)) {
253 foreach ($rows as $row) {
254 $arguments = array('table' => $row['tablename'], 'id' => $row['recuid'], 'field' => $row['field'], 'scope' => self::REFERENCES_ParentOf);
255 $callbackResponse = $this->dependency->executeEventCallback(self::EVENT_CreateParentReference, $this, $arguments);
256 if ($callbackResponse !== self::RESPONSE_Skip) {
257 $this->parents[] = $this->getDependency()->getFactory()->getReferencedElement(
258 $row['tablename'],
259 $row['recuid'],
260 $row['field'],
261 array(),
262 $this->getDependency()
263 );
264 }
265 }
266 }
267 }
268 return $this->parents;
269 }
270
271 /**
272 * Determines whether there are child or parent references.
273 *
274 * @return bool
275 */
276 public function hasReferences() {
277 return count($this->getChildren()) > 0 || count($this->getParents()) > 0;
278 }
279
280 /**
281 * Gets the outermost parent element.
282 *
283 * @return ElementEntity
284 */
285 public function getOuterMostParent() {
286 if (!isset($this->outerMostParent)) {
287 $parents = $this->getParents();
288 if (count($parents) === 0) {
289 $this->outerMostParent = $this;
290 } else {
291 $this->outerMostParent = FALSE;
292 /** @var $parent \TYPO3\CMS\Version\Dependency\ReferenceEntity */
293 foreach ($parents as $parent) {
294 $outerMostParent = $parent->getElement()->getOuterMostParent();
295 if ($outerMostParent instanceof \TYPO3\CMS\Version\Dependency\ElementEntity) {
296 $this->outerMostParent = $outerMostParent;
297 break;
298 } elseif ($outerMostParent === FALSE) {
299 break;
300 }
301 }
302 }
303 }
304 return $this->outerMostParent;
305 }
306
307 /**
308 * Gets nested children accumulated.
309 *
310 * @return array|ReferenceEntity[]
311 */
312 public function getNestedChildren() {
313 if (!isset($this->nestedChildren)) {
314 $this->nestedChildren = array();
315 $children = $this->getChildren();
316 /** @var $child \TYPO3\CMS\Version\Dependency\ReferenceEntity */
317 foreach ($children as $child) {
318 $this->nestedChildren = array_merge($this->nestedChildren, array($child->getElement()->__toString() => $child->getElement()), $child->getElement()->getNestedChildren());
319 }
320 }
321 return $this->nestedChildren;
322 }
323
324 /**
325 * Converts the object for string representation.
326 *
327 * @param string $table
328 * @param int $id
329 * @return string
330 */
331 static public function getIdentifier($table, $id) {
332 return $table . ':' . $id;
333 }
334
335 /**
336 * Gets the database record of this element.
337 *
338 * @return array
339 */
340 public function getRecord() {
341 if (empty($this->record['uid']) || (int)$this->record['uid'] !== $this->getId()) {
342 $this->record = array();
343 $row = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('uid,pid,t3ver_wsid,t3ver_state,t3ver_oid', $this->getTable(), 'uid=' . $this->getId());
344 if (is_array($row)) {
345 $this->record = $row;
346 }
347 }
348 return $this->record;
349 }
350
351 }