<?php
declare(strict_types=1);
class Reader {
public function __construct(
private int $id,
private string $name,
private string $email
) {}
public function getId(): int { return $this->id; }
public function getName(): string { return $this->name; }
public function getEmail(): string { return $this->email; }
}
class Book {
public function __construct(
private string $isbn,
private string $title,
private string $author,
private int $copies
) {}
public function getTitle(): string { return $this->title; }
public function isAvailable(): bool { return $this->copies > 0; }
public function take(): void {
if (!$this->isAvailable()) {
throw new RuntimeException("Нет свободных экземпляров");
}
$this->copies--;
}
public function giveBack(): void { $this->copies++; }
}
class Booking {
private bool $returned = false;
public function __construct(
private Reader $reader,
private Book $book,
private DateTimeImmutable $dueDate
) {}
public function getReader(): Reader { return $this->reader; }
public function getBook(): Book { return $this->book; }
public function isOverdue(): bool {
return !$this->returned && new DateTimeImmutable() > $this->dueDate;
}
public function close(): void {
if (!$this->returned) {
$this->returned = true;
$this->book->giveBack();
}
}
}
class Library {
private array $books = [];
private array $readers = [];
private array $bookings = [];
public function addBook(Book $book): void { $this->books[] = $book; }
public function registerReader(Reader $reader): void { $this->readers[] = $reader; }
public function findByTitle(string $title): array {
return array_values(array_filter(
$this->books,
fn(Book $b) => mb_stripos($b->getTitle(), $title) !== false
));
}
public function issueBook(Reader $reader, Book $book, int $days = 14): Booking {
$book->take();
$booking = new Booking($reader, $book, new DateTimeImmutable("+$days days"));
$this->bookings[] = $booking;
return $booking;
}
public function returnBook(Booking $booking): void { $booking->close(); }
public function getOverdueNotifications(): array {
$messages = [];
foreach ($this->bookings as $booking) {
if ($booking->isOverdue()) {
$messages[] = sprintf(
"%s (%s), верните книгу «%s»",
$booking->getReader()->getName(),
$booking->getReader()->getEmail(),
$booking->getBook()->getTitle()
);
}
}
return $messages;
}
}