<?php
namespace WebBundle\Service;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\ORMException;
use Exception;
use FlexApp\Enum\LoggerJobNameEnum;
use FlexApp\Events\Style43\RegistrationSuccessEvent;
use FlexApp\Exceptions\PortalApiClientException;
use FlexApp\Exceptions\UserIsNotValidException;
use FlexApp\Service\Canonicalizer;
use FlexApp\Service\LogsManager;
use FlexApp\Service\UserPortalService;
use Monolog\Logger;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Form\FormFactory;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use WebBundle\Entity\OrderAddress;
use WebBundle\Entity\User;
use WebBundle\Form\RegistrationFormType;
use WebBundle\Form\UserRegistrationForm;
use WebBundle\Helper\App;
use WebBundle\Helper\Mailer;
use WebBundle\Helper\PortalHelper;
use WebBundle\Helper\UserHelper;
class RegistrationService
{
private $container;
private $portalService;
private $registrationForm;
private $user = null;
private $logger;
private $em;
/**
* @var EventDispatcherInterface
*/
private $eventDispatcher;
/** @required */
public UserPortalService $userPortalService;
/** @required */
public LocationService $locationService;
/** @required */
public Mailer $mailer;
/** @required */
public UserPasswordHasherInterface $userPasswordHasher;
/** @required */
public Canonicalizer $canonicalizer;
private LogsManager $logsManager;
public function __construct(
ContainerInterface $container,
PortalHelper $portalService,
Logger $logger,
EntityManager $em,
EventDispatcherInterface $eventDispatcher,
LogsManager $logsManager
) {
$this->container = $container;
$this->portalService = $portalService;
$this->logger = $logger;
$this->em = $em;
$this->eventDispatcher = $eventDispatcher;
$this->logsManager = $logsManager;
}
/**
* Создает нового пользователя, возвращает true если создался и false в противном случае.
*
* @param Request $request
*
* @return User|null
*
* @throws ORMException
* @throws UniqueConstraintViolationException
* @throws Exception
*/
public function register(Request $request): ?User
{
/** @var $formFactory FormFactory */
$formFactory = $this->container->get('form.factory');
$userRegistrationForm = new UserRegistrationForm();
$this->registrationForm = $formFactory->create(RegistrationFormType::class, $userRegistrationForm);
$this->registrationForm->setData($userRegistrationForm);
$this->registrationForm->handleRequest($request);
if (
!$this->registrationForm->isSubmitted()
|| !$this->registrationForm->isValid()
|| !$userRegistrationForm->getPlainPassword()
|| !$userRegistrationForm->getEmail()
) {
return null;
}
$token = UserHelper::getInstance()->getToken();
$user = new User();
$user->setToken($token);
$user->setEnabled(true);
$user->setProved(false);
$user->setEmail($userRegistrationForm->getEmail());
$user->setUsername(null);
$user->setAlias(UserHelper::getUsernameEmail($userRegistrationForm->getEmail()));
$orderAddress = new OrderAddress();
$orderAddress->setIsMainRecipient(true);
$orderAddress->setToken($token);
$user->addOrderAddress($orderAddress);
if ('999' != $userRegistrationForm->getCountry()) {
$user->getMainRecipientAddress()->setCountry($this->em->getReference('WebBundle\Entity\ListCountry', $userRegistrationForm->getCountry()));
}
$user->getMainRecipientAddress()->setZipCode($userRegistrationForm->getZip());
$this->user = $user;
$this->updateUser($user, $userRegistrationForm->getPlainPassword());
$this->mailer->sendUserRegEmailMessage($user, '********');
$this->sendUserToNewPortal($request, $user);
return $this->user;
}
/**
* Автоматическое создание пользователя NEW used ONLY in TileExpert !!!
*
* @param $email
* @param array $data
*
* @return User|null
*
* @throws Exception
*/
public function autoRegisterNew($email, $data = [])
{
$data['email'] = $email;
$oServiceUser = App::getContainer()->get('app.service.user_profile');
try {
// обновляем данные юзера / или рега
$oUser = $oServiceUser->saveUserByData($data);
} catch (UserIsNotValidException $exception) {
throw new BadRequestHttpException('User is not valid.');
}
if ($oServiceUser->hasErrors()) {
// тут желательно отдать ошибку
$error = $oServiceUser->getErrors();
throw new BadRequestHttpException($error);
}
if (!$oUser) {
throw new Exception('Failed to get user');
}
if ('error' == $oUser->getUnid()) {
$attempts = 5;
do {
// если не первая попытка то делаем паузу
if ($attempts < 5) {
sleep(2);
}
--$attempts;
$unid = $oServiceUser->getUserPortalUnid($oUser);
} while ($attempts > 0 && !$unid);
if (!$unid) {
throw new Exception('Failed to get unid');
}
}
if (!('' === $oUser->getUnid() || 'error' === $oUser->getUnid() || null === $oUser->getUnid())) {
$this->eventDispatcher->dispatch(new RegistrationSuccessEvent($oUser));
$this->userPortalService->updateOrdersByUser($oUser);
}
return $oUser;
}
/**
* @return mixed
*/
public function getUser()
{
return $this->user;
}
/**
* Возвращает форму для регистрации.
*
* @return mixed
*/
public function getRegistrationForm()
{
return $this->registrationForm;
}
public function updateUser(User $user, ?string $password = null)
{
if (null !== $password) {
$user->setPassword(
$this->userPasswordHasher->hashPassword($user, $password)
);
}
$emailCanonical = $this->canonicalizer->canonicalize($user->getEmail());
$user->setEmail($emailCanonical);
if (!$this->em->contains($user)) {
$this->em->persist($user);
}
$this->em->flush();
}
/**
* Добавление пользователя на новый портал
*/
private function sendUserToNewPortal(Request $request, User $user): void
{
$record = $this->locationService->getCityRecord($request->getClientIp());
$contact = [
'ContactStatus' => [7],
'FirstName' => "",
'ContactName' => "",
'EmailValues' => [$user->getEmail()],
'MainEmail' => $user->getEmail(),
'DocumentType' => 'Person',
'siteToken' => $user->getToken(),
'source' => 'RegistrationService::register',
'responsibleUnid' => 'B450D722-E901-27CF-DDCC-F6AF86BF5A5D',
'responsibleName' => 'Pavel Popov',
'Comment' => null !== $record ?
implode(', ', array_filter([$record->country->name, $record->city->name])) . ' (' . $request->getClientIp() . ')' :
$request->getClientIp(),
];
try {
$result = $this->portalService->createContactWithAdditionalFunctional($contact);
if (!empty($result) && !empty($result['contactUnid'])) {
$user->setUnid($result['contactUnid']);
$this->updateUser($user);
$this->userPortalService->updateOrdersByUser($user);
$this->user = $user;
$this->logger->info('CONTACT REG: ' . print_r($contact, true));
$this->logger->info('CONTACT REG RESULT: ' . print_r($contact, true));
$this->logsManager->logInfo(
[
'message' => [
'CONTACT REG: ' . print_r($contact, true),
'CONTACT REG RESULT: ' . print_r($contact, true),
],
],
LoggerJobNameEnum::REGISTRATION_SERVICE_LOG
);
$this->eventDispatcher->dispatch(new RegistrationSuccessEvent($this->user));
}
} catch (PortalApiClientException $e) {
$this->logger->error('Отправка контакта на портал неуспешна: ' . $e->getMessage());
$this->logsManager->logInfo(
[
'message' => 'Отправка контакта на портал неуспешна: ' . $e->getMessage(),
],
LoggerJobNameEnum::REGISTRATION_SERVICE_LOG
);
}
}
}