2 namespace TYPO3\CMS\Extbase\DomainObject
;
5 * This file is part of the TYPO3 CMS project.
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.
11 * For the full copyright and license information, please read the
12 * LICENSE.txt file that was distributed with this source code.
14 * The TYPO3 project - inspiring people to share!
17 use TYPO3\CMS\Extbase\Persistence\Generic\LazyLoadingProxy
;
20 * A generic Domain Object.
22 * All Model domain objects need to inherit from either AbstractEntity or AbstractValueObject, as this provides important framework information.
24 abstract class AbstractDomainObject
implements DomainObjectInterface
, \TYPO3\CMS\Extbase\Persistence\ObjectMonitoringInterface
27 * @var int The uid of the record. The uid is only unique in the context of the database table.
32 * @var int The uid of the localized record. In TYPO3 v4.x the property "uid" holds the uid of the record in default language (the translationOrigin).
34 protected $_localizedUid;
37 * @var int The uid of the language of the object. In TYPO3 v4.x this is the uid of the language record in the table sys_language.
39 protected $_languageUid;
42 * @var int The uid of the versioned record.
44 protected $_versionedUid;
47 * @var int The id of the page the record is "stored".
52 * TRUE if the object is a clone
56 private $_isClone = false
;
59 * @var array An array holding the clean property values. Set right after reconstitution of the object
61 private $_cleanProperties = [];
66 * @return int the uid or NULL if none set yet.
68 public function getUid()
70 if ($this->uid
!== null
) {
71 return (int)$this->uid
;
79 * @param int|null $pid
81 public function setPid($pid)
86 $this->pid
= (int)$pid;
93 * @return int The pid or NULL if none set yet.
95 public function getPid()
97 if ($this->pid
=== null
) {
100 return (int)$this->pid
;
104 * Reconstitutes a property. Only for internal use.
106 * @param string $propertyName
107 * @param mixed $propertyValue
110 public function _setProperty($propertyName, $propertyValue)
112 if ($this->_hasProperty($propertyName)) {
113 $this->{$propertyName} = $propertyValue;
120 * Returns the property value of the given property name. Only for internal use.
122 * @param string $propertyName
123 * @return mixed The propertyValue
125 public function _getProperty($propertyName)
127 return $this->{$propertyName};
131 * Returns a hash map of property names and property values. Only for internal use.
133 * @return array The properties
135 public function _getProperties()
137 $properties = get_object_vars($this);
138 foreach ($properties as $propertyName => $propertyValue) {
139 if ($propertyName[0] === '_') {
140 unset($properties[$propertyName]);
147 * Returns the property value of the given property name. Only for internal use.
149 * @param string $propertyName
150 * @return bool TRUE bool true if the property exists, FALSE if it doesn't exist or NULL in case of an error.
152 public function _hasProperty($propertyName)
154 return property_exists($this, $propertyName);
158 * Returns TRUE if the object is new (the uid was not set, yet). Only for internal use
162 public function _isNew()
164 return $this->uid
=== null
;
168 * Register an object's clean state, e.g. after it has been reconstituted
171 * @param string $propertyName The name of the property to be memorized. If omitted all persistable properties are memorized.
173 public function _memorizeCleanState($propertyName = null
)
175 if ($propertyName !== null
) {
176 $this->_memorizePropertyCleanState($propertyName);
178 $this->_cleanProperties
= [];
179 $properties = get_object_vars($this);
180 foreach ($properties as $propertyName => $propertyValue) {
181 if ($propertyName[0] === '_') {
184 // Do not memorize "internal" properties
185 $this->_memorizePropertyCleanState($propertyName);
191 * Register an properties's clean state, e.g. after it has been reconstituted
194 * @param string $propertyName The name of the property to be memorized. If omittet all persistable properties are memorized.
196 public function _memorizePropertyCleanState($propertyName)
198 $propertyValue = $this->{$propertyName};
199 if (is_object($propertyValue)) {
200 $this->_cleanProperties
[$propertyName] = clone $propertyValue;
201 // We need to make sure the clone and the original object
202 // are identical when compared with == (see _isDirty()).
203 // After the cloning, the Domain Object will have the property
204 // "isClone" set to TRUE, so we manually have to set it to FALSE
205 // again. Possible fix: Somehow get rid of the "isClone" property,
206 // which is currently needed in Fluid.
207 if ($propertyValue instanceof \TYPO3\CMS\Extbase\DomainObject\AbstractDomainObject
) {
208 $this->_cleanProperties
[$propertyName]->_setClone(false
);
211 $this->_cleanProperties
[$propertyName] = $propertyValue;
216 * Returns a hash map of clean properties and $values.
220 public function _getCleanProperties()
222 return $this->_cleanProperties
;
226 * Returns the clean value of the given property. The returned value will be NULL if the clean state was not memorized before, or
227 * if the clean value is NULL.
229 * @param string $propertyName The name of the property to be memorized.
230 * @return mixed The clean property value or NULL
232 public function _getCleanProperty($propertyName)
234 return isset($this->_cleanProperties
[$propertyName]) ?
$this->_cleanProperties
[$propertyName] : null
;
238 * Returns TRUE if the properties were modified after reconstitution
240 * @param string $propertyName An optional name of a property to be checked if its value is dirty
241 * @throws \TYPO3\CMS\Extbase\Persistence\Generic\Exception\TooDirtyException
244 public function _isDirty($propertyName = null
)
246 if ($this->uid
!== null
&& $this->_getCleanProperty('uid') !== null
&& $this->uid
!= $this->_getCleanProperty('uid')) {
247 throw new \TYPO3\CMS\Extbase\Persistence\Generic\Exception\
TooDirtyException('The uid "' . $this->uid
. '" has been modified, that is simply too much.', 1222871239);
250 if ($propertyName === null
) {
251 foreach ($this->_getCleanProperties() as $propertyName => $cleanPropertyValue) {
252 if ($this->isPropertyDirty($cleanPropertyValue, $this->{$propertyName}) === true
) {
257 if ($this->isPropertyDirty($this->_getCleanProperty($propertyName), $this->{$propertyName}) === true
) {
265 * Checks the $value against the $cleanState.
267 * @param mixed $previousValue
268 * @param mixed $currentValue
271 protected function isPropertyDirty($previousValue, $currentValue)
273 // In case it is an object and it implements the ObjectMonitoringInterface, we call _isDirty() instead of a simple comparison of objects.
274 // We do this, because if the object itself contains a lazy loaded property, the comparison of the objects might fail even if the object didn't change
275 if (is_object($currentValue)) {
276 $currentTypeString = null
;
277 if ($currentValue instanceof LazyLoadingProxy
) {
278 $currentTypeString = $currentValue->_getTypeAndUidString();
279 } elseif ($currentValue instanceof DomainObjectInterface
) {
280 $currentTypeString = get_class($currentValue) . ':' . $currentValue->getUid();
283 if ($currentTypeString !== null
) {
284 $previousTypeString = null
;
285 if ($previousValue instanceof LazyLoadingProxy
) {
286 $previousTypeString = $previousValue->_getTypeAndUidString();
287 } elseif ($previousValue instanceof DomainObjectInterface
) {
288 $previousTypeString = get_class($previousValue) . ':' . $previousValue->getUid();
291 $result = $currentTypeString !== $previousTypeString;
292 } elseif ($currentValue instanceof \TYPO3\CMS\Extbase\Persistence\ObjectMonitoringInterface
) {
293 $result = !is_object($previousValue) ||
$currentValue->_isDirty() ||
get_class($previousValue) !== get_class($currentValue);
295 // For all other objects we do only a simple comparison (!=) as we want cloned objects to return the same values.
296 $result = $previousValue != $currentValue;
299 $result = $previousValue !== $currentValue;
305 * Returns TRUE if the object has been clonesd, cloned, FALSE otherwise.
307 * @return bool TRUE if the object has been cloned
309 public function _isClone()
311 return $this->_isClone
;
315 * Setter whether this Domain Object is a clone of another one.
316 * NEVER SET THIS PROPERTY DIRECTLY. We currently need it to make the
317 * _isDirty check inside AbstractEntity work, but it is just a work-
322 public function _setClone($clone)
324 $this->_isClone
= (bool
)$clone;
328 * Clone method. Sets the _isClone property.
330 public function __clone()
332 $this->_isClone
= true
;
336 * Returns the class name and the uid of the object as string
340 public function __toString()
342 return get_class($this) . ':' . (string)$this->uid
;