public function processRelationships($object, $entity = null)
{
$class = get_class($object);
$em = $this->doctrine->getManagerForClass($class);
$reflection = new \ReflectionClass($class);
/** @var \Doctrine\Common\Persistence\Mapping\ClassMetadata $metadata */
$metadata = $em->getMetadataFactory()->getMetadataFor($class);
// Look for relationships, compare against preloaded entity
foreach ($metadata->getAssociationNames() as $fieldName) {
// This can happen for Doctrine's Mongo ODM because while it adheres to the interface it throws an exception :(
try {
$mappedBy = $metadata->getAssociationMappedByTargetField($fieldName);
} catch (\BadMethodCallException $e) {
$mappedBy = null;
// Not defined by the interface, but both ORM & Mongo have it and we can use it to get what we want
if (method_exists($metadata, 'getFieldMapping')) {
$mapping = $metadata->getFieldMapping($fieldName);
if (isset($mapping['association']) && !empty($mapping['mappedBy'])) {
$mappedBy = $mapping['mappedBy'];
}
}
}
if (!$reflection->hasProperty($fieldName)) {
continue;
}
$property = $reflection->getProperty($fieldName);
$property->setAccessible(true);
$value = $property->getValue($object);
if (!$value) {
continue;
}
if ($metadata->isCollectionValuedAssociation($fieldName)) {
foreach ($value as $k => $v) {
// If the parent object is new, or if the relation has already been persisted
// set the mappedBy to the current object so that ids fill in properly
if ($this->isNew($object) && !empty($mappedBy)) {
$ref = new \ReflectionObject($v);
if ($ref->hasProperty($mappedBy)) {
$prop = $ref->getProperty($mappedBy);
$prop->setAccessible(true);
$prop->setValue($v, $object);
$this->processRelationships($v);
}
}
$vid = IdHelper::getId($v);
// If we have an object that already exists, merge it before we persist
if ($vid !== null && $this->isNew($object)) {
$value[$k] = $em->merge($v);
}
}
// Existing objects with collections may need to have missing values removed from them
if (!$this->isNew($object) && $entity) {
$original = $property->getValue($entity);
foreach ($original as $v) {
$checkIfExists = function ($key, $element) use($v) {
return IdHelper::getId($v) == IdHelper::getId($element);
};
$exists = $value->exists($checkIfExists);
if ($value && $value != $object && !$exists) {
$em->remove($v);
}
}
}
} elseif ($metadata->isSingleValuedAssociation($fieldName)) {
if ($this->isNew($object) && !$this->isNew($value)) {
$property->setValue($object, $em->merge($value));
}
}
}
}