add domain layer, config, and entry point
Domain: User, Session, EmailAddress, DTOs, repositories, services (PasswordHasher, TokenGenerator, Clock). Config: PHP-DI container definitions and Slim routes. Entry point: public/index.php with slim-bridge.
This commit is contained in:
parent
e54197f8a5
commit
9703f82788
18 changed files with 335 additions and 0 deletions
54
backend/app/Shared/ValueObject/EmailAddress.php
Normal file
54
backend/app/Shared/ValueObject/EmailAddress.php
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
<?php
|
||||
|
||||
namespace App\Shared\ValueObject;
|
||||
|
||||
use InvalidArgumentException;
|
||||
|
||||
final readonly class EmailAddress
|
||||
{
|
||||
private string $normalized;
|
||||
|
||||
private string $domain;
|
||||
|
||||
private const ERROR_MESSAGE = 'Invalid email address:';
|
||||
|
||||
public function __construct(string $email)
|
||||
{
|
||||
|
||||
$trimmed = trim($email);
|
||||
|
||||
if ($trimmed === '' || ! str_contains($trimmed, '@')) {
|
||||
throw new InvalidArgumentException(self::ERROR_MESSAGE." $email");
|
||||
}
|
||||
|
||||
[$local, $domain] = explode('@', $trimmed, 2);
|
||||
$this->domain = mb_strtolower($domain);
|
||||
$normalized = $local.'@'.$this->domain;
|
||||
|
||||
if (filter_var($normalized, FILTER_VALIDATE_EMAIL) === false) {
|
||||
throw new InvalidArgumentException(self::ERROR_MESSAGE." $email");
|
||||
}
|
||||
|
||||
$this->normalized = $normalized;
|
||||
}
|
||||
|
||||
public function value(): string
|
||||
{
|
||||
return $this->normalized;
|
||||
}
|
||||
|
||||
public function equals(self $other): bool
|
||||
{
|
||||
return $this->normalized === $other->normalized;
|
||||
}
|
||||
|
||||
public function getDomain(): string
|
||||
{
|
||||
return $this->domain;
|
||||
}
|
||||
|
||||
public function __toString(): string
|
||||
{
|
||||
return $this->normalized;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue