<?php
namespace App\Controller;
use App\Entity\Organization;
use App\Entity\UserReview;
use App\Event\AppEvents;
use App\Event\Review\UserEvent;
use App\Helper\ReviewValidatorHelper;
use App\Model\Builder\OrganizationBuilder;
use App\Model\Builder\RegisterParty\UserBuilder;
use App\ValueObject\SearchCriteria\OrganizationSearchCriteria;
use App\ValueObject\SearchCriteria\ReviewSearchCriteria;
use App\ValueObject\SearchCriteria\UserSearchCriteria;
use App\ValueObject\UserTypes;
use Ecommerce121\UtilBundle\Controller\ControllerBase;
use Symfony\Component\Routing\Annotation\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use App\Model\Builder\RegisterParty\UserBuilder as RegisterUserBuilder;
use App\Model\Form\RegisterParty\UserForm as RegisterUserForm;
use Symfony\Component\Form\FormError;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Form\Form;
use App\Entity\User;
use Ecommerce121\UtilBundle\Controller\ControllerUtil;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\Security\Core\Encoder\EncoderFactoryInterface;
use Ecommerce121\UtilBundle\Lib\ReflectionUtil;
/**
* Class RegistrationController
*
* @Route("/registration")
*/
class RegistrationController extends ControllerBase
{
/**
* @var EncoderFactoryInterface
*/
protected $encoderFactory;
/**
* @var ReviewValidatorHelper
*/
protected $reviewValidatorHelper;
/**
* RegistrationController constructor.
*
* @param ControllerUtil $controllerUtil
* @param EncoderFactoryInterface $encoderFactory
* @param ReviewValidatorHelper $reviewValidatorHelper
*/
public function __construct(
ControllerUtil $controllerUtil,
EncoderFactoryInterface $encoderFactory,
ReviewValidatorHelper $reviewValidatorHelper
) {
parent::__construct($controllerUtil);
$this->encoderFactory = $encoderFactory;
$this->reviewValidatorHelper = $reviewValidatorHelper;
}
/**
* @Route("", name="app_registration_index")
* @Template("Registration/index.html.twig")
*
* @param Request $request HTTP request.
*
* @return array|RedirectResponse
*/
public function indexAction(Request $request)
{
$builder = new RegisterUserBuilder();
$builder->type = UserTypes::REGISTER_PARTY;
$user = $this->getUser();
$isNewUserOrSuperAdminUser = $user instanceof User && $user->isSuperAdmin() || !$user instanceof User;
$otherRegParty = $this->getEntityManager()->getRepository(Organization::class)->findOneBy(['name' => 'Other Registering Party (Organization)']);
$form = $this->createForm(
RegisterUserForm::class,
$builder,
[
'is_new' => true,
'is_munireg' => false,
'is_granted_admin' => false,
'is_non_registered' => true,
'is_captcha_for_register' => true,
'only_super_admins' => $isNewUserOrSuperAdminUser,
]
);
$form->handleRequest($request);
$isValidEmail = $this->isValidEmail($form['email']->getData());
if ($form->isSubmitted() && !$isValidEmail) {
$form->get('email')->addError(new FormError('Email already in use.'));
}
if ($form->isSubmitted() && $form->isValid() && $isValidEmail) {
$registerAsIndividual = (bool) $request->request->get('registerAsIndividual');
$builder->registerAsIndividual = $registerAsIndividual;
$this->createUser($form, $builder);
$detailUrl = $this->generateUrl('app_login');
/** @var Session $session */
$session = $request->getSession();
$session->getFlashBag()->add(
'message_register',
'Thank you for registering. Your account has been activated, and you can now have access to your registrations.'
);
return $this->redirect($detailUrl);
}
return ['builder' => $builder, 'form' => $form->createView(), 'otherRegParty' => $otherRegParty];
}
/**
* Creates user for both form's post Municipal and Register.
*
* @param Form $form
* @param UserBuilder $builder
* @return User
*/
private function createUser(Form $form, $builder)
{
$em = $this->getEntityManager();
$user = $builder->getEntity();
$encoder = $this->encoderFactory->getEncoder(User::class);
$salt = md5(uniqid(null, true));
$individualUserOrgId = $_ENV['INDIVIDUAL_USER_ORGANIZATION_ID'];
$encodedPassword = $encoder->encodePassword($form['password']->getData(), $salt);
$user->changePassword($encodedPassword);
ReflectionUtil::setInaccesibleProperty($user, 'salt', $salt);
if (!$user->getRegisterAsIndividual()) {
$user = $this->associateOrganization($user);
}
$formData = $form->getData();
if ($formData->registerAsIndividual) {
$user->setRegisterAsIndividual($formData->registerAsIndividual);
}
if ($builder->organization == null) {
if ($builder->registerAsIndividual === true) {
$individualOwnerOrg = $this->getEntityManager()->getRepository(Organization::class)->findOneBy(['id' => $individualUserOrgId]);
$user->setOrganization($individualOwnerOrg);
} else {
$organization = new Organization(
$user->getRequestedOrganization(),
$user->getEmail(),
$user->getAddressFirst(),
$user->getZipCode(),
$user->getCity(),
$user->getState(),
$user->getPhone(),
Null,
serialize(['www.munireg.com']),
);
$em->persist($organization);
$user->setOrganization($organization);
}
}
$em->persist($user);
$em->flush();
$this->dispatchEvent(AppEvents::USER_REGISTRATION_APPROVED, new UserEvent($user));
return $user;
}
/**
* @param $email
*
* @return bool
*/
private function isValidEmail($email)
{
$userCriteria = new UserSearchCriteria();
$userCriteria->email = $email;
$users = $this->getEntityManager()->getRepository(User::class)->countByCriteria($userCriteria);
$reviewCriteria = new ReviewSearchCriteria();
$reviewCriteria->email = $email;
$reviewCriteria->userRegistration = true;
$reviews = $this
->getEntityManager()
->getRepository(UserReview::class)
->countByCriteria($reviewCriteria);
$totalFound = $users + $reviews;
return ($totalFound == 0);
}
/**
* @param User $user
*
* @return User
*/
private function associateOrganization(User $user)
{
$email = $user->getEmail();
$arr = explode('@', $email);
$domain = $arr[1];
$criteria = new OrganizationSearchCriteria();
$criteria->domains = $domain;
$name = $user->getRequestedOrganization();
if ($name) {
$criteria->name = $name;
}
$count = $this->getEntityManager()->getRepository(Organization::class)->countByCriteria($criteria);
$organizations = $this->getEntityManager()->getRepository(Organization::class)->search($criteria);
if ($count == 1) {
$organization = $organizations[0];
$user->setOrganization($organization);
}
return $user;
}
}