/** * Creates the translation for object being flushed * * @param TranslatableAdapter $ea * @param object $object * @param boolean $isInsert * @throws UnexpectedValueException - if locale is not valid, or * primary key is composite, missing or invalid * @return void */ private function handleTranslatableObjectUpdate(TranslatableAdapter $ea, $object, $isInsert) { $om = $ea->getObjectManager(); $wrapped = AbstractWrapper::wrap($object, $om); $meta = $wrapped->getMetadata(); $config = $this->getConfiguration($om, $meta->name); // no need cache, metadata is loaded only once in MetadataFactoryClass $translationClass = $this->getTranslationClass($ea, $config['useObjectClass']); $translationMetadata = $om->getClassMetadata($translationClass); // check for the availability of the primary key $objectId = $wrapped->getIdentifier(); // load the currently used locale $locale = $this->getTranslatableLocale($object, $meta); $uow = $om->getUnitOfWork(); $oid = spl_object_hash($object); $changeSet = $ea->getObjectChangeSet($uow, $object); $translatableFields = $config['fields']; foreach ($translatableFields as $field) { $wasPersistedSeparetely = false; $skip = isset($this->translatedInLocale[$oid]) && $locale === $this->translatedInLocale[$oid]; $skip = $skip && !isset($changeSet[$field]); if ($skip) { continue; // locale is same and nothing changed } $translation = null; foreach ($ea->getScheduledObjectInsertions($uow) as $trans) { if ($locale !== $this->defaultLocale && get_class($trans) === $translationClass && $trans->getLocale() === $this->defaultLocale && $trans->getObject() === $object) { $this->setTranslationInDefaultLocale($oid, $trans); break; } } // lookup persisted translations if ($ea->usesPersonalTranslation($translationClass)) { foreach ($ea->getScheduledObjectInsertions($uow) as $trans) { $wasPersistedSeparetely = get_class($trans) === $translationClass && $trans->getLocale() === $locale && $trans->getField() === $field && $trans->getObject() === $object; if ($wasPersistedSeparetely) { $translation = $trans; break; } } } // check if translation allready is created if (!$isInsert && !$translation) { $translation = $ea->findTranslation($wrapped, $locale, $field, $translationClass, $config['useObjectClass']); } // create new translation if translation not already created and locale is differentent from default locale, otherwise, we have the date in the original record $persistNewTranslation = !$translation && ($locale !== $this->defaultLocale || $this->persistDefaultLocaleTranslation); if ($persistNewTranslation) { $translation = $translationMetadata->newInstance(); $translation->setLocale($locale); $translation->setField($field); if ($ea->usesPersonalTranslation($translationClass)) { $translation->setObject($object); } else { $translation->setObjectClass($config['useObjectClass']); $translation->setForeignKey($objectId); } } if ($translation) { // set the translated field, take value using reflection $value = $wrapped->getPropertyValue($field); $content = $ea->getTranslationValue($object, $field); $translation->setContent($content); // check if need to update in database $transWrapper = AbstractWrapper::wrap($translation, $om); if (!empty($content) && ($isInsert || !$transWrapper->getIdentifier() || isset($changeSet[$field]))) { if ($isInsert && !$objectId && !$ea->usesPersonalTranslation($translationClass)) { // if we do not have the primary key yet available // keep this translation in memory to insert it later with foreign key $this->pendingTranslationInserts[spl_object_hash($object)][] = $translation; } else { // persist and compute change set for translation if ($wasPersistedSeparetely) { $ea->recomputeSingleObjectChangeset($uow, $translationMetadata, $translation); } else { $om->persist($translation); $uow->computeChangeSet($translationMetadata, $translation); } } } } if ($isInsert && $this->getTranslationInDefaultLocale($oid) !== null) { // We can't rely on object field value which is created in non default locale. // If we provide translation for default locale as well, the latter is considered to be trusted // and object content should be overridden. $wrapped->setPropertyValue($field, $this->getTranslationInDefaultLocale($oid)->getContent()); $ea->recomputeSingleObjectChangeset($uow, $meta, $object); $this->removeTranslationInDefaultLocale($oid); } } $this->translatedInLocale[$oid] = $locale; // check if we have default translation and need to reset the translation if (!$isInsert && strlen($this->defaultLocale)) { $this->validateLocale($this->defaultLocale); $modifiedChangeSet = $changeSet; foreach ($changeSet as $field => $changes) { if (in_array($field, $translatableFields)) { if ($locale !== $this->defaultLocale) { $ea->setOriginalObjectProperty($uow, $oid, $field, $changes[0]); unset($modifiedChangeSet[$field]); } } } $ea->recomputeSingleObjectChangeset($uow, $meta, $object); // cleanup current changeset only if working in a another locale different than de default one, otherwise the changeset will always be reverted if ($locale !== $this->defaultLocale) { $ea->clearObjectChangeSet($uow, $oid); // recompute changeset only if there are changes other than reverted translations if ($modifiedChangeSet) { foreach ($modifiedChangeSet as $field => $changes) { $ea->setOriginalObjectProperty($uow, $oid, $field, $changes[0]); } $ea->recomputeSingleObjectChangeset($uow, $meta, $object); } } } }
/** * Checks if the translation entity belongs to the object in question * * @param TranslatableAdapter $ea * @param object $trans * @param object $object * * @return boolean */ private function belongsToObject(TranslatableAdapter $ea, $trans, $object) { if ($ea->usesPersonalTranslation(get_class($trans))) { return $trans->getObject() === $object; } return $trans->getForeignKey() === $object->getId() && $trans->getObjectClass() === get_class($object); }
/** * Creates all additional translations created * through repository * * @param TranslatableAdapter $ea * @param object $object * @param boolean $inserting * @return void */ private function processAdditionalTranslations(TranslatableAdapter $ea, $object, $inserting) { $oid = spl_object_hash($object); if (isset($this->additionalTranslations[$oid])) { $om = $ea->getObjectManager(); $uow = $om->getUnitOfWork(); $meta = $om->getClassMetadata(get_class($object)); $objectId = $ea->extractIdentifier($om, $object); $transClass = $this->getTranslationClass($ea, $meta->name); foreach ($this->additionalTranslations[$oid] as $field => $translations) { foreach ($translations as $locale => $content) { $trans = null; if (!$inserting) { $trans = $ea->findTranslation($objectId, $meta->name, $locale, $field, $transClass); } if (!$trans) { $trans = new $transClass(); $trans->setField($field); $trans->setObjectClass($meta->name); $trans->setForeignKey($objectId); $trans->setLocale($locale); } $trans->setContent($ea->getTranslationValue($object, $field, $content)); if ($inserting && !$objectId) { $this->pendingTranslationInserts[spl_object_hash($object)][] = $trans; } elseif ($trans->getId()) { $om->persist($trans); $transMeta = $om->getClassMetadata($transClass); $uow->computeChangeSet($transMeta, $trans); } else { $ea->insertTranslationRecord($trans); } } } } }