<?php
namespace App\Entity;
use App\Entity\Email\RecipientInterface;
use App\Entity\LegalEntity\Member\Company;
use App\Entity\LegalEntity\Order\AbstractInvoice;
use App\Entity\Substance\Ec;
use App\Entity\Traits\IdTrait;
use App\Entity\User\History;
use App\Entity\User\MailArchive\Message;
use App\Entity\User\Profile;
use App\Entity\User\Settings;
use App\Entity\User\Token;
use App\Entity\User\Tutorial;
use Carbon\Carbon;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Validator\Constraints as Assert;
/**
* Class User.
*
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
*
* @ORM\Table(name="security_user")
*
* @UniqueEntity(fields={"email", "removed"})
*/
class User extends AbstractEntity implements UserInterface, PasswordAuthenticatedUserInterface, RecipientInterface, \Serializable
{
use IdTrait;
/**
* @ORM\Column(type="string")
*
* @Assert\NotBlank()
*
* @Assert\Email()
*/
private string $email;
/**
* @ORM\Column(type="string")
*
* @Assert\NotBlank()
*/
private ?string $password = '__uninitialised__';
/**
* @var Profile
*
* @ORM\OneToOne(targetEntity="App\Entity\User\Profile", mappedBy="user", cascade={"all"})
*
* @Assert\Valid()
*/
private $profile;
/**
* @var History[]|ArrayCollection
*
* @ORM\OneToMany(targetEntity="App\Entity\User\History", mappedBy="user", cascade={"all"})
*/
private $history;
/**
* @var Group[]|ArrayCollection
*
* @ORM\ManyToMany(targetEntity="App\Entity\Group", inversedBy="users", cascade={"all"})
*
* @ORM\JoinTable(name="_join_table_security_user_and_group")
*/
private $groups;
private ?string $plainPassword = null;
/**
* @var Company[]|ArrayCollection
*
* @ORM\OneToMany(targetEntity="App\Entity\LegalEntity\Member\Company", mappedBy="user")
*/
private $memberCompanies;
/**
* @var LegalEntity[]|ArrayCollection
*
* @ORM\OneToMany(targetEntity="App\Entity\LegalEntity", mappedBy="user")
*/
private $entities;
/**
* @var Message[]|ArrayCollection
*
* @ORM\OneToMany(targetEntity="App\Entity\User\MailArchive\Message", mappedBy="user")
*/
private $mailArchive;
/**
* @var LeadRegistrant[]|ArrayCollection
*
* @ORM\OneToMany(targetEntity="App\Entity\LeadRegistrant", mappedBy="user")
*/
private $leadRegistrantFor;
/**
* @var LeadRegistrant[]|ArrayCollection
*
* @ORM\OneToMany(targetEntity="App\Entity\LeadRegistrant", mappedBy="spoc")
*/
private $spocLeadRegistrantFor;
/**
* @var bool
*
* @ORM\Column(type="boolean")
*/
private $systemUser = false;
/**
* @ORM\Column(type="datetime", nullable=true)
*/
private ?Carbon $invited = null;
/**
* @var ArrayCollection|Notification[]
*
* @ORM\OneToMany(targetEntity="App\Entity\Notification", mappedBy="user")
*
* @ORM\OrderBy({"createdAt" = "DESC"})
*/
protected $notifications;
/**
* @var Tutorial
*
* @ORM\Embedded(class="App\Entity\User\Tutorial")
*/
private $tutorial;
/**
* @var Settings
*
* @ORM\Embedded(class="App\Entity\User\Settings")
*/
private $settings;
/**
* @var bool
*
* @ORM\Column(type="boolean")
*/
protected $removed = false;
/**
* @var int
*
* @ORM\Column(type="integer")
*/
private $failures = 0;
/**
* @var Token
*
* @ORM\Embedded(class="App\Entity\User\Token")
*/
private $token;
private int $invoiceCount = 0;
public function __construct()
{
parent::__construct();
$this->profile = (new Profile())
->setUser($this);
$this->groups = new ArrayCollection();
$this->history = new ArrayCollection();
$this->memberCompanies = new ArrayCollection();
$this->entities = new ArrayCollection();
$this->leadRegistrantFor = new ArrayCollection();
$this->spocLeadRegistrantFor = new ArrayCollection();
$this->notifications = new ArrayCollection();
$this->tutorial = new Tutorial();
$this->settings = new Settings();
$this->token = new Token();
}
public function getRoles()
{
$ret = [];
foreach ($this->getGroups() as $group) {
if (!$group instanceof Group) {
continue;
}
$ret[] = $group->getId();
}
return $ret;
}
public function getPassword(): ?string
{
return $this->password;
}
public function getSalt()
{
return '';
}
public function getUserIdentifier(): string
{
return (string) $this->email;
}
public function getUsername()
{
return $this->getEmail();
}
public function eraseCredentials()
{
$this->plainPassword = null;
}
public function setEmail(string $email): User
{
$this->email = trim($email);
return $this;
}
/**
* @return string
*/
public function getEmail(): ?string
{
return trim($this->email);
}
public function setPassword(string $password): User
{
$this->password = $password;
return $this;
}
/**
* @return string
*/
public function getPlainPassword(): ?string
{
return $this->plainPassword;
}
/**
* @param string $plainPassword
*/
public function setPlainPassword(string $plainPassword = null): User
{
$this->plainPassword = $plainPassword;
$this->password = null;
return $this;
}
public function getProfile(): Profile
{
if (null === $this->profile) {
$this->profile = (new Profile())->setUser($this);
}
return $this->profile;
}
public function setProfile(Profile $profile)
{
$this->profile = $profile;
$this->profile->setUser($this);
}
/**
* Add history.
*/
public function addHistory(History $history)
{
$this->history[] = $history;
}
/**
* Remove history.
*/
public function removeHistory(History $history)
{
$this->history->removeElement($history);
}
/**
* Get history.
*
* @return History[]|ArrayCollection
*/
public function getHistory()
{
return $this->history;
}
/**
* Add group.
*
* @return $this
*/
public function addGroup(Group $group): self
{
if (!$this->groups->contains($group)) {
$this->groups->add($group);
}
return $this;
}
/**
* Remove group.
*
* @return $this
*/
public function removeGroup(Group $group): self
{
$this->groups->removeElement($group);
return $this;
}
/**
* Get groups.
*
* @return Group[]|ArrayCollection
*/
public function getGroups()
{
return $this->groups;
}
public function getName(): string
{
switch ($this->getEmail()) {
case '[email protected]':
return 'SIEF.space import user';
break;
case '[email protected]':
return 'SIEF.space system user';
break;
default:
$p = $this->getProfile();
if (!empty($p->getFirstName()) && !empty($p->getSurName())) {
return sprintf('%s, %s', $p->getSurName(), $p->getFirstName());
} elseif (!empty($p->getFirstName())) {
return $p->getFirstName();
} else {
return $this->getEmail();
}
break;
}
}
public function getSalutation(): string
{
$p = $this->getProfile();
if (!empty($p->getFirstName())) {
return $p->getFirstName();
} else {
return 'Mr./Ms.';
}
}
/**
* @return LegalEntity[]|ArrayCollection
*/
public function getNonMemberEntities()
{
$ret = new ArrayCollection();
foreach ($this->entities as $entity) {
if ($entity->isMember()) {
continue;
}
$ret->add($entity);
}
return $ret;
}
/**
* @return LegalEntity[]|ArrayCollection
*/
public function getMemberEntities()
{
$ret = new ArrayCollection();
foreach ($this->entities as $entity) {
if (!$entity->isMember()) {
continue;
}
$ret->add($entity);
}
// Also include entities for which the user is a single point of contact
foreach ($this->getMemberCompanies() as $company) {
if (!$company->isActive()) {
continue;
}
foreach ($company->getLegalEntities() as $entity) {
if (!$entity->isMember()) {
continue;
}
if ($ret->contains($entity)) {
continue;
}
$ret->add($entity);
}
}
return $ret;
}
/**
* @return LegalEntity[]|ArrayCollection
*/
public function getEntities()
{
return $this->entities;
}
public function getValidEntityCount(): int
{
$entities = array_merge(
$this->getMemberEntities()->filter(function (LegalEntity $entity) {
return $entity->isAccessible();
})->toArray(),
$this->getNonMemberEntities()->filter(function (LegalEntity $entity) {
return $entity->isAccessible();
})->toArray()
);
return count($entities);
}
public function getValidApprovedEntityCount(): int
{
$entities = array_merge(
$this->getMemberEntities()->filter(function (LegalEntity $entity) {
return $entity->isApproved();
})->toArray(),
$this->getNonMemberEntities()->filter(function (LegalEntity $entity) {
return $entity->isApproved();
})->toArray()
);
return count($entities);
}
/**
* @return Message[]|ArrayCollection
*/
public function getMailArchive()
{
return $this->mailArchive;
}
public function addToMailArchive(Message $message): User
{
$this->mailArchive->add($message);
$message->setUser($this);
return $this;
}
/**
* @return LeadRegistrant[]|ArrayCollection
*/
public function getLeadRegistrantFor()
{
return $this->leadRegistrantFor;
}
public function removeLeadRegistrant(LeadRegistrant $leadRegistrant): User
{
$this->leadRegistrantFor->remove($leadRegistrant);
return $this;
}
public function addLeadRegistrant(LeadRegistrant $leadRegistrant): User
{
if ($leadRegistrant->getUser() instanceof User) {
$leadRegistrant->getUser()->removeLeadRegistrant($leadRegistrant);
}
$this->leadRegistrantFor->add($leadRegistrant);
$leadRegistrant->setUser($this);
return $this;
}
public function __toString()
{
return $this->getName();
}
public function isStaff(bool $allowReadyOnly = true): bool
{
$groups = ['ROLE_STAFF'];
if ($allowReadyOnly) {
$groups[] = 'ROLE_STAFF_RO';
}
return !empty(array_intersect($this->getRoles(), $groups));
}
public function isSysAdmin(): bool
{
return in_array('ROLE_SYS_ADMIN', $this->getRoles(), true);
}
public function serialize()
{
return serialize([
$this->id,
$this->email,
$this->password,
]);
}
public function unserialize($serialized)
{
list(
$this->id,
$this->email,
$this->password,
) = unserialize($serialized);
}
public function isSystemUser(): bool
{
return $this->systemUser;
}
/**
* @return $this
*/
public function setSystemUser(bool $systemUser): User
{
$this->systemUser = $systemUser;
return $this;
}
public function getInvited(): ?Carbon
{
return $this->invited;
}
public function setInvited(?Carbon $invited): User
{
$this->invited = $invited;
return $this;
}
public function getInvoiceCount(): int
{
return $this->invoiceCount;
$ret = 0;
foreach ($this->getEntities() as $entity) {
$ret += $entity->getInvoices()->filter(function (AbstractInvoice $invoice) {
return !empty($invoice->getFile()->getPath()) && !$invoice->isHidden();
})->count();
}
return $ret;
}
/**
* @internal
*
* @return $this
*/
public function setInvoiceCount(int $invoiceCount): self
{
$this->invoiceCount = $invoiceCount;
return $this;
}
public function getFirstName()
{
return $this->getProfile()->getFirstName();
}
public function getSurName()
{
return $this->getProfile()->getSurName();
}
/**
* @return Notification[]|ArrayCollection
*/
public function getNotifications()
{
return $this->notifications;
}
public function hasEc(Ec $ec): bool
{
foreach ($this->getMemberEntities() as $member) {
if ($member->hasEc($ec)) {
return true;
}
}
foreach ($this->getEntities() as $nonMember) {
if ($nonMember->hasEc($ec)) {
return true;
}
}
foreach ($this->getMergedLeadRegistrantFor() as $leadRegistrant) {
if ($leadRegistrant->getEc() === $ec) {
return true;
}
}
return false;
}
public function getTutorial(): Tutorial
{
return $this->tutorial;
}
/**
* @return Company[]|ArrayCollection
*/
public function getMemberCompanies()
{
return $this->memberCompanies;
}
/**
* @return Company[]|ArrayCollection
*/
public function getAssociatedMemberCompanies(): ArrayCollection
{
$ret = new ArrayCollection();
foreach ($this->getMemberCompanies() as $company) {
if (!$company->isActive()) {
continue;
}
$ret->add($company);
}
foreach ($this->getMemberEntities() as $entity) {
if (!$entity->isAccessible()) {
continue;
}
$company = $entity->getMemberCompany();
if (!$company->isActive()) {
continue;
}
if ($ret->contains($company)) {
continue;
}
$ret->add($company);
}
return $ret;
}
public function getSettings(): Settings
{
return $this->settings;
}
public function isRemovable(): bool
{
return !$this->isSysAdmin() && !$this->isSystemUser() && $this->memberCompanies->isEmpty()
&& $this->entities->isEmpty();
}
public function isRemoved(): bool
{
return $this->removed;
}
/**
* @return $this
*/
public function setRemoved(bool $removed): self
{
$this->removed = $removed;
return $this;
}
/**
* @return LeadRegistrant[]|ArrayCollection
*/
public function getSpocLeadRegistrantFor()
{
return $this->spocLeadRegistrantFor;
}
/**
* @return LeadRegistrant[]|ArrayCollection
*/
public function getMergedLeadRegistrantFor()
{
return new ArrayCollection(
array_merge($this->leadRegistrantFor->toArray(), $this->spocLeadRegistrantFor->toArray())
);
}
public function HasActiveLeadRegistrants()
{
$result = false;
/** @var LeadRegistrant $registrant */
foreach ($this->getMergedLeadRegistrantFor() as $registrant) {
if ($registrant->isActive()) {
$result = true;
}
}
return $result;
}
public function getFailures(): int
{
return $this->failures;
}
public function incrementFailures(): self
{
++$this->failures;
return $this;
}
public function resetFailures(): self
{
$this->failures = 0;
return $this;
}
public function getToken(): Token
{
return $this->token;
}
public function __serialize(): array
{
return [
$this->id,
$this->email,
$this->password,
];
}
public function __unserialize(array $data): void
{
list(
$this->id,
$this->email,
$this->password,
) = $data;
}
}