src/Entity/Customer.php line 78
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM,
Doctrine\DBAL\Types\Types,
Doctrine\Common\Collections\ArrayCollection,
Doctrine\Common\Collections\Collection;
use Symfony\Component\Serializer\Annotation\Groups,
Symfony\Component\Validator\Constraints as Assert,
Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface,
Symfony\Component\Security\Core\User\UserInterface,
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface,
Symfony\Component\Validator\Constraint;
use ApiPlatform\Metadata\ApiResource,
ApiPlatform\Metadata\ApiProperty,
ApiPlatform\Metadata\Get,
ApiPlatform\Metadata\GetCollection,
ApiPlatform\Metadata\Post,
ApiPlatform\Metadata\Put,
ApiPlatform\Metadata\Delete,
ApiPlatform\Metadata\ApiFilter,
ApiPlatform\Doctrine\Orm\Filter\SearchFilter,
ApiPlatform\Doctrine\Orm\Filter\BooleanFilter,
ApiPlatform\Doctrine\Orm\Filter\OrderFilter;
use App\Entity\Trait\IdTrait,
App\Entity\Trait\UuidTrait,
App\Entity\Trait\TimestampableTrait,
App\Entity\Trait\StatTrait,
App\Entity\Interface\SimpleEntityInterface,
App\Entity\Interface\StatableInterface,
App\Entity\Interface\PasswordResetableInterface;
use App\Enum\Language,
App\Validator\Constraints\User as CustomAssert,
App\Repository\CustomerRepository,
App\StateProcessor\CustomerRegister\PostRegisterProcessor,
App\Doctrine\DBAL\Types\CustomerLoginMethodsType,
App\Enum\CustomerLoginMethod;
#[ApiResource(
description: 'Customers',
normalizationContext: ['groups' => ['read', 'read:' . self::class]],
denormalizationContext: ['groups' => ['write']],
order: ['createdAt' => 'desc'],
operations: [
new GetCollection(
security: 'is_granted("' . self::class . '")'
),
new Post(
uriTemplate: '/customers/register',
denormalizationContext: ['groups' => ['register']],
processor: PostRegisterProcessor::class,
validationContext: ['groups' => [Constraint::DEFAULT_GROUP, 'register']],
),
new Post(
processor: PostRegisterProcessor::class,
validationContext: ['groups' => [Constraint::DEFAULT_GROUP, 'post']],
),
new Get(
security: 'is_granted("' . self::class . '")'
),
new Put(
security: 'is_granted("' . self::class . '")'
),
new Delete(
security: 'is_granted("' . self::class . '")'
)
],
extraProperties: ['standard_put' => false],
)]
#[ApiFilter(SearchFilter::class, properties: ['email' => 'partial', 'fullName' => 'partial'])]
#[ApiFilter(BooleanFilter::class, properties: ['stat'])]
#[ApiFilter(OrderFilter::class, properties: ['email', 'fullName', 'stat', 'createdAt', 'updatedAt'])]
#[ORM\Entity(repositoryClass: CustomerRepository::class)]
class Customer implements
SimpleEntityInterface,
StatableInterface,
UserInterface,
PasswordAuthenticatedUserInterface,
PasswordResetableInterface
{
use IdTrait,
UuidTrait,
TimestampableTrait,
StatTrait;
const MAX_PREVIOUS_PASSWORDS = 5;
#[ApiProperty(description: 'Email')]
#[Groups(['read', 'write', 'register'])]
#[Assert\NotBlank]
#[Assert\Email]
#[ORM\Column(type: Types::STRING, length: 191, unique: true)]
private string $email;
#[ApiProperty(description: 'Persisted password')]
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
private ?string $password = null;
#[ApiProperty(description: 'New password')]
#[Groups(['write', 'register'])]
#[Assert\NotBlank(groups: ['post', 'register'])]
#[Assert\Length(max: 50, groups: [Constraint::DEFAULT_GROUP, 'profile'])]
#[Assert\Regex(
pattern: '/^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-\.]).{8,}$/',
match: true,
message: 'Password must consist of at least 8 characters (upper case, lower case, number, special character)',
groups: [Constraint::DEFAULT_GROUP, 'profile']
)]
#[Assert\NotCompromisedPassword(groups: [Constraint::DEFAULT_GROUP, 'profile'])]
#[CustomAssert\PreviousPasswords(groups: [Constraint::DEFAULT_GROUP, 'profile'])]
private ?string $rawPassword = null;
#[ApiProperty(description: 'New password repeat')]
#[Groups(['write', 'register'])]
#[Assert\Expression(
expression: 'value === this.getRawPassword()',
message: 'Passwords do not match.',
groups: ['post', 'register', 'profile']
)]
private ?string $rawPasswordRepeat = null;
#[ApiProperty(description: 'Current password')]
#[CustomAssert\CurrentPassword(groups: ['profile'])]
private ?string $currentPassword = null;
#[ApiProperty(description: 'Previous passwords')]
#[ORM\Column(type: Types::JSON)]
private array $previousPasswords = [];
#[ApiProperty(description: 'Name and surname')]
#[Groups(['read', 'write', 'register'])]
#[Assert\NotBlank]
#[Assert\Length(min: 3)]
#[ORM\Column(type: Types::STRING, length: 255)]
private string $fullName;
#[ApiProperty(description: 'Is regulations accepted')]
#[Groups(['register'])]
#[Assert\IsTrue(groups: ['register'])]
private bool $isRegulationsAccepted = false;
#[ApiProperty(description: 'Is privacy policy accepted')]
#[Groups(['register'])]
#[Assert\IsTrue(groups: ['register'])]
private bool $isPrivacyPolicyAccepted = false;
#[ApiProperty(description: 'Login methods')]
#[ORM\Column(type: CustomerLoginMethodsType::NAME)]
private array $loginMethods = [];
#[ApiProperty(description: 'Google id')]
#[Groups(['read:' . self::class])]
#[ORM\Column(type: Types::STRING, length: 1023, nullable: true)]
private ?string $googleId = null;
#[ApiProperty(description: 'Google hash')]
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
private ?string $googleHash = null;
#[ApiProperty(description: 'Google hash generated at')]
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)]
private ?\DateTimeImmutable $googleHashGeneratedAt = null;
#[ApiProperty(description: 'Orcid id')]
#[Groups(['read:' . self::class])]
#[ORM\Column(type: Types::STRING, length: 1023, nullable: true)]
private ?string $orcidId = null;
#[ApiProperty(description: 'Orcid hash')]
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
private ?string $orcidHash = null;
#[ApiProperty(description: 'Orcid hash generated at')]
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)]
private ?\DateTimeImmutable $orcidHashGeneratedAt = null;
#[ApiProperty(description: 'Register hash')]
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
private ?string $registerHash = null;
#[ApiProperty(description: 'Register hash generated at')]
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)]
private ?\DateTimeImmutable $registerHashGeneratedAt = null;
#[ApiProperty(description: 'Reset password hash')]
#[ORM\Column(type: Types::STRING, length: 255, nullable: true)]
private ?string $resetPasswordHash = null;
#[ApiProperty(description: 'Reset password hash generated at')]
#[ORM\Column(type: Types::DATETIME_IMMUTABLE, nullable: true)]
private ?\DateTimeImmutable $resetPasswordHashGeneratedAt = null;
#[ApiProperty(description: 'Is confirmed')]
#[Groups(['read:' . self::class])]
#[ORM\Column(type: Types::BOOLEAN, options: ['default' => false])]
private bool $isConfirmed = false;
#[ApiProperty(description: 'Register language')]
#[Groups(['read:' . self::class, 'register'])]
#[ORM\Column(
type: Types::STRING,
enumType: Language::class,
length: 255,
options: ['default' => Language::EN]
)]
private Language $registerLanguage = Language::EN;
#[ApiProperty(description: 'Last login at')]
#[Groups(['read:' . self::class])]
#[ORM\Column(type: Types::DATETIME_IMMUTABLE)]
private \DateTimeImmutable $lastLoginAt;
#[ApiProperty(description: 'Directories')]
#[ORM\OneToMany(targetEntity: CustomerDirectory::class, mappedBy: 'parent', cascade: ['persist', 'remove'])]
#[ORM\OrderBy(['createdAt' => 'desc'])]
private Collection $directories;
private ?array $directoriesItemsUuids = null;
#[ORM\OneToMany(targetEntity: CustomerNotification::class, mappedBy: 'parent', cascade: ['persist', 'remove'])]
#[ORM\OrderBy(['createdAt' => 'desc'])]
private Collection $notifications;
public function __construct(string $email)
{
$this->setUuid();
$this->email = $email;
$this->lastLoginAt = new \DateTimeImmutable();
$this->directories = new ArrayCollection();
$this->notifications = new ArrayCollection();
$this->createdAt = new \DateTimeImmutable();
$this->updatedAt = new \DateTimeImmutable();
}
public function getEmail(): string
{
return $this->email;
}
public function getPassword(): ?string
{
return $this->password;
}
public function getRawPassword(): ?string
{
return $this->rawPassword;
}
public function setRawPassword(?string $rawPassword, UserPasswordHasherInterface $encoder): self
{
if (! $rawPassword) {
return $this;
}
$this->rawPassword = $rawPassword;
$this->password = $encoder->hashPassword($this, $rawPassword);
if (count($this->previousPasswords) >= self::MAX_PREVIOUS_PASSWORDS) {
$this->previousPasswords = array_slice($this->previousPasswords, 1);
}
$this->previousPasswords[] = password_hash($rawPassword, PASSWORD_DEFAULT);
$this->resetPasswordHash = null;
$this->resetPasswordHashGeneratedAt = null;
$this->addLoginMethod(CustomerLoginMethod::PASSWORD);
return $this;
}
public function getRawPasswordRepeat(): ?string
{
return $this->rawPasswordRepeat;
}
public function setRawPasswordRepeat(?string $rawPasswordRepeat): self
{
$this->rawPasswordRepeat = $rawPasswordRepeat;
return $this;
}
public function setHashedPassword(string $hashedPassword): self
{
$this->password = $hashedPassword;
return $this;
}
public function getCurrentPassword(): ?string
{
return $this->currentPassword;
}
public function setCurrentPassword(?string $currentPassword): self
{
$this->currentPassword = $currentPassword;
return $this;
}
public function getPreviousPasswords(): array
{
return $this->previousPasswords;
}
public function getFullName(): string
{
return $this->fullName;
}
public function setFullName(string $fullName): self
{
$this->fullName = $fullName;
return $this;
}
public function getIsRegulationsAccepted(): bool
{
return $this->isRegulationsAccepted;
}
public function setIsRegulationsAccepted(bool $isRegulationsAccepted): self
{
$this->isRegulationsAccepted = $isRegulationsAccepted;
return $this;
}
public function getIsPrivacyPolicyAccepted(): bool
{
return $this->isPrivacyPolicyAccepted;
}
public function setIsPrivacyPolicyAccepted(bool $isPrivacyPolicyAccepted): self
{
$this->isPrivacyPolicyAccepted = $isPrivacyPolicyAccepted;
return $this;
}
public function getLoginMethods(): array
{
return $this->loginMethods;
}
private function addLoginMethod(CustomerLoginMethod $method): self
{
if ($this->isLoginMethodAvailable($method)) {
return $this;
}
$this->loginMethods[] = $method;
return $this;
}
public function isLoginMethodAvailable(CustomerLoginMethod $method): bool
{
return in_array($method, $this->loginMethods);
}
public function isPasswordLoginMethodAvailable(): bool
{
return in_array(CustomerLoginMethod::PASSWORD, $this->loginMethods);
}
public function getGoogleId(): ?string
{
return $this->googleId;
}
public function setGoogleId(string $googleId): self
{
$this->googleId = $googleId;
return $this;
}
public function setGoogleHash(string $googleHash): self
{
$this->googleHash = $googleHash;
$this->googleHashGeneratedAt = new \DateTimeImmutable();
return $this;
}
public function getGoogleHash(): ?string
{
return $this->googleHash;
}
public function getGoogleHashGeneratedAt(): ?\DateTimeImmutable
{
return $this->googleHashGeneratedAt;
}
public function addGoogleLogin(): self
{
if ($this->isLoginMethodAvailable(CustomerLoginMethod::GOOGLE)) {
return $this;
}
$this->addLoginMethod(CustomerLoginMethod::GOOGLE);
$this->googleHash = null;
$this->googleHashGeneratedAt = null;
return $this;
}
public function getOrcidId(): ?string
{
return $this->orcidId;
}
public function setOrcidId(string $orcidId): self
{
$this->orcidId = $orcidId;
return $this;
}
public function setOrcidHash(string $orcidHash): self
{
$this->orcidHash = $orcidHash;
$this->orcidHashGeneratedAt = new \DateTimeImmutable();
return $this;
}
public function getOrcidHash(): ?string
{
return $this->orcidHash;
}
public function getOrcidHashGeneratedAt(): ?\DateTimeImmutable
{
return $this->orcidHashGeneratedAt;
}
public function addOrcidLogin(): self
{
if ($this->isLoginMethodAvailable(CustomerLoginMethod::ORCID)) {
return $this;
}
$this->addLoginMethod(CustomerLoginMethod::ORCID);
$this->orcidHash = null;
$this->orcidHashGeneratedAt = null;
return $this;
}
public function setRegisterHash(string $registerHash): self
{
$this->registerHash = $registerHash;
$this->registerHashGeneratedAt = new \DateTimeImmutable();
return $this;
}
public function getRegisterHash(): ?string
{
return $this->registerHash;
}
public function getRegisterHashGeneratedAt(): ?\DateTimeImmutable
{
return $this->registerHashGeneratedAt;
}
public function setResetPasswordHash(string $hash): self
{
$this->resetPasswordHash = $hash;
$this->resetPasswordHashGeneratedAt = new \DateTimeImmutable();
return $this;
}
public function getResetPasswordHash(): ?string
{
return $this->resetPasswordHash;
}
public function getResetPasswordHashGeneratedAt(): ?\DateTimeImmutable
{
return $this->resetPasswordHashGeneratedAt;
}
public function getIsConfirmed(): bool
{
return $this->isConfirmed;
}
public function confirmRegister(): self
{
if ($this->isConfirmed) {
return $this;
}
$this->isConfirmed = true;
$this->stat = true;
$this->registerHash = null;
$this->registerHashGeneratedAt = null;
return $this;
}
public function getRegisterLanguage(): Language
{
return $this->registerLanguage;
}
public function setRegisterLanguage(Language $registerLanguage): self
{
$this->registerLanguage = $registerLanguage;
return $this;
}
public function getLastLoginAt(): \DateTimeImmutable
{
return $this->lastLoginAt;
}
public function setLastLoginAt(\DateTimeImmutable $lastLoginAt): self
{
$this->lastLoginAt = $lastLoginAt;
return $this;
}
/**
* @return Collection|CustomerDirectory[]
*/
public function getDirectories(): Collection
{
return $this->directories;
}
public function addDirectory(CustomerDirectory $directory): self
{
if ($this->directories->contains($directory)) {
return $this;
}
$this->directories[] = $directory;
return $this;
}
public function removeDirectory(CustomerDirectory $directory): self
{
$this->directories->removeElement($directory);
return $this;
}
/**
* @return Collection|CustomerNotification[]
*/
public function getNotifications(): Collection
{
return $this->notifications;
}
public function addNotification(CustomerNotification $notification): self
{
if ($this->notifications->contains($notification)) {
return $this;
}
$this->notifications[] = $notification;
return $this;
}
public function removeNotification(CustomerNotification $notification): self
{
$this->notifications->removeElement($notification);
return $this;
}
public function getDirectoriesItemsUuids(): array
{
if (! $this->directoriesItemsUuids) {
$this->directoriesItemsUuids = [];
/** @var CustomerDirectory $directory */
foreach ($this->getDirectories() as $directory) {
/** @var CustomerDirectoryItem $item */
foreach ($directory->getItems() as $item) {
$this->directoriesItemsUuids[] = $item->getVolume()?->getUuid();
$this->directoriesItemsUuids[] = $item->getIssue()?->getUuid();
$this->directoriesItemsUuids[] = $item->getArticle()?->getUuid();
}
}
}
return $this->directoriesItemsUuids;
}
public function getUsername(): string
{
return $this->email;
}
public function getUserIdentifier(): string
{
return $this->email;
}
public function getRoles(): array
{
return ['ROLE_CUSTOMER'];
}
public function getSalt(): ?string
{
return null;
}
public function eraseCredentials(): void
{
return;
}
}