<?php
/**
* @license Silk Software House Sp. Z O. O.
*/
declare(strict_types=1);
namespace App\Entity;
use App\Entity\Traits\IdTrait;
use App\Entity\Traits\TimePreUpdateTrait;
use App\Entity\Traits\TimeTrait;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\UserInterface;
use DateTime;
use Exception;
use App\Validator\Constraints as AppAssert;
/**
* Class User.
*
* @ORM\Entity(repositoryClass="App\Repository\UserRepository")
* @ORM\Table(name="users")
* @ORM\HasLifecycleCallbacks()
*
* @UniqueEntity(fields={"email"}, repositoryMethod="findCaseInsensitiveByEmail")
* @UniqueEntity(fields={"username"}, repositoryMethod="findCaseInsensitiveByUsername")
*/
class User implements UserInterface
{
use IdTrait;
use TimeTrait;
use TimePreUpdateTrait;
/**
* Username.
*
* @var string
*
* @ORM\Column(name="username", type="text", unique=true)
*/
private string $username = '';
/**
* Email.
*
* @ORM\Column(name="email", type="string", length=180, unique=true)
*/
private string $email = '';
/**
* Roles.
*
* @ORM\Column(name="roles", type="json")
*/
private array $roles = [];
/**
* Password.
*
* @var string The hashed password
*
* @ORM\Column(name="password", type="string")
*/
private string $password = '';
/**
* Customer.
*
* @var Customer|null
*
* @AppAssert\ValidCustomerForUser()
*
* @ORM\ManyToOne(targetEntity="App\Entity\Customer", inversedBy="users", cascade={"persist"})
* @ORM\JoinColumn(name="customer_id", nullable=true)
*/
private ?Customer $customer = null;
/**
* Hash used to change password.
*
* @var string|null
*
* @ORM\Column(name="hash", type="text", nullable=true, options={
* "comment": "Hash used to generate password resetting url."
* })
*/
private ?string $hash = null;
/**
* Time to which hash will be active.
*
* @var DateTime|null
*
* @ORM\Column(name="hash_validity_ends_at", type="datetime", nullable=true, options={
* "comment": "Hash validity ends at.",
* })
*/
private ?DateTime $hashValidityEndsAt = null;
/**
* Time when this user was activated.
*
* @var DateTime|null
*
* @ORM\Column(name="activated_at", type="datetime", nullable=true, options={
* "comment": "Activated at.",
* })
*/
private ?DateTime $activatedAt = null;
/**
* Time when the user was blocked.
*
* @var DateTime|null
*
* @ORM\Column(name="blocked_at", type="datetime", nullable=true, options={
* "comment": "Blocked at.",
* })
*/
private ?DateTime $blockedAt = null;
/**
* User setting.
*
* @var UserSetting|null
*
* @ORM\OneToOne(targetEntity="App\Entity\UserSetting", mappedBy="user")
*/
private ?UserSetting $setting = null;
/**
* Phone.
*
* @var string|null
*
* @ORM\Column(name="phone", type="text", nullable=true, options={
* "comment": "Phone."
* })
*/
private ?string $phone = null;
/**
* Surname.
*
* @var string|null
*
* @ORM\Column(name="surname", type="text", nullable=true, options={
* "comment": "Surname."
* })
*/
private ?string $surname = null;
/**
* First name.
*
* @var string|null
*
* @ORM\Column(name="first_name", type="text", nullable=true, options={
* "comment": "First name."
* })
*/
private ?string $firstName = null;
/**
* Get email.
*
* @return string|null
*/
public function getEmail(): ?string
{
return $this->email;
}
/**
* Set email.
*
* @param string $email
*
* @return User
*/
public function setEmail(string $email): self
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* @return string
*
* @see UserInterface
*/
public function getUsername(): string
{
return $this->username;
}
/**
* Get roles.
*
* @return array
*
* @see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
/**
* Set roles.
*
* @param array $roles
*
* @return User
*/
public function setRoles(array $roles): self
{
$this->roles = $roles;
return $this;
}
/**
* Get roles extended.
*
* @return string
*/
public function getRoleSingle(): string
{
if ($this->hasRole('ROLE_ADMIN')) {
return 'ROLE_ADMIN';
}
if ($this->hasRole('ROLE_CUSTOMER')) {
return 'ROLE_CUSTOMER';
}
return 'ROLE_USER';
}
/**
* Set role single.
*
* @param string $role
*
* @return User
*/
public function setRoleSingle(string $role): self
{
return $this->setRoles([$role]);
}
/**
* Has role.
*
* @param string $role
*
* @return bool
*/
public function hasRole(string $role): bool
{
return in_array($role, $this->getRoles());
}
/**
* Get password.
*
* @see UserInterface
*
* @return string
*/
public function getPassword(): string
{
return $this->password;
}
/**
* Set password.
*
* @param string $password
*
* @return User
*/
public function setPassword(string $password): self
{
$this->password = $password;
return $this;
}
/**
* @see UserInterface
*/
public function eraseCredentials()
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
/**
* Get customer.
*
* @return Customer|null
*/
public function getCustomer(): ?Customer
{
return $this->customer;
}
/**
* Set customer.
*
* @param Customer|null $customer
*
* @return User
*/
public function setCustomer(?Customer $customer): self
{
$this->customer = $customer;
return $this;
}
/**
* @inheritDoc
*/
public function getSalt()
{
// TODO: Implement getSalt() method.
}
/**
* Get hash.
*
* @return string|null
*/
public function getHash(): ?string
{
return $this->hash;
}
/**
* Set hash.
*
* @param string|null $hash
*
* @return User
*/
public function setHash(?string $hash): self
{
$this->hash = $hash;
return $this;
}
/**
* Get hash validity ends at.
*
* @return DateTime|null
*/
public function getHashValidityEndsAt(): ?DateTime
{
return $this->hashValidityEndsAt;
}
/**
* Set hash validity ends at.
*
* @param DateTime|null $hashValidityEndsAt
*
* @return User
*/
public function setHashValidityEndsAt(?DateTime $hashValidityEndsAt): self
{
$this->hashValidityEndsAt = $hashValidityEndsAt;
return $this;
}
/**
* Start the password resetting process.
*
* @return User
*/
public function startPasswordResettingProcess(): self
{
$this->hash = md5(uniqid((string)mt_rand(), true));
try {
$this->hashValidityEndsAt = new DateTime('+30min');
} catch (Exception $e) {
}
return $this;
}
/**
* Can password resetting be triggered?
*
* @return bool
*/
public function canPasswordResettingBeTriggered(): bool
{
try {
return !$this->hashValidityEndsAt || $this->hashValidityEndsAt < new DateTime();
} catch (Exception $e) {
}
return false;
}
/**
* Is hash correct?
*
* @param string|null $hash
*
* @return bool
*/
public function getIsHashCorrect(?string $hash): bool
{
try {
return $hash && $hash === $this->hash && $this->hashValidityEndsAt >= new DateTime();
} catch (Exception $e) {
}
return false;
}
/**
* Get activated at.
*
* @return DateTime|null
*/
public function getActivatedAt(): ?DateTime
{
return $this->activatedAt;
}
/**
* Set activated at.
*
* @param DateTime|null $activatedAt
*
* @return User
*/
public function setActivatedAt(?DateTime $activatedAt): self
{
$this->activatedAt = $activatedAt;
return $this;
}
/**
* Get blocked at.
*
* @return DateTime|null
*/
public function getBlockedAt(): ?DateTime
{
return $this->blockedAt;
}
/**
* Set blocked at.
*
* @param DateTime|null $blockedAt
*
* @return User
*/
public function setBlockedAt(?DateTime $blockedAt): self
{
$this->blockedAt = $blockedAt;
return $this;
}
/**
* Set username.
*
* @param string $username
*
* @return User
*/
public function setUsername(string $username): self
{
$this->username = $username;
return $this;
}
/**
* Get active customer.
*
* @return Customer|null
*/
public function getActiveCustomer(): ?Customer
{
return $this->customer && (!$this->customer->getActiveTo() || $this->customer->getActiveTo() > new DateTime())
? $this->customer : null;
}
/**
* To string.
*
* @return string
*/
public function __toString()
{
return $this->username ?? '';
}
/**
* Belongs to.
*
* @param User $user
*
* @return bool
*/
public function belongsTo(self $user): bool
{
if ($user->hasRole('ROLE_ADMIN')) {
return true;
}
if (!$user->hasRole('ROLE_CUSTOMER') || !$this->getActiveCustomer() || !$user->getActiveCustomer()) {
return false;
}
return $user->getActiveCustomer()->getId() === $this->getActiveCustomer()->getId();
}
/**
* Get user setting.
*
* @return UserSetting|null
*/
public function getSetting(): ?UserSetting
{
return $this->setting;
}
/**
* @return int[]
*/
public function getUsedDevicesIds(): array
{
return $this->setting ? $this->setting->getUsedDevices()->map(function (Device $device) {
return $device->getId();
})->toArray() : [];
}
/**
* Set user setting.
*
* @param UserSetting|null $setting
*
* @return User
*/
public function setSetting(?UserSetting $setting): self
{
$this->setting = $setting;
return $this;
}
/**
* Get phone.
*
* @return string|null
*/
public function getPhone(): ?string
{
return $this->phone;
}
/**
* Set phone.
*
* @param string|null $phone
*
* @return User
*/
public function setPhone(?string $phone): self
{
$this->phone = $phone;
return $this;
}
/**
* Get surname.
*
* @return string|null
*/
public function getSurname(): ?string
{
return $this->surname;
}
/**
* Set surname.
*
* @param string|null $surname
*
* @return User
*/
public function setSurname(?string $surname): self
{
$this->surname = $surname;
return $this;
}
/**
* Get first name.
*
* @return string|null
*/
public function getFirstName(): ?string
{
return $this->firstName;
}
/**
* Set the first name.
*
* @param string|null $firstName
*
* @return User
*/
public function setFirstName(?string $firstName): self
{
$this->firstName = $firstName;
return $this;
}
/**
* Get a standard recipe.
*
* @return Recipe|null
*/
public function getStandardRecipe(): ?Recipe
{
return $this->getSetting() ? $this->getSetting()->getStandardRecipe() : null;
}
/**
* Sanitize
*
* @return void
*/
public function normalize(): void
{
if ($this->username) {
$this->username = strtolower($this->username);
}
if ($this->email) {
$this->email = strtolower($this->email);
}
}
}