From 037458c9c67827dbb1a3750792eb69180244449f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ewilan=20Rivi=C3=A8re?= Date: Sun, 30 Jun 2024 15:07:28 +0200 Subject: [PATCH 1/3] README --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 715cd26..4c2d1f7 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ PHP package to read metadata and extract covers from eBooks, comics and audiobooks. +> Because metadata are the key against chaos. + - eBooks: `.epub`, `.pdf`, `.azw`, `.azw3`, `.kf8`, `.kfx`, `.mobi`, `.prc`, `.fb2` - Comics: `.cbz`, `.cbr`, `.cb7`, `.cbt` (metadata from [github.com/anansi-project](https://github.com/anansi-project)) - Audiobooks: `.mp3`, `.m4a`, `.m4b`, `.flac`, `.ogg` with external package[`kiwilan/php-audio`](https://github.com/kiwilan/php-audio) (**MUST** be installed separately) From ea189a3083c193500e4a7d4d43a31368c37c4365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ewilan=20Rivi=C3=A8re?= Date: Wed, 10 Jul 2024 15:40:57 +0200 Subject: [PATCH 2/3] v2.6.1 Refactor `MetaTitle::class` - `getSeriesSlugSimple()`, `getSlugSimple()` are deprecated - `getSlug()` have now multiple parameters to customize the slug: `removeDeterminers`, `addSeries`, `addVolume`, `addAuthor`, `addYear`, `addExtension`, `addLanguage` (all are `true` by default) - `getSeriesSlug()` have now multiple parameters to customize the slug: `removeDeterminers`, `addAuthor`, `addExtension`, `addLanguage` (`removeDeterminers`, `addExtension`, `addLanguage` are `true` by default, `addAuthor` is `false` by default) --- README.md | 11 +- composer.json | 2 +- src/Models/MetaTitle.php | 262 ++++++++++++++++++++++++++------------- tests/EpubTest.php | 2 +- tests/MetaTitleTest.php | 130 ++++++++++++++++++- 5 files changed, 309 insertions(+), 98 deletions(-) diff --git a/README.md b/README.md index 4c2d1f7..54d9cef 100644 --- a/README.md +++ b/README.md @@ -230,9 +230,14 @@ $ebook = Ebook::read('path/to/ebook.epub'); $metaTitle = $ebook->getMetaTitle(); // ?MetaTitle $metaTitle->getSlug(); // string => slug title, like `lord-of-the-rings-en-01-fellowship-of-the-ring-j-r-r-tolkien-1954-epub` -$metaTitle->getSlugSimple(); // string => slug title simple, like `the-fellowship-of-the-ring` -$metaTitle->getSeriesSlug(); // ?string => slug series title, like `lord-of-the-rings-en-j-r-r-tolkien-epub` -$metaTitle->getSeriesSlugSimple(); // ?string => slug series title simple, like `the-lord-of-the-rings` +$metaTitle->getSeriesSlug(); // ?string => slug series title, like `lord-of-the-rings-en-epub` +``` + +You can customize slug with `MetaTitle::class`: + +```php +$meta->getSlug(removeDeterminers: true, addSeries: true, addVolume: true, addAuthor: true, addYear: true, addExtension: true, addLanguage: true); +$meta->getSeriesSlug(removeDeterminers: true, addAuthor: false, addExtension: true, addLanguage: true); ``` ### Cover diff --git a/composer.json b/composer.json index 31e7712..5593755 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.6.0", + "version": "2.6.1", "keywords": [ "php", "ebook", diff --git a/src/Models/MetaTitle.php b/src/Models/MetaTitle.php index 7c6a044..58c0d0b 100644 --- a/src/Models/MetaTitle.php +++ b/src/Models/MetaTitle.php @@ -279,6 +279,9 @@ class MetaTitle ]; protected function __construct( + protected ?string $originalTitle = null, + protected ?string $originalSeries = null, + protected ?string $title = null, protected ?string $language = null, protected ?string $series = null, @@ -286,14 +289,12 @@ protected function __construct( protected ?string $author = null, protected ?string $year = null, protected ?string $extension = null, - - protected ?string $slug = null, - protected ?string $slugSimple = null, - protected ?string $seriesSlug = null, - protected ?string $seriesSlugSimple = null, + protected ?string $titleDeterminer = null, + protected ?string $seriesDeterminer = null, protected bool $useIntl = true, - ) {} + ) { + } /** * Create a new MetaTitle instance from an Ebook. @@ -307,6 +308,8 @@ public static function fromEbook(Ebook $ebook, bool $useIntl = true): ?self } $self = new self( + originalTitle: $ebook->getTitle(), + originalSeries: $ebook->getSeries(), title: $ebook->getTitle(), language: $ebook->getLanguage(), series: $ebook->getSeries(), @@ -314,8 +317,8 @@ public static function fromEbook(Ebook $ebook, bool $useIntl = true): ?self author: $ebook->getAuthorMain()?->getName(), year: $ebook->getPublishDate()?->format('Y'), extension: $ebook->getExtension(), + useIntl: $useIntl, ); - $self->useIntl = $useIntl; $self->parse(); return $self; @@ -337,6 +340,8 @@ public static function fromData( bool $useIntl = true, ): self { $self = new self( + originalTitle: $title, + originalSeries: $series, title: $title, language: $language, series: $series, @@ -353,106 +358,187 @@ public static function fromData( private function parse(): static { - $title = $this->generateSlug($this->title); - $language = $this->language ? $this->generateSlug($this->language) : null; - $series = $this->series ? $this->generateSlug($this->series) : null; - $volume = $this->parseVolume($this->volume); - $author = $this->author ? $this->generateSlug($this->author) : null; - $year = $this->year ? $this->generateSlug($this->year) : null; - $extension = $this->extension ? strtolower($this->extension) : null; - - if (! $title) { + $this->title = $this->generateSlug($this->title); + $this->language = $this->language ? $this->generateSlug($this->language) : null; + $this->series = $this->series ? $this->generateSlug($this->series) : null; + $this->volume = $this->parseVolume($this->volume); + $this->author = $this->author ? $this->generateSlug($this->author) : null; + $this->year = $this->year ? $this->generateSlug($this->year) : null; + $this->extension = $this->extension ? strtolower($this->extension) : null; + + if (! $this->title) { return $this; } - $title = $this->removeDots($title); - $language = $this->removeDots($language); - $series = $this->removeDots($series); - $author = $this->removeDots($author); - $year = $this->removeDots($year); + $this->title = $this->removeDots($this->title); + $this->language = $this->removeDots($this->language); + $this->series = $this->removeDots($this->series); + $this->author = $this->removeDots($this->author); + $this->year = $this->removeDots($this->year); + + $this->titleDeterminer = $this->removeDeterminers($this->originalTitle, $this->language); + $this->seriesDeterminer = $this->removeDeterminers($this->originalSeries, $this->language); + + return $this; + } - $titleDeterminer = $this->removeDeterminers($this->title, $this->language); - $seriesDeterminer = $this->removeDeterminers($this->series, $this->language); + /** + * Get slug of book title with addional metadata, like `lord-of-the-rings-001-fellowship-of-the-ring-j-r-r-tolkien-1954-epub-en` with default values. + * + * @param bool $removeDeterminers Remove determiners, here `The` + * @param bool $addSeries Add serie title, here `Lord of the Rings` (if book has series) + * @param bool $addVolume Add volume, here `1` + * @param bool $addAuthor Add author name, here `J. R. R. Tolkien` + * @param bool $addYear Add year, here `1954` + * @param bool $addExtension Add extension, here `epub` + * @param bool $addLanguage Add language, here `en` + */ + public function getSlug( + bool $removeDeterminers = true, + bool $addSeries = true, + bool $addVolume = true, + bool $addAuthor = true, + bool $addYear = true, + bool $addExtension = true, + bool $addLanguage = true, + ): string { + $params = []; if ($this->series) { - $this->slug = $this->generateSlug([ - $seriesDeterminer, - $language, - $volume, - $titleDeterminer, - $author, - $year, - $extension, - ]); + if ($addSeries) { + if ($removeDeterminers) { + $params[] = $this->seriesDeterminer; + } else { + $params[] = $this->series; + } + } + + if ($addLanguage) { + $params[] = $this->language; + } + + if ($addVolume) { + $params[] = $this->volume; + } + + if ($removeDeterminers) { + $params[] = $this->titleDeterminer; + } else { + $params[] = $this->title; + } + + if ($addAuthor) { + $params[] = $this->author; + } + + if ($addYear) { + $params[] = $this->year; + } + + if ($addExtension) { + $params[] = $this->extension; + } + + return $this->generateSlug($params); + } + + if ($removeDeterminers) { + $params[] = $this->titleDeterminer; } else { - $this->slug = $this->generateSlug([ - $titleDeterminer, - $language, - $author, - $year, - $extension, - ]); + $params[] = $this->title; } - $this->slugSimple = $this->generateSlug([$title]); - if (! $this->series) { - return $this; + if ($addLanguage) { + $params[] = $this->language; } - $this->seriesSlug = $this->generateSlug([ - $seriesDeterminer, - $language, - $author, - $extension, - ]); - $this->seriesSlugSimple = $this->generateSlug([$series]); + if ($addAuthor) { + $params[] = $this->author; + } - return $this; - } + if ($addYear) { + $params[] = $this->year; + } - /** - * Get slug of book title with addional metadata, like `lord-of-the-rings-001-fellowship-of-the-ring-j-r-r-tolkien-1954-epub-en`. - * - * - Remove determiners, here `The` - * - Add serie title, here `Lord of the Rings` - * - Add volume, here `1` - * - Add author name, here `J. R. R. Tolkien` - * - Add year, here `1954` - * - Add extension, here `epub` - * - Add language, here `en` - */ - public function getSlug(): string - { - return $this->slug; + if ($addExtension) { + $params[] = $this->extension; + } + + return $this->generateSlug($params); } /** + * @deprecated Use `getSlug()` with parameters instead. + * * Get simple slug of book title, like `the-fellowship-of-the-ring`. */ public function getSlugSimple(): string { - return $this->slugSimple; + return $this->getSlug( + removeDeterminers: false, + addSeries: false, + addVolume: false, + addAuthor: false, + addYear: false, + addExtension: false, + addLanguage: false, + ); } /** * Get slug of serie title, like `lord-of-the-rings-j-r-r-tolkien-epub-en`. * - * - Remove determiners, here `The` - * - Add author name, here `J. R. R. Tolkien` - * - Add extension, here `epub` - * - Add language, here `en` + * @param bool $removeDeterminers, here `The` + * @param bool $addAuthor name, here `J. R. R. Tolkien`, default `false` + * @param bool $addExtension, here `epub` + * @param bool $addLanguage, here `en` */ - public function getSeriesSlug(): ?string - { - return $this->seriesSlug; + public function getSeriesSlug( + bool $removeDeterminers = true, + bool $addAuthor = false, + bool $addExtension = true, + bool $addLanguage = true, + ): ?string { + if (! $this->series) { + return null; + } + + $params = []; + + if ($removeDeterminers) { + $params[] = $this->seriesDeterminer; + } else { + $params[] = $this->series; + } + + if ($addLanguage) { + $params[] = $this->language; + } + + if ($addAuthor) { + $params[] = $this->author; + } + + if ($addExtension) { + $params[] = $this->extension; + } + + return $this->generateSlug($params); } /** + * @deprecated Use `getSeriesSlug()` instead. + * * Get simple slug of serie title, like `the-lord-of-the-rings`. */ public function getSeriesSlugSimple(): ?string { - return $this->seriesSlugSimple; + return $this->getSeriesSlug( + removeDeterminers: false, + addAuthor: false, + addExtension: false, + addLanguage: false, + ); } /** @@ -460,7 +546,7 @@ public function getSeriesSlugSimple(): ?string */ public function getSlugSort(): string { - return $this->slug; + return $this->getSlug(); } /** @@ -468,7 +554,7 @@ public function getSlugSort(): string */ public function getSlugUnique(): string { - return $this->slug; + return $this->getSlug(); } /** @@ -476,7 +562,7 @@ public function getSlugUnique(): string */ public function getSerieSlug(): ?string { - return $this->seriesSlugSimple; + return $this->getSeriesSlugSimple(); } /** @@ -484,7 +570,7 @@ public function getSerieSlug(): ?string */ public function getSerieSlugSort(): ?string { - return $this->seriesSlug; + return $this->getSeriesSlug(); } /** @@ -492,7 +578,7 @@ public function getSerieSlugSort(): ?string */ public function getSerieSlugUnique(): ?string { - return $this->seriesSlug; + return $this->getSeriesSlug(); } /** @@ -500,7 +586,7 @@ public function getSerieSlugUnique(): ?string */ public function getSlugSortWithSerie(): string { - return $this->slug; + return $this->getSlug(); } /** @@ -508,7 +594,7 @@ public function getSlugSortWithSerie(): string */ public function getUniqueFilename(): string { - return $this->slug; + return $this->getSlug(); } private function parseVolume(?string $volume): ?string @@ -563,8 +649,8 @@ private function removeDeterminers(?string $string, ?string $language): ?string $lowercaseArticles = array_map('lcfirst', $articlesLang); $articlesLang = array_merge($uppercaseArticles, $lowercaseArticles); - foreach ($articlesLang as $key => $value) { - $string = preg_replace('/^'.preg_quote($value, '/').'/i', '', $string); + foreach ($articlesLang as $articleLang) { + $string = preg_replace('/^'.preg_quote($articleLang, '/').'/i', '', $string); } return $string; @@ -597,16 +683,16 @@ private function generateSlug(array|string $strings): ?string public function toArray(): array { return [ - 'slug' => $this->slug, - 'slugSimple' => $this->slugSimple, - 'seriesSlug' => $this->seriesSlug, - 'seriesSlugSimple' => $this->seriesSlugSimple, + 'slug' => $this->getSlug(), + 'slugSimple' => $this->getSlugSimple(), + 'seriesSlug' => $this->getSeriesSlug(), + 'seriesSlugSimple' => $this->getSeriesSlugSimple(), ]; } public function __toString(): string { - return "{$this->slug}"; + return $this->getSlug(); } /** diff --git a/tests/EpubTest.php b/tests/EpubTest.php index 3ec25e2..491a569 100644 --- a/tests/EpubTest.php +++ b/tests/EpubTest.php @@ -73,7 +73,7 @@ $meta = $ebook->getMetaTitle(); expect($meta->getSlug())->toBe('earths-children-en-001-clan-of-the-cave-bear-jean-m-auel-1980-epub'); - expect($meta->getSeriesSlug())->toBe('earths-children-en-jean-m-auel-epub'); + expect($meta->getSeriesSlug())->toBe('earths-children-en-epub'); expect($meta->toArray())->toBeArray(); expect($meta->__toString())->toBeString(); diff --git a/tests/MetaTitleTest.php b/tests/MetaTitleTest.php index 137f872..f29ff3f 100644 --- a/tests/MetaTitleTest.php +++ b/tests/MetaTitleTest.php @@ -15,9 +15,14 @@ $meta = MetaTitle::fromEbook($ebook); expect($meta->getSlug())->toBe('a-comme-association-fr-001-pale-lumiere-des-tenebres-pierre-bottero-1980-epub'); + expect($meta->getSeriesSlug())->toBe('a-comme-association-fr-epub'); + // deprecated expect($meta->getSlugSimple())->toBe('la-pale-lumiere-des-tenebres'); - expect($meta->getSeriesSlug())->toBe('a-comme-association-fr-pierre-bottero-epub'); expect($meta->getSeriesSlugSimple())->toBe('a-comme-association'); +}); + +it('can use setters', function () { + $ebook = Ebook::read(EPUB); $ebook->setTitle('The Fellowship of the Ring'); $ebook->setVolume(1); @@ -27,8 +32,9 @@ $meta = MetaTitle::fromEbook($ebook); expect($meta->getSlug())->toBe('lord-of-the-rings-en-001-fellowship-of-the-ring-j-r-r-tolkien-1980-epub'); + expect($meta->getSeriesSlug())->toBe('lord-of-the-rings-en-epub'); + // deprecated expect($meta->getSlugSimple())->toBe('the-fellowship-of-the-ring'); - expect($meta->getSeriesSlug())->toBe('lord-of-the-rings-en-j-r-r-tolkien-epub'); expect($meta->getSeriesSlugSimple())->toBe('the-lord-of-the-rings'); $ebook->setTitle('Artemis'); @@ -39,10 +45,13 @@ $meta = MetaTitle::fromEbook($ebook); expect($meta->getSlug())->toBe('artemis-en-andy-weir-1980-epub'); - expect($meta->getSlugSimple())->toBe('artemis'); expect($meta->getSeriesSlug())->toBeNull(); + // deprecated + expect($meta->getSlugSimple())->toBe('artemis'); expect($meta->getSeriesSlugSimple())->toBeNull(); +}); +it('can use from data', function () { $meta = MetaTitle::fromData( title: 'The Fellowship of the Ring', volume: 1, @@ -54,8 +63,9 @@ ); expect($meta->getSlug())->toBe('lord-of-the-rings-en-001-fellowship-of-the-ring-j-r-r-tolkien-1980-epub'); + expect($meta->getSeriesSlug())->toBe('lord-of-the-rings-en-epub'); + // deprecated expect($meta->getSlugSimple())->toBe('the-fellowship-of-the-ring'); - expect($meta->getSeriesSlug())->toBe('lord-of-the-rings-en-j-r-r-tolkien-epub'); expect($meta->getSeriesSlugSimple())->toBe('the-lord-of-the-rings'); }); @@ -71,8 +81,9 @@ ); expect($meta->getSlug())->toBe('a-comme-association-fr-001.5-pale-lumiere-des-tenebres-pierre-bottero-epub'); + expect($meta->getSeriesSlug())->toBe('a-comme-association-fr-epub'); + // deprecated expect($meta->getSlugSimple())->toBe('la-pale-lumiere-des-tenebres'); - expect($meta->getSeriesSlug())->toBe('a-comme-association-fr-pierre-bottero-epub'); expect($meta->getSeriesSlugSimple())->toBe('a-comme-association'); }); @@ -107,3 +118,112 @@ expect($meta->getSlug())->toBe('assassin-royal-fr-050-apprenti-assassin-robin-hobb-1980-epub'); }); + +it('can use params', function () { + $ebook = Ebook::read(EPUB); + + $ebook->setTitle('La pâle lumière des ténèbres'); + $ebook->setVolume(1); + $ebook->setSeries('A comme Association'); + $ebook->setLanguage('fr'); + $ebook->setAuthorMain(new BookAuthor('Pierre Bottero')); + $meta = MetaTitle::fromEbook($ebook); + + expect($meta->getSlug( + removeDeterminers: true, + addSeries: true, + addVolume: true, + addAuthor: true, + addYear: true, + addExtension: true, + addLanguage: true, + ))->toBe('a-comme-association-fr-001-pale-lumiere-des-tenebres-pierre-bottero-1980-epub'); + expect($meta->getSlug( + removeDeterminers: false, + addSeries: true, + addVolume: true, + addAuthor: true, + addYear: true, + addExtension: true, + addLanguage: true, + ))->toBe('a-comme-association-fr-001-la-pale-lumiere-des-tenebres-pierre-bottero-1980-epub'); + expect($meta->getSlug( + removeDeterminers: false, + addSeries: false, + addVolume: true, + addAuthor: true, + addYear: true, + addExtension: true, + addLanguage: true, + ))->toBe('fr-001-la-pale-lumiere-des-tenebres-pierre-bottero-1980-epub'); + expect($meta->getSlug( + removeDeterminers: false, + addSeries: false, + addVolume: false, + addAuthor: true, + addYear: true, + addExtension: true, + addLanguage: true, + ))->toBe('fr-la-pale-lumiere-des-tenebres-pierre-bottero-1980-epub'); + expect($meta->getSlug( + removeDeterminers: false, + addSeries: false, + addVolume: false, + addAuthor: false, + addYear: true, + addExtension: true, + addLanguage: true, + ))->toBe('fr-la-pale-lumiere-des-tenebres-1980-epub'); + expect($meta->getSlug( + removeDeterminers: false, + addSeries: false, + addVolume: false, + addAuthor: false, + addYear: false, + addExtension: true, + addLanguage: true, + ))->toBe('fr-la-pale-lumiere-des-tenebres-epub'); + expect($meta->getSlug( + removeDeterminers: false, + addSeries: false, + addVolume: false, + addAuthor: false, + addYear: false, + addExtension: false, + addLanguage: true, + ))->toBe('fr-la-pale-lumiere-des-tenebres'); + expect($meta->getSlug( + removeDeterminers: false, + addSeries: false, + addVolume: false, + addAuthor: false, + addYear: false, + addExtension: false, + addLanguage: false, + ))->toBe('la-pale-lumiere-des-tenebres'); + + expect($meta->getSeriesSlug( + removeDeterminers: false, + addAuthor: true, + addExtension: true, + addLanguage: true, + ))->toBe('a-comme-association-fr-pierre-bottero-epub'); + expect($meta->getSeriesSlug( + removeDeterminers: false, + addAuthor: false, + addExtension: true, + addLanguage: true, + ))->toBe('a-comme-association-fr-epub'); + expect($meta->getSeriesSlug( + removeDeterminers: false, + addAuthor: false, + addExtension: false, + addLanguage: true, + ))->toBe('a-comme-association-fr'); + expect($meta->getSeriesSlug( + removeDeterminers: false, + addAuthor: false, + addExtension: false, + addLanguage: false, + ))->toBe('a-comme-association'); +}); From b086201b1f8da88d0aa595ca77eef381dc0d46b4 Mon Sep 17 00:00:00 2001 From: ewilan-riviere Date: Wed, 10 Jul 2024 13:41:23 +0000 Subject: [PATCH 3/3] Fix styling --- src/Models/MetaTitle.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Models/MetaTitle.php b/src/Models/MetaTitle.php index 58c0d0b..89f7d6e 100644 --- a/src/Models/MetaTitle.php +++ b/src/Models/MetaTitle.php @@ -293,8 +293,7 @@ protected function __construct( protected ?string $seriesDeterminer = null, protected bool $useIntl = true, - ) { - } + ) {} /** * Create a new MetaTitle instance from an Ebook.