ctrl-f5/ctrl-common

View on GitHub
src/EntityService/AbstractDoctrineService.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php

namespace Ctrl\Common\EntityService;

use Ctrl\Common\EntityService\Finder\Doctrine\Finder;
use Ctrl\Common\EntityService\Finder\FinderInterface;
use Ctrl\Common\EntityService\Finder\PaginatableResultInterface;
use Ctrl\Common\EntityService\Finder\ResultInterface;
use Doctrine\Common\Persistence\ObjectManager;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityNotFoundException;
use Doctrine\ORM\EntityRepository;

abstract class AbstractDoctrineService implements ServiceInterface
{
    /**
     * @var ObjectManager|EntityManager
     */
    private $doctrine;

    /**
     * @var EntityRepository
     */
    private $repository;

    /**
     * @var string
     */
    protected $rootAlias;

    /**
     * @var FinderInterface
     */
    protected $finder;

    /**
     * @return string
     */
    abstract public function getEntityClass();

    /**
     * @return string
     */
    public function getRootAlias()
    {
        if (!$this->rootAlias) {
            $arr = explode('\\', $this->getEntityClass());
            $this->rootAlias = lcfirst(end($arr));
        }

        return $this->rootAlias;
    }

    /**
     * @param ObjectManager|EntityManager $doctrine
     * @return $this
     */
    public function setDoctrine($doctrine)
    {
        $this->doctrine = $doctrine;
        return $this;
    }

    /**
     * @return EntityRepository
     */
    protected function getEntityRepository()
    {
        if (!$this->repository) {
            if (!$this->doctrine) {
                throw new \RuntimeException('doctrine not set');
            }
            $this->repository = $this->doctrine->getRepository($this->getEntityClass());
        }

        return $this->repository;
    }

    /**
     * @return FinderInterface
     */
    public function getFinder()
    {
        if (!$this->finder) {
            $this->finder = new Finder(
                $this->getEntityRepository(),
                $this->getRootAlias()
            );
        }

        return $this->finder;
    }

    /**
     * @param array $criteria
     * @param array $orderBy
     * @return PaginatableResultInterface|ResultInterface
     */
    public function find(array $criteria = array(), array $orderBy = array())
    {
        return $this->getFinder()->find($criteria, $orderBy);
    }

    /**
     * @param object $entity
     * @return bool
     * @throws \InvalidArgumentException
     */
    public function assertEntityInstance($entity)
    {
        $class = $this->getEntityClass();
        if (!(is_object($entity) && $entity instanceof $class)) {
            throw new \InvalidArgumentException(
                sprintf('Service can only handle entities of class %s', $class)
            );
        }
    }

    /**
     * @param object|int $idOrEntity
     * @param bool $failOnNotFound
     * @return $this
     * @throws EntityNotFoundException
     */
    public function remove($idOrEntity, $failOnNotFound = false)
    {
        $entity = (is_object($idOrEntity)) ?
            $idOrEntity:
            $this->getFinder()->get($idOrEntity);

        if (!$entity && $failOnNotFound) {
            throw new EntityNotFoundException(sprintf(
                "Entity of type %s with id %s could not be found",
                $this->getEntityClass(),
                is_object($idOrEntity) ? $idOrEntity->getId(): $idOrEntity
            ));
        }

        $this->assertEntityInstance($entity);

        $this->doctrine->remove($entity);
        $this->doctrine->flush();

        return $this;
    }

    /**
     * @param object $entity
     * @param bool $flush
     * @return $this
     */
    public function persist($entity, $flush = true)
    {
        $this->assertEntityInstance($entity);

        $this->doctrine->persist($entity);
        if ($flush) $this->flush();

        return $this;
    }

    /**
     * @return $this
     */
    public function flush()
    {
        $this->doctrine->flush();

        return $this;
    }
}