<?php namespace App\Service\Dto; use App\Service\Response\ResponseServiceInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\PropertyInfo\Extractor\ReflectionExtractor; use Symfony\Component\Serializer\Annotation\Ignore; use Symfony\Component\Serializer\Encoder\JsonEncoder; use Symfony\Component\Serializer\NameConverter\CamelCaseToSnakeCaseNameConverter; use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer; use Symfony\Component\Serializer\Normalizer\ObjectNormalizer; use Symfony\Component\Serializer\Serializer; use Symfony\Component\Validator\Validator\ValidatorInterface; abstract class BaseDto implements DtoServiceInterface { private ?Request $request = null; public function __construct( private ?ValidatorInterface $validator, ?RequestStack $requestStack = null, ) { if ($requestStack) { $this->request = $requestStack->getCurrentRequest(); } } /** * Получение класса Dto * * @return DtoServiceInterface|null */ #[Ignore] public function getClass(): ?DtoServiceInterface { if ($this->request) { try { $normalizer = new ObjectNormalizer( null, new CamelCaseToSnakeCaseNameConverter(), null, new ReflectionExtractor() ); $serializer = new Serializer( [$normalizer, new DateTimeNormalizer()], [new JsonEncoder()] ); return $serializer->deserialize($this->request->getContent(), static::class, 'json'); } catch (\Exception $exception) { return null; } } return null; } public function toArray(): ?array { try { $normalizer = new ObjectNormalizer( null, new CamelCaseToSnakeCaseNameConverter(), null, new ReflectionExtractor() ); $serializer = new Serializer([$normalizer], [new JsonEncoder()]); $data = $serializer->serialize($this->getClass(), 'json'); return json_decode($data, true, 512, JSON_THROW_ON_ERROR); } catch (\Exception $oException) { return null; } } /** * Валидация Dto * * @param ResponseServiceInterface $response * * @return bool */ public function validate(ResponseServiceInterface $response): bool { $bValid = true; if ($classObj = $this->getClass()) { $aErrors = $this->validator->validate($classObj); if (count($aErrors) > 0) { foreach ($aErrors as $error) { $response->addError($error->getMessage()); $response->setStatusCode(Response::HTTP_UNPROCESSABLE_ENTITY); } $bValid = false; } } else { $response->addError("Данные не получены"); $response->setStatusCode(Response::HTTP_UNPROCESSABLE_ENTITY); $bValid = false; } return $bValid; } }