diff --git a/composer.json b/composer.json index 1de6224..27138ad 100644 --- a/composer.json +++ b/composer.json @@ -1,7 +1,7 @@ { "name": "kiwilan/php-ebook", "description": "PHP package to read metadata and extract covers from eBooks, comics and audiobooks.", - "version": "2.3.7", + "version": "2.3.8", "keywords": [ "php", "ebook", diff --git a/src/Ebook.php b/src/Ebook.php index fc97a2d..3d2531c 100755 --- a/src/Ebook.php +++ b/src/Ebook.php @@ -114,6 +114,7 @@ public static function read(string $path): ?self $self->convertEbook(); $self->cover = $self->parser->getModule()->toCover(); $self->metaTitle = MetaTitle::fromEbook($self); + $self->clean(); $time = microtime(true) - $start; $self->execTime = (float) number_format((float) $time, 5, '.', ''); @@ -255,6 +256,30 @@ private function pdf(): EbookModule return PdfModule::make($this); } + private function clean(): self + { + $authors = []; + foreach ($this->authors as $author) { + if (! $author->getName()) { + continue; + } + + $authors[] = $author; + } + + $this->authors = $authors; + + if ($this->authorMain && ! $this->authorMain->getName()) { + $this->authorMain = null; + + if (count($this->authors) > 0) { + $this->authorMain = reset($this->authors); + } + } + + return $this; + } + private function convertEbook(): self { $ebook = $this->parser->getModule()->toEbook(); diff --git a/src/Formats/Epub/EpubModule.php b/src/Formats/Epub/EpubModule.php index 8895fc4..fb5c37b 100644 --- a/src/Formats/Epub/EpubModule.php +++ b/src/Formats/Epub/EpubModule.php @@ -99,8 +99,8 @@ public function toEbook(): Ebook $this->ebook->setTags($tags); $rating = null; - if (! empty($this->opf->getMeta())) { - foreach ($this->opf->getMeta() as $meta) { + if (! empty($this->opf->getMetaItems())) { + foreach ($this->opf->getMetaItems() as $meta) { if ($meta->getName() === 'calibre:series') { $this->ebook->setSeries($meta->getContents()); } diff --git a/src/Formats/Epub/Parser/OpfItem.php b/src/Formats/Epub/Parser/OpfItem.php index 5401c70..b60bb81 100644 --- a/src/Formats/Epub/Parser/OpfItem.php +++ b/src/Formats/Epub/Parser/OpfItem.php @@ -298,11 +298,33 @@ public function getDcLanguage(): ?string } /** + * @deprecated Use `getMetaItems` instead. + * * @return BookMeta[] */ public function getMeta(): array { - return $this->meta; + return $this->getMetaItems(); + } + + /** + * @return BookMeta[] + */ + public function getMetaItems(): array + { + $items = []; + foreach ($this->meta as $item) { + $items[$item->getName()] = $item; + } + + return $items; + } + + public function getMetaItem(string $key): ?BookMeta + { + $meta = array_filter($this->meta, fn (BookMeta $item) => $item->getName() === $key); + + return array_shift($meta); } public function getCoverPath(): ?string diff --git a/tests/OpfTest.php b/tests/OpfTest.php index 78e1d78..61290bb 100644 --- a/tests/OpfTest.php +++ b/tests/OpfTest.php @@ -2,6 +2,7 @@ use Kiwilan\Ebook\Formats\Epub\Parser\EpubContainer; use Kiwilan\Ebook\Formats\Epub\Parser\OpfItem; +use Kiwilan\Ebook\Models\BookMeta; use Kiwilan\XmlReader\XmlReader; it('can parse epub container', function (string $path) { @@ -38,11 +39,56 @@ expect($opf->getDcIdentifiers())->toBeArray(); expect($opf->getDcSubject())->toBeArray(); expect($opf->getDcLanguage())->toBeString(); - expect($opf->getMeta())->toBeArray(); + expect($opf->getMetaItems())->toBeArray(); expect($opf->getCoverPath())->toBeString(); expect($opf->getEpubVersion())->toBeGreaterThanOrEqual(2); })->with([EPUB_OPF_EPUB2, EPUB_OPF_EPUB3, EPUB_OPF_INSURGENT, EPUB_OPF_LAGUERREETERNELLE, EPUB_OPF_EPEEETMORT, EPUB_OPF_NOT_FORMATTED]); +it('can parse epub opf meta items', function () { + $opf = OpfItem::make(file_get_contents(EPUB_OPF_EPUB2), EPUB_OPF_EPUB2); + + $meta = $opf->getMetaItems(); + + // calibre:title_sort + // calibre:series + // calibre:series_index + // calibre:timestamp + // calibre:rating + // cover + // calibre:author_link_map + + $title_sort = $opf->getMetaItem('calibre:title_sort'); + $series = $opf->getMetaItem('calibre:series'); + $series_index = $opf->getMetaItem('calibre:series_index'); + $timestamp = $opf->getMetaItem('calibre:timestamp'); + $rating = $opf->getMetaItem('calibre:rating'); + $cover = $opf->getMetaItem('cover'); + $author_link_map = $opf->getMetaItem('calibre:author_link_map'); + $not_exist = $opf->getMetaItem('not_exist'); + + expect($meta)->toBeArray(); + expect(get_class($title_sort))->toBe(BookMeta::class); + expect(get_class($series))->toBe(BookMeta::class); + expect(get_class($series_index))->toBe(BookMeta::class); + expect(get_class($timestamp))->toBe(BookMeta::class); + expect(get_class($rating))->toBe(BookMeta::class); + expect(get_class($cover))->toBe(BookMeta::class); + expect(get_class($author_link_map))->toBe(BookMeta::class); + expect($not_exist)->toBeNull(); + + expect($title_sort->getContents())->toBeString(); + expect($series->getContents())->toBeString(); + expect($series_index->getContents())->toBeString(); + expect($timestamp->getContents())->toBeString(); + expect($rating->getContents())->toBeString(); + expect($cover->getContents())->toBeString(); + expect($author_link_map->getContents())->toBeString(); + + expect($series->getContents())->toBe('Les Enfants de la Terre'); + expect($series_index->getContents())->toBe('1.0'); + expect($timestamp->getContents())->toBe('2023-03-25T10:32:21+00:00'); +}); + it('can parse epub opf alt', function () { $opf = OpfItem::make(file_get_contents(EPUB_OPF_EPUB3_ALT), EPUB_OPF_EPUB3_ALT); @@ -60,7 +106,7 @@ expect($opf->getDcDate())->toBeNull(); expect($opf->getDcSubject())->toBeArray(); expect($opf->getDcLanguage())->toBeString(); - expect($opf->getMeta())->toBeArray(); + expect($opf->getMetaItems())->toBeArray(); expect($opf->getCoverPath())->toBeString(); expect($opf->getEpubVersion())->toBeGreaterThanOrEqual(2); }); @@ -79,7 +125,7 @@ expect($opf->getDcIdentifiers())->toBeArray(); expect($opf->getDcSubject())->toBeArray(); expect($opf->getDcLanguage())->toBeString(); - expect($opf->getMeta())->toBeArray(); + expect($opf->getMetaItems())->toBeArray(); expect($opf->getCoverPath())->toBeString(); expect($opf->getEpubVersion())->toBeGreaterThanOrEqual(2); });