diff --git a/src/Entity/Base/TimestampTrait.php b/src/Entity/Base/TimestampTrait.php index c4c74255..9091fe70 100644 --- a/src/Entity/Base/TimestampTrait.php +++ b/src/Entity/Base/TimestampTrait.php @@ -32,26 +32,26 @@ use Symfony\Component\Serializer\Annotation\Groups; trait TimestampTrait { /** - * @var DateTime|null the date when this element was modified the last time - * @ORM\Column(type="datetime", name="last_modified", options={"default":"CURRENT_TIMESTAMP"}) + * @var \DateTimeInterface|null the date when this element was modified the last time */ #[Groups(['extended', 'full'])] - protected ?DateTime $lastModified = null; + #[ORM\Column(name: 'last_modified', type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, options: ['default' => 'CURRENT_TIMESTAMP'])] + protected ?\DateTimeInterface $lastModified = null; /** - * @var DateTime|null the date when this element was created - * @ORM\Column(type="datetime", name="datetime_added", options={"default":"CURRENT_TIMESTAMP"}) + * @var \DateTimeInterface|null the date when this element was created */ #[Groups(['extended', 'full'])] - protected ?DateTime $addedDate = null; + #[ORM\Column(name: 'datetime_added', type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, options: ['default' => 'CURRENT_TIMESTAMP'])] + protected ?\DateTimeInterface $addedDate = null; /** * Returns the last time when the element was modified. * Returns null if the element was not yet saved to DB yet. * - * @return DateTime|null the time of the last edit + * @return \DateTimeInterface|null the time of the last edit */ - public function getLastModified(): ?DateTime + public function getLastModified(): ?\DateTimeInterface { return $this->lastModified; } @@ -60,19 +60,18 @@ trait TimestampTrait * Returns the date/time when the element was created. * Returns null if the element was not yet saved to DB yet. * - * @return DateTime|null the creation time of the part + * @return \DateTimeInterface|null the creation time of the part */ - public function getAddedDate(): ?DateTime + public function getAddedDate(): ?\DateTimeInterface { return $this->addedDate; } /** * Helper for updating the timestamp. It is automatically called by doctrine before persisting. - * - * @ORM\PrePersist - * @ORM\PreUpdate */ + #[ORM\PrePersist] + #[ORM\PreUpdate] public function updateTimestamps(): void { $this->lastModified = new DateTime('now'); diff --git a/src/Entity/Contracts/TimeStampableInterface.php b/src/Entity/Contracts/TimeStampableInterface.php index e198ae7c..6393d629 100644 --- a/src/Entity/Contracts/TimeStampableInterface.php +++ b/src/Entity/Contracts/TimeStampableInterface.php @@ -30,15 +30,15 @@ interface TimeStampableInterface * Returns the last time when the element was modified. * Returns null if the element was not yet saved to DB yet. * - * @return DateTime|null the time of the last edit + * @return \DateTimeInterface|null the time of the last edit */ - public function getLastModified(): ?DateTime; + public function getLastModified(): ?\DateTimeInterface; /** * Returns the date/time when the element was created. * Returns null if the element was not yet saved to DB yet. * - * @return DateTime|null the creation time of the part + * @return \DateTimeInterface|null the creation time of the part */ - public function getAddedDate(): ?DateTime; + public function getAddedDate(): ?\DateTimeInterface; } diff --git a/src/Entity/Contracts/TimeTravelInterface.php b/src/Entity/Contracts/TimeTravelInterface.php index c756f53e..064f4fec 100644 --- a/src/Entity/Contracts/TimeTravelInterface.php +++ b/src/Entity/Contracts/TimeTravelInterface.php @@ -41,5 +41,5 @@ interface TimeTravelInterface /** * Returns the timestamp associated with this change. */ - public function getTimestamp(): DateTime; + public function getTimestamp(): \DateTimeInterface; } diff --git a/src/Entity/LogSystem/AbstractLogEntry.php b/src/Entity/LogSystem/AbstractLogEntry.php index 76b0d746..95bb7b76 100644 --- a/src/Entity/LogSystem/AbstractLogEntry.php +++ b/src/Entity/LogSystem/AbstractLogEntry.php @@ -49,31 +49,15 @@ use Psr\Log\LogLevel; /** * This entity describes an entry in the event log. - * - * @ORM\Entity(repositoryClass="App\Repository\LogEntryRepository") - * @ORM\Table("log", indexes={ - * @ORM\Index(name="log_idx_type", columns={"type"}), - * @ORM\Index(name="log_idx_type_target", columns={"type", "target_type", "target_id"}), - * @ORM\Index(name="log_idx_datetime", columns={"datetime"}), - * }) - * @ORM\InheritanceType("SINGLE_TABLE") - * @ORM\DiscriminatorColumn(name="type", type="smallint") - * @ORM\DiscriminatorMap({ - * 1 = "UserLoginLogEntry", - * 2 = "UserLogoutLogEntry", - * 3 = "UserNotAllowedLogEntry", - * 4 = "ExceptionLogEntry", - * 5 = "ElementDeletedLogEntry", - * 6 = "ElementCreatedLogEntry", - * 7 = "ElementEditedLogEntry", - * 8 = "ConfigChangedLogEntry", - * 9 = "LegacyInstockChangedLogEntry", - * 10 = "DatabaseUpdatedLogEntry", - * 11 = "CollectionElementDeleted", - * 12 = "SecurityEventLogEntry", - * 13 = "PartStockChangedLogEntry", - * }) */ +#[ORM\Entity(repositoryClass: 'App\Repository\LogEntryRepository')] +#[ORM\InheritanceType('SINGLE_TABLE')] +#[ORM\DiscriminatorColumn(name: 'type', type: 'smallint')] +#[ORM\DiscriminatorMap([1 => 'UserLoginLogEntry', 2 => 'UserLogoutLogEntry', 3 => 'UserNotAllowedLogEntry', 4 => 'ExceptionLogEntry', 5 => 'ElementDeletedLogEntry', 6 => 'ElementCreatedLogEntry', 7 => 'ElementEditedLogEntry', 8 => 'ConfigChangedLogEntry', 9 => 'LegacyInstockChangedLogEntry', 10 => 'DatabaseUpdatedLogEntry', 11 => 'CollectionElementDeleted', 12 => 'SecurityEventLogEntry', 13 => 'PartStockChangedLogEntry'])] +#[ORM\Table('log')] +#[ORM\Index(name: 'log_idx_type', columns: ['type'])] +#[ORM\Index(name: 'log_idx_type_target', columns: ['type', 'target_type', 'target_id'])] +#[ORM\Index(name: 'log_idx_datetime', columns: ['datetime'])] abstract class AbstractLogEntry extends AbstractDBElement { public const LEVEL_EMERGENCY = 0; @@ -143,35 +127,35 @@ abstract class AbstractLogEntry extends AbstractDBElement ]; /** @var User|null The user which has caused this log entry - * @ORM\ManyToOne(targetEntity="App\Entity\UserSystem\User", fetch="EAGER") - * @ORM\JoinColumn(name="id_user", nullable=true, onDelete="SET NULL") */ + #[ORM\ManyToOne(targetEntity: 'App\Entity\UserSystem\User', fetch: 'EAGER')] + #[ORM\JoinColumn(name: 'id_user', onDelete: 'SET NULL')] protected ?User $user = null; /** * @var string The username of the user which has caused this log entry (shown if the user is deleted) - * @ORM\Column(type="string", nullable=false) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] protected string $username = ''; - /** @var DateTime The datetime the event associated with this log entry has occured - * @ORM\Column(type="datetime", name="datetime") + /** @var \DateTimeInterface|null The datetime the event associated with this log entry has occured */ - protected ?DateTime $timestamp = null; + #[ORM\Column(name: 'datetime', type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE)] + protected ?\DateTimeInterface $timestamp = null; /** @var int The priority level of the associated level. 0 is highest, 7 lowest - * @ORM\Column(type="tinyint", name="level", nullable=false) */ + #[ORM\Column(type: 'tinyint', name: 'level')] protected int $level; /** @var int The ID of the element targeted by this event - * @ORM\Column(name="target_id", type="integer", nullable=false) */ + #[ORM\Column(name: 'target_id', type: \Doctrine\DBAL\Types\Types::INTEGER)] protected int $target_id = 0; /** @var int The Type of the targeted element - * @ORM\Column(name="target_type", type="smallint", nullable=false) */ + #[ORM\Column(name: 'target_type', type: \Doctrine\DBAL\Types\Types::SMALLINT)] protected int $target_type = 0; /** @var string The type of this log entry, aka the description what has happened. @@ -181,8 +165,8 @@ abstract class AbstractLogEntry extends AbstractDBElement protected string $typeString = 'unknown'; /** @var array The extra data in raw (short form) saved in the DB - * @ORM\Column(name="extra", type="json") */ + #[ORM\Column(name: 'extra', type: \Doctrine\DBAL\Types\Types::JSON)] protected array $extra = []; public function __construct() @@ -264,7 +248,7 @@ abstract class AbstractLogEntry extends AbstractDBElement /** * Returns the timestamp when the event that caused this log entry happened. */ - public function getTimestamp(): DateTime + public function getTimestamp(): \DateTimeInterface { return $this->timestamp; } @@ -274,7 +258,7 @@ abstract class AbstractLogEntry extends AbstractDBElement * * @return $this */ - public function setTimestamp(DateTime $timestamp): self + public function setTimestamp(\DateTimeInterface $timestamp): self { $this->timestamp = $timestamp; diff --git a/src/Entity/Parts/Part.php b/src/Entity/Parts/Part.php index c4e9d00a..df127d94 100644 --- a/src/Entity/Parts/Part.php +++ b/src/Entity/Parts/Part.php @@ -47,15 +47,13 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; * * The class properties are split over various traits in directory PartTraits. * Otherwise, this class would be too big, to be maintained. - * - * @ORM\Entity(repositoryClass="App\Repository\PartRepository") - * @ORM\Table("`parts`", indexes={ - * @ORM\Index(name="parts_idx_datet_name_last_id_needs", columns={"datetime_added", "name", "last_modified", "id", "needs_review"}), - * @ORM\Index(name="parts_idx_name", columns={"name"}), - * @ORM\Index(name="parts_idx_ipn", columns={"ipn"}), - * }) */ #[UniqueEntity(fields: ['ipn'], message: 'part.ipn.must_be_unique')] +#[ORM\Entity(repositoryClass: 'App\Repository\PartRepository')] +#[ORM\Table('`parts`')] +#[ORM\Index(name: 'parts_idx_datet_name_last_id_needs', columns: ['datetime_added', 'name', 'last_modified', 'id', 'needs_review'])] +#[ORM\Index(name: 'parts_idx_name', columns: ['name'])] +#[ORM\Index(name: 'parts_idx_ipn', columns: ['ipn'])] class Part extends AttachmentContainingDBElement { use AdvancedPropertyTrait; @@ -68,54 +66,44 @@ class Part extends AttachmentContainingDBElement use ProjectTrait; /** @var Collection - * @ORM\OneToMany(targetEntity="App\Entity\Parameters\PartParameter", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) - * @ORM\OrderBy({"group" = "ASC" ,"name" = "ASC"}) */ #[Assert\Valid] #[Groups(['full'])] + #[ORM\OneToMany(targetEntity: 'App\Entity\Parameters\PartParameter', mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] + #[ORM\OrderBy(['group' => 'ASC', 'name' => 'ASC'])] protected Collection $parameters; - /** - * @ORM\Column(type="datetime", name="datetime_added", options={"default":"CURRENT_TIMESTAMP"}) - */ - protected ?DateTime $addedDate = null; /** ************************************************************* * Overridden properties * (They are defined here and not in a trait, to avoid conflicts). ****************************************************************/ - /** * @var string The name of this part - * @ORM\Column(type="string") */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING)] protected string $name = ''; /** * @var Collection - * @ORM\OneToMany(targetEntity="App\Entity\Attachments\PartAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) - * @ORM\OrderBy({"name" = "ASC"}) */ #[Assert\Valid] #[Groups(['full'])] + #[ORM\OneToMany(targetEntity: 'App\Entity\Attachments\PartAttachment', mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] + #[ORM\OrderBy(['name' => 'ASC'])] protected Collection $attachments; - /** - * @var DateTime|null the date when this element was modified the last time - * @ORM\Column(type="datetime", name="last_modified", options={"default":"CURRENT_TIMESTAMP"}) - */ - protected ?DateTime $lastModified = null; - /** * @var Attachment|null - * @ORM\ManyToOne(targetEntity="App\Entity\Attachments\Attachment") - * @ORM\JoinColumn(name="id_preview_attachment", referencedColumnName="id", onDelete="SET NULL", nullable=true) */ #[Assert\Expression('value == null or value.isPicture()', message: 'part.master_attachment.must_be_picture')] + #[ORM\ManyToOne(targetEntity: 'App\Entity\Attachments\Attachment')] + #[ORM\JoinColumn(name: 'id_preview_attachment', onDelete: 'SET NULL')] protected ?Attachment $master_picture_attachment = null; public function __construct() { + $this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); parent::__construct(); $this->partLots = new ArrayCollection(); $this->orderdetails = new ArrayCollection(); diff --git a/src/Entity/Parts/PartLot.php b/src/Entity/Parts/PartLot.php index e8bc4917..eb47581e 100644 --- a/src/Entity/Parts/PartLot.php +++ b/src/Entity/Parts/PartLot.php @@ -40,84 +40,83 @@ use Symfony\Component\Validator\Context\ExecutionContextInterface; * This entity describes a lot where parts can be stored. * It is the connection between a part and its store locations. * - * @ORM\Entity() - * @ORM\Table(name="part_lots", indexes={ - * @ORM\Index(name="part_lots_idx_instock_un_expiration_id_part", columns={"instock_unknown", "expiration_date", "id_part"}), - * @ORM\Index(name="part_lots_idx_needs_refill", columns={"needs_refill"}), - * }) - * @ORM\HasLifecycleCallbacks() * @ValidPartLot() */ +#[ORM\Entity] +#[ORM\HasLifecycleCallbacks] +#[ORM\Table(name: 'part_lots')] +#[ORM\Index(name: 'part_lots_idx_instock_un_expiration_id_part', columns: ['instock_unknown', 'expiration_date', 'id_part'])] +#[ORM\Index(name: 'part_lots_idx_needs_refill', columns: ['needs_refill'])] class PartLot extends AbstractDBElement implements TimeStampableInterface, NamedElementInterface { use TimestampTrait; /** * @var string A short description about this lot, shown in table - * @ORM\Column(type="text") */ #[Groups(['simple', 'extended', 'full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] protected string $description = ''; /** * @var string a comment stored with this lot - * @ORM\Column(type="text") */ #[Groups(['full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] protected string $comment = ''; /** - * @var ?DateTime Set a time until when the lot must be used. + * @var \DateTimeInterface|null Set a time until when the lot must be used. * Set to null, if the lot can be used indefinitely. - * @ORM\Column(type="datetime", name="expiration_date", nullable=true) */ #[Groups(['extended', 'full', 'import'])] - protected ?DateTime $expiration_date = null; + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, name: 'expiration_date', nullable: true)] + protected ?\DateTimeInterface $expiration_date = null; /** * @var Storelocation|null The storelocation of this lot - * @ORM\ManyToOne(targetEntity="Storelocation") - * @ORM\JoinColumn(name="id_store_location", referencedColumnName="id", nullable=true) * @Selectable() */ #[Groups(['simple', 'extended', 'full', 'import'])] + #[ORM\ManyToOne(targetEntity: 'Storelocation')] + #[ORM\JoinColumn(name: 'id_store_location')] protected ?Storelocation $storage_location = null; /** * @var bool If this is set to true, the instock amount is marked as not known - * @ORM\Column(type="boolean") */ #[Groups(['simple', 'extended', 'full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] protected bool $instock_unknown = false; /** * @var float For continuous sizes (length, volume, etc.) the instock is saved here. - * @ORM\Column(type="float") */ #[Assert\PositiveOrZero] #[Groups(['simple', 'extended', 'full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::FLOAT)] protected float $amount = 0.0; /** * @var bool determines if this lot was manually marked for refilling - * @ORM\Column(type="boolean") */ #[Groups(['extended', 'full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] protected bool $needs_refill = false; /** * @var Part The part that is stored in this lot - * @ORM\ManyToOne(targetEntity="Part", inversedBy="partLots") - * @ORM\JoinColumn(name="id_part", referencedColumnName="id", nullable=false, onDelete="CASCADE") */ #[Assert\NotNull] + #[ORM\ManyToOne(targetEntity: 'Part', inversedBy: 'partLots')] + #[ORM\JoinColumn(name: 'id_part', nullable: false, onDelete: 'CASCADE')] protected Part $part; /** * @var User|null The owner of this part lot - * @ORM\ManyToOne(targetEntity="App\Entity\UserSystem\User") - * @ORM\JoinColumn(name="id_owner", referencedColumnName="id", nullable=true, onDelete="SET NULL") */ + #[ORM\ManyToOne(targetEntity: 'App\Entity\UserSystem\User')] + #[ORM\JoinColumn(name: 'id_owner', onDelete: 'SET NULL')] protected ?User $owner = null; public function __clone() @@ -189,7 +188,7 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named /** * Gets the expiration date for the part lot. Returns null, if no expiration date was set. */ - public function getExpirationDate(): ?DateTime + public function getExpirationDate(): ?\DateTimeInterface { return $this->expiration_date; } @@ -197,11 +196,11 @@ class PartLot extends AbstractDBElement implements TimeStampableInterface, Named /** * Sets the expiration date for the part lot. Set to null, if the part lot does not expire. * - * @param DateTime|null $expiration_date + * @param \DateTimeInterface|null $expiration_date * * @return PartLot */ - public function setExpirationDate(?DateTime $expiration_date): self + public function setExpirationDate(?\DateTimeInterface $expiration_date): self { $this->expiration_date = $expiration_date; diff --git a/src/Entity/Parts/PartTraits/ProjectTrait.php b/src/Entity/Parts/PartTraits/ProjectTrait.php index 795b5393..a8a7162c 100644 --- a/src/Entity/Parts/PartTraits/ProjectTrait.php +++ b/src/Entity/Parts/PartTraits/ProjectTrait.php @@ -4,6 +4,7 @@ namespace App\Entity\Parts\PartTraits; use App\Entity\ProjectSystem\Project; use App\Entity\ProjectSystem\ProjectBOMEntry; +use Doctrine\Common\Collections\ArrayCollection; use Doctrine\Common\Collections\Collection; use Doctrine\ORM\Mapping as ORM; @@ -13,7 +14,7 @@ trait ProjectTrait * @var \Doctrine\Common\Collections\Collection<\App\Entity\ProjectSystem\ProjectBOMEntry> $project_bom_entries */ #[ORM\OneToMany(targetEntity: 'App\Entity\ProjectSystem\ProjectBOMEntry', mappedBy: 'part', cascade: ['remove'], orphanRemoval: true)] - protected \Doctrine\Common\Collections\Collection $project_bom_entries = []; + protected \Doctrine\Common\Collections\Collection $project_bom_entries; /** * @var Project|null If a project is set here, then this part is special and represents the builds of a project. diff --git a/src/Entity/UserSystem/User.php b/src/Entity/UserSystem/User.php index 6dc06455..be4998e4 100644 --- a/src/Entity/UserSystem/User.php +++ b/src/Entity/UserSystem/User.php @@ -54,14 +54,12 @@ use Jbtronics\TFAWebauthn\Model\TwoFactorInterface as WebauthnTwoFactorInterface /** * This entity represents a user, which can log in and have permissions. * Also, this entity is able to save some information about the user, like the names, email-address and other info. - * - * @ORM\Entity(repositoryClass="App\Repository\UserRepository") - * @ORM\Table("`users`", indexes={ - * @ORM\Index(name="user_idx_username", columns={"name"}) - * }) - * @ORM\EntityListeners({"App\EntityListeners\TreeCacheInvalidationListener"}) */ #[UniqueEntity('name', message: 'validator.user.username_already_used')] +#[ORM\Entity(repositoryClass: 'App\Repository\UserRepository')] +#[ORM\EntityListeners(['App\EntityListeners\TreeCacheInvalidationListener'])] +#[ORM\Table('`users`')] +#[ORM\Index(name: 'user_idx_username', columns: ['name'])] class User extends AttachmentContainingDBElement implements UserInterface, HasPermissionsInterface, TwoFactorInterface, BackupCodeInterface, TrustedDeviceInterface, WebauthnTwoFactorInterface, PreferredProviderInterface, PasswordAuthenticatedUserInterface, SamlUserInterface { @@ -74,175 +72,167 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe /** * @var bool Determines if the user is disabled (user can not log in) - * @ORM\Column(type="boolean") */ #[Groups(['extended', 'full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] protected bool $disabled = false; /** * @var string|null The theme - * @ORM\Column(type="string", name="config_theme", nullable=true) * @ValidTheme() */ #[Groups(['full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, name: 'config_theme', nullable: true)] protected ?string $theme = null; /** * @var string|null the hash of a token the user must provide when he wants to reset his password - * @ORM\Column(type="string", nullable=true) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, nullable: true)] protected ?string $pw_reset_token = null; - /** - * @ORM\Column(type="text", name="config_instock_comment_a") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, name: 'config_instock_comment_a')] protected string $instock_comment_a = ''; - /** - * @ORM\Column(type="text", name="config_instock_comment_w") - */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT, name: 'config_instock_comment_w')] protected string $instock_comment_w = ''; /** * @var string A self-description of the user - * @ORM\Column(type="text") */ #[Groups(['full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::TEXT)] protected string $aboutMe = ''; /** @var int The version of the trusted device cookie. Used to invalidate all trusted device cookies at once. - * @ORM\Column(type="integer") */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] protected int $trustedDeviceCookieVersion = 0; /** * @var string[]|null A list of backup codes that can be used, if the user has no access to its Google Authenticator device - * @ORM\Column(type="json") */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] protected ?array $backupCodes = []; - /** - * @ORM\Id() - * @ORM\GeneratedValue() - * @ORM\Column(type="integer") - */ + #[ORM\Id] + #[ORM\GeneratedValue] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::INTEGER)] protected ?int $id = null; /** * @var Group|null the group this user belongs to * DO NOT PUT A fetch eager here! Otherwise, you can not unset the group of a user! This seems to be some kind of bug in doctrine. Maybe this is fixed in future versions. - * @ORM\ManyToOne(targetEntity="Group", inversedBy="users") - * @ORM\JoinColumn(name="group_id", referencedColumnName="id") * @Selectable() */ #[Groups(['extended', 'full', 'import'])] + #[ORM\ManyToOne(targetEntity: 'Group', inversedBy: 'users')] + #[ORM\JoinColumn(name: 'group_id')] protected ?Group $group = null; /** * @var string|null The secret used for Google authenticator - * @ORM\Column(name="google_authenticator_secret", type="string", nullable=true) */ + #[ORM\Column(name: 'google_authenticator_secret', type: \Doctrine\DBAL\Types\Types::STRING, nullable: true)] protected ?string $googleAuthenticatorSecret = null; /** * @var string|null The timezone the user prefers - * @ORM\Column(type="string", name="config_timezone", nullable=true) */ #[Assert\Timezone] #[Groups(['full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, name: 'config_timezone', nullable: true)] protected ?string $timezone = ''; /** * @var string|null The language/locale the user prefers - * @ORM\Column(type="string", name="config_language", nullable=true) */ #[Assert\Language] #[Groups(['full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, name: 'config_language', nullable: true)] protected ?string $language = ''; /** * @var string|null The email address of the user - * @ORM\Column(type="string", length=255, nullable=true) */ #[Assert\Email] #[Groups(['simple', 'extended', 'full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] protected ?string $email = ''; /** * @var bool True if the user wants to show his email address on his (public) profile - * @ORM\Column(type="boolean", options={"default": false}) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN, options: ['default' => false])] protected bool $show_email_on_profile = false; /** * @var string|null The department the user is working - * @ORM\Column(type="string", length=255, nullable=true) */ #[Groups(['simple', 'extended', 'full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] protected ?string $department = ''; /** * @var string|null The last name of the User - * @ORM\Column(type="string", length=255, nullable=true) */ #[Groups(['simple', 'extended', 'full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] protected ?string $last_name = ''; /** * @var string|null The first name of the User - * @ORM\Column(type="string", length=255, nullable=true) */ #[Groups(['simple', 'extended', 'full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 255, nullable: true)] protected ?string $first_name = ''; /** * @var bool True if the user needs to change password after log in - * @ORM\Column(type="boolean") */ #[Groups(['extended', 'full', 'import'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] protected bool $need_pw_change = true; /** * @var string|null The hashed password - * @ORM\Column(type="string", nullable=true) */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, nullable: true)] protected ?string $password = null; - /** - * @ORM\Column(type="string", length=180, unique=true) - */ #[Assert\NotBlank] #[Assert\Regex('/^[\w\.\+\-\$]+$/', message: 'user.invalid_username')] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::STRING, length: 180, unique: true)] protected string $name = ''; /** * @var array|null - * @ORM\Column(type="json") */ + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::JSON)] protected ?array $settings = []; /** * @var Collection - * @ORM\OneToMany(targetEntity="App\Entity\Attachments\UserAttachment", mappedBy="element", cascade={"persist", "remove"}, orphanRemoval=true) - * @ORM\OrderBy({"name" = "ASC"}) */ + #[ORM\OneToMany(targetEntity: 'App\Entity\Attachments\UserAttachment', mappedBy: 'element', cascade: ['persist', 'remove'], orphanRemoval: true)] + #[ORM\OrderBy(['name' => 'ASC'])] protected Collection $attachments; - /** @var DateTime|null The time when the backup codes were generated - * @ORM\Column(type="datetime", nullable=true) + /** @var \DateTimeInterface|null The time when the backup codes were generated */ #[Groups(['full'])] - protected ?DateTime $backupCodesGenerationDate = null; + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: true)] + protected ?\DateTimeInterface $backupCodesGenerationDate; /** @var Collection - * @ORM\OneToMany(targetEntity="App\Entity\UserSystem\U2FKey", mappedBy="user", cascade={"REMOVE"}, orphanRemoval=true) */ + #[ORM\OneToMany(targetEntity: 'App\Entity\UserSystem\U2FKey', mappedBy: 'user', cascade: ['REMOVE'], orphanRemoval: true)] protected Collection $u2fKeys; /** * @var Collection - * @ORM\OneToMany(targetEntity="App\Entity\UserSystem\WebauthnKey", mappedBy="user", cascade={"REMOVE"}, orphanRemoval=true) */ + #[ORM\OneToMany(targetEntity: 'App\Entity\UserSystem\WebauthnKey', mappedBy: 'user', cascade: ['REMOVE'], orphanRemoval: true)] protected Collection $webauthn_keys; /** @@ -250,36 +240,37 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe * Dont use fetch=EAGER here, this will cause problems with setting the currency setting. * TODO: This is most likely a bug in doctrine/symfony related to the UniqueEntity constraint (it makes a db call). * TODO: Find a way to use fetch EAGER (this improves performance a bit) - * @ORM\ManyToOne(targetEntity="App\Entity\PriceInformations\Currency") - * @ORM\JoinColumn(name="currency_id", referencedColumnName="id") * @Selectable() */ #[Groups(['extended', 'full', 'import'])] + #[ORM\ManyToOne(targetEntity: 'App\Entity\PriceInformations\Currency')] + #[ORM\JoinColumn(name: 'currency_id')] protected ?Currency $currency; /** * @var PermissionData|null * @ValidPermission() - * @ORM\Embedded(class="PermissionData", columnPrefix="permissions_") */ #[Groups(['simple', 'extended', 'full', 'import'])] + #[ORM\Embedded(class: 'PermissionData', columnPrefix: 'permissions_')] protected ?PermissionData $permissions = null; /** - * @var DateTime|null the time until the password reset token is valid - * @ORM\Column(type="datetime", nullable=true, options={"default": null}) + * @var \DateTimeInterface|null the time until the password reset token is valid */ - protected ?DateTime $pw_reset_expires; + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::DATETIME_MUTABLE, nullable: true)] + protected ?\DateTimeInterface $pw_reset_expires; /** * @var bool True if the user was created by a SAML provider (and therefore cannot change its password) - * @ORM\Column(type="boolean") */ #[Groups(['extended', 'full'])] + #[ORM\Column(type: \Doctrine\DBAL\Types\Types::BOOLEAN)] protected bool $saml_user = false; public function __construct() { + $this->attachments = new \Doctrine\Common\Collections\ArrayCollection(); parent::__construct(); $this->permissions = new PermissionData(); $this->u2fKeys = new ArrayCollection(); @@ -484,7 +475,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe /** * Gets the datetime when the password reset token expires. */ - public function getPwResetExpires(): DateTime + public function getPwResetExpires(): \DateTimeInterface { return $this->pw_reset_expires; } @@ -494,7 +485,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe * * @return User */ - public function setPwResetExpires(DateTime $pw_reset_expires): self + public function setPwResetExpires(\DateTimeInterface $pw_reset_expires): self { $this->pw_reset_expires = $pw_reset_expires; @@ -876,7 +867,7 @@ class User extends AttachmentContainingDBElement implements UserInterface, HasPe /** * Return the date when the backup codes were generated. */ - public function getBackupCodesGenerationDate(): ?DateTime + public function getBackupCodesGenerationDate(): ?\DateTimeInterface { return $this->backupCodesGenerationDate; }