<?php
namespace App\Entity;
use ApiPlatform\Doctrine\Orm\Filter\SearchFilter;
use ApiPlatform\Metadata\ApiFilter;
use ApiPlatform\Metadata\ApiResource;
use ApiPlatform\Metadata\Delete;
use ApiPlatform\Metadata\Get;
use ApiPlatform\Metadata\GetCollection;
use ApiPlatform\Metadata\Post;
use ApiPlatform\Metadata\Put;
use App\ApiPlatform\Extension\UsersExtension;
use App\ApiPlatform\State\MeStateProvider;
use App\ApiPlatform\State\UserProcessor;
use App\Controller\Action\GetMeAction;
use App\Controller\Action\UserActionPlansController;
use App\Controller\Action\UsersPAController;
use DateTime;
use DateTimeImmutable;
use App\Traits\AutoTimestampTrait;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\DBAL\Types\Types;
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\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
#[ORM\Table(name: 'user')]
#[ORM\Entity]
#[ApiResource(
normalizationContext: ['datetime_format' => 'Y-m-d', 'groups' => ['user.get', 'message.get']],
denormalizationContext: ['groups' => ['user.write', 'user.write']],
operations: [
new GetCollection(
order: ['firstname' => 'ASC'],
),
new Get(),
new Get(
provider: MeStateProvider::class,
name: '_api_/me',
uriTemplate: '/me',
controller: GetMeAction::class
),
new Get(
provider: MeStateProvider::class,
name: '_api_/users_PA/{site_id}',
uriTemplate: '/users_PA/{site_id}',
controller: UsersPAController::class,
write: false,
read: false
), new Put(
processor: UserProcessor::class,
security: "is_granted('EDIT', object)",
securityMessage: "You can only edit your own account unless you're an administrator.",
denormalizationContext: ['groups' => ['user.write']]
),
new Delete(
security: 'user.isMasterAdmin()',
),
new Post(
security: 'user.isMasterAdmin()',
)
]
)]
#[ApiFilter(
SearchFilter::class,
properties: [
'customer' => 'exact',
'email' => 'partial',
'firstname' => 'partial',
'lastname' => 'partial',
'department' => 'partial',
]
)]
#[UniqueEntity('email')]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
use AutoTimestampTrait;
const ROLE_ADMIN = 'ROLE_ADMIN';
const ROLE_USER = 'ROLE_USER';
#[ORM\Column(name: 'id', type: 'integer', nullable: false)]
#[ORM\Id]
#[ORM\GeneratedValue(strategy: 'IDENTITY')]
#[Groups(['user.get', 'plan.get', 'task.get', 'comment.get'])]
private int $id;
#[ORM\Column(name: 'firstname', type: 'string', length: 30, nullable: false)]
#[Groups(['user.get', 'user.write', 'profile.write', 'plan.get', 'task.get', 'comment.get'])]
private ?string $firstname = null;
#[ORM\Column(name: 'lastname', type: 'string', length: 30, nullable: false)]
#[Groups(['user.get', 'user.write', 'profile.write', 'plan.get', 'task.get', 'comment.get'])]
private ?string $lastname = null;
#[ORM\Column(name: 'department', type: 'string', length: 30, nullable: true)]
#[Groups(['user.get', 'user.write', 'profile.write'])]
private ?string $department = null;
#[ORM\Column(name: 'position', type: 'string', length: 30, nullable: true)]
#[Groups(['user.get', 'user.write', 'profile.write'])]
private ?string $position = null;
#[ORM\Column(name: 'email', type: 'string', length: 255, nullable: false)]
#[Groups(['user.get', 'profile.write', 'user.write'])]
#[Assert\Email()]
private ?string $email = null;
#[ORM\Column(name: 'password', type: 'text', length: 65535, nullable: true)]
private ?string $password = null;
#[ORM\Column(name: 'phone', type: 'string', length: 30, nullable: true)]
#[Groups(['user.get', 'profile.write', 'user.write'])]
private ?string $phone = null;
#[ORM\Column(name: 'mobile', type: 'string', length: 30, nullable: true)]
#[Groups(['user.get', 'profile.write', 'user.write'])]
private ?string $mobile = null;
#[ORM\Column(name: 'website', type: 'string', length: 255, nullable: true)]
#[Groups(['user.get', 'profile.write', 'user.write'])]
private ?string $website = null;
#[ORM\Column(type: 'json')]
#[Groups(['user.get', 'user.write'])]
private $roles = [];
#[ORM\ManyToOne(inversedBy: 'users')]
#[ORM\JoinColumn(nullable: true)]
#[Groups(['user.get', 'user.write'])]
private ?Customer $customer = null;
#[ORM\OneToMany(mappedBy: 'user', targetEntity: UserSite::class, orphanRemoval: true, cascade: ['persist'])]
#[Groups(['user.get', 'user.write'])]
private Collection $userSites;
#[Groups(['user.write', 'profile.write'])]
private ?string $plainPassword = null;
#[ORM\Column(type: Types::TEXT, nullable: true)]
private ?string $activationToken = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $activationTokenCreatedAt = null;
#[ORM\Column]
#[Groups(['user.write', 'profile.write', 'user.get'])]
private bool $isEnabled = true;
#[ORM\Column(nullable: true)]
#[Groups(['user.write', 'user.get', ])]
private ?\DateTimeImmutable $expireAt = null;
#[Groups(['document.get'])]
#[ORM\Column(type: 'datetime')]
protected $createdAt;
#[Groups(['document.get'])]
#[ORM\Column(type: 'datetime')]
protected $updatedAt;
#[ORM\Column(name: 'application_master', type: 'string', nullable: true)]
#[Groups(['user.get', 'user.write'])]
private ?string $applicationMaster = null;
#[ORM\Column(name: 'lang', type: 'string', nullable: true)]
#[Groups(['user.get', 'user.write'])]
private ?string $lang = 'fr';
#[ORM\OneToMany(mappedBy: 'userId', targetEntity: Export::class)]
private Collection $exports;
#[ORM\Column(name: 'customer_associated ', type: 'json', nullable: true)]
#[Groups(['user.get', 'user.write'])]
private ?array $customerAssociated = [];
#[ORM\OneToMany(mappedBy: 'site', targetEntity: Affectation::class, cascade: ['persist'], orphanRemoval: true)]
#[Groups(['user.write'])]
private Collection $affectations;
#[ORM\Column(nullable: true)]
#[Groups(['user.get', 'user.write'])]
private ?bool $hideInPA = null;
#[ORM\OneToMany(mappedBy: 'user', targetEntity: Discussion::class)]
private Collection $discussions;
#[ORM\Column]
#[Groups(['user.get', 'user.write', 'message.get'])]
private ?bool $isHotline = false;
#[ORM\OneToMany(mappedBy: 'user', targetEntity: SiteQuestions::class)]
private Collection $siteQuestions;
#[ORM\ManyToOne(inversedBy: 'profile_picture')]
#[Groups(['user.get', 'user.write'])]
private ?Media $profile_picture = null;
#[ORM\Column(nullable: true)]
private ?DateTime $lockedAt = null;
#[ORM\Column(nullable: true)]
private int $attempts = 0;
public function __construct()
{
$this->sites = new ArrayCollection();
$this->userSites = new ArrayCollection();
$this->exports = new ArrayCollection();
$this->affectations = new ArrayCollection();
$this->discussions = new ArrayCollection();
$this->siteQuestions = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getFirstname(): ?string
{
return $this->firstname;
}
public function setFirstname(string $firstname): self
{
$this->firstname = $firstname;
return $this;
}
public function getLastname(): ?string
{
return $this->lastname;
}
public function setLastname(string $lastname): self
{
$this->lastname = $lastname;
return $this;
}
public function getDepartment(): ?string
{
return $this->department;
}
public function setDepartment(string $department): self
{
$this->department = $department;
return $this;
}
public function getPosition(): ?string
{
return $this->position;
}
public function setPosition(string $position): self
{
$this->position = $position;
return $this;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
public function getPhone(): ?string
{
return $this->phone;
}
public function setPhone(string $phone): self
{
$this->phone = $phone;
return $this;
}
public function getMobile(): ?string
{
return $this->mobile;
}
public function setMobile(string $mobile): self
{
$this->mobile = $mobile;
return $this;
}
public function getWebsite(): ?string
{
return $this->website;
}
public function setWebsite(string $website): self
{
$this->website = $website;
return $this;
}
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->email;
}
public function hasRole(string $role): bool
{
return in_array($role, $this->roles);
}
/**
* @see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
if (empty($this->roles))
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
public function addRole(string $role)
{
if (in_array($role, $this->roles)) {
return;
}
$this->roles[] = $role;
return $this;
}
/**
* @see PasswordAuthenticatedUserInterface
*/
public function getPassword(): string
{
return $this->password;
}
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* @see UserInterface
*/
public function eraseCredentials()
{
$this->plainPassword = null;
}
public function getPlainPassword(): ?string
{
return $this->plainPassword;
}
public function setPlainPassword(string $plainPassword = null): self
{
$this->plainPassword = $plainPassword;
return $this;
}
public function __toString()
{
return (string)($this->firstname . ' ' . $this->lastname);
}
public function getCustomer(): ?Customer
{
return $this->customer;
}
public function setCustomer(?Customer $customer): self
{
$this->customer = $customer;
return $this;
}
/**
* @return Collection<int, UserSite>
*/
public function getUserSites(): Collection
{
return $this->userSites;
}
public function addUserSite(UserSite $userSite): self
{
if (!$this->userSites->contains($userSite)) {
$this->userSites->add($userSite);
$userSite->setUser($this);
}
return $this;
}
public function removeUserSite(UserSite $userSite): self
{
if ($this->userSites->removeElement($userSite)) {
// set the owning side to null (unless already changed)
if ($userSite->getUser() === $this) {
$userSite->setUser(null);
}
}
return $this;
}
public function getActivationToken(): ?string
{
return $this->activationToken;
}
public function setActivationToken(?string $activationToken): self
{
$this->activationToken = $activationToken;
return $this;
}
public function getActivationTokenCreatedAt(): ?\DateTimeImmutable
{
return $this->activationTokenCreatedAt;
}
public function setActivationTokenCreatedAt(?\DateTimeImmutable $activationTokenCreatedAt): self
{
$this->activationTokenCreatedAt = $activationTokenCreatedAt;
return $this;
}
public function isIsEnabled(): ?bool
{
return $this->isEnabled;
}
public function setIsEnabled(bool $isEnabled): self
{
$this->isEnabled = $isEnabled;
return $this;
}
public function isAdmin()
{
return in_array(self::ROLE_ADMIN, $this->roles);
}
public function isMasterAdmin()
{
return $this->getApplicationMaster() !== null;
}
public function getExpireAt(): ?\DateTimeImmutable
{
return $this->expireAt;
}
public function setExpireAt(?\DateTimeImmutable $expireAt): self
{
$this->expireAt = $expireAt;
return $this;
}
/**
* @return string|null
*/
public function getApplicationMaster(): ?string
{
return $this->applicationMaster;
}
/**
* @param string|null $applicationMaster
*/
public function setApplicationMaster(?string $applicationMaster): void
{
$this->applicationMaster = $applicationMaster;
}
/**
* @return string|null
*/
public function getLang(): ?string
{
return $this->lang;
}
/**
* @param string|null $lang
*/
public function setLang(?string $lang): void
{
$this->lang = $lang;
}
/**
* @return Collection<int, Export>
*/
public function getExports(): Collection
{
return $this->exports;
}
public function addExport(Export $export): self
{
if (!$this->exports->contains($export)) {
$this->exports->add($export);
$export->setUserId($this);
}
return $this;
}
public function removeExport(Export $export): self
{
if ($this->exports->removeElement($export)) {
// set the owning side to null (unless already changed)
if ($export->getUserId() === $this) {
$export->setUserId(null);
}
}
return $this;
}
/**
* @return array|null
*/
public function getCustomerAssociated(): ?array
{
return $this->customerAssociated;
}
/**
* @param array|null $customerAssociated
*/
public function setCustomerAssociated(?array $customerAssociated): void
{
$this->customerAssociated = $customerAssociated;
}
/**
* @return Collection<int, Affectation>
*/
public function getAffectations(): Collection
{
return $this->affectations;
}
public function addAffectation(Affectation $affectation): self
{
if (!$this->affectations->contains($affectation)) {
$this->affectations->add($affectation);
$affectation->setSite($this);
}
return $this;
}
public function removeAffectation(Affectation $affectation): self
{
if ($this->affectations->removeElement($affectation)) {
// set the owning side to null (unless already changed)
if ($affectation->getSite() === $this) {
$affectation->setSite(null);
}
}
return $this;
}
public function isHideInPA(): ?bool
{
return $this->hideInPA;
}
public function setHideInPA(?bool $hideInPA): self
{
$this->hideInPA = $hideInPA;
return $this;
}
/**
* @return Collection<int, Discussion>
*/
public function getDiscussions(): Collection
{
return $this->discussions;
}
public function addDiscussion(Discussion $discussion): self
{
if (!$this->discussions->contains($discussion)) {
$this->discussions->add($discussion);
$discussion->setUser($this);
}
return $this;
}
public function removeDiscussion(Discussion $discussion): self
{
if ($this->discussions->removeElement($discussion)) {
// set the owning side to null (unless already changed)
if ($discussion->getUser() === $this) {
$discussion->setUser(null);
}
}
return $this;
}
public function isIsHotline(): ?bool
{
return $this->isHotline;
}
public function setIsHotline(bool $isHotline): self
{
$this->isHotline = $isHotline;
return $this;
}
/**
* @return Collection<int, SiteQuestions>
*/
public function getSiteQuestions(): Collection
{
return $this->siteQuestions;
}
public function addSiteQuestion(SiteQuestions $siteQuestion): self
{
if (!$this->siteQuestions->contains($siteQuestion)) {
$this->siteQuestions->add($siteQuestion);
$siteQuestion->setUser($this);
}
return $this;
}
public function removeSiteQuestion(SiteQuestions $siteQuestion): self
{
if ($this->siteQuestions->removeElement($siteQuestion)) {
// set the owning side to null (unless already changed)
if ($siteQuestion->getUser() === $this) {
$siteQuestion->setUser(null);
}
}
return $this;
}
public function getProfilePicture(): ?Media
{
return $this->profile_picture;
}
public function setProfilePicture(?Media $profile_picture): self
{
$this->profile_picture = $profile_picture;
return $this;
}
public function getLockedAt(): ?DateTime
{
return $this->lockedAt;
}
public function setLockedAt(?DateTime $lockedAt): self
{
$this->lockedAt = $lockedAt;
return $this;
}
public function getAttempts(): int
{
return $this->attempts;
}
public function setAttempts(int $attempts): self
{
$this->attempts = $attempts;
return $this;
}
}