<?php
namespace App\EventSubscriber;
use Psr\Log\LogLevel;
use App\Entity\Beneficiary;
use Psr\Log\LoggerInterface;
use App\Entity\FreematicaReport;
use App\Entity\PotentialBeneficiary;
use App\Event\Freematica\ErrorObjectEvent;
use App\Event\Freematica\SavedObjectEvent;
use App\Event\Freematica\ObjectExistsEvent;
use App\Event\Freematica\ConnectionErrorEvent;
use App\Event\Freematica\EmptyCollectionEvent;
use App\Event\Freematica\DuplicatedObjectEvent;
use App\Event\Freematica\CreateReportErrorEvent;
use App\Event\Freematica\ImportClientErrorEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class FreematicaSubscriber implements EventSubscriberInterface
{
// Gender object messages
public const MALE = 'el';
public const FEMALE = 'la';
// Object names
public const BENEFICIARY_NAME = 'beneficiario';
public const POTENTIAL_BENEFICIARY_NAME = 'beneficiario potencial';
public const FREEMATICA_REPORT_NAME = 'parte';
public const NAMES = [
self::BENEFICIARY_NAME,
self::POTENTIAL_BENEFICIARY_NAME,
self::FREEMATICA_REPORT_NAME
];
public const PLURALS = [
self::BENEFICIARY_NAME => 'beneficiarios',
self::FREEMATICA_REPORT_NAME => 'partes',
];
public const GENDER_NAMES = [
self::BENEFICIARY_NAME => self::MALE,
self::POTENTIAL_BENEFICIARY_NAME => self::MALE,
self::FREEMATICA_REPORT_NAME => self::MALE,
];
// Actions
public const ERROR = 0;
public const SUCCESS = 1;
public const CREATE_ACTION = [self::ERROR => 'insertar', self::SUCCESS => 'insertado'];
public const UPDATE_ACTION = [self::ERROR => 'actualizar', self::SUCCESS => 'actualizado'];
/** @var LoggerInterface $beneficiaryLogger */
private $beneficiaryLogger;
/** @var LoggerInterface $beneficiaryLogger */
private $clientLogger;
/** @var LoggerInterface $reportLogger */
private $reportLogger;
/** @var LoggerInterface $errorLogger */
private $errorLogger;
/**
* FreematicaSubscriber constructor.
* @param LoggerInterface $freematicaBeneficiaryLogger
* @param LoggerInterface $freematicaClientLogger
* @param LoggerInterface $freematicaReportLogger
* @param LoggerInterface $freematicaErrorLogger
*/
public function __construct(
LoggerInterface $freematicaBeneficiaryLogger,
LoggerInterface $freematicaClientLogger,
LoggerInterface $freematicaReportLogger,
LoggerInterface $freematicaErrorLogger
) {
$this->beneficiaryLogger = $freematicaBeneficiaryLogger;
$this->clientLogger = $freematicaClientLogger;
$this->reportLogger = $freematicaReportLogger;
$this->errorLogger = $freematicaErrorLogger;
}
/**
* @return array
*/
public static function getSubscribedEvents(): array
{
return [
ObjectExistsEvent::class => 'onObjectExists',
DuplicatedObjectEvent::class => 'onDuplicatedObject',
ErrorObjectEvent::class => 'onErrorObject',
SavedObjectEvent::class => 'onSavedObject',
ConnectionErrorEvent::class => 'onConnectionError',
EmptyCollectionEvent::class => 'onEmptyCollection',
CreateReportErrorEvent::class => 'onCreateReportError',
ImportClientErrorEvent::class => 'onImportClientError'
];
}
/**
* Dispatch when object exists in our database
*
* @param ObjectExistsEvent $event
*/
public function onObjectExists(ObjectExistsEvent $event)
{
$object = $event->getObject();
$code = $event->getCode();
$name = $this->getObjectName($object);
if (!$event->isUpdate()) {
$message = ucfirst($name) . " con código de Freematica $code ya existe";
$this->writeNotInfoLog($object, LogLevel::WARNING, $message);
}
}
/**
* Dispatch when object is duplicated in Freematica
*
* @param DuplicatedObjectEvent $event
*/
public function onDuplicatedObject(DuplicatedObjectEvent $event)
{
$name = $event->getName();
$id = $event->getId();
$identifier = $event->getIdentifier();
$logger = $this->getLoggerByName($name);
$message = ucfirst($name) . ' ' . $id . ' duplicado (' . $identifier . ')';
$logger->log(LogLevel::WARNING, $message);
}
/**
* @param ErrorObjectEvent $event
*/
public function onErrorObject(ErrorObjectEvent $event)
{
$object = $event->getObject();
$name = $this->getObjectName($object);
$code = $event->getCode();
$exceptionMessage = $event->getMessage();
$action = $this->getAction($event->isUpdate());
$message = "No se ha podido " . $action[self::ERROR] . " $name con código de Freematica " .
$code . ": " . $exceptionMessage;
$this->writeNotInfoLog($object, LogLevel::ERROR, $message);
}
/**
* @param SavedObjectEvent $event
*/
public function onSavedObject(SavedObjectEvent $event)
{
$object = $event->getObject();
$code = $event->getCode();
$name = $this->getObjectName($object);
$action = $this->getAction($event->isUpdate());
if ($this->isInfoLoggeableObject($object)) {
$message = "Se ha " . $action[self::SUCCESS] . " $name " . $code;
$logger = $this->getLogger($object);
$logger->info($message);
}
}
/**
* @param ConnectionErrorEvent $event
*/
public function onConnectionError(ConnectionErrorEvent $event)
{
$this->errorLogger->error($event->getMessage());
}
/**
* @param EmptyCollectionEvent $event
*/
public function onEmptyCollection(EmptyCollectionEvent $event)
{
if (!$event->getSize()) {
$logger = $this->getLoggerByName($event->getClassName());
$collection = $this->getObjectPluralName($event->getClassName());
$logger->warning('No hay ' . $collection . ' para importar');
}
}
/**
* @param CreateReportErrorEvent $event
* @return void
*/
public function onCreateReportError(CreateReportErrorEvent $event)
{
$this->reportLogger->warning($event->getErrorMessage());
}
/**
* @param ImportClientErrorEvent $event
* @return void
*/
public function onImportClientError(ImportClientErrorEvent $event)
{
$this->clientLogger->warning($event->getErrorMessage());
}
/**
* @param object $object
* @return bool
*/
private function isNotInfoLoggeableObject(object $object): bool
{
switch (true) {
case $object instanceof Beneficiary:
case $object instanceof PotentialBeneficiary:
case $object instanceof FreematicaReport:
return true;
}
return false;
}
/**
* @param object $object
* @return bool
*/
private function isInfoLoggeableObject(object $object): bool
{
switch (true) {
case $object instanceof PotentialBeneficiary:
return true;
}
return false;
}
/**
* @param object $object
* @return string|null
*/
private function getObjectName(object $object): ?string
{
switch (true) {
case $object instanceof Beneficiary:
return $this->getConcatName(self::BENEFICIARY_NAME);
case $object instanceof PotentialBeneficiary:
return $this->getConcatName(self::POTENTIAL_BENEFICIARY_NAME);
case $object instanceof FreematicaReport:
return $this->getConcatName(self::FREEMATICA_REPORT_NAME);
}
return null;
}
/**
* @param string $value
* @return string
*/
private function getConcatName(string $value): string
{
return self::GENDER_NAMES[$value] . ' ' . $value;
}
/**
* @param string $className
* @return string|null
*/
private function getObjectPluralName(string $className): ?string
{
switch ($className) {
case Beneficiary::class:
return $this->getPlural(self::BENEFICIARY_NAME);
case FreematicaReport::class:
return $this->getPlural(self::FREEMATICA_REPORT_NAME);
}
return null;
}
/**
* @param string $value
* @return string
*/
private function getPlural(string $value): string
{
return self::PLURALS[$value];
}
/**
* @param object $object
* @return LoggerInterface|null
*/
private function getLogger(object $object): ?LoggerInterface
{
switch (true) {
case $object instanceof Beneficiary:
case $object instanceof PotentialBeneficiary:
return $this->beneficiaryLogger;
case $object instanceof FreematicaReport:
return $this->reportLogger;
}
return null;
}
/**
* @param string $name
* @return LoggerInterface|null
*/
private function getLoggerByName(string $name): ?LoggerInterface
{
switch ($name) {
case self::BENEFICIARY_NAME:
case self::POTENTIAL_BENEFICIARY_NAME:
return $this->beneficiaryLogger;
case self::FREEMATICA_REPORT_NAME:
return $this->reportLogger;
}
return null;
}
/**
* @param object $object
* @param string $type
* @param string $message
*/
private function writeNotInfoLog(object $object, string $type, string $message): void
{
if ($message && $this->isNotInfoLoggeableObject($object)) {
$logger = $this->getLogger($object);
$logger->log($type, $message);
}
}
/**
* @param bool $update
* @return string[]
*/
private function getAction(bool $update): array
{
return $update ? self::UPDATE_ACTION : self::CREATE_ACTION;
}
}