src/Entity/Customer.php line 78

  1. <?php
  2. namespace App\Entity;
  3. use Doctrine\ORM\Mapping as ORM,
  4.     Doctrine\DBAL\Types\Types,
  5.     Doctrine\Common\Collections\ArrayCollection,
  6.     Doctrine\Common\Collections\Collection;
  7. use Symfony\Component\Serializer\Annotation\Groups,
  8.     Symfony\Component\Validator\Constraints as Assert,
  9.     Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface,
  10.     Symfony\Component\Security\Core\User\UserInterface,
  11.     Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface,
  12.     Symfony\Component\Validator\Constraint;
  13. use ApiPlatform\Metadata\ApiResource,
  14.     ApiPlatform\Metadata\ApiProperty,
  15.     ApiPlatform\Metadata\Get,
  16.     ApiPlatform\Metadata\GetCollection,
  17.     ApiPlatform\Metadata\Post,
  18.     ApiPlatform\Metadata\Put,
  19.     ApiPlatform\Metadata\Delete,
  20.     ApiPlatform\Metadata\ApiFilter,
  21.     ApiPlatform\Doctrine\Orm\Filter\SearchFilter,
  22.     ApiPlatform\Doctrine\Orm\Filter\BooleanFilter,
  23.     ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
  24. use App\Entity\Trait\IdTrait,
  25.     App\Entity\Trait\UuidTrait,
  26.     App\Entity\Trait\TimestampableTrait,
  27.     App\Entity\Trait\StatTrait,
  28.     App\Entity\Interface\SimpleEntityInterface,
  29.     App\Entity\Interface\StatableInterface,
  30.     App\Entity\Interface\PasswordResetableInterface;
  31. use App\Enum\Language,
  32.     App\Validator\Constraints\User as CustomAssert,
  33.     App\Repository\CustomerRepository,
  34.     App\StateProcessor\CustomerRegister\PostRegisterProcessor,
  35.     App\Doctrine\DBAL\Types\CustomerLoginMethodsType,
  36.     App\Enum\CustomerLoginMethod;
  37. #[ApiResource(
  38.     description'Customers',
  39.     normalizationContext: ['groups' => ['read''read:' self::class]],
  40.     denormalizationContext: ['groups' => ['write']],
  41.     order: ['createdAt' => 'desc'],
  42.     operations: [
  43.         new GetCollection(
  44.             security'is_granted("' self::class . '")'
  45.         ),
  46.         new Post(
  47.             uriTemplate'/customers/register',
  48.             denormalizationContext: ['groups' => ['register']],
  49.             processorPostRegisterProcessor::class,
  50.             validationContext: ['groups' => [Constraint::DEFAULT_GROUP'register']],
  51.         ),
  52.         new Post(
  53.             processorPostRegisterProcessor::class,
  54.             validationContext: ['groups' => [Constraint::DEFAULT_GROUP'post']],
  55.         ),
  56.         new Get(
  57.             security'is_granted("' self::class . '")'
  58.         ),
  59.         new Put(
  60.             security'is_granted("' self::class . '")'
  61.         ),
  62.         new Delete(
  63.             security'is_granted("' self::class . '")'
  64.         )
  65.     ],
  66.     extraProperties: ['standard_put' => false],
  67. )]
  68. #[ApiFilter(SearchFilter::class, properties: ['email' => 'partial''fullName' => 'partial'])]
  69. #[ApiFilter(BooleanFilter::class, properties: ['stat'])]
  70. #[ApiFilter(OrderFilter::class, properties: ['email''fullName''stat''createdAt''updatedAt'])]
  71. #[ORM\Entity(repositoryClassCustomerRepository::class)]
  72. class Customer implements
  73.     SimpleEntityInterface,
  74.     StatableInterface,
  75.     UserInterface,
  76.     PasswordAuthenticatedUserInterface,
  77.     PasswordResetableInterface
  78. {
  79.     use IdTrait,
  80.         UuidTrait,
  81.         TimestampableTrait,
  82.         StatTrait;
  83.     const MAX_PREVIOUS_PASSWORDS 5;
  84.     #[ApiProperty(description'Email')]
  85.     #[Groups(['read''write''register'])]
  86.     #[Assert\NotBlank]
  87.     #[Assert\Email]
  88.     #[ORM\Column(typeTypes::STRINGlength191uniquetrue)]
  89.     private string $email;
  90.     #[ApiProperty(description'Persisted password')]
  91.     #[ORM\Column(typeTypes::STRINGlength255nullabletrue)]
  92.     private ?string $password null;
  93.     #[ApiProperty(description'New password')]
  94.     #[Groups(['write''register'])]
  95.     #[Assert\NotBlank(groups: ['post''register'])]
  96.     #[Assert\Length(max50groups: [Constraint::DEFAULT_GROUP'profile'])]
  97.     #[Assert\Regex(
  98.         pattern'/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-\.]).{8,}$/',
  99.         match: true,
  100.         message'Password must consist of at least 8 characters (upper case, lower case, number, special character)',
  101.         groups: [Constraint::DEFAULT_GROUP'profile']
  102.     )]
  103.     #[Assert\NotCompromisedPassword(groups: [Constraint::DEFAULT_GROUP'profile'])]
  104.     #[CustomAssert\PreviousPasswords(groups: [Constraint::DEFAULT_GROUP'profile'])]
  105.     private ?string $rawPassword null;
  106.     #[ApiProperty(description'New password repeat')]
  107.     #[Groups(['write''register'])]
  108.     #[Assert\Expression(
  109.         expression'value === this.getRawPassword()',
  110.         message'Passwords do not match.',
  111.         groups: ['post''register''profile']
  112.     )]
  113.     private ?string $rawPasswordRepeat null;
  114.     #[ApiProperty(description'Current password')]
  115.     #[CustomAssert\CurrentPassword(groups: ['profile'])]
  116.     private ?string $currentPassword null;
  117.     #[ApiProperty(description'Previous passwords')]
  118.     #[ORM\Column(typeTypes::JSON)]
  119.     private array $previousPasswords = [];
  120.     #[ApiProperty(description'Name and surname')]
  121.     #[Groups(['read''write''register'])]
  122.     #[Assert\NotBlank]
  123.     #[Assert\Length(min3)]
  124.     #[ORM\Column(typeTypes::STRINGlength255)]
  125.     private string $fullName;
  126.     #[ApiProperty(description'Is regulations accepted')]
  127.     #[Groups(['register'])]
  128.     #[Assert\IsTrue(groups: ['register'])]
  129.     private bool $isRegulationsAccepted false;
  130.     #[ApiProperty(description'Is privacy policy accepted')]
  131.     #[Groups(['register'])]
  132.     #[Assert\IsTrue(groups: ['register'])]
  133.     private bool $isPrivacyPolicyAccepted false;
  134.     #[ApiProperty(description'Login methods')]
  135.     #[ORM\Column(typeCustomerLoginMethodsType::NAME)]
  136.     private array $loginMethods = [];
  137.     #[ApiProperty(description'Google id')]
  138.     #[Groups(['read:' self::class])]
  139.     #[ORM\Column(typeTypes::STRINGlength1023nullabletrue)]
  140.     private ?string $googleId null;
  141.     #[ApiProperty(description'Google hash')]
  142.     #[ORM\Column(typeTypes::STRINGlength255nullabletrue)]
  143.     private ?string $googleHash null;
  144.     #[ApiProperty(description'Google hash generated at')]
  145.     #[ORM\Column(typeTypes::DATETIME_IMMUTABLEnullabletrue)]
  146.     private ?\DateTimeImmutable $googleHashGeneratedAt null;
  147.     #[ApiProperty(description'Orcid id')]
  148.     #[Groups(['read:' self::class])]
  149.     #[ORM\Column(typeTypes::STRINGlength1023nullabletrue)]
  150.     private ?string $orcidId null;
  151.     #[ApiProperty(description'Orcid hash')]
  152.     #[ORM\Column(typeTypes::STRINGlength255nullabletrue)]
  153.     private ?string $orcidHash null;
  154.     #[ApiProperty(description'Orcid hash generated at')]
  155.     #[ORM\Column(typeTypes::DATETIME_IMMUTABLEnullabletrue)]
  156.     private ?\DateTimeImmutable $orcidHashGeneratedAt null;
  157.     #[ApiProperty(description'Register hash')]
  158.     #[ORM\Column(typeTypes::STRINGlength255nullabletrue)]
  159.     private ?string $registerHash null;
  160.     #[ApiProperty(description'Register hash generated at')]
  161.     #[ORM\Column(typeTypes::DATETIME_IMMUTABLEnullabletrue)]
  162.     private ?\DateTimeImmutable $registerHashGeneratedAt null;
  163.     #[ApiProperty(description'Reset password hash')]
  164.     #[ORM\Column(typeTypes::STRINGlength255nullabletrue)]
  165.     private ?string $resetPasswordHash null;
  166.     #[ApiProperty(description'Reset password hash generated at')]
  167.     #[ORM\Column(typeTypes::DATETIME_IMMUTABLEnullabletrue)]
  168.     private ?\DateTimeImmutable $resetPasswordHashGeneratedAt null;
  169.     #[ApiProperty(description'Is confirmed')]
  170.     #[Groups(['read:' self::class])]
  171.     #[ORM\Column(typeTypes::BOOLEANoptions: ['default' => false])]
  172.     private bool $isConfirmed false;
  173.     #[ApiProperty(description'Register language')]
  174.     #[Groups(['read:' self::class, 'register'])]
  175.     #[ORM\Column(
  176.         typeTypes::STRING,
  177.         enumTypeLanguage::class,
  178.         length255,
  179.         options: ['default' => Language::EN]
  180.     )]
  181.     private Language $registerLanguage Language::EN;
  182.     #[ApiProperty(description'Last login at')]
  183.     #[Groups(['read:' self::class])]
  184.     #[ORM\Column(typeTypes::DATETIME_IMMUTABLE)]
  185.     private \DateTimeImmutable $lastLoginAt;
  186.     #[ApiProperty(description'Directories')]
  187.     #[ORM\OneToMany(targetEntityCustomerDirectory::class, mappedBy'parent'cascade: ['persist''remove'])]
  188.     #[ORM\OrderBy(['createdAt' => 'desc'])]
  189.     private Collection $directories;
  190.     private ?array $directoriesItemsUuids null;
  191.     #[ORM\OneToMany(targetEntityCustomerNotification::class, mappedBy'parent'cascade: ['persist''remove'])]
  192.     #[ORM\OrderBy(['createdAt' => 'desc'])]
  193.     private Collection $notifications;
  194.     public function __construct(string $email)
  195.     {
  196.         $this->setUuid();
  197.         $this->email $email;
  198.         $this->lastLoginAt = new \DateTimeImmutable();
  199.         $this->directories = new ArrayCollection();
  200.         $this->notifications = new ArrayCollection();
  201.         $this->createdAt = new \DateTimeImmutable();
  202.         $this->updatedAt = new \DateTimeImmutable();
  203.     }
  204.     public function getEmail(): string
  205.     {
  206.         return $this->email;
  207.     }
  208.     public function getPassword(): ?string
  209.     {
  210.         return $this->password;
  211.     }
  212.     public function getRawPassword(): ?string
  213.     {
  214.         return $this->rawPassword;
  215.     }
  216.     public function setRawPassword(?string $rawPasswordUserPasswordHasherInterface $encoder): self
  217.     {
  218.         if (! $rawPassword) {
  219.             return $this;
  220.         }
  221.         $this->rawPassword $rawPassword;
  222.         $this->password $encoder->hashPassword($this$rawPassword);
  223.         if (count($this->previousPasswords) >= self::MAX_PREVIOUS_PASSWORDS) {
  224.             $this->previousPasswords array_slice($this->previousPasswords1);
  225.         }
  226.         $this->previousPasswords[] = password_hash($rawPasswordPASSWORD_DEFAULT);
  227.         $this->resetPasswordHash null;
  228.         $this->resetPasswordHashGeneratedAt null;
  229.         $this->addLoginMethod(CustomerLoginMethod::PASSWORD);
  230.         return $this;
  231.     }
  232.     public function getRawPasswordRepeat(): ?string
  233.     {
  234.         return $this->rawPasswordRepeat;
  235.     }
  236.     public function setRawPasswordRepeat(?string $rawPasswordRepeat): self
  237.     {
  238.         $this->rawPasswordRepeat $rawPasswordRepeat;
  239.         return $this;
  240.     }
  241.     public function setHashedPassword(string $hashedPassword): self
  242.     {
  243.         $this->password $hashedPassword;
  244.         return $this;
  245.     }
  246.     public function getCurrentPassword(): ?string
  247.     {
  248.         return $this->currentPassword;
  249.     }
  250.     public function setCurrentPassword(?string $currentPassword): self
  251.     {
  252.         $this->currentPassword $currentPassword;
  253.         return $this;
  254.     }
  255.     public function getPreviousPasswords(): array
  256.     {
  257.         return $this->previousPasswords;
  258.     }
  259.     public function getFullName(): string
  260.     {
  261.         return $this->fullName;
  262.     }
  263.     public function setFullName(string $fullName): self
  264.     {
  265.         $this->fullName $fullName;
  266.         return $this;
  267.     }
  268.     public function getIsRegulationsAccepted(): bool
  269.     {
  270.         return $this->isRegulationsAccepted;
  271.     }
  272.     public function setIsRegulationsAccepted(bool $isRegulationsAccepted): self
  273.     {
  274.         $this->isRegulationsAccepted $isRegulationsAccepted;
  275.         return $this;
  276.     }
  277.     public function getIsPrivacyPolicyAccepted(): bool
  278.     {
  279.         return $this->isPrivacyPolicyAccepted;
  280.     }
  281.     public function setIsPrivacyPolicyAccepted(bool $isPrivacyPolicyAccepted): self
  282.     {
  283.         $this->isPrivacyPolicyAccepted $isPrivacyPolicyAccepted;
  284.         return $this;
  285.     }
  286.     public function getLoginMethods(): array
  287.     {
  288.         return $this->loginMethods;
  289.     }
  290.     private function addLoginMethod(CustomerLoginMethod $method): self
  291.     {
  292.         if ($this->isLoginMethodAvailable($method)) {
  293.             return $this;
  294.         }
  295.         $this->loginMethods[] = $method;
  296.         return $this;
  297.     }
  298.     public function isLoginMethodAvailable(CustomerLoginMethod $method): bool
  299.     {
  300.         return in_array($method$this->loginMethods);
  301.     }
  302.     public function isPasswordLoginMethodAvailable(): bool
  303.     {
  304.         return in_array(CustomerLoginMethod::PASSWORD$this->loginMethods);
  305.     }
  306.     public function getGoogleId(): ?string
  307.     {
  308.         return $this->googleId;
  309.     }
  310.     public function setGoogleId(string $googleId): self
  311.     {
  312.         $this->googleId $googleId;
  313.         return $this;
  314.     }
  315.     public function setGoogleHash(string $googleHash): self
  316.     {
  317.         $this->googleHash $googleHash;
  318.         $this->googleHashGeneratedAt = new \DateTimeImmutable();
  319.         return $this;
  320.     }
  321.     public function getGoogleHash(): ?string
  322.     {
  323.         return $this->googleHash;
  324.     }
  325.     public function getGoogleHashGeneratedAt(): ?\DateTimeImmutable
  326.     {
  327.         return $this->googleHashGeneratedAt;
  328.     }
  329.     public function addGoogleLogin(): self
  330.     {
  331.         if ($this->isLoginMethodAvailable(CustomerLoginMethod::GOOGLE)) {
  332.             return $this;
  333.         }
  334.         $this->addLoginMethod(CustomerLoginMethod::GOOGLE);
  335.         $this->googleHash null;
  336.         $this->googleHashGeneratedAt null;
  337.         return $this;
  338.     }
  339.     public function getOrcidId(): ?string
  340.     {
  341.         return $this->orcidId;
  342.     }
  343.     public function setOrcidId(string $orcidId): self
  344.     {
  345.         $this->orcidId $orcidId;
  346.         return $this;
  347.     }
  348.     public function setOrcidHash(string $orcidHash): self
  349.     {
  350.         $this->orcidHash $orcidHash;
  351.         $this->orcidHashGeneratedAt = new \DateTimeImmutable();
  352.         return $this;
  353.     }
  354.     public function getOrcidHash(): ?string
  355.     {
  356.         return $this->orcidHash;
  357.     }
  358.     public function getOrcidHashGeneratedAt(): ?\DateTimeImmutable
  359.     {
  360.         return $this->orcidHashGeneratedAt;
  361.     }
  362.     public function addOrcidLogin(): self
  363.     {
  364.         if ($this->isLoginMethodAvailable(CustomerLoginMethod::ORCID)) {
  365.             return $this;
  366.         }
  367.         $this->addLoginMethod(CustomerLoginMethod::ORCID);
  368.         $this->orcidHash null;
  369.         $this->orcidHashGeneratedAt null;
  370.         return $this;
  371.     }
  372.     public function setRegisterHash(string $registerHash): self
  373.     {
  374.         $this->registerHash $registerHash;
  375.         $this->registerHashGeneratedAt = new \DateTimeImmutable();
  376.         return $this;
  377.     }
  378.     public function getRegisterHash(): ?string
  379.     {
  380.         return $this->registerHash;
  381.     }
  382.     public function getRegisterHashGeneratedAt(): ?\DateTimeImmutable
  383.     {
  384.         return $this->registerHashGeneratedAt;
  385.     }
  386.     public function setResetPasswordHash(string $hash): self
  387.     {
  388.         $this->resetPasswordHash $hash;
  389.         $this->resetPasswordHashGeneratedAt = new \DateTimeImmutable();
  390.         return $this;
  391.     }
  392.     public function getResetPasswordHash(): ?string
  393.     {
  394.         return $this->resetPasswordHash;
  395.     }
  396.     public function getResetPasswordHashGeneratedAt(): ?\DateTimeImmutable
  397.     {
  398.         return $this->resetPasswordHashGeneratedAt;
  399.     }
  400.     public function getIsConfirmed(): bool
  401.     {
  402.         return $this->isConfirmed;
  403.     }
  404.     public function confirmRegister(): self
  405.     {
  406.         if ($this->isConfirmed) {
  407.             return $this;
  408.         }
  409.         $this->isConfirmed true;
  410.         $this->stat true;
  411.         $this->registerHash null;
  412.         $this->registerHashGeneratedAt null;
  413.         return $this;
  414.     }
  415.     public function getRegisterLanguage(): Language
  416.     {
  417.         return $this->registerLanguage;
  418.     }
  419.     public function setRegisterLanguage(Language $registerLanguage): self
  420.     {
  421.         $this->registerLanguage $registerLanguage;
  422.         return $this;
  423.     }
  424.     public function getLastLoginAt(): \DateTimeImmutable
  425.     {
  426.         return $this->lastLoginAt;
  427.     }
  428.     public function setLastLoginAt(\DateTimeImmutable $lastLoginAt): self
  429.     {
  430.         $this->lastLoginAt $lastLoginAt;
  431.         return $this;
  432.     }
  433.     /**
  434.      * @return Collection|CustomerDirectory[]
  435.      */
  436.     public function getDirectories(): Collection
  437.     {
  438.         return $this->directories;
  439.     }
  440.     public function addDirectory(CustomerDirectory $directory): self
  441.     {
  442.         if ($this->directories->contains($directory)) {
  443.             return $this;
  444.         }
  445.         $this->directories[] = $directory;
  446.         return $this;
  447.     }
  448.     public function removeDirectory(CustomerDirectory $directory): self
  449.     {
  450.         $this->directories->removeElement($directory);
  451.         return $this;
  452.     }
  453.     /**
  454.      * @return Collection|CustomerNotification[]
  455.      */
  456.     public function getNotifications(): Collection
  457.     {
  458.         return $this->notifications;
  459.     }
  460.     public function addNotification(CustomerNotification $notification): self
  461.     {
  462.         if ($this->notifications->contains($notification)) {
  463.             return $this;
  464.         }
  465.         $this->notifications[] = $notification;
  466.         return $this;
  467.     }
  468.     public function removeNotification(CustomerNotification $notification): self
  469.     {
  470.         $this->notifications->removeElement($notification);
  471.         return $this;
  472.     }
  473.     public function getDirectoriesItemsUuids(): array
  474.     {
  475.         if (! $this->directoriesItemsUuids) {
  476.             $this->directoriesItemsUuids = [];
  477.             /** @var CustomerDirectory $directory */
  478.             foreach ($this->getDirectories() as $directory) {
  479.                 /** @var CustomerDirectoryItem $item */
  480.                 foreach ($directory->getItems() as $item) {
  481.                     $this->directoriesItemsUuids[] = $item->getVolume()?->getUuid();
  482.                     $this->directoriesItemsUuids[] = $item->getIssue()?->getUuid();
  483.                     $this->directoriesItemsUuids[] = $item->getArticle()?->getUuid();
  484.                 }
  485.             }
  486.         }
  487.         return $this->directoriesItemsUuids;
  488.     }
  489.     public function getUsername(): string
  490.     {
  491.         return $this->email;
  492.     }
  493.     public function getUserIdentifier(): string
  494.     {
  495.         return $this->email;
  496.     }
  497.     public function getRoles(): array
  498.     {
  499.         return ['ROLE_CUSTOMER'];
  500.     }
  501.     public function getSalt(): ?string
  502.     {
  503.         return null;
  504.     }
  505.     public function eraseCredentials(): void
  506.     {
  507.         return;
  508.     }
  509. }