AzuraCast/src/Controller/Api/AbstractCrudController.php

160 lines
4.8 KiB
PHP

<?php
namespace App\Controller\Api;
use Azura\Http\Router;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Query;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Validator\ConstraintViolationList;
use Symfony\Component\Validator\Validator\ValidatorInterface;
abstract class AbstractCrudController
{
/** @var EntityManager */
protected $em;
/** @var Serializer */
protected $serializer;
/** @var ValidatorInterface */
protected $validator;
/** @var string The fully-qualified (::class) class name of the entity being managed. */
protected $entityClass;
/** @var string The route name used to generate the "self" links for each record. */
protected $resourceRouteName;
/**
* @param EntityManager $em
* @param Serializer $serializer
* @param ValidatorInterface $validator
*/
public function __construct(EntityManager $em, Serializer $serializer, ValidatorInterface $validator)
{
$this->em = $em;
$this->serializer = $serializer;
$this->validator = $validator;
}
/**
* @param object $record
* @param Router $router
* @return mixed
*/
protected function _viewRecord($record, Router $router)
{
if (!($record instanceof $this->entityClass)) {
throw new \InvalidArgumentException(sprintf('Record must be an instance of %s.', $this->entityClass));
}
$return = $this->_normalizeRecord($record);
$return['links'] = [
'self' => (string)$router->fromHere($this->resourceRouteName, ['id' => $record->getId()], [], true),
];
return $return;
}
protected function _normalizeRecord($record, array $context = [])
{
return $this->serializer->normalize($record, null, array_merge($context, [
ObjectNormalizer::ENABLE_MAX_DEPTH => true,
ObjectNormalizer::MAX_DEPTH_HANDLER => function ($innerObject, $outerObject, string $attributeName, string $format = null, array $context = array()) {
return $this->_displayShortenedObject($innerObject);
},
ObjectNormalizer::CIRCULAR_REFERENCE_HANDLER => function ($object, string $format = null, array $context = array()) {
return $this->_displayShortenedObject($object);
},
]));
}
/**
* @param object $object
* @return mixed
*/
protected function _displayShortenedObject($object)
{
if (method_exists($object, 'getName')) {
return $object->getName();
}
return $object->getId();
}
/**
* @param array $data
* @param object|null $record
* @return object
* @throws \App\Exception\Validation
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
protected function _createRecord($data, $record = null): object
{
if (null === $record) {
$record = new $this->entityClass();
}
return $this->_editRecord($data, $record);
}
/**
* @param array $data
* @param object $record
* @return object
* @throws \App\Exception\Validation
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
protected function _editRecord($data, $record): object
{
if (!($record instanceof $this->entityClass)) {
throw new \InvalidArgumentException(sprintf('Record must be an instance of %s.', $this->entityClass));
}
$this->_denormalizeToRecord($data, $record);
$errors = $this->validator->validate($record);
if (count($errors) > 0) {
$e = new \App\Exception\Validation((string)$errors);
$e->setDetailedErrors($errors);
throw $e;
}
$this->em->persist($record);
$this->em->flush($record);
return $record;
}
/**
* @param array $data
* @param object $record
* @param array $context
*/
protected function _denormalizeToRecord($data, $record, array $context = []): void
{
$this->serializer->denormalize($data, $this->entityClass, null, array_merge($context, [
AbstractNormalizer::OBJECT_TO_POPULATE => $record,
]));
}
/**
* @param object $record
* @throws \Doctrine\ORM\ORMException
* @throws \Doctrine\ORM\OptimisticLockException
*/
protected function _deleteRecord($record): void
{
if (!($record instanceof $this->entityClass)) {
throw new \InvalidArgumentException(sprintf('Record must be an instance of %s.', $this->entityClass));
}
$this->em->remove($record);
$this->em->flush($record);
}
}