<?php
namespace App\Repository\WebServices;
use App\Serializer\Normalizer\CrossSystemIdMapper;
use App\Services\ApiConsumerService;
use App\Services\CriteriaToRequest;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Criteria;
use Psr\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
use Symfony\Component\Serializer\Normalizer\AbstractNormalizer;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\SerializerInterface;
use Symfony\Contracts\Translation\TranslatorInterface;
abstract class AbstractWsRepository
{
protected $ruta;
protected $entidad;
protected $cache;
protected $global;
protected $expire;
public function getEntityClass()
{
return $this->entidad;
}
// Forzar la extensión de clase para definir este método
// abstract protected function getValor();
// abstract protected function valorPrefijo($prefijo);
public function __construct(
protected ApiConsumerService $apiConsumerService,
protected CriteriaToRequest $criteriaToRequest,
protected SerializerInterface $serializer,
protected TranslatorInterface $translator,
protected SessionInterface $session,
protected CrossSystemIdMapper $crossSystemIdMapper,
protected RequestStack $requestStack,
protected EventDispatcherInterface $eventDispatcher
)
{
// Extraer el nombre de la clase sin "Repository"
$className = (new \ReflectionClass($this))->getShortName();
$entityName = str_replace('Repository', '', $className);
// ejemplo: "cms/" Ojo a la barra final
$this->ruta = $this->ruta ?: strtolower(preg_replace('/([a-z])([A-Z])/', '$1-$2', $entityName)) . '/';
// metemos aquí la ruta por si cambia no cambiar abajo
$this->entidad = $this->entidad ? "App\Entity\\{$this->entidad}" : "App\Entity\\{$entityName}";
}
protected function preSave($object)
{
return $object;
}
protected function postSave($object)
{
return $object;
}
// Métodos comunes
public function save($object)
{
$this->preSave($object);
$clase = $this->serializer->serialize($object, 'json', [
ObjectNormalizer::SKIP_NULL_VALUES => true,
'normalizer_type' => 'hermes',
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => function ($object) {
if (method_exists($object, 'getId') && $object->getId() !== null) {
return ['id' => $object->getId()];
}
return ['_circular_reference' => get_class($object)];
},
AbstractNormalizer::CIRCULAR_REFERENCE_LIMIT => 3,
]);
// WORKAROUND para Evento: filtrar campos que causan problemas en Hermes
if ($object instanceof \App\Entity\Evento) {
$data = json_decode($clase, true);
$camposProblematicos = ['pacientes', 'responsables', 'pacientes_filter', 'grupos_pacientes_filter', 'organigramas_filter', 'lista_espera', 'sesiones', 'listaespera', 'formulario_respuestas'];
foreach ($camposProblematicos as $campo) {
unset($data[$campo]);
}
// Filtrar TODOS los campos null restantes
$data = array_filter($data, function($value) {
return $value !== null;
});
$clase = json_encode($data);
}
$response = $this->apiConsumerService->postData($this->ruta . $object->getId(), $clase);
$idSourceSystem = json_decode($response, true)['id'];
$object->setId($idSourceSystem);
$this->postSave($object);
}
public function all($subParameters = '', $cachear = null): ?ArrayCollection
{
$cachear = $cachear ?? $this->cache ?? true;
$queryParams = [];
try {
$data = $this->apiConsumerService->getData($this->ruta . $subParameters, $queryParams, $cachear, $this->global, $this->expire);
} catch (NotAcceptableHttpException $e) {
return null;
}
if (!class_exists($this->entidad)) throw new \Exception("API consumer class no exist $this->entidad");
if (!$data) return null;
$valores = $this->serializer->deserialize($data, $this->entidad . '[]', 'json',
['normalizer_type' => 'hermes']);
$valores = new ArrayCollection($valores);
return $valores;
}
public function findById(int $id, $cachear = null, $extraparams = [])
{
$cachear = $cachear ?? $this->cache ?? true;
$queryParams = [];
if (!empty($extraparams)) {
foreach ($extraparams as $key => $value) {
$queryParams[$key] = $value;
}
}
try {
$data = $this->apiConsumerService->getData($this->ruta . $id, $queryParams, $cachear, $this->global, $this->expire);
} catch (NotAcceptableHttpException $e) {
return null;
}
if (!class_exists($this->entidad)) return null;
if (!$data) return null;
$valor = $this->serializer->deserialize($data, $this->entidad, 'json',
['normalizer_type' => 'hermes']);
return $valor;
}
public function findOne(Criteria $criteria, $cachear = null, $extraparams = [])
{
$cachear = $cachear ?? $this->cache ?? true;
$valoreS = $this->find($criteria, $cachear, $extraparams);
if ($valoreS and $valoreS->count()) return $valoreS->first();
return null;
}
public function find(Criteria $criteria, $cachear = null, $extraparams = []): ?ArrayCollection
{
$cachear = $cachear ?? $this->cache ?? true;
if (!empty($extraparams)) {
foreach ($extraparams as $key => $value) {
$queryParams[$key] = $value;
}
}
$queryParams['criteria'] = ($this->criteriaToRequest)($criteria);
try {
$data = $this->apiConsumerService->getData($this->ruta, $queryParams, $cachear, $this->global, $this->expire);
} catch (NotAcceptableHttpException $e) {
return new ArrayCollection([]);
}
if (!class_exists($this->entidad)) return new ArrayCollection([]);
if (!$data) return new ArrayCollection([]);
$valores = $this->serializer->deserialize($data, $this->entidad . '[]', 'json', ['normalizer_type' => 'hermes']);
$valores = new ArrayCollection($valores);
return $valores;
}
public function delete($object, bool $force = false): void
{
}//function
public function saveAndGet($object, $queryParams = [])
{
$clase = $this->serializer->serialize($object, 'json', [
ObjectNormalizer::SKIP_NULL_VALUES => true,
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => function ($object) {
if (method_exists($object, 'getId') && $object->getId() !== null) {
return ['id' => $object->getId()];
}
return ['_circular_reference' => get_class($object)];
},
]);
$id = $object->getId() ?: '';
$response = $this->apiConsumerService->postData($this->ruta . $id, $clase, $queryParams);
return $this->serializer->deserialize($response, $this->entidad, 'json',
['normalizer_type' => 'hermes']);
}
public function setGlobal($global)
{
$this->global = $global;
return $this;
}
public function setExpire($expire)
{
$this->expire = $expire;
return $this;
}
public function setCache($cache)
{
$this->cache = $cache;
return $this;
}
public function getClass()
{
return get_called_class();
}
}