edmondscommerce/doctrine-static-meta

View on GitHub
src/Entity/Savers/EntitySaverFactory.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

declare(strict_types=1);

namespace EdmondsCommerce\DoctrineStaticMeta\Entity\Savers;

use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Proxy\Proxy;
use EdmondsCommerce\DoctrineStaticMeta\CodeGeneration\NamespaceHelper;
use EdmondsCommerce\DoctrineStaticMeta\Entity\Interfaces\EntityInterface;

use function get_class;
use function str_replace;

class EntitySaverFactory
{
    /**
     * @var EntityManagerInterface
     */
    protected $entityManager;

    /**
     * @var EntitySaver
     */
    protected $genericEntitySaver;
    /**
     * @var EntitySaver
     */
    protected $genericSaver;
    /**
     * @var NamespaceHelper
     */
    protected $namespaceHelper;

    public function __construct(
        EntityManagerInterface $entityManager,
        EntitySaver $genericSaver,
        NamespaceHelper $namespaceHelper
    ) {
        $this->entityManager   = $entityManager;
        $this->genericSaver    = $genericSaver;
        $this->namespaceHelper = $namespaceHelper;
    }

    /**
     * Gets the Entity Specific Saver if one is defined, otherwise the standard Entity Saver
     *
     * @param EntityInterface $entity
     *
     * @return EntitySaverInterface
     */
    public function getSaverForEntity(
        EntityInterface $entity
    ): EntitySaverInterface {
        $fqn = $this->getEntityNamespace($entity);

        return $this->getSaverForEntityFqn($fqn);
    }

    /**
     * It is possible to pass a proxy to the class which will trigger a fatal error due to autoloading problems.
     *
     * This will resolve the namespace to that of the entity, rather than the proxy. May need to update this to handle
     * other cases
     *
     * @param EntityInterface $entity
     *
     * @return string
     */
    private function getEntityNamespace(EntityInterface $entity): string
    {
        if ($entity instanceof Proxy) {
            $proxyFqn  = get_class($entity);
            $namespace = $this->entityManager->getConfiguration()->getProxyNamespace();
            $marker    = \Doctrine\Persistence\Proxy::MARKER;

            return str_replace($namespace . '\\' . $marker . '\\', '', $proxyFqn);
        }

        return $this->namespaceHelper->getObjectFqn($entity);
    }

    /**
     * @param string $entityFqn
     *
     * @return EntitySaverInterface
     */
    public function getSaverForEntityFqn(string $entityFqn): EntitySaverInterface
    {
        $saverFqn = $this->getSaverFqn($entityFqn);
        if (class_exists($saverFqn)) {
            return new $saverFqn($this->entityManager, $this->namespaceHelper);
        }

        return $this->genericSaver;
    }

    /**
     * Get the fully qualified name of the saver for the entity we are testing.
     *
     * @param string $entityFqn
     *
     * @return string
     */
    protected function getSaverFqn(
        string $entityFqn
    ): string {

        return str_replace(
            'Entities',
            'Entity\\Savers',
            $entityFqn
        ) . 'Saver';
    }
}