<?php
namespace Boab\CmsBundle\Manager;
use Symfony\Component\Form\FormFactoryInterface;
use Symfony\Component\HttpFoundation\Request;
use Boab\CmsBundle\Repository\ContentRepositoryInterface;
use Boab\CmsBundle\Entity\RouteContentInterface;
use Boab\CmsBundle\Entity\ContentInterface;
use Boab\CmsBundle\Event\ContentPostPersistEvent;
use Boab\CmsBundle\Event\ContentPrePersistEvent;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\ORM\EntityManager;
use InvalidArgumentException;
use Symfony\Component\Routing\RouterInterface;
use Boab\CmsBundle\Events;
use Boab\CmsBundle\Util\DataTable\DataTableContextInterface;
use Exception;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class ContentTypeManager implements ContentTypeManagerInterface
{
private $contentRepository;
private $formFactory;
private $entityManager;
private $router;
private $eventDispatcher;
private $contentTypes = [];
public function __construct(
ContentRepositoryInterface $contentRepository,
EntityManager $entityManager,
FormFactoryInterface $formFactory,
RouterInterface $router,
EventDispatcherInterface $eventDispatcher)
{
$this->contentRepository = $contentRepository;
$this->entityManager = $entityManager;
$this->formFactory = $formFactory;
$this->router = $router;
$this->eventDispatcher = $eventDispatcher;
}
public function addContentType(TypeManagerInterface $contentType)
{
$this->contentTypes[] = $contentType;
}
public function getContentTypes() : array
{
return $this->contentTypes;
}
public function getType(string $type):TypeManagerInterface
{
foreach ($this->getContentTypes() as $typeManager) {
if($typeManager->supports($type)){
return $typeManager;
}
}
throw new \InvalidArgumentException(sprintf("Invalid content type identifier ( %s )", $type));
}
public function getTypeByClass($class)
{
foreach ($this->getContentTypes() as $type) {
if ($class === $type->getEntityClass()) {
return $type;
}
}
throw new \InvalidArgumentException(sprintf("Invalid content type class ( %s )", $class));
}
public function getTypeByObject(ContentInterface $object)
{
return $this->getTypeByClass(get_class($object));
}
public function getTypeByContent(ContentInterface $object)
{
return $this->getTypeByClass(get_class($object));
}
public function getCollection(Request $request, int $pageNumber)
{
$typeId = $request->get('routeDocument')->getContentTypeId();
$typeManager = $this->getType($typeId);
if(!$typeManager){
throw new InvalidArgumentException(sprintf("The type manager does not exists for typeId %s", $typeId));
}
return $typeManager->getCollection($request, $pageNumber);
}
public function getContent(Request $request)
{
$route = $request->get('routeDocument');
if(!$route instanceof RouteContentInterface){
throw new \Exception(sprintf('Your route must implements %s to call the method %s', RouteContentInterface::class, __METHOD__));
}
$typeManager = $this->getType($route->getContentType());
return $typeManager->getContent($request);
}
public function getContents(array $params)
{
return $this->contentRepository->findContents($params);
}
public function searchContent(array $params)
{
return $this->contentRepository->findContentBySearchTerm($params);
}
public function create(ContentInterface $content): ContentInterface
{
$typeManager = $this->getTypeByObject($content);
if(method_exists($typeManager,'prePersist')){
$typeManager->prePersist($content);
}
$content->setDateCreated(new \DateTime('now'));
$event = new ContentPrePersistEvent($content);
$this->eventDispatcher->dispatch($event, Events::CONTENT_PRE_PERSIST);
try{
$this->entityManager->persist($content);
$this->entityManager->flush();
}catch(UniqueConstraintViolationException $e){
throw new Exception("An content with the same title exists already");
}
$postEvent = new ContentPostPersistEvent($content);
$this->eventDispatcher->dispatch($postEvent, Events::CONTENT_POST_PERSIST);
return $content;
}
public function update(ContentInterface $content)
{
$typeManager = $this->getTypeByObject($content);
if(method_exists($typeManager,'preUpdate')){
$typeManager->preUpdate($content);
}
$this->entityManager->persist($content);
$this->entityManager->flush();
$this->entityManager->refresh($content);
}
public function remove(ContentInterface $content)
{
$typeManager = $this->getTypeByObject($content);
if(method_exists($typeManager,'preRemove')){
$typeManager->preRemove($content);
}
$this->contentRepository->delete($content);
}
public function getSearchForm($type, array $options=[])
{
$typeManager = $this->getType($type);
$builder = $this->formFactory->createNamedBuilder($type);
$builder->setMethod('GET');
if(!method_exists($typeManager, 'buildSearchForm')){
return;
}
$typeManager->buildSearchForm($builder, [
"type"=>$type
]);
$action = $this->router->generate("app.search_content", ["type"=>$type]);
$builder->setAction($action);
return $builder->getForm();
}
public function filterResults($data=[], int $page):?iterable
{
$typeManager = $this->getType($data["type"]);
$collection = $typeManager->filterResults($data["query"], $page);
return $collection;
}
}