You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
120 lines
3.3 KiB
120 lines
3.3 KiB
<?php |
|
|
|
declare(strict_types=1); |
|
|
|
namespace AutoStore\Infrastructure\Repositories; |
|
|
|
use AutoStore\Application\Exceptions\ApplicationException; |
|
use AutoStore\Application\Interfaces\IUserRepository; |
|
use AutoStore\Domain\Entities\User; |
|
use AutoStore\Domain\Exceptions\DomainException; |
|
use AutoStore\Infrastructure\Mappers\UserMapper; |
|
use Psr\Log\LoggerInterface; |
|
|
|
class FileUserRepository implements IUserRepository |
|
{ |
|
private string $storagePath; |
|
private LoggerInterface $logger; |
|
private array $users = []; |
|
|
|
public function __construct(string $storagePath, LoggerInterface $logger) |
|
{ |
|
$this->storagePath = $storagePath; |
|
$this->logger = $logger; |
|
|
|
$this->ensureStorageDirectoryExists(); |
|
$this->loadUsers(); |
|
} |
|
|
|
public function save(User $user): void |
|
{ |
|
$this->users[$user->getId()] = UserMapper::toArray($user); |
|
$this->persistUsers(); |
|
|
|
$this->logger->info("User saved: {$user->getId()}"); |
|
} |
|
|
|
public function findById(string $id): ?User |
|
{ |
|
if (!isset($this->users[$id])) { |
|
return null; |
|
} |
|
|
|
try { |
|
return UserMapper::fromArray($this->users[$id]); |
|
} catch (DomainException $e) { |
|
$this->logger->error("Failed to create user from data: " . $e->getMessage()); |
|
return null; |
|
} |
|
} |
|
|
|
public function findByUsername(string $username): ?User |
|
{ |
|
foreach ($this->users as $userData) { |
|
if ($userData['username'] === $username) { |
|
try { |
|
return UserMapper::fromArray($userData); |
|
} catch (DomainException $e) { |
|
$this->logger->error("Failed to create user from data: " . $e->getMessage()); |
|
return null; |
|
} |
|
} |
|
} |
|
|
|
return null; |
|
} |
|
|
|
public function exists(string $id): bool |
|
{ |
|
return isset($this->users[$id]); |
|
} |
|
|
|
private function ensureStorageDirectoryExists(): void |
|
{ |
|
if (!is_dir($this->storagePath)) { |
|
if (!mkdir($this->storagePath, 0755, true)) { |
|
throw new ApplicationException("Failed to create storage directory: {$this->storagePath}"); |
|
} |
|
} |
|
} |
|
|
|
private function loadUsers(): void |
|
{ |
|
$filename = $this->storagePath . '/users.json'; |
|
|
|
if (!file_exists($filename)) { |
|
return; |
|
} |
|
|
|
$content = file_get_contents($filename); |
|
|
|
if ($content === false) { |
|
throw new ApplicationException("Failed to read users file: {$filename}"); |
|
} |
|
|
|
$data = json_decode($content, true); |
|
|
|
if ($data === null) { |
|
throw new ApplicationException("Failed to decode users JSON: " . json_last_error_msg()); |
|
} |
|
|
|
$this->users = $data; |
|
$this->logger->info("Loaded " . count($this->users) . " users from storage"); |
|
} |
|
|
|
private function persistUsers(): void |
|
{ |
|
$filename = $this->storagePath . '/users.json'; |
|
$content = json_encode($this->users, JSON_PRETTY_PRINT); |
|
|
|
if ($content === false) { |
|
throw new ApplicationException("Failed to encode users to JSON"); |
|
} |
|
|
|
$result = file_put_contents($filename, $content); |
|
|
|
if ($result === false) { |
|
throw new ApplicationException("Failed to write users file: {$filename}"); |
|
} |
|
} |
|
} |