<?php
namespace App\BackendBundle\Helper;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Exception\ForeignKeyConstraintViolationException;
use Doctrine\DBAL\Statement;
use Doctrine\ORM\EntityManagerInterface;
use Psr\Log\LoggerInterface;
use Ramsey\Uuid\Uuid;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
use Symfony\Component\Routing\Router;
use Symfony\Cmf\Component\Routing\ChainRouter;
use App\BackendBundle\Helper\MenuHelper;
use App\Entity\News;
use App\Entity\User;
use App\Entity\UserActivationLink;
use App\Entity\UserData;
use App\Entity\UserPasswordChange;
use App\Entity\UserSetting;
use App\Entity\UserRole;
use App\Entity\Person;
use DateTime;
use Symfony\Component\Security\Core\User\UserInterface;
class UserHelper
{
private EntityManagerInterface $em;
private Connection $connection;
private MenuHelper $menuHelper;
private TokenStorageInterface $securityTokenStorage;
private ChainRouter $router;
private LoggerInterface $logger;
private UserPasswordHasherInterface $passwordHasher;
public function __construct(
EntityManagerInterface $em,
MenuHelper $menuHelper,
TokenStorageInterface $tokenStorage,
UserPasswordHasherInterface $hasher,
ChainRouter $router,
LoggerInterface $logger
)
{
$this->em = $em;
$this->connection = $this->em->getConnection();
$this->menuHelper = $menuHelper;
$this->securityTokenStorage = $tokenStorage;
$this->passwordHasher = $hasher;
$this->router = $router;
$this->logger = $logger;
}
public function getUserByID($userID): ?User
{
return $this->em->getRepository(User::class)->findOneBy(array('id' => $userID));
}
public function getUserByEmail($email): ?User
{
return $this->em->getRepository(User::class)->findOneBy(array('email' => $email));
}
public function createUser($email, $password, $isActive = true, $roleNames = array()): User
{
$user = new User();
$uuid = Uuid::uuid7();
$user->setUuid($uuid);
$user->setUsername($email);
$encPassword = $this->passwordHasher->hashPassword($user, $password);
$user->setPassword($encPassword);
$user->setEmail($email);
$user->setIsActive($isActive);
$user->setCreatedAt(new DateTime());
$user->setLastLogin(null);
foreach ($roleNames as $roleName) {
$role = $this->getRoleByName($roleName);
if (!empty($role)) {
$user->addRole($role);
}
}
$this->em->persist($user);
$this->em->flush();
$this->createUserSetting($user);
return $user;
}
public function createPerson($firstname, $lastname, $sex, $birthday): Person
{
$person = new Person();
$person->setFirstname($firstname);
$person->setLastname($lastname);
$person->setBirthday($birthday);
$person->setSex($sex);
$this->em->persist($person);
$this->em->flush();
return $person;
}
public function createUserData(User $user, $person, $communication, $address): UserData
{
$userData = new UserData();
$userData->setUser($user);
$userData->setPerson($person);
$userData->setCommunication($communication);
$userData->setAddress($address);
$userData->setChangedAt(new DateTime());
$this->em->persist($userData);
$this->em->flush();
return $userData;
}
public function updateUser(User $user, $email, $password, $active): void
{
$user->setUsername($email);
$user->setEmail($email);
if (!empty($password)) {
$encPassword = $this->passwordHasher->hashPassword($user, $password);
$user->setPassword($encPassword);
}
$user->setIsActive($active);
$this->em->persist($user);
$this->em->flush();
}
public function updatePerson(Person $person, $gender, $firstname, $lastname): void
{
$person->setSex($gender);
$person->setFirstname($firstname);
$person->setLastname($lastname);
$this->em->persist($person);
$this->em->flush();
}
public function updatePersonTitles(Person $person, $arrTitles): void
{
$person->getTitles()->clear();
if (!empty($arrTitles)) {
foreach ($arrTitles as $title) {
$person->addTitle($title);
}
}
$this->em->persist($person);
$this->em->flush();
}
public function updateUserSetting(UserSetting $userSetting): UserSetting
{
$userSetting->setChangedAt(new \DateTime());
$this->em->persist($userSetting);
$this->em->flush();
return $userSetting;
}
public function getUserData(User $user): ?UserData
{
return $this->em->getRepository(UserData::class)->findOneBy(array('user' => $user));
}
public function getPersonById($id): ?Person
{
return $this->em->getRepository(Person::class)->findOneBy(array('id' => $id));
}
public function getRoleArray(): array
{
$allRoles = $this->em->getRepository(UserRole::class)->findAll();
$result = array();
/* @var $role UserRole */
foreach ($allRoles as $role) {
$roleName = $role->getName();
$result[$roleName] = $role;
}
return $result;
}
public function getRoleByID($roleID): ?UserRole
{
return $this->em->getRepository(UserRole::class)->findOneBy(array('id' => $roleID));
}
public function getRoleByName($name): ?UserRole
{
return $this->em->getRepository(UserRole::class)->findOneBy(array('name' => $name));
}
public function isUserLoggedIn()
{
$token = $this->securityTokenStorage->getToken();
if (empty($token)) {
return false;
}
$user = $token->getUser();
if ($user == null) {
return false;
}
if (is_string($user) && $user == 'anon.') {
return false;
}
return $user->hasRole('ROLE_USER');
}
public function getNewsUrl(User $user = null): ?string
{
if ($user == null) {
return null;
}
if ($user->isCompany()) {
return $this->router->generate('company_news_page');
}
if ($user->isBoPartner()) {
return $this->router->generate('bopartner_news_page');
}
if ($user->isTeacher()) {
return $this->router->generate('teacher_news_page');
}
if ($user->isDirector()) {
return $this->router->generate('director_news_page');
}
return null;
}
/* Bookmark system with symfony is disabled - bookmarks are only available with angular */
public function canBookmark(User $user = null): bool
{
return false;
}
public function getEncodedPassword($user, $plainPassword): string
{
return $this->passwordHasher->hashPassword($user, $plainPassword);
}
public function getUsersByRoleID($roleID)
{
$sqlText = 'SELECT user FROM App\Entity\User user
LEFT JOIN user.roles role
WHERE role.id = :roleID';
$query = $this->em->createQuery($sqlText);
$query->setParameter('roleID', $roleID);
return $query->getResult();
}
public function deleteUserProvider($userID): void
{
try {
$user = $this->em->getRepository(User::class)->findOneBy(array('id' => $userID));
$this->deleteProfiles($user);
$this->deleteUserData($user);
$this->deletePasswordChanges($user);
$this->em->remove($user);
$this->em->flush();
} catch (ForeignKeyConstraintViolationException $exc) {
throw $exc;
}
}
public function deleteUserTeacher($userID): void
{
try {
$user = $this->em->getRepository(User::class)->findOneBy(array('id' => $userID));
$this->deleteActivationLinks($user);
$this->deleteUserNews($user);
$this->deleteUserData($user);
$this->deletePasswordChanges($user);
$this->em->remove($user);
$this->em->flush();
} catch (ForeignKeyConstraintViolationException $exc) {
throw $exc;
}
}
private function deleteUserNews(User $user): void
{
$newsEntries = $this->em->getRepository(News::class)->findBy(array('receiverUser' => $user));
/* @var $newsEntry News */
foreach ($newsEntries as $newsEntry) {
$this->em->remove($newsEntry);
}
$this->em->flush();
}
private function deleteActivationLinks(User $user): void
{
$activationLinks = $this->em->getRepository(UserActivationLink::class)->findBy(array('user' => $user));
/* @var $activationLink UserActivationLink */
foreach ($activationLinks as $activationLink) {
$this->em->remove($activationLink);
}
$this->em->flush();
}
private function deleteUserData(User $user): void
{
$userData = $user->getUserData();
if ($userData == null) {
return;
}
$address = $userData->getAddress();
if ($address != null) {
$this->em->remove($address->getAddressLatLon());
$this->em->remove($address);
}
$comm = $userData->getCommunication();
if ($comm != null) {
$this->em->remove($comm);
}
$person = $userData->getPerson();
if ($comm != null) {
$this->em->remove($person);
}
$this->em->remove($userData);
$this->em->flush();
}
private function deletePasswordChanges(User $user): void
{
$userPasswordChanges = $this->em->getRepository(UserPasswordChange::class)->findBy(array('user' => $user));
if (count($userPasswordChanges) <= 0) {
return;
}
foreach ($userPasswordChanges as $userPasswordChange) {
$this->em->remove($userPasswordChange);
}
$this->em->flush();
}
/**
* @throws Exception
*/
private function deleteProfiles(User $user): void
{
$userID = $user->getId();
$this->deleteUserCompanyProfileNameRequests($userID);
$this->deleteUserCompanyProfileMappings($userID);
$this->deleteUserBoPartnerProfileNameRequests($userID);
$this->deleteUserBoPartnerProfileMappings($userID);
$this->deleteUserSchoolProfileNameRequests($userID);
$this->deleteUserSchoolProfileMappings($userID);
}
/**
* @throws Exception
*/
public function deleteUserCompanyProfileNameRequests($userID): void
{
$connection = $this->em->getConnection();
$sqlDelete = 'DELETE FROM company_profile_name_request WHERE user_id=:userID';
/* @var $deleteStmt Statement */
$deleteStmt = $connection->prepare($sqlDelete);
$deleteStmt->bindParam('userID', $userID);
$deleteStmt->execute();
}
/**
* @throws Exception
*/
public function deleteUserCompanyProfileMappings($userID): void
{
$connection = $this->em->getConnection();
$sqlDelete = 'DELETE FROM company_profile_mapping WHERE user_id=:userID';
/* @var $deleteStmt Statement */
$deleteStmt = $connection->prepare($sqlDelete);
$deleteStmt->bindParam('userID', $userID);
$deleteStmt->execute();
}
/**
* @throws Exception
*/
public function deleteUserBoPartnerProfileNameRequests($userID): void
{
$connection = $this->em->getConnection();
$sqlDelete = 'DELETE FROM bopartner_profile_name_request WHERE user_id=:userID';
/* @var $deleteStmt Statement */
$deleteStmt = $connection->prepare($sqlDelete);
$deleteStmt->bindParam('userID', $userID);
$deleteStmt->execute();
}
/**
* @throws Exception
*/
public function deleteUserBoPartnerProfileMappings($userID): void
{
$connection = $this->em->getConnection();
$sqlDelete = 'DELETE FROM bopartner_profile_mapping WHERE user_id=:userID';
/* @var $deleteStmt Statement */
$deleteStmt = $connection->prepare($sqlDelete);
$deleteStmt->bindParam('userID', $userID);
$deleteStmt->execute();
}
/**
* @throws Exception
*/
public function deleteUserSchoolProfileNameRequests($userID): void
{
$connection = $this->em->getConnection();
$sqlDelete = 'DELETE FROM school_profile_name_request WHERE user_id=:userID';
/* @var $deleteStmt Statement */
$deleteStmt = $connection->prepare($sqlDelete);
$deleteStmt->bindParam('userID', $userID);
$deleteStmt->execute();
}
/**
* @throws Exception
*/
public function deleteUserSchoolProfileMappings($userID): void
{
$connection = $this->em->getConnection();
$sqlDelete = 'DELETE FROM school_director_mapping WHERE user_id=:userID';
/* @var $deleteStmt Statement */
$deleteStmt = $connection->prepare($sqlDelete);
$deleteStmt->bindParam('userID', $userID);
$deleteStmt->execute();
}
public function generateToken(): string
{
$now = new DateTime();
$str = $now->format('d-m-Y H:i:s ');
$str .= 'berufsreisetoken';
$str .= rand(0, 1000);
$hashAlgo = 'sha256';
return hash($hashAlgo, $str);
}
public function toggleUserActive(User $user): User
{
$currentState = $user->getIsActive();
$user->setIsActive(!$currentState);
$this->em->persist($user);
$this->em->flush();
return $user;
}
public function createUserSetting(User $user = null): ?UserSetting
{
if (empty($user)) {
return null;
}
$userSetting = new UserSetting();
$userSetting->setUser($user);
$selectedUserRole = $this->menuHelper->getDefaultUserRole($user);
$userSetting->setSelectedUserRole($selectedUserRole);
$userSetting->setCreatedAt(new DateTime());
$this->em->persist($userSetting);
$this->em->flush();
return $userSetting;
}
/**
* @throws Exception
*/
public function addUserRole(User $user = null, string $roleText = '')
{
if (empty($user)) {
return null;
}
$userID = $user->getId();
$hasRole = $user->hasRole($roleText);
if ($hasRole) {
return null;
}
/* @var $role UserRole */
$role = $this->getRoleByName($roleText);
if (empty($role)) {
return null;
}
$roleID = $role->getId();
$connection = $this->em->getConnection();
$insertSQL = "INSERT INTO user_role_mapping (user_id, user_role_id) VALUES(:userID, :roleID)";
$stmt = $connection->prepare($insertSQL);
$stmt->bindValue('userID', $userID);
$stmt->bindValue('roleID', $roleID);
$stmt->execute();
}
/**
* @throws Exception
*/
public function removeUserRole(User $user = null, string $roleText = '')
{
if (empty($user)) {
return null;
}
$userID = $user->getId();
$hasRole = $user->hasRole($roleText);
if (!$hasRole) {
return null;
}
/* @var $role UserRole */
$role = $this->getRoleByName($roleText);
if (empty($role)) {
return null;
}
$roleID = $role->getId();
$connection = $this->em->getConnection();
$deleteSQL = "DELETE FROM user_role_mapping WHERE user_id=:userID AND user_role_id=:roleID";
$stmt = $connection->prepare($deleteSQL);
$stmt->bindValue('userID', $userID);
$stmt->bindValue('roleID', $roleID);
$stmt->execute();
}
public function isPasswordValid(User $user, $plaintextPassword): bool
{
return $this->passwordHasher->isPasswordValid($user, $plaintextPassword);
}
/**
* @throws Exception
*/
public function updateLastLogin(?UserInterface $user)
{
if ($user == null) {
return;
}
$userId=$user->getId();
$updateSQL = "UPDATE user SET last_login = NOW() WHERE id=:userID";
$stmt = $this->connection->prepare($updateSQL);
$stmt->bindValue('userID', $userId);
$stmt->execute();
}
}