<?php
namespace App\Entity;
use App\Entity\ConversationMessage\ConversationMessageAttachmentFile;
use App\Entity\ExternalPartner\ExternalPartner;
use App\Entity\ExternalPartner\IntegratedExternalPartnerCustomer;
use App\Entity\ExternalPartner\UserAdditionalInfo;
use App\Entity\Membership\BillwerkContract;
use App\Entity\Membership\RecurrentJobBooking;
use App\Entity\Profile\JoboffererProfile;
use App\Entity\Profile\JobseekerProfile;
use App\Exception\InvalidEmailException;
use App\Service\MailService;
use App\Service\Membership\BillwerkSynchronizationService;
use App\Utility\DateTimeUtility;
use App\Utility\ReflectionHelper;
use DateTime;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Exception;
use FOS\UserBundle\Model\User as FOSUser;
use FrontendSpaApi\Entity\ApiKey as FrontendSpaApiKey;
use InvalidArgumentException;
use JanusHercules\Membership\Domain\Entity\FlexMembershipRecurrentJobSlot;
use MobileAppApi\Entity\ApiKey as MobileAppApiKey;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
*
* @ORM\Table(
* name="users",
* indexes={
*
* @ORM\Index(name="created_at_idx", columns={"created_at"}),
* @ORM\Index(name="email_idx", columns={"email"}),
* @ORM\Index(name="username_idx", columns={"username"})
* }
* )
*/
class User extends FOSUser
{
public const string ROLE_NAME_JOBOFFERER = 'ROLE_JOBOFFERER';
public const string ROLE_NAME_JOBSEEKER = 'ROLE_JOBSEEKER';
public const string ROLE_NAME_ADMIN = 'ROLE_ADMIN';
// Can access all admin areas, but cannot modify or delete stuff
public const string ROLE_NAME_ADMIN_READONLY = 'ROLE_ADMIN_READONLY';
// Can access the user admin page only, and cannot modify or delete users there
public const string ROLE_NAME_ADMIN_PROFILEVERIFIER = 'ROLE_ADMIN_PROFILEVERIFIER';
// Only users with this role are allowed to change data related to content distribution (e.g. CPC info in feeds)
public const string ROLE_NAME_ADMIN_CONTENT_DISTRIBUTION = 'ROLE_ADMIN_CONTENT_DISTRIBUTION';
// Only users with this role are allowed to modify data on blacklisting portal
public const string ROLE_NAME_ADMIN_BLACKLISTING = 'ROLE_ADMIN_BLACKLISTING';
public const string ROLE_NAME_ADMIN_USER_CREATOR = 'ROLE_ADMIN_USER_CREATOR';
// No admin rights, but flagged features are "on" for users with this role
public const string ROLE_NAME_EXTERNAL_FEATURE_TESTER = 'ROLE_EXTERNAL_FEATURE_TESTER';
// No admin rights, but can browse wanted jobs and other stuff through a dedicated interface
public const string ROLE_NAME_NAVIGATOR = 'ROLE_NAVIGATOR';
// No admin rights, but can browse the quota portal
public const string ROLE_NAME_INTEGRATED_EXTERNAL_PARTNER_MANAGER = 'ROLE_INTEGRATED_EXTERNAL_PARTNER_MANAGER';
// For normal jobofferer users that "simulate" an external partner (e.g. by linking external application urls)
public const string ROLE_NAME_QUASI_EXTERNAL_PARTNER = 'ROLE_QUASI_EXTERNAL_PARTNER';
public const string ROLE_NAME_CUSTOMER_SPECIFIC_EXTERNAL_PARTNER_EVENT_AGGREGATIONS_READER = 'ROLE_CUSTOMER_SPECIFIC_EXTERNAL_PARTNER_EVENT_AGGREGATIONS_READER';
public const string ROLE_NAME_SPECIFIC_CUSTOMER_CAMPAIGNS_READER = 'ROLE_SPECIFIC_CUSTOMER_CAMPAIGNS_READER';
public const string ROLE_NAME_SPECIFIC_CUSTOMER_CAMPAIGNS_WRITER = 'ROLE_SPECIFIC_CUSTOMER_CAMPAIGNS_WRITER';
public const string ROLE_NAME_SPECIFIC_CUSTOMER_GAUGES_READER = 'ROLE_SPECIFIC_CUSTOMER_GAUGES_READER';
public const string ROLE_NAME_EXTERNAL_JOB_POSTING_CRAWLER_MANAGER = 'ROLE_EXTERNAL_JOB_POSTING_CRAWLER_MANAGER';
public const string ROLE_NAME_SALES_RECRUITER = 'ROLE_SALES_RECRUITER';
public const string ROLE_NAME_RECURRENT_JOBS_MANAGER = 'ROLE_RECURRENT_JOBS_MANAGER';
public const string ROLE_NAME_AGENTUR_FUER_ARBEIT_MANAGER = 'ROLE_AGENTUR_FUER_ARBEIT_MANAGER';
public const string ROLE_NAME_SELF_SERVICE_CAMPAIGN_ADMIN = 'ROLE_SELF_SERVICE_CAMPAIGN_ADMIN';
public const string ROLE_NAME_MEMBERSHIP_ACTIONS_TESTER = 'ROLE_MEMBERSHIP_ACTIONS_TESTER';
public const string ROLE_NAME_APPLICATION_APPOINTMENT_SCHEDULING_MANAGER = 'ROLE_APPLICATION_APPOINTMENT_SCHEDULING_MANAGER';
public const string ROLE_NAME_APPLICATION_APPOINTMENT_SCHEDULING_MANAGER_READONLY = 'ROLE_APPLICATION_APPOINTMENT_SCHEDULING_MANAGER_READONLY';
public const int USER_TYPE_JOBOFFERER = 0;
public const int USER_TYPE_JOBSEEKER = 1;
public const int CREATED_VIA_JOBOO_REGISTRATION = 0;
public const int CREATED_VIA_RECRUIT_DL_RECURRENT_JOB_LANDINGPAGE = 1;
public const int CREATED_VIA_AN_EXTERNAL_PARTNER_SERVICE = 8;
public const int CREATED_VIA_RECURRENT_JOBS_MASS_EDITOR = 11;
public const int CREATED_VIA_JOBOO_RECURRENT_JOB_LANDINGPAGE = 12;
public const int CREATED_VIA_JOBOO_ONLINE_RECURRENT_JOB_LANDINGPAGE = 14;
public const int CREATED_VIA_GOOGLE_IDENTITY_OAUTH2 = 16;
public const int CREATED_VIA_GOOGLE_IDENTITY_GSI = 17;
public const int CREATED_VIA_MOBILE_APP = 22;
public const int CREATED_VIA_FACEBOOK_LEAD_USER_CREATION = 23;
public const int CREATED_VIA_CAMPAIGN_WUNSCHJOBS_JOBSEEKER_FLOW = 24;
public const int CREATED_VIA_DIGITAL_ESTATE_CONTENT = 25;
public const int CREATED_VIA_INCOMING_APPLICATION_PERSPECTIVE = 26;
public const int CREATED_VIA_INCOMING_REGISTRATION_PERSPECTIVE = 27;
public const int CREATED_VIA_WANTED_JOBS_SEARCH_ANONYMOUS_USER_FORM = 28;
public const int CREATED_VIA_RECURRENT_JOB_DETAILPAGE_ANONYMOUS_USER = 29;
public const int CREATED_VIA_APPLICATION_APPOINTMENT_SCHEDULING_SERVICE = 30;
public const int CREATED_VIA_ACTIVATE_JOBRADAR_IN_ANONYMOUS_JOB_SEARCH = 31;
public const int CREATED_VIA_CUSTOMER_LANDINGPAGE_ANONYMOUS_USER = 32;
public const int CREATED_VIA_EMAIL_QUICK_REGISTRATION = 33;
/**
* @throws Exception
*/
public function __construct(?string $id = null)
{
parent::__construct();
if (!is_null($id)) {
$this->id = $id;
}
$this->setIsGoGastro(false);
$this->setIsLockedByAdmin(false);
$this->jobseekerProfiles = new ArrayCollection();
$this->joboffererProfiles = new ArrayCollection();
$this->onetimeLoginTokens = new ArrayCollection();
$this->notificationSettings = new ArrayCollection();
$this->createdAt = DateTimeUtility::createDateTimeUtc();
$this->createdVia = self::CREATED_VIA_JOBOO_REGISTRATION;
$this->billwerkContracts = new ArrayCollection();
$this->emailDeliveryNotifications = new ArrayCollection();
$this->notificationStates = new ArrayCollection();
$this->externalPartnerUserAdditionalInfos = new ArrayCollection();
$this->cleverpushSubscriptions = new ArrayCollection();
$this->mobileAppApiKeys = new ArrayCollection();
$this->frontendSpaApiKeys = new ArrayCollection();
$this->integratedExternalPartnerCustomers = new ArrayCollection();
$this->recurrentJobBookings = new ArrayCollection();
$this->userAdditionalInfos = new ArrayCollection();
$this->recurrentJobSlots = new ArrayCollection();
}
/**
* @ORM\GeneratedValue(strategy="CUSTOM")
*
* @ORM\CustomIdGenerator(class="App\Utility\DatabaseIdGenerator")
*
* @ORM\Column(name="id", type="guid")
*
* @ORM\Id
*/
protected $id;
public function getId(): ?string
{
return $this->id;
}
/**
* @var bool
*
* @ORM\Column(name="is_go_gastro", type="boolean", nullable=false)
*/
protected $isGoGastro;
public function isGoGastro(): bool
{
return $this->isGoGastro;
}
public function setIsGoGastro(bool $isGoGastro): void
{
$this->isGoGastro = $isGoGastro;
}
/**
* @Assert\Email(
* mode="strict",
* groups={"Registration"}
* )
*/
protected $email;
/**
* @var DateTime
*
* @ORM\Column(name="created_at", type="datetime", nullable=false)
*/
protected $createdAt;
/**
* @return DateTime
*/
public function getCreatedAt()
{
return $this->createdAt;
}
public function setCreatedAt(DateTime $createdAt)
{
$this->createdAt = $createdAt;
}
/**
* @var bool
*
* @ORM\Column(name="created_via", type="integer", nullable=false)
*/
protected $createdVia;
/** @throws Exception */
public function setCreatedVia(int $createdVia): void
{
if (!ReflectionHelper::hasConstWithValue(self::class, 'CREATED_VIA_', $createdVia)) {
throw new Exception("Not a valid value for createdVia: '{$createdVia}'.");
}
$this->createdVia = $createdVia;
}
public function getCreatedVia(): int
{
return $this->createdVia;
}
/**
* @var ?DateTime
*
* @ORM\Column(name="lastseen_at", type="datetime", nullable=true)
*/
protected $lastseenAt;
public function getLastseenAt(): ?DateTime
{
return $this->lastseenAt;
}
public function setLastseenAt(?DateTime $lastseenAt)
{
$this->lastseenAt = $lastseenAt;
}
/**
* @var ExternalPartner|null
*
* @ORM\ManyToOne(targetEntity="App\Entity\ExternalPartner\ExternalPartner", inversedBy="users", cascade={"persist"})
*
* @ORM\JoinColumn(name="external_partners_id", referencedColumnName="id", nullable=true, onDelete="CASCADE")
*/
protected $externalPartner;
public function getExternalPartner(): ?ExternalPartner
{
return $this->externalPartner;
}
/** @throws Exception */
public function setExternalPartner(?ExternalPartner $externalPartner, bool $mustBeJobofferer = true): void
{
if (!is_null($externalPartner) && $mustBeJobofferer && !$this->isJobofferer()) {
throw new Exception("Setting an external partner on user {$this->getId()} is not possible because this user is not a jobofferer.");
}
if (!is_null($externalPartner)) {
foreach ($this->getJoboffererProfiles() as $joboffererProfile) {
foreach ($joboffererProfile->getRecurrentJobs() as $recurrentJob) {
if (!is_null($recurrentJob->getQuota())) {
if ($recurrentJob->getQuota()->getIntegratedExternalPartnerCustomer()->getExternalPartner()->getId() !== $externalPartner->getId()) {
throw new Exception("Setting the external partner {$externalPartner->getId()} on user {$this->getId()} is not possible because this user has a recurrent job with a quota linked to external partner {$recurrentJob->getQuota()->getIntegratedExternalPartnerCustomer()->getExternalPartner()->getId()}.");
}
}
}
}
}
$this->externalPartner = $externalPartner;
}
/**
* @ORM\ManyToMany(targetEntity="App\Entity\ExternalPartner\IntegratedExternalPartnerCustomer")
*
* @ORM\JoinTable(name="users_integrated_external_partner_customers",
* joinColumns={@ORM\JoinColumn(name="users_id", referencedColumnName="id", unique=true)},
* inverseJoinColumns={@ORM\JoinColumn(name="integrated_external_partner_customers_id", referencedColumnName="id", onDelete="CASCADE")}
* )
*
* Note: The naming here is potentially misleading.
* A user can only be linked to exactly zero or exactly one integrated external partner customer,
* but not to multiple integrated external partner customers!
*
* The reason that $integratedExternalPartnerCustomers is a "plural" collection is only
* due to the fact that upon implementation of this relationship, we wanted to avoid extending
* the large users table with another column, and instead use a separate table.
*/
protected Collection $integratedExternalPartnerCustomers;
public function getIntegratedExternalPartnerCustomer(): ?IntegratedExternalPartnerCustomer
{
if ($this->integratedExternalPartnerCustomers->count() === 0) {
return null;
}
return $this->integratedExternalPartnerCustomers->first();
}
/** @throws Exception */
public function setIntegratedExternalPartnerCustomer(?IntegratedExternalPartnerCustomer $customer, bool $mustBeJobofferer = true): void
{
if (!is_null($customer) && $mustBeJobofferer && !$this->isJobofferer()) {
throw new Exception("Setting the integrated external partner customer {$customer->getInternalId()} on user {$this->getId()} is not possible because this user is not a jobofferer.");
}
if (!is_null($customer)) {
foreach ($this->getJoboffererProfiles() as $joboffererProfile) {
foreach ($joboffererProfile->getRecurrentJobs() as $recurrentJob) {
if (!is_null($recurrentJob->getQuota())) {
if ($recurrentJob->getQuota()->getIntegratedExternalPartnerCustomer()->getId() !== $customer->getId()) {
throw new Exception("Setting the integrated external partner customer {$customer->getInternalId()} on user {$this->getId()} is not possible because this user has a recurrent job with a quota linked to customer {$recurrentJob->getQuota()->getIntegratedExternalPartnerCustomer()->getInternalId()}.");
}
}
}
}
}
if (!is_null($this->getExternalPartner())) {
if ($this->getExternalPartner()->getId() !== $customer->getExternalPartner()->getId()) {
throw new Exception("Setting the integrated external partner customer {$customer->getInternalId()} on user {$this->getId()} is not possible because this user is linked to external partner {$this->getExternalPartner()->getId()} while the customer belongs to external partner {$customer->getExternalPartner()->getId()}.");
}
}
$this->integratedExternalPartnerCustomers->clear();
$this->integratedExternalPartnerCustomers->add($customer);
}
/**
* @var JobseekerProfile[]|Collection
*
* @ORM\OneToMany(targetEntity="\App\Entity\Profile\JobseekerProfile", mappedBy="user", cascade={"persist", "remove"})
*/
protected $jobseekerProfiles;
public function addJobseekerProfile(JobseekerProfile $jobseekerProfile): void
{
$this->jobseekerProfiles[] = $jobseekerProfile;
}
public function getJobseekerProfiles()
{
return $this->jobseekerProfiles;
}
/**
* @var JoboffererProfile[]|Collection
*
* @ORM\OneToMany(targetEntity="\App\Entity\Profile\JoboffererProfile", mappedBy="user", cascade={"persist", "remove"})
*/
protected $joboffererProfiles;
public function addJoboffererProfile(JoboffererProfile $joboffererProfile): void
{
$this->joboffererProfiles[] = $joboffererProfile;
}
public function getJoboffererProfiles()
{
return $this->joboffererProfiles;
}
/**
* @var OnetimeLoginToken|Collection
*
* @ORM\OneToMany(targetEntity="\App\Entity\OnetimeLoginToken", mappedBy="user", cascade={"persist", "remove"})
*/
protected $onetimeLoginTokens;
public function addOnetimeLoginToken(OnetimeLoginToken $onetimeLoginToken): void
{
$this->onetimeLoginTokens[] = $onetimeLoginToken;
}
public function getOnetimeLoginTokens()
{
return $this->onetimeLoginTokens;
}
/**
* @var FirebaseToken[]|Collection
*
* @ORM\OneToMany(targetEntity="\App\Entity\FirebaseToken", mappedBy="user", cascade={"persist", "remove"})
*/
protected $firebaseTokens;
public function addFirebaseTokens(FirebaseToken $firebaseToken): void
{
$this->firebaseTokens[] = $firebaseToken;
}
public function getFirebaseTokens(): Collection
{
return $this->firebaseTokens;
}
public function canReceiveMobileAppPushNotifications(): bool
{
return
!$this->isLocked()
&& !$this->isPaused()
&& sizeof($this->firebaseTokens) > 0
;
}
/**
* @var NotificationSetting|Collection
*
* @ORM\OneToMany(targetEntity="\App\Entity\NotificationSetting", mappedBy="user", cascade={"persist", "remove"})
*/
protected $notificationSettings;
public function addNotificationSetting(NotificationSetting $notificationSetting): void
{
$this->notificationSettings[] = $notificationSetting;
}
public function getNotificationSettings()
{
return $this->notificationSettings;
}
/**
* @var NotificationState|Collection
*
* @ORM\OneToMany(targetEntity="\App\Entity\NotificationState", mappedBy="user", cascade={"persist", "remove"})
*/
protected $notificationStates;
public function addNotificationState(NotificationState $notificationState): void
{
$this->notificationStates[] = $notificationState;
}
public function getNotificationStates()
{
return $this->notificationStates;
}
/**
* @var ConversationMessageAttachmentFile[]|Collection
*
* @ORM\OneToMany(targetEntity="\App\Entity\ConversationMessage\ConversationMessageAttachmentFile", mappedBy="user", cascade={"persist", "remove"})
*/
protected $conversationMessageAttachmentFiles;
/**
* @var CleverpushSubscription[]|Collection|null
*
* @ORM\OneToMany(targetEntity="App\Entity\CleverpushSubscription", mappedBy="user", cascade={"persist", "remove"})
*/
protected $cleverpushSubscriptions;
public function getCleverpushSubscriptions()
{
return $this->cleverpushSubscriptions;
}
public function addCleverpushSubscription(CleverpushSubscription $cleverpushSubscription): void
{
$this->cleverpushSubscriptions[] = $cleverpushSubscription;
}
/**
* @var string
*
* @ORM\Column(name="encodedRegistrationCarryThroughData", type="string", length=8192, nullable=true)
*/
protected $encodedRegistrationCarryThroughData;
public function setEncodedRegistrationCarryThroughData(string $data): void
{
$this->encodedRegistrationCarryThroughData = $data;
}
public function getEncodedRegistrationCarryThroughData()
{
return $this->encodedRegistrationCarryThroughData;
}
/**
* @var bool
*
* @ORM\Column(name="is_locked_by_admin", type="boolean", nullable=false)
*/
protected $isLockedByAdmin;
public function isLockedByAdmin(): bool
{
return $this->isLockedByAdmin;
}
public function setIsLockedByAdmin(bool $isLockedByAdmin)
{
$this->isLockedByAdmin = $isLockedByAdmin;
}
public function isLocked(): bool
{
return $this->isLockedByAdmin;
}
/**
* @var bool
*
* @ORM\Column(name="has_system_generated_password", type="boolean", nullable=false)
*/
protected $hasSystemGeneratedPassword;
public function hasSystemGeneratedPassword(): bool
{
return $this->hasSystemGeneratedPassword;
}
public function setHasSystemGeneratedPassword(bool $hasSystemGeneratedPassword): void
{
$this->hasSystemGeneratedPassword = $hasSystemGeneratedPassword;
}
/**
* @var ?string
*
* @ORM\Column(name="billwerk_customer_id", type="text", length=512, nullable=true)
*
* In a sense, this attribute is a bit redundant, but it's still here for historic/backwards-compatibility reasons.
*
* In general, one Joboo User can and will be linked to multiple Billwerk Customers; it's not a 1:1
* relation. This is because our Billwerk order/checkout process currently isn't capable of recognizing
* that a Membership contract is about to get purchased from an already existing Billwerk customer.
*
* This means that every order/checkpout process creates a new Customer at Billwerk.
*
* Also @see BillwerkContract: multiple rows can be linked to the same users_id.
*
* Therefore, this attribute means "the customer of the contract that is currently relevant for us in
* terms of Membership", which in turn is defined as "the customer from the Contract we got
* synced from Billwerk most recently for the first time". In other words: whenever a new "ContractCreated"
* webhook comes in, and whenever a Contract disappears (annulation), this value changes.
*
* @see BillwerkSynchronizationService::mapUserToBillwerkCustomerIdOfLatestContract() to see how this
* attribute is determined and set.
*/
protected $billwerkCustomerId;
public function setBillwerkCustomerId(?string $billwerkCustomerId)
{
$this->billwerkCustomerId = $billwerkCustomerId;
}
public function getBillwerkCustomerId(): ?string
{
return $this->billwerkCustomerId;
}
/**
* @var BillwerkContract[]|ArrayCollection|array
*
* @ORM\OneToMany(targetEntity="App\Entity\Membership\BillwerkContract", mappedBy="user", cascade={"persist", "remove"}, fetch="EAGER")
*
* @ORM\OrderBy({"createdAt": "ASC"})
*/
protected $billwerkContracts;
/**
* @return BillwerkContract[]|array|ArrayCollection
*/
public function getBillwerkContracts()
{
return $this->billwerkContracts;
}
/**
* @param BillwerkContract[]|array|ArrayCollection $billwerkContracts
*/
public function setBillwerkContracts($billwerkContracts): void
{
$this->billwerkContracts = $billwerkContracts;
}
/**
* @var ?string
*
* @deprecated This has been deprecated in favor of the MobileAppApiKey[] entity below
*
* @ORM\Column(name="mobile_app_api_key_id", type="text", length=63, nullable=true)
*/
protected $mobileAppApiKeyId;
/**
* @var MobileAppApiKey[]|ArrayCollection|array
*
* @ORM\OneToMany(targetEntity="MobileAppApi\Entity\ApiKey", mappedBy="user", cascade={"persist", "remove"}, fetch="EXTRA_LAZY")
*/
protected $mobileAppApiKeys;
/** @return MobileAppApiKey[]|ArrayCollection|array */
public function getMobileAppApiKeys(): Collection
{
return $this->mobileAppApiKeys;
}
public function addMobileAppApiKey(MobileAppApiKey $newApiKey): void
{
foreach ($this->mobileAppApiKeys as $apiKey) {
if ($apiKey->getId() === $newApiKey->getId()) {
throw new InvalidArgumentException("A mobile app api key with id '{$apiKey->getId()}' is already attached to this user.");
}
}
$this->mobileAppApiKeys->add($newApiKey);
}
/**
* @var FrontendSpaApiKey[]|ArrayCollection|array
*
* @ORM\OneToMany(targetEntity="FrontendSpaApi\Entity\ApiKey", mappedBy="user", cascade={"persist", "remove"}, fetch="EXTRA_LAZY")
*/
protected $frontendSpaApiKeys;
/** @return FrontendSpaApiKey[]|ArrayCollection|array */
public function getFrontendSpaApiKeys(): Collection
{
return $this->frontendSpaApiKeys;
}
public function addFrontendSpaApiKey(FrontendSpaApiKey $newApiKey): void
{
foreach ($this->frontendSpaApiKeys as $apiKey) {
if ($apiKey->getId() === $newApiKey->getId()) {
throw new InvalidArgumentException("A frontend spa api key with id '{$apiKey->getId()}' is already attached to this user.");
}
}
$this->frontendSpaApiKeys->add($newApiKey);
}
/**
* @var DirectLoginAuthKey[]|ArrayCollection|array
*
* @ORM\OneToMany(targetEntity="App\Entity\DirectLoginAuthKey", mappedBy="user", cascade={"persist", "remove"}, fetch="EXTRA_LAZY")
*/
protected $directLoginAuthKeys;
/** @return DirectLoginAuthKey[]|ArrayCollection|array */
public function getDirectLoginAuthKeys(): Collection
{
return $this->directLoginAuthKeys;
}
public function addDirectLoginAuthKey(DirectLoginAuthKey $newAuthKey): void
{
foreach ($this->directLoginAuthKeys as $authKey) {
if ($authKey->getId() === $newAuthKey->getId()) {
throw new InvalidArgumentException("A mobile direct login auth key with id '{$authKey->getId()}' is already attached to this user.");
}
}
$this->directLoginAuthKeys->add($newAuthKey);
}
/**
* @var EmailDeliveryNotification[]|ArrayCollection|array
*
* @ORM\OneToMany(targetEntity="App\Entity\EmailDeliveryNotification", mappedBy="user", cascade={"persist", "remove"}, fetch="EXTRA_LAZY")
*/
protected $emailDeliveryNotifications;
/**
* @return EmailDeliveryNotification[]|array|ArrayCollection
*/
public function getEmailDeliveryNotifications()
{
return $this->emailDeliveryNotifications;
}
/**
* @param EmailDeliveryNotification[]|array|ArrayCollection $emailDeliveryNotifications
*/
public function setEmailDeliveryNotifications($emailDeliveryNotifications): void
{
$this->emailDeliveryNotifications = $emailDeliveryNotifications;
}
// This allows registration using only email
public function setEmail($email)
{
if (!is_null($email) && $email !== '' && !MailService::emailAddressIsValidForMailer($email)) {
throw new InvalidEmailException("E-mail {$email} is not valid for SwiftMailer.");
}
$email = is_null($email) ? '' : $email;
parent::setEmail($email);
$this->setUsername($email);
return $this;
}
public function hasAtLeastOneAdminRole(): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN)
|| $this->hasRole(self::ROLE_NAME_ADMIN_READONLY)
|| $this->hasRole(self::ROLE_NAME_ADMIN_PROFILEVERIFIER)
|| $this->hasRole(self::ROLE_NAME_ADMIN_USER_CREATOR)
|| $this->hasRole(self::ROLE_NAME_ADMIN_CONTENT_DISTRIBUTION)
|| $this->hasRole(self::ROLE_NAME_ADMIN_BLACKLISTING)
) {
return true;
} else {
return false;
}
}
public function isNavigator(): bool
{
return $this->hasRole(self::ROLE_NAME_NAVIGATOR);
}
public function isIntegratedExternalPartnerManager(): bool
{
return $this->hasRole(self::ROLE_NAME_INTEGRATED_EXTERNAL_PARTNER_MANAGER);
}
public function isAllowedToUseFlaggedFeatures(): bool
{
if ($this->hasAtLeastOneAdminRole() || $this->hasRole(self::ROLE_NAME_EXTERNAL_FEATURE_TESTER)) {
return true;
} else {
return false;
}
}
public function isAllowedToRemoveUsers(): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN)) {
return true;
} else {
return false;
}
}
public function isAllowedToModifyUsers(): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN)) {
return true;
} else {
return false;
}
}
public function isAllowedToEditClearings(): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN)) {
return true;
} else {
return false;
}
}
public function isAllowedToEditFAQs(): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN)) {
return true;
} else {
return false;
}
}
public function isAllowedToReadRecurrentJobsOverviewData(): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN)
|| $this->hasRole(self::ROLE_NAME_ADMIN_READONLY)
) {
return true;
} else {
return false;
}
}
public function isAllowedToModifyRecurrentJobs(): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN)
|| $this->hasRole(self::ROLE_NAME_RECURRENT_JOBS_MANAGER)
) {
return true;
} else {
return false;
}
}
public function isAllowedToLogIntoUsers(): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN)
|| $this->hasRole(self::ROLE_NAME_ADMIN_READONLY)
) {
return true;
} else {
return false;
}
}
public function isAllowedToReadContentDistributionData(): bool
{
return $this->isAllowedToModifyContentDistributionData();
}
public function isAllowedToModifyContentDistributionData(): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN_CONTENT_DISTRIBUTION)
) {
return true;
} else {
return false;
}
}
public function isAllowedToModifyBlacklistingData(): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN_BLACKLISTING)
) {
return true;
} else {
return false;
}
}
public function isAllowedToCreateUsers(): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN_USER_CREATOR)
) {
return true;
} else {
return false;
}
}
public function isAllowedToModifyAgenturFuerArbeitData(): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN)
|| $this->hasRole(self::ROLE_NAME_AGENTUR_FUER_ARBEIT_MANAGER)
) {
return true;
} else {
return false;
}
}
public function isAllowedToViewExternalPartnerCustomerReporting(): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN_READONLY)
|| $this->hasRole(self::ROLE_NAME_ADMIN)
|| (
$this->hasRole(self::ROLE_NAME_CUSTOMER_SPECIFIC_EXTERNAL_PARTNER_EVENT_AGGREGATIONS_READER)
&& $this->hasRole(self::ROLE_NAME_SPECIFIC_CUSTOMER_CAMPAIGNS_READER)
&& $this->hasRole(self::ROLE_NAME_SPECIFIC_CUSTOMER_GAUGES_READER)
)
) {
return true;
}
return false;
}
public function isAllowedToReadExternalPartnerEventAggregationsOfCustomer(IntegratedExternalPartnerCustomer $customer): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN_READONLY)
|| $this->hasRole(self::ROLE_NAME_ADMIN)
) {
return true;
}
if ($this->hasRole(self::ROLE_NAME_CUSTOMER_SPECIFIC_EXTERNAL_PARTNER_EVENT_AGGREGATIONS_READER)) {
if (!is_null($this->getIntegratedExternalPartnerCustomer())
&& $this->getIntegratedExternalPartnerCustomer()->getId() === $customer->getId()
) {
return true;
}
}
return false;
}
public function isAllowedToReadCampaignsOfCustomer(IntegratedExternalPartnerCustomer $customer): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN_READONLY)
|| $this->hasRole(self::ROLE_NAME_ADMIN)
) {
return true;
}
if ($this->hasRole(self::ROLE_NAME_SPECIFIC_CUSTOMER_CAMPAIGNS_READER)) {
if (!is_null($this->getIntegratedExternalPartnerCustomer())
&& $this->getIntegratedExternalPartnerCustomer()->getId() === $customer->getId()
) {
return true;
}
}
return false;
}
public function isAllowedToWriteCampaignsOfCustomer(IntegratedExternalPartnerCustomer $customer): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN)) {
return true;
}
if ($this->hasRole(self::ROLE_NAME_SPECIFIC_CUSTOMER_CAMPAIGNS_WRITER)) {
if (!is_null($this->getIntegratedExternalPartnerCustomer())
&& $this->getIntegratedExternalPartnerCustomer()->getId() === $customer->getId()
) {
return true;
}
}
return false;
}
public function isAllowedToReadGaugesOfCustomer(IntegratedExternalPartnerCustomer $customer): bool
{
if ($this->hasRole(self::ROLE_NAME_ADMIN_READONLY)
|| $this->hasRole(self::ROLE_NAME_ADMIN)
) {
return true;
}
if ($this->hasRole(self::ROLE_NAME_SPECIFIC_CUSTOMER_GAUGES_READER)) {
if (!is_null($this->getIntegratedExternalPartnerCustomer())
&& $this->getIntegratedExternalPartnerCustomer()->getId() === $customer->getId()
) {
return true;
}
}
return false;
}
public function isJobseeker(): bool
{
if ($this->hasRole(self::ROLE_NAME_JOBSEEKER)) {
return true;
} else {
return false;
}
}
public function isJobofferer(): bool
{
if ($this->hasRole(self::ROLE_NAME_JOBOFFERER)) {
return true;
} else {
return false;
}
}
public function isQuasiExternalPartner(): bool
{
if ($this->hasRole(self::ROLE_NAME_QUASI_EXTERNAL_PARTNER)) {
return true;
} else {
return false;
}
}
public function hasJobseekerProfile(): bool
{
if ($this->jobseekerProfiles->count() === 0) {
return false;
} else {
return true;
}
}
public function hasJoboffererProfile(): bool
{
if ($this->joboffererProfiles->count() === 0) {
return false;
} else {
return true;
}
}
public function hasAtLeastBasePlusProfile(): bool
{
if ($this->isJobofferer() && $this->hasJoboffererProfile()) {
$profile = $this->getDefaultJoboffererProfile();
if (!is_null($profile)) {
return $profile->isBasePlusProfile();
}
}
if ($this->isJobseeker() && $this->hasJobseekerProfile()) {
$profile = $this->getDefaultJobseekerProfile();
if (!is_null($profile)) {
return $profile->isBasePlusProfile();
}
}
return false;
}
/**
* @ORM\Column(name="accepted_terms_and_conditions", type="boolean", nullable=false)
*/
protected bool $acceptedTermsAndConditions = false;
public function setAcceptedTermsAndConditions(bool $termsAndConditions): void
{
$this->acceptedTermsAndConditions = $termsAndConditions;
}
public function hasAcceptedTermsAndConditions(): bool
{
return $this->acceptedTermsAndConditions;
}
public function hasExtendedDefaultProfile(): bool
{
if ($this->isJobofferer() && $this->hasJoboffererProfile()) {
$profile = $this->getDefaultJoboffererProfile();
if (!is_null($profile)) {
return $profile->isExtendedProfile();
}
}
if ($this->isJobseeker() && $this->hasJobseekerProfile()) {
$profile = $this->getDefaultJobseekerProfile();
if (!is_null($profile)) {
return $profile->isExtendedProfile();
}
}
return false;
}
/**
* @throws Exception
*/
public function getDefaultJobseekerProfile(): ?JobseekerProfile
{
if (!$this->hasJobseekerProfile()) {
return null;
} else {
$profiles = $this->getJobseekerProfiles();
/** @var JobseekerProfile $profile */
foreach ($profiles as $profile) {
if ($profile->isDefault() === true) {
return $profile;
}
}
}
throw new Exception('None of user ' . $this->getId() . ' job seeker profiles is marked as default!');
}
/**
* @throws Exception
*/
public function getDefaultJoboffererProfile(): ?JoboffererProfile
{
if (!$this->hasJoboffererProfile()) {
return null;
} else {
$profiles = $this->getJoboffererProfiles();
/** @var JoboffererProfile $profile */
foreach ($profiles as $profile) {
if ($profile->isDefault() === true) {
return $profile;
}
}
}
throw new Exception('None of user ' . $this->getId() . ' job offerer profiles is marked as default!');
}
/**
* @throws Exception
*/
public function getDefaultProfile(): ?Profile
{
if ($this->isJobofferer()) {
return $this->getDefaultJoboffererProfile();
}
if ($this->isJobseeker()) {
return $this->getDefaultJobseekerProfile();
}
throw new Exception('User ' . $this->getId() . ' is neither jobofferer nor jobseeker!');
}
public function hasPhoto(): bool
{
if ($this->isJobofferer()) {
return $this->getDefaultJoboffererProfile()->hasPhoto();
}
if ($this->isJobseeker()) {
return $this->getDefaultJobseekerProfile()->hasPhoto();
}
return false;
}
public function getPhotoFileName(): string
{
if ($this->isJobofferer()) {
return $this->getDefaultJoboffererProfile()->getPhotoFileName();
}
if ($this->isJobseeker()) {
return $this->getDefaultJobseekerProfile()->getPhotoFileName();
}
return '';
}
public function isPaused(): bool
{
return ($this->isJobseeker() && $this->hasJobseekerProfile() && $this->getDefaultJobseekerProfile()->isPaused())
|| ($this->isJobofferer() && $this->hasJoboffererProfile() && $this->getDefaultJoboffererProfile()->isPaused());
}
/**
* @var UserAdditionalInfo|Collection
*
* @ORM\OneToMany(targetEntity="App\Entity\ExternalPartner\UserAdditionalInfo", mappedBy="user", cascade={"persist", "remove"})
*/
protected $externalPartnerUserAdditionalInfos;
public function getExternalPartnerUserAdditionalInfoStringValueByName(string $infoName): ?string
{
/** @var UserAdditionalInfo $externalPartnerUserAdditionalInfo */
foreach ($this->externalPartnerUserAdditionalInfos as $externalPartnerUserAdditionalInfo) {
if ($externalPartnerUserAdditionalInfo->getInfoName() === $infoName) {
return $externalPartnerUserAdditionalInfo->getInfoStringValue();
}
}
return null;
}
/** @throws Exception */
public function setExternalPartnerUserAdditionalInfoStringValueByName(string $infoName, string $stringValue): void
{
/** @var UserAdditionalInfo $externalPartnerUserAdditionalInfo */
foreach ($this->externalPartnerUserAdditionalInfos as $externalPartnerUserAdditionalInfo) {
if ($externalPartnerUserAdditionalInfo->getInfoName() === $infoName) {
$externalPartnerUserAdditionalInfo->setInfoStringValue($stringValue);
return;
}
}
$externalPartnerUserAdditionalInfo = new UserAdditionalInfo();
$externalPartnerUserAdditionalInfo->setUser($this);
$externalPartnerUserAdditionalInfo->setInfoName($infoName);
$externalPartnerUserAdditionalInfo->setInfoStringValue($stringValue);
$this->externalPartnerUserAdditionalInfos->add($externalPartnerUserAdditionalInfo);
}
public function getExternalPartnerUserAdditionalInfoIntValueByName(string $infoName): ?int
{
/** @var UserAdditionalInfo $externalPartnerUserAdditionalInfo */
foreach ($this->externalPartnerUserAdditionalInfos as $externalPartnerUserAdditionalInfo) {
if ($externalPartnerUserAdditionalInfo->getInfoName() === $infoName) {
return $externalPartnerUserAdditionalInfo->getInfoIntValue();
}
}
return null;
}
/** @throws Exception */
public function setExternalPartnerUserAdditionalInfoIntValueByName(string $infoName, int $intValue): void
{
/** @var UserAdditionalInfo $externalPartnerUserAdditionalInfo */
foreach ($this->externalPartnerUserAdditionalInfos as $externalPartnerUserAdditionalInfo) {
if ($externalPartnerUserAdditionalInfo->getInfoName() === $infoName) {
$externalPartnerUserAdditionalInfo->setInfoIntValue($intValue);
return;
}
}
$externalPartnerUserAdditionalInfo = new UserAdditionalInfo();
$externalPartnerUserAdditionalInfo->setUser($this);
$externalPartnerUserAdditionalInfo->setInfoName($infoName);
$externalPartnerUserAdditionalInfo->setInfoIntValue($intValue);
$this->externalPartnerUserAdditionalInfos->add($externalPartnerUserAdditionalInfo);
}
/**
* @var \App\Entity\UserAdditionalInfo|Collection
*
* @ORM\OneToMany(targetEntity="App\Entity\UserAdditionalInfo", mappedBy="user", cascade={"persist", "remove"})
*/
protected $userAdditionalInfos;
public function getUserAdditionalInfos(): Collection
{
return $this->userAdditionalInfos;
}
public function getUserAdditionalInfoStringValueByName(string $infoName): ?string
{
/** @var \App\Entity\UserAdditionalInfo $userAdditionalInfo */
foreach ($this->userAdditionalInfos as $userAdditionalInfo) {
if ($userAdditionalInfo->getInfoName() === $infoName) {
return $userAdditionalInfo->getInfoStringValue();
}
}
return null;
}
/** @throws Exception */
public function setUserAdditionalInfoStringValueByName(string $infoName, string $stringValue): void
{
if (!empty($this->userAdditionalInfos)) {
/** @var \App\Entity\UserAdditionalInfo $userAdditionalInfo */
foreach ($this->userAdditionalInfos as $userAdditionalInfo) {
if ($userAdditionalInfo->getInfoName() === $infoName) {
$userAdditionalInfo->setInfoStringValue($stringValue);
return;
}
}
}
$userAdditionalInfo = new \App\Entity\UserAdditionalInfo();
$userAdditionalInfo->setUser($this);
$userAdditionalInfo->setInfoName($infoName);
$userAdditionalInfo->setInfoStringValue($stringValue);
$this->userAdditionalInfos->add($userAdditionalInfo);
}
public function getUserAdditionalInfoIntValueByName(string $infoName): ?int
{
/** @var \App\Entity\UserAdditionalInfo $userAdditionalInfo */
foreach ($this->userAdditionalInfos as $userAdditionalInfo) {
if ($userAdditionalInfo->getInfoName() === $infoName) {
return $userAdditionalInfo->getInfoIntValue();
}
}
return null;
}
/** @throws Exception */
public function setUserAdditionalInfoIntValueByName(string $infoName, int $intValue): void
{
/** @var \App\Entity\UserAdditionalInfo $userAdditionalInfo */
foreach ($this->userAdditionalInfos as $userAdditionalInfo) {
if ($userAdditionalInfo->getInfoName() === $infoName) {
$userAdditionalInfo->setInfoIntValue($intValue);
return;
}
}
$userAdditionalInfo = new \App\Entity\UserAdditionalInfo();
$userAdditionalInfo->setUser($this);
$userAdditionalInfo->setInfoName($infoName);
$userAdditionalInfo->setInfoIntValue($intValue);
$this->userAdditionalInfos->add($userAdditionalInfo);
}
/**
* @var RecurrentJobBooking[]|Collection
*
* @ORM\OneToMany(targetEntity="App\Entity\Membership\RecurrentJobBooking", mappedBy="user", cascade={"persist", "remove"})
*/
private Collection $recurrentJobBookings;
public function getRecurrentJobBookings(): Collection
{
return $this->recurrentJobBookings;
}
public function addRecurrentJobBooking(RecurrentJobBooking $recurrentJobBooking): void
{
$this->recurrentJobBookings->add($recurrentJobBooking);
}
public function isLinkedToExternalPartner(): bool
{
return !is_null($this->externalPartner);
}
public function isLinkedToExternalPartnerWithId(int $externalPartnerId): bool
{
return !is_null($this->externalPartner) && $this->externalPartner->getId() === $externalPartnerId;
}
/** @throws Exception */
public function isOwnerOfProfile(Profile $profile): bool
{
return $this->getDefaultProfile()->getId() === $profile->getId();
}
public function mustNotReceiveMails(): bool
{
return $this->getCreatedVia() === self::CREATED_VIA_RECRUIT_DL_RECURRENT_JOB_LANDINGPAGE && !$this->enabled;
}
public function getUserIdentifier(): string
{
return (string)$this->getEmail();
}
public function isAccountNonLocked(): bool
{
return !$this->isLocked();
}
public function __toString(): string
{
return (string)$this->getUsername() . ' - userId=' . $this->getId();
}
/**
* @var FlexMembershipRecurrentJobSlot[]|Collection
*
* @ORM\OneToMany(targetEntity="JanusHercules\Membership\Domain\Entity\FlexMembershipRecurrentJobSlot", mappedBy="user", cascade={"persist", "remove"})
*/
private Collection $recurrentJobSlots;
public function getRecurrentJobSlots(): Collection
{
return $this->recurrentJobSlots;
}
public function addRecurrentJobSlot(FlexMembershipRecurrentJobSlot $recurrentJobSlot): void
{
$this->recurrentJobBookings->add($recurrentJobSlot);
}
public function removeRecurrentJobSlot(FlexMembershipRecurrentJobSlot $recurrentJobSlotToRemove): void
{
foreach ($this->recurrentJobSlots as $key => $slot) {
if ($slot->getId() === $recurrentJobSlotToRemove->getId()) {
$this->recurrentJobSlots->remove($key);
}
}
}
}