/**
* Prepares the update query to upsert a given document object in mongodb.
*
* @param object $document
* @return array $updateData
*/
public function prepareUpsertData($document)
{
$class = $this->dm->getClassMetadata(get_class($document));
$changeset = $this->uow->getDocumentChangeSet($document);
$updateData = array();
foreach ($changeset as $fieldName => $change) {
$mapping = $class->fieldMappings[$fieldName];
/* Do nothing for embed-many or reference-many collections. If it
* uses an atomic strategy, the data will be included when preparing
* the atomic query in DocumentPersister::executeUpserts(). Other
* strategies will be handled by CollectionPersister.
*/
if ($mapping['type'] === ClassMetadata::MANY) {
continue;
}
list($old, $new) = $change;
// @Inc
if ($mapping['type'] === 'increment') {
if ($new >= $old) {
$updateData['$inc'][$mapping['name']] = $new - $old;
} else {
$updateData['$inc'][$mapping['name']] = ($old - $new) * -1;
}
// @Field, @String, @Date, etc.
} elseif (!isset($mapping['association'])) {
if (isset($new) || $mapping['nullable'] === true) {
$updateData['$set'][$mapping['name']] = is_null($new) ? null : Type::getType($mapping['type'])->convertToDatabaseValue($new);
}
// @EmbedOne
} elseif (isset($mapping['association']) && $mapping['association'] === ClassMetadata::EMBED_ONE) {
// If we have a new embedded document then lets set the whole thing
if ($new && $this->uow->isScheduledForInsert($new)) {
$updateData['$set'][$mapping['name']] = $this->prepareEmbeddedDocumentValue($mapping, $new);
// If we don't have a new value then do nothing on upsert
} elseif (!$new) {
// Update existing embedded document
} else {
$update = $this->prepareUpsertData($new);
foreach ($update as $cmd => $values) {
foreach ($values as $key => $value) {
$updateData[$cmd][$mapping['name'] . '.' . $key] = $value;
}
}
}
// @ReferenceOne
} elseif (isset($mapping['association']) && $mapping['association'] === ClassMetadata::REFERENCE_ONE && $mapping['isOwningSide']) {
if (isset($new) || $mapping['nullable'] === true) {
$updateData['$set'][$mapping['name']] = is_null($new) ? null : $this->prepareReferencedDocumentValue($mapping, $new);
}
}
// @EmbedMany and @ReferenceMany are handled by CollectionPersister
}
// add discriminator if the class has one
if (isset($class->discriminatorField)) {
$updateData['$set'][$class->discriminatorField] = isset($class->discriminatorValue) ? $class->discriminatorValue : $class->name;
}
return $updateData;
}