<?php
namespace WebBundle\Service;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\ORMException;
use Exception;
use FlexApp\Events\Style43\RegistrationSuccessEvent;
use FlexApp\Exceptions\PortalApiClientException;
use FlexApp\Exceptions\UserIsNotValidException;
use FlexApp\Service\Canonicalizer;
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\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 UserPasswordHasherInterface $userPasswordHasher;
/** @required */
public Canonicalizer $canonicalizer;
public function __construct(
ContainerInterface $container,
PortalHelper $portalService,
Logger $logger,
EntityManager $em,
EventDispatcherInterface $eventDispatcher
)
{
$this->container = $container;
$this->portalService = $portalService;
$this->logger = $logger;
$this->em = $em;
$this->eventDispatcher = $eventDispatcher;
}
/**
* Создает нового пользователя, возвращает true если создался и false в противном случае.
*
* @param Request $request
*
* @return User|null
*
* @throws ORMException
* @throws UniqueConstraintViolationException
* @throws Exception
*/
public function register(Request $request)
{
/** @var $formFactory FormFactory */
$formFactory = $this->container->get('form.factory');
$token = UserHelper::getInstance()->getToken();
$user = new User();
if ($user->getOrderAddresses()->count() === 0) {
$orderAddress = new OrderAddress();
$orderAddress->setIsMainRecipient(true);
$orderAddress->setToken($user->getToken() ?: UserHelper::getInstance()->getToken());
$user->addOrderAddress($orderAddress);
}
$user->setEnabled(true);
$user->setProved(false);
$user->setToken($token);
$this->registrationForm = $formFactory->create(RegistrationFormType::class, $user);
$this->registrationForm->setData($user);
$this->registrationForm->handleRequest($request);
if ($this->registrationForm->isSubmitted() && $this->registrationForm->isValid()) {
$data = $this->registrationForm->getData();
if ($data->getPlainPassword() && $data->getEmail()) {
// $username = str_replace('@', '_', $data->getEmail());
$user->setUsername(null);
$user->setAlias(UserHelper::getUsernameEmail($data->getEmail()));
// Создание пользователя
$countryCode = $user->getCountry();
if ('999' != $countryCode) {
$user->getMainRecipientAddress()->setCountry($this->em->getReference('WebBundle\Entity\ListCountry', $user->getCountry()));
}
$user->getMainRecipientAddress()->setZipCode($user->getZip());
$this->user = $user;
$this->updateUser($this->user);
/** @var Mailer $mailer */
$mailer = $this->container->get('app.user.resetting_mailer');
$mailer->sendUserRegEmailMessage($user, true);
$record = $this->container->get('app.service.location')->getCityRecord($request->getClientIp());
// не отправлять если email null todo переделать это после перехода на sf4
if ($data->getEmail()) {
// Добавление пользователя на новый портал
$contact = [
'ContactStatus' => [7],
'FirstName' => "",
'ContactName' => "",
'EmailValues' => [$data->getEmail()],
'MainEmail' => $data->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(),
];
$portalService = $this->container->get('portal');
try {
$result = $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->eventDispatcher->dispatch(new RegistrationSuccessEvent($this->user));
}
} catch (PortalApiClientException $e) {
$this->logger->error('Отправка контакта на портал неуспешна: ' . $e->getMessage());
}
}
return $this->user;
} else {
return null;
}
}
return null;
}
/**
* Автоматическое создание пользователя 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;
}
/**
* Заполняет нужные поля у пользователя, которые невозможно заполнить с помощью handleRequest.
* Метод делает запрос к сервису создания контактов.
*
* @param User $user
*
* @return User
*
* @throws Exception
*/
private function addUserData(User $user)
{
$contact = [
'LastName' => '',
'FirstName' => $user->getUsername(),
'EmailValues' => [$user->getEmail()],
'siteToken' => $user->getToken(),
'file' => 'WebBundle/Service/RegistrationService.php',
];
$result = $this->portalService->createContact($contact);
$user_unid = '';
if ($result['success'] ?? null) {
$user_unid = $result['contactUnid'] ?? null;
}
$user->setUnid($user_unid);
return $user;
}
private function updateUser(User $user)
{
// encode the plain password
$user->setPassword(
$this->userPasswordHasher->hashPassword(
$user,
$this->registrationForm->get('plainPassword')->getData()
)
);
$emailCanonical = $this->canonicalizer->canonicalize($user->getEmail());
$user->setEmail($emailCanonical);
if (!$this->em->contains($user)) {
$this->em->persist($user);
}
$this->em->flush();
}
}