id; } /** * File name of the original cover, see CoverStorage. */ public function getCover(): ?string { return $this->cover; } public function setCover(?string $cover): static { $this->cover = $cover; return $this; } public function setId(?int $id): static { $this->id = $id; return $this; } public function getTitle(): ?string { return $this->title; } public function setTitle(?string $title): static { $this->title = $title; return $this; } public function getAuthor(): ?string { return $this->author; } public function setAuthor(?string $author): static { $this->author = $author; return $this; } public function getLanguage(): ?string { return $this->language; } public function setLanguage(?string $language): static { $this->language = $language; return $this; } public function getEdition(): ?string { return $this->edition; } public function setEdition(?string $edition): static { $this->edition = $edition; return $this; } public function getPublisher(): ?string { return $this->publisher; } public function setPublisher(?string $publisher): static { $this->publisher = $publisher; return $this; } public function getPublicationLoc(): ?string { return $this->publicationLoc; } public function setPublicationLoc(?string $publicationLoc): static { $this->publicationLoc = $publicationLoc; return $this; } public function getPublicationYear(): ?int { return $this->publicationYear; } public function setPublicationYear(?int $publicationYear): static { $this->publicationYear = $publicationYear; return $this; } #[Assert\Callback] public function validateStandardNumbers(ExecutionContextInterface $context): void { foreach ([LabelType::ISBN, LabelType::ISSN] as $type) { $value = $this->firstLabel($type)?->getLabel(); if ($value !== null && !$type->isValid($value)) { $context->buildViolation('label_invalid_number') ->setTranslationDomain('messages') ->atPath($type->value) ->addViolation(); } } } public function getIsbn(): ?string { return $this->firstLabel(LabelType::ISBN)?->getLabel(); } public function setIsbn(?string $isbn): static { $this->replaceFirstLabel(LabelType::ISBN, $isbn); return $this; } public function getIssn(): ?string { return $this->firstLabel(LabelType::ISSN)?->getLabel(); } public function setIssn(?string $issn): static { $this->replaceFirstLabel(LabelType::ISSN, $issn); return $this; } /** * @return Collection */ abstract public function getLabels(): Collection; abstract protected function createLabel(string $label, LabelType $type): AbstractLabel; /** * @return list */ public function getTextLabels(): array { return array_values($this->getLabels()->filter( static fn(AbstractLabel $label): bool => $label->getType() === LabelType::TEXT, )->toArray()); } public function addLabel(string $text, LabelType $type = LabelType::TEXT): void { $text = $type->normalize($text); foreach ($this->getLabels() as $label) { if ($label->getType() === $type && $label->getLabel() === $text) { return; } } $this->getLabels()->add($this->createLabel($text, $type)); } public function removeLabel(AbstractLabel $label): void { $this->getLabels()->removeElement($label); } public function getPlacement(): ?string { return $this->placement; } public function setPlacement(?string $placement): static { $this->placement = $placement; return $this; } public function getLastSeen(): ?\DateTimeImmutable { return $this->lastSeen; } public function setLastSeen(?\DateTimeImmutable $lastSeen): static { $this->lastSeen = $lastSeen; return $this; } /** * Records that the book was found at $placement during an inventory. */ public function seenAt(string $placement, \DateTimeImmutable $at): void { $this->placement = $placement; $this->lastSeen = $at; } /** * Copies the bibliographic data and labels, keeping the ID; used when a book moves between * collections. */ protected function copyDataFrom(self $source): void { $this->id = $source->id; $this->title = $source->title; $this->author = $source->author; $this->language = $source->language; $this->edition = $source->edition; $this->publisher = $source->publisher; $this->publicationLoc = $source->publicationLoc; $this->publicationYear = $source->publicationYear; $this->placement = $source->placement; $this->cover = $source->cover; $this->lastSeen = $source->lastSeen; foreach ($source->getLabels() as $label) { $this->addLabel($label->getLabel(), $label->getType()); } } private function firstLabel(LabelType $type): ?AbstractLabel { foreach ($this->getLabels() as $label) { if ($label->getType() === $type) { return $label; } } return null; } private function replaceFirstLabel(LabelType $type, ?string $value): void { $value = $type->normalize((string)$value); $current = $this->firstLabel($type); if ($current?->getLabel() === $value) { return; } if ($current !== null) { $this->removeLabel($current); } if ($value !== '') { $this->addLabel($value, $type); } } }