<?php
namespace App\InsuranceCompany\Common\Insis\Subscriber;
use App\InsuranceCompany\Common\Insis\InsuranceSvcRsTypeInterface;
use App\InsuranceCompany\Common\Insis\InsuranceSvcTypeInterface;
use App\InsuranceCompany\Common\Insis\RegisterAddCovAnnexRs;
use Phpro\SoapClient\Event\FaultEvent;
use Phpro\SoapClient\Event\ResponseEvent;
use Phpro\SoapClient\Exception\SoapException;
use Phpro\SoapClient\Type\ResultInterface;
use Psr\Log\LoggerInterface;
use RuntimeException;
use SoapFault;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Throwable;
/**
* Class ErrorHandlingSubscriber
*/
class ErrorHandlingSubscriber implements EventSubscriberInterface
{
/**
* @var string
*/
protected string $exceptionClass;
/**
* @var string
*/
protected string $insuranceSvcTypeClass;
/**
* @var string
*/
protected string $insuranceSvcTypeRsClass;
/**
* Constructor
*
* @param LoggerInterface $logger
*/
public function __construct(
protected LoggerInterface $logger,
)
{
}
/**
* @param ResponseEvent $event
*/
public function onClientResponse(ResponseEvent $event)
{
$response = $event->getResponse();
if (!($response instanceof InsuranceSvcTypeInterface)) {
throw new RuntimeException('Invalid response type received');
}
/**
* @noinspection PhpPossiblePolymorphicInvocationInspection
* @todo ErrorInterface
*/
$error = $response->getError();
if ($error === null) {
return;
}
$module = $error->getModule();
$errorId = $error->getErrorId();
$errorDescr = $error->getErrorDescr();
// if ($errorDescr === 'PROCESS=FAILURE; ERROR_MESSAGE=6600_19: Стикерът съществува в Регистъра за Бланки под строга отчетност, но вече е използван или регистриран в друг офис.;') {
// $errorDescr = 'PROCESS=SUCCESSFULLY; ANNEX_ID=3; INSTALL_ID=3114602626;';
// }
if (
$module === 'WEBSVC' &&
$errorId === 'INSIS_ERROR' &&
str_contains($errorDescr, 'PROCESS=') &&
str_contains($errorDescr, ';')
) {
$parts = array_filter(array_map('trim', explode(';', $errorDescr)));
$errorInfo = [];
$errorDetails = [];
foreach ($parts as $part) {
$parts2 = array_map('trim', explode('=', $part, 2));
if (count($parts2) > 1) {
$key = $parts2[0];
$value = $parts2[1];
$errorInfo[$key] = $value;
if ($key === 'ERROR_MESSAGE') {
$errorParts = array_map('trim', explode(':', $value, 2));
if (count($errorParts) > 1) {
$errorDetails = [
'code' => $errorParts[0],
'message' => $errorParts[1],
];
}
}
}
else {
$errorInfo[] = $parts2[0];
}
}
switch ($errorInfo['PROCESS']) {
case 'FAILURE':
if (!empty($errorDetails)) {
$errorDescr = $errorDetails['message'] . ' (' . $errorDetails['code'] . ')';
}
break;
case 'SUCCESSFULLY':
$event->registerResponse($this->getResponse(new RegisterAddCovAnnexRs(
$errorInfo['ANNEX_ID'] ?? null,
$errorInfo['INSTALL_ID'] ?? null,
$errorInfo['NEW_GREEN_CARD_NO'] ?? null,
)));
return;
default:
$errorDescr = 'Unknown process value: ' . var_export($errorInfo['PROCESS'], true);
break;
}
}
throw new $this->exceptionClass(
$errorDescr . ' (' . $error->getErrorID() . '@' . $error->getModule() . ')', 0, null,
$errorId, $errorDescr, $module,
);
}
/**
* @param FaultEvent $event
*/
public function onClientFault(FaultEvent $event)
{
$soapException = $event->getSoapException();
if (
$soapException->getMessage() === 'JBO-26061: Error while opening JDBC connection.' || (
str_starts_with(
$soapException->getMessage(),
'WEB.COMMON.LOGIN.AUTH_FAILED: weblogic.common.resourcepool.ResourceLimitException: No resources ' .
'currently available in pool '
) &&
str_ends_with(
$soapException->getMessage(),
' to allocate to applications, please increase the size of the pool and retry..'
)
)
) {
throw $this->getInsuranceCompanyUnavailableException($soapException);
}
$soapFault = $soapException->getPrevious();
if (!($soapFault instanceof SoapFault)) {
return;
}
if (str_contains(
$soapFault->detail?->exception ?? '',
'Caused by: oracle.jbo.JboException: Proxy session initialization failed!ORA-28000: The account is locked.',
)) {
throw $this->getInsuranceCompanyUnavailableException($soapException);
}
}
private function getResponse(ResultInterface $result): InsuranceSvcTypeInterface
{
/**
* @var InsuranceSvcTypeInterface $insuranceSvc
*/
$insuranceSvc = new $this->insuranceSvcTypeClass();
/**
* @var InsuranceSvcRsTypeInterface $insuranceSvcRs
*/
$insuranceSvcRs = new $this->insuranceSvcTypeRsClass();
// TODO
/** @noinspection PhpUndefinedFieldInspection */
$insuranceSvcRs->_result = $result;
$insuranceSvc->setInsuranceSvcRs($insuranceSvcRs);
return $insuranceSvc;
}
/**
* @param Throwable $previous
* @return SoapException
*/
private function getInsuranceCompanyUnavailableException(Throwable $previous): SoapException
{
return new SoapException(
'В момента няма достъп до застрахователната компания',
$previous->getCode(),
$previous,
);
}
/**
* {@inheritdoc}
* @noinspection PhpArrayShapeAttributeCanBeAddedInspection
*/
public static function getSubscribedEvents(): array
{
return [
ResponseEvent::class => 'onClientResponse',
FaultEvent::class => 'onClientFault',
];
}
}