public function testPropertyGetterWillSkipClassesNotRetrievedByTheRuntimeReflectionService() { /* @var $reflectionService ReflectionService|\PHPUnit_Framework_MockObject_MockObject */ $reflectionService = $this->getMock('Doctrine\\Common\\Persistence\\Mapping\\ReflectionService'); $reflectionService->expects($this->once())->method('getClass')->with(ClassWithMixedProperties::CLASSNAME); $reflectionService->expects($this->never())->method('getAccessibleProperty'); $getter = new ReflectionPropertiesGetter($reflectionService); $this->assertEmpty($getter->getProperties(ClassWithMixedProperties::CLASSNAME)); }
/** * @param object $entity * @param object $managedCopy * * @throws ORMException * @throws OptimisticLockException * @throws TransactionRequiredException */ private function mergeEntityStateIntoManagedCopy($entity, $managedCopy) { $class = $this->em->getClassMetadata(get_class($entity)); foreach ($this->reflectionPropertiesGetter->getProperties($class->name) as $prop) { $name = $prop->name; $prop->setAccessible(true); if (!isset($class->associationMappings[$name])) { if (!$class->isIdentifier($name)) { $prop->setValue($managedCopy, $prop->getValue($entity)); } } else { $assoc2 = $class->associationMappings[$name]; if ($assoc2['type'] & ClassMetadata::TO_ONE) { $other = $prop->getValue($entity); if ($other === null) { $prop->setValue($managedCopy, null); } else { if ($other instanceof Proxy && !$other->__isInitialized()) { // do not merge fields marked lazy that have not been fetched. return; } if (!$assoc2['isCascadeMerge']) { if ($this->getEntityState($other) === self::STATE_DETACHED) { $targetClass = $this->em->getClassMetadata($assoc2['targetEntity']); $relatedId = $targetClass->getIdentifierValues($other); if ($targetClass->subClasses) { $other = $this->em->find($targetClass->name, $relatedId); } else { $other = $this->em->getProxyFactory()->getProxy($assoc2['targetEntity'], $relatedId); $this->registerManaged($other, $relatedId, array()); } } $prop->setValue($managedCopy, $other); } } } else { $mergeCol = $prop->getValue($entity); if ($mergeCol instanceof PersistentCollection && !$mergeCol->isInitialized()) { // do not merge fields marked lazy that have not been fetched. // keep the lazy persistent collection of the managed copy. return; } $managedCol = $prop->getValue($managedCopy); if (!$managedCol) { $managedCol = new PersistentCollection($this->em, $this->em->getClassMetadata($assoc2['targetEntity']), new ArrayCollection()); $managedCol->setOwner($managedCopy, $assoc2); $prop->setValue($managedCopy, $managedCol); $this->originalEntityData[spl_object_hash($entity)][$name] = $managedCol; } if ($assoc2['isCascadeMerge']) { $managedCol->initialize(); // clear and set dirty a managed collection if its not also the same collection to merge from. if (!$managedCol->isEmpty() && $managedCol !== $mergeCol) { $managedCol->unwrap()->clear(); $managedCol->setDirty(true); if ($assoc2['isOwningSide'] && $assoc2['type'] == ClassMetadata::MANY_TO_MANY && $class->isChangeTrackingNotify()) { $this->scheduleForDirtyCheck($managedCopy); } } } } } if ($class->isChangeTrackingNotify()) { // Just treat all properties as changed, there is no other choice. $this->propertyChanged($managedCopy, $name, null, $prop->getValue($managedCopy)); } } }