/** * Stores or updates an object in the underlying storage. * * @param object $object The object to persist * @param string $parentIdentifier * @return string * @author Karsten Dambekalns <*****@*****.**> */ protected function persistObject($object, $parentIdentifier = NULL) { $classSchema = $this->classSchemata[$object->FLOW3_AOP_Proxy_getProxyTargetClassName()]; if ($this->persistenceSession->hasObject($object)) { $identifier = $this->persistenceSession->getIdentifierByObject($object); $objectState = self::OBJECT_RECONSTITUTED; } else { $identifier = $this->createObjectRecord($object, $parentIdentifier); $objectState = self::OBJECT_NEW; } $this->visitedDuringPersistence[$object] = $identifier; $properties = array(); foreach ($classSchema->getProperties() as $propertyName => $propertyMetaData) { $propertyValue = $object->FLOW3_AOP_Proxy_getProperty($propertyName); $propertyType = $propertyMetaData['type']; $this->checkType($propertyType, $propertyValue); // handle only dirty properties here if ($object instanceof \F3\FLOW3\Persistence\Aspect\DirtyMonitoringInterface && $object->FLOW3_Persistence_isDirty($propertyName)) { switch ($propertyType) { case 'DateTime': $properties[$propertyName] = array('parent' => $identifier, 'type' => $propertyType, 'multivalue' => FALSE, 'value' => array(array('value' => $this->processDateTime($propertyValue), 'index' => NULL, 'type' => $propertyType))); break; case 'array': $properties[$propertyName] = array('parent' => $identifier, 'type' => $propertyType, 'multivalue' => TRUE, 'value' => $this->processArray($propertyValue, $identifier, $this->getCleanState($object, $propertyName))); break; case 'SplObjectStorage': $properties[$propertyName] = array('parent' => $identifier, 'type' => $propertyType, 'multivalue' => TRUE, 'value' => $this->processSplObjectStorage($propertyValue, $identifier, $this->getCleanState($object, $propertyName))); break; case 'integer': case 'float': case 'string': case 'boolean': $properties[$propertyName] = array('parent' => $identifier, 'type' => $propertyType, 'multivalue' => FALSE, 'value' => array(array('value' => $propertyValue, 'index' => NULL, 'type' => $propertyType))); } } // handle all objects now, because even clean ones need to be traversed // as dirty checking is not recursive if (is_object($propertyValue) && $propertyValue instanceof \F3\FLOW3\AOP\ProxyInterface) { if ($object->FLOW3_Persistence_isDirty($propertyName)) { $properties[$propertyName] = array('parent' => $identifier, 'type' => $propertyType, 'multivalue' => FALSE, 'value' => array(array('index' => NULL, 'type' => $propertyType))); if ($this->visitedDuringPersistence->contains($propertyValue)) { $properties[$propertyName]['value'][0]['value'] = $this->visitedDuringPersistence[$propertyValue]; } else { $properties[$propertyName]['value'][0]['value'] = $this->persistObject($propertyValue, $identifier); } } elseif (!$this->visitedDuringPersistence->contains($propertyValue)) { $this->persistObject($propertyValue, $identifier); } } } if (count($properties)) { $this->setProperties($properties); if ($objectState === self::OBJECT_RECONSTITUTED) { $this->emitPersistedUpdatedObject($object); } } if ($objectState === self::OBJECT_NEW) { $this->emitPersistedNewObject($object); } if ($classSchema->getModelType() === \F3\FLOW3\Reflection\ClassSchema::MODELTYPE_ENTITY) { $object->FLOW3_Persistence_memorizeCleanState(); } return $identifier; }
/** * Compares two objects non-recursively by the properties known in their * class schema if possible. Otherwise a regular non-strict comparison is * made. * * @param object $object1 * @param object $object2 * @return boolean * @author Karsten Dambekalns <*****@*****.**> */ protected function areObjectsDifferent($object1, $object2) { if (!$object1 instanceof $object2) { return TRUE; } if (!$object1 instanceof \F3\FLOW3\AOP\ProxyInterface || $object1 instanceof \DateTime || $object1 instanceof \SplObjectStorage) { return $object1 != $object2; } $propertyNames = array_keys($this->reflectionService->getClassSchema($object1->FLOW3_AOP_Proxy_getProxyTargetClassName())->getProperties()); foreach ($propertyNames as $propertyName) { if (!(property_exists($object1, $propertyName) && property_exists($object2, $propertyName))) { return TRUE; } $p1 = $object1->FLOW3_AOP_Proxy_getProperty($propertyName); $p2 = $object2->FLOW3_AOP_Proxy_getProperty($propertyName); if ($p1 !== $p2) { return TRUE; } } return FALSE; }