Skip to content

Commit

Permalink
Improve support for cloning entities with Gedmo translations
Browse files Browse the repository at this point in the history
  • Loading branch information
jorrit committed Mar 11, 2022
1 parent 34fa8c6 commit b26548c
Showing 1 changed file with 79 additions and 19 deletions.
98 changes: 79 additions & 19 deletions src/Admin/Extension/CloneAdminExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@

use Doctrine\Common\Util\ClassUtils;
use Doctrine\ORM\EntityManagerInterface;
use Gedmo\Translatable\Entity\MappedSuperclass\AbstractPersonalTranslation;
use Gedmo\Translatable\TranslatableListener;
use Jorrit\SonataCloneActionBundle\Controller\CloneController;
use Sonata\AdminBundle\Admin\AbstractAdminExtension;
use Sonata\AdminBundle\Admin\AdminInterface;
use Sonata\AdminBundle\Datagrid\ListMapper;
use Sonata\AdminBundle\Form\FormMapper;
use Sonata\AdminBundle\Route\RouteCollection;
use Sonata\TranslationBundle\Model\Gedmo\AbstractPersonalTranslatable;
use Sonata\TranslationBundle\Model\Gedmo\AbstractPersonalTranslation;
use Symfony\Component\Form\Extension\Core\Type\HiddenType;
use Symfony\Component\PropertyAccess\PropertyAccess;
use Symfony\Component\PropertyInfo\PropertyListExtractorInterface;

class CloneAdminExtension extends AbstractAdminExtension
{

public const REQUEST_ATTRIBUTE = '_clone_subject';

/**
Expand All @@ -40,7 +40,8 @@ public function __construct(
PropertyListExtractorInterface $propertyInfoExtractor,
EntityManagerInterface $entityManager,
?TranslatableListener $translatableListener = null
) {
)
{
$this->propertyInfoExtractor = $propertyInfoExtractor;
$this->entityManager = $entityManager;
$this->translatableListener = $translatableListener;
Expand Down Expand Up @@ -130,6 +131,10 @@ public function configureFormFields(FormMapper $formMapper)
*/
public function prePersist(AdminInterface $admin, $object)
{
if ($this->translatableListener === null) {
return;
}

$request = $admin->getRequest();
if ($request === null) {
return;
Expand All @@ -141,27 +146,82 @@ public function prePersist(AdminInterface $admin, $object)
}

$subjectId = $postValues[self::REQUEST_ATTRIBUTE];
$defaultLocale = $this->translatableListener->getDefaultLocale();
$meta = $this->entityManager->getClassMetadata(get_class($object));
$objectLocale = $this->translatableListener->getTranslatableLocale($object, $meta, $this->entityManager);

// Load the original object in the default locale.
$this->translatableListener->setTranslatableLocale($defaultLocale);
$subject = $admin->getModelManager()->find($admin->getClass(), $subjectId);
$this->translatableListener->setTranslatableLocale($objectLocale);
if (!$subject) {
throw new \RuntimeException(sprintf('unable to find the object with id: %s', $subjectId));
}

if ($this->translatableListener !== null && $object instanceof AbstractPersonalTranslatable) {
$eventAdapter = new \Gedmo\Translatable\Mapping\Event\Adapter\ORM();
$subjectclass = ClassUtils::getClass($subject);
$config = $this->translatableListener->getConfiguration($this->entityManager, $subjectclass);
$translationClass = $this->translatableListener->getTranslationClass($eventAdapter, $config['useObjectClass']);

$translationRepository = $this->entityManager->getRepository($translationClass);
$translations = $translationRepository->findBy(['object' => $subject]);
foreach ($translations as $translation) {
/* @var AbstractPersonalTranslation $clonedTranslation */
$clonedTranslation = new $translationClass;
$clonedTranslation->setLocale($translation->getLocale());
$clonedTranslation->setContent($translation->getContent());
$clonedTranslation->setField($translation->getField());
$object->addTranslation($clonedTranslation);
$this->entityManager->persist($clonedTranslation);
$subjectclass = ClassUtils::getClass($subject);
$config = $this->translatableListener->getConfiguration($this->entityManager, $subjectclass);
if (empty($config)) {
return;
}

$eventAdapter = new \Gedmo\Translatable\Mapping\Event\Adapter\ORM();
$translationClass = $this->translatableListener->getTranslationClass($eventAdapter, $config['useObjectClass']);

$translationRepository = $this->entityManager->getRepository($translationClass);
$translations = $translationRepository->findBy(['object' => $subject]);
foreach ($translations as $translation) {
if ($translation->getLocale() === $objectLocale) {
// When editing a non-default locale while cloning, don't copy these values from the original subject.
continue;
}
/* @var AbstractPersonalTranslation $clonedTranslation */
$clonedTranslation = new $translationClass;
$clonedTranslation->setLocale($translation->getLocale());
$clonedTranslation->setContent($translation->getContent());
$clonedTranslation->setField($translation->getField());
$clonedTranslation->setObject($object);
$this->entityManager->persist($clonedTranslation);
}

// Handle translating a different locale than the default.
if ($objectLocale !== $defaultLocale) {
// Set the locale of $object to the default and set the fields to the original fields.
$reflectionClass = $meta->getReflectionClass();
\assert($reflectionClass !== null);

$localeProperty = $reflectionClass->getProperty($config['locale']);
$localeProperty->setAccessible(true);
$localeProperty->setValue($object, $defaultLocale);

// Handle all translatable fields.
foreach ($config['fields'] as $fieldName) {
$fieldProperty = $meta->getReflectionProperty($fieldName);
if ($fieldProperty === null) {
continue;
}

$defaultValue = $fieldProperty->getValue($subject);

$fieldIsFallback = !empty($config['fallback'][$fieldName]);
$translatedFieldValue = $fieldProperty->getValue($object);

if ($fieldIsFallback && $translatedFieldValue === $defaultValue) {
$translatedFieldValue = null;
}

// Add the translation for the non-default locale.
if ($translatedFieldValue !== null) {
/* @var AbstractPersonalTranslation $clonedTranslation */
$clonedTranslation = new $translationClass;
$clonedTranslation->setLocale($objectLocale);
$clonedTranslation->setContent($translatedFieldValue);
$clonedTranslation->setField($fieldName);
$clonedTranslation->setObject($object);
$this->entityManager->persist($clonedTranslation);
}

// Set the default translation.
$fieldProperty->setValue($object, $defaultValue);
}
}
}
Expand Down

0 comments on commit b26548c

Please sign in to comment.