open-orchestra/open-orchestra-model-bundle

View on GitHub
ModelBundle/EventListener/UpdateNonTranslatableContentFieldsListener.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php

namespace OpenOrchestra\ModelBundle\EventListener;

use Doctrine\ODM\MongoDB\Event\LifecycleEventArgs;
use OpenOrchestra\ModelInterface\Model\ContentAttributeInterface;
use OpenOrchestra\ModelInterface\Model\ContentInterface;
use OpenOrchestra\ModelInterface\Model\FieldTypeInterface;
use OpenOrchestra\ModelInterface\Repository\ContentRepositoryInterface;
use OpenOrchestra\ModelInterface\Repository\ContentTypeRepositoryInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;

/**
 * Class UpdateNonTranslatableContentFieldsListener
 */
class UpdateNonTranslatableContentFieldsListener implements ContainerAwareInterface
{
    use ContainerAwareTrait;

    protected $contentManaged = array();
    protected $contentAttributeClass;
    protected $immutableData;

    /**
     * @param string $contentAttributeClass
     * @param array  $immutableData
     */
    public function __construct($contentAttributeClass, array $immutableData = array())
    {
        $this->contentAttributeClass = $contentAttributeClass;
        $this->immutableData = $immutableData;
    }

    /**
     * @param LifecycleEventArgs $event
     */
    public function preUpdate(LifecycleEventArgs $event)
    {
        if (!($object = $event->getDocument()) instanceof ContentInterface || in_array($object->getContentId(), $this->contentManaged)) {
            return;
        }

        $this->contentManaged[] = $object->getContentId();

        $contents = $this->getContentRepository()->findByContentId($object->getContentId());
        $contentType = $this->getContentTypeRepository()->findOneByContentTypeIdInLastVersion($object->getContentType());

        /** @var ContentInterface $content */
        foreach ($contents as $content) {
            if ($content != $object) {
                foreach ($this->immutableData as $immutableData) {
                    $getter = $this->generateGetter($immutableData, $object);
                    $setter = 'set' . ucfirst($immutableData);
                    $content->$setter($object->$getter());
                }
                /** @var FieldTypeInterface $field */
                foreach ($contentType->getFields() as $field) {
                    if (!$field->isTranslatable()) {
                        $contentAttribute = $this->getContentAttribute($content, $field->getFieldId());
                        $contentAttribute->setValue($object->getAttributeByName($field->getFieldId())->getValue());
                    }
                }

            }
            $event->getDocumentManager()->flush($content);
        }
    }

    /**
     * @return ContentRepositoryInterface
     */
    protected function getContentRepository()
    {
        return $this->container->get('open_orchestra_model.repository.content');
    }

    /**
     * @param string           $immutableData
     * @param ContentInterface $object
     * @return string
     */
    protected function generateGetter($immutableData, ContentInterface $object)
    {
        foreach (array('get', 'is', 'has') as $prefix) {
            $getter = $prefix . ucfirst($immutableData);
            if (method_exists($object, $getter)) {
                return $getter;
            }
        }

        return $immutableData;
    }

    /**
     * @return ContentTypeRepositoryInterface
     */
    protected function getContentTypeRepository()
    {
        return $this->container->get('open_orchestra_model.repository.content_type');
    }

    /**
     * @param ContentInterface $content
     * @param string           $fieldId
     *
     * @return ContentAttributeInterface
     */
    protected function getContentAttribute(ContentInterface $content, $fieldId)
    {
        $contentAttribute = $content->getAttributeByName($fieldId);

        if (!$contentAttribute instanceof ContentAttributeInterface) {
            $contentAttributeClass = $this->contentAttributeClass;
            /** @var ContentAttributeInterface $contentAttribute */
            $contentAttribute = new $contentAttributeClass();
            $contentAttribute->setName($fieldId);
            $content->addAttribute($contentAttribute);
        }

        return $contentAttribute;
    }
}