|null $meta Meta. * @param DateTimeImmutable $created_at Created UTC. * @param DateTimeImmutable $updated_at Updated UTC. * @param DateTimeImmutable|null $deleted_at Soft delete. * * @throws \Bookline\Domain\Shared\DomainException When invariants fail. */ public function __construct( private ?int $id, private Uuid $uuid, private ?int $wp_user_id, private string $display_name, private EmailAddress $email, private ?PhoneNumber $phone, private ?string $bio, private ?int $avatar_id, private TimeZoneId $timezone, private AgentStatus $status, private ?string $colour, private int $sort_order, private ?array $meta, private DateTimeImmutable $created_at, private DateTimeImmutable $updated_at, private ?DateTimeImmutable $deleted_at = null, ) { if ( '' === trim( $this->display_name ) ) { throw new DomainException( 'agent.name_empty', 'Agent display name must not be empty.' ); } if ( null !== $this->colour && 1 !== preg_match( '/^#[0-9A-Fa-f]{6}$/', $this->colour ) ) { throw new DomainException( 'agent.colour_invalid', 'Colour must be #RRGGBB.' ); } if ( null !== $this->wp_user_id && $this->wp_user_id < 1 ) { throw new DomainException( 'agent.wp_user_id', 'wp_user_id must be positive when set.' ); } } /** * Database id. * * @since 0.1.0 */ public function id(): ?int { return $this->id; } /** * Public UUID. * * @since 0.1.0 */ public function uuid(): Uuid { return $this->uuid; } /** * Wp user id. * * @since 0.1.0 */ public function wp_user_id(): ?int { return $this->wp_user_id; } /** * Display name. * * @since 0.1.0 */ public function display_name(): string { return $this->display_name; } /** * Email. * * @since 0.1.0 */ public function email(): EmailAddress { return $this->email; } /** * Phone. * * @since 0.1.0 */ public function phone(): ?PhoneNumber { return $this->phone; } /** * Bio. * * @since 0.1.0 */ public function bio(): ?string { return $this->bio; } /** * Avatar id. * * @since 0.1.0 */ public function avatar_id(): ?int { return $this->avatar_id; } /** * Timezone. * * @since 0.1.0 */ public function timezone(): TimeZoneId { return $this->timezone; } /** * Status. * * @since 0.1.0 */ public function status(): AgentStatus { return $this->status; } /** * Colour. * * @since 0.1.0 */ public function colour(): ?string { return $this->colour; } /** * Sort order. * * @since 0.1.0 */ public function sort_order(): int { return $this->sort_order; } /** * Opaque meta payload. * * @return array|null * * @since 0.1.0 */ public function meta(): ?array { return $this->meta; } /** * Created at. * * @since 0.1.0 */ public function created_at(): DateTimeImmutable { return $this->created_at; } /** * Updated at. * * @since 0.1.0 */ public function updated_at(): DateTimeImmutable { return $this->updated_at; } /** * Deleted at. * * @since 0.1.0 */ public function deleted_at(): ?DateTimeImmutable { return $this->deleted_at; } /** * Whether soft-deleted. * * @since 0.1.0 */ public function is_deleted(): bool { return null !== $this->deleted_at; } /** * Assign the database id after insert. * * @param int $id New id. * * @throws \Bookline\Domain\Shared\DomainException When id is already set or invalid. * * @since 0.1.0 */ public function assign_id( int $id ): void { if ( null !== $this->id ) { throw new DomainException( 'agent.id_assigned', 'Agent id is already assigned.' ); } $this->id = $id; } /** * Constructor. * * @param DateTimeImmutable $when Deletion instant UTC. * * @since 0.1.0 */ public function soft_delete( DateTimeImmutable $when ): void { if ( null !== $this->deleted_at ) { return; } $this->deleted_at = $when; $this->updated_at = $when; $this->status = AgentStatus::Inactive; } }