Skip to content

Commit

Permalink
Merge pull request #52 from kiwilan/develop
Browse files Browse the repository at this point in the history
v2.2.0
  • Loading branch information
ewilan-riviere authored Sep 24, 2023
2 parents f3af4c5 + f718fe1 commit 884a43c
Show file tree
Hide file tree
Showing 73 changed files with 87,910 additions and 39,134 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ psalm.xml
vendor
.php-cs-fixer.cache
.DS_Store
CHANGELOG-draft.md
node_modules
130 changes: 75 additions & 55 deletions README.md

Large diffs are not rendered by default.

17 changes: 11 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "kiwilan/php-ebook",
"description": "PHP package to read metadata and extract covers from eBooks (.epub, .cbz, .cbr, .cb7, .cbt, .pdf) and audiobooks (.mp3, .m4a, .m4b, .flac, .ogg).",
"version": "2.1.02",
"description": "PHP package to read metadata and extract covers from eBooks, comics and audiobooks.",
"version": "2.2.0",
"keywords": [
"php",
"ebook",
Expand All @@ -21,7 +21,12 @@
"comicinfo",
"comic",
"cbam",
"calibre"
"calibre",
"azw",
"azw3",
"mobi",
"audiobook",
"fb2"
],
"homepage": "https://github.com/kiwilan/php-ebook",
"license": "MIT",
Expand All @@ -34,9 +39,9 @@
],
"require": {
"php": "^8.1",
"kiwilan/php-archive": "^2.1.01",
"kiwilan/php-audio": "^3.0.0",
"kiwilan/php-xml-reader": "^1.0.1"
"kiwilan/php-archive": "^2.1.02",
"kiwilan/php-audio": "^3.0.01",
"kiwilan/php-xml-reader": "^1.0.11"
},
"require-dev": {
"laravel/pint": "^1.7",
Expand Down
154 changes: 116 additions & 38 deletions src/Ebook.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,15 @@
use Kiwilan\Audio\Audio;
use Kiwilan\Ebook\Creator\EbookCreator;
use Kiwilan\Ebook\Enums\EbookFormatEnum;
use Kiwilan\Ebook\Formats\Audio\AudiobookMetadata;
use Kiwilan\Ebook\Formats\Cba\CbaMetadata;
use Kiwilan\Ebook\Formats\Audio\AudiobookModule;
use Kiwilan\Ebook\Formats\Cba\CbaModule;
use Kiwilan\Ebook\Formats\Djvu\DjvuModule;
use Kiwilan\Ebook\Formats\EbookMetadata;
use Kiwilan\Ebook\Formats\Epub\EpubMetadata;
use Kiwilan\Ebook\Formats\Mobi\MobiMetadata;
use Kiwilan\Ebook\Formats\Pdf\PdfMetadata;
use Kiwilan\Ebook\Formats\EbookModule;
use Kiwilan\Ebook\Formats\Epub\EpubModule;
use Kiwilan\Ebook\Formats\Fb2\Fb2Module;
use Kiwilan\Ebook\Formats\Mobi\MobiModule;
use Kiwilan\Ebook\Formats\Pdf\PdfModule;
use Kiwilan\Ebook\Tools\BookAuthor;
use Kiwilan\Ebook\Tools\BookIdentifier;
use Kiwilan\Ebook\Tools\MetaTitle;
Expand Down Expand Up @@ -76,6 +79,7 @@ protected function __construct(
protected ?Audio $audio = null,
protected bool $isArchive = false,
protected bool $isAudio = false,
protected bool $isMobi = false,
protected bool $isBadFile = false,
protected ?EbookMetadata $metadata = null,
protected bool $hasMetadata = false,
Expand All @@ -91,18 +95,23 @@ public static function read(string $path): ?self
$self = self::parseFile($path);

$format = match ($self->format) {
EbookFormatEnum::AUDIOBOOK => $self->audiobook(),
EbookFormatEnum::CBA => $self->cba(),
EbookFormatEnum::DJVU => $self->djvu(),
EbookFormatEnum::EPUB => $self->epub(),
EbookFormatEnum::FB2 => $self->fb2(),
EbookFormatEnum::MOBI => $self->mobi(),
EbookFormatEnum::CBA => $self->cba(),
EbookFormatEnum::PDF => $self->pdf(),
EbookFormatEnum::AUDIOBOOK => $self->audiobook(),
default => null,
};

if ($format === null) {
return null;
}

$self->metadata = EbookMetadata::make($format);
$self->convertEbook();
$self->cover = $self->metadata->getModule()->toCover();
$self->metaTitle = MetaTitle::make($self);

$time = microtime(true) - $start;
Expand Down Expand Up @@ -141,8 +150,9 @@ private static function parseFile(string $path): Ebook
$cbaExtensions = ['cbz', 'cbr', 'cb7', 'cbt'];
$archiveExtensions = ['epub', 'pdf', ...$cbaExtensions];
$audiobookExtensions = ['mp3', 'm4a', 'm4b', 'flac', 'ogg'];
$mobipocketExtensions = ['mobi', 'azw', 'azw3', 'azw4', 'kf8', 'prc', 'tpz'];
$allowExtensions = [...$archiveExtensions, ...$audiobookExtensions, ...$mobipocketExtensions];
$mobipocketExtensions = ['mobi', 'azw', 'azw3', 'azw4', 'kf8', 'kfx', 'prc', 'tpz'];
$extrasExtensions = ['lrf', 'lrx', 'fb2', 'rtf', 'ibooks', 'pdb', 'snb', 'djvu', 'djv'];
$allowExtensions = [...$archiveExtensions, ...$audiobookExtensions, ...$mobipocketExtensions, ...$extrasExtensions];

if (! file_exists($path)) {
throw new \Exception("File not found: {$path}");
Expand All @@ -155,8 +165,18 @@ private static function parseFile(string $path): Ebook
$self = new self($path, $filename, $basename, $extension);

$self->format = match ($extension) {
'azw' => $self->format = EbookFormatEnum::MOBI,
'azw3' => $self->format = EbookFormatEnum::MOBI,
'djvu' => $self->format = EbookFormatEnum::DJVU,
'djv' => $self->format = EbookFormatEnum::DJVU,
'epub' => $self->format = EbookFormatEnum::EPUB,
'mobi' => $self->format = EbookFormatEnum::MOBI,
'lrf' => $self->format = EbookFormatEnum::MOBI,
'kf8' => $self->format = EbookFormatEnum::MOBI,
'kfx' => $self->format = EbookFormatEnum::MOBI,
'prc' => $self->format = EbookFormatEnum::MOBI,
// 'rtf' => $self->format = EbookFormatEnum::RTF,
'fb2' => $self->format = EbookFormatEnum::FB2,
'pdf' => $self->format = EbookFormatEnum::PDF,
default => null,
};
Expand Down Expand Up @@ -196,49 +216,41 @@ private static function parseFile(string $path): Ebook
return $self;
}

private function epub(): self
private function audiobook(): EbookModule
{
$this->metadata = EbookMetadata::make(EpubMetadata::make($this));
$this->convertEbook();
$this->cover = $this->metadata->getModule()->toCover();

return $this;
return AudiobookModule::make($this);
}

private function mobi(): self
private function cba(): EbookModule
{
$this->metadata = EbookMetadata::make(MobiMetadata::make($this));
$this->convertEbook();
$this->cover = $this->metadata->getModule()->toCover();
return CbaModule::make($this);
}

return $this;
private function djvu(): EbookModule
{
return DjvuModule::make($this);
}

private function cba(): self
private function epub(): EbookModule
{
$this->metadata = EbookMetadata::make(CbaMetadata::make($this));
$this->convertEbook();
$this->cover = $this->metadata->getModule()->toCover();
return EpubModule::make($this);
}

return $this;
private function fb2(): EbookModule
{
return Fb2Module::make($this);
}

private function pdf(): self
private function mobi(): EbookModule
{
$this->metadata = EbookMetadata::make(PdfMetadata::make($this));
$this->convertEbook();
$this->cover = $this->metadata->getModule()->toCover();
$this->isMobi = true;

return $this;
return MobiModule::make($this);
}

private function audiobook(): self
private function pdf(): EbookModule
{
$this->metadata = EbookMetadata::make(AudiobookMetadata::make($this));
$this->convertEbook();
$this->cover = $this->metadata->getModule()->toCover();

return $this;
return PdfModule::make($this);
}

private function convertEbook(): self
Expand Down Expand Up @@ -286,7 +298,7 @@ public function toXml(string $path): ?string
}

$ebook = $this->archive->find($path);
$content = $this->archive->getContent($ebook);
$content = $this->archive->getContents($ebook);

return $content;
}
Expand Down Expand Up @@ -489,6 +501,14 @@ public function isAudio(): bool
return $this->isAudio;
}

/**
* Whether the ebook is a mobi.
*/
public function isMobi(): bool
{
return ! $this->isAudio;
}

/**
* Whether the ebook is a bad file.
*/
Expand Down Expand Up @@ -645,6 +665,20 @@ public function setAuthorMain(?BookAuthor $authorMain): self
return $this;
}

public function setAuthor(BookAuthor $author): self
{
$this->authors = [
$author,
...$this->authors,
];

if (! $this->authorMain) {
$this->authorMain = $author;
}

return $this;
}

/**
* @param BookAuthor[] $authors
*/
Expand Down Expand Up @@ -681,6 +715,22 @@ public function setPublisher(?string $publisher): self
return $this;
}

public function setIdentifier(BookIdentifier $identifier): self
{
$key = $identifier->getScheme() ?? uniqid();

if (array_key_exists($key, $this->identifiers)) {
$key = uniqid();
$this->identifiers[$key] = $identifier;

return $this;
}

$this->identifiers[$key] = $identifier;

return $this;
}

/**
* @param BookIdentifier[] $identifiers
*/
Expand All @@ -705,13 +755,28 @@ public function setLanguage(?string $language): self
return $this;
}

public function setTag(?string $tag): self
{
if (! $tag) {
return $this;
}

$tag = trim($tag);
$this->tags = [
$tag,
...$this->tags,
];

return $this;
}

/**
* @param string[]|null $tags
*/
public function setTags(?array $tags): self
{
if (! $tags) {
$tags = [];
return $this;
}

$this->tags = $tags;
Expand Down Expand Up @@ -765,6 +830,19 @@ public function setHasMetadata(bool $hasMetadata): self
return $this;
}

public function setExtra(mixed $value, string $key = null): self
{
if (! $key) {
$this->extras[] = $value;

return $this;
}

$this->extras[$key] = $value;

return $this;
}

/**
* @param array<string, mixed> $extras
*/
Expand Down
41 changes: 32 additions & 9 deletions src/EbookCover.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,67 @@ class EbookCover
{
protected function __construct(
protected ?string $path = null,
protected ?string $content = null,
protected ?string $contents = null,
) {
}

public static function make(?string $path, ?string $content): ?self
public static function make(string $path = null, string $contents = null): ?self
{
if ($content === null) {
if ($contents === null) {
return null;
}

$content = base64_encode($content);
if (! EbookCover::isBase64($contents)) {
$contents = base64_encode($contents);
}

return new self($path, $contents);
}

return new self($path, $content);
private static function isBase64(string $contents): bool
{
return (bool) preg_match('`^[a-zA-Z0-9+/]+={0,2}$`', $contents);
}

/**
* Get the cover path.
*/
public function getPath(): ?string
{
return $this->path;
}

/**
* @deprecated Use getContents() instead.
*/
public function getContent(bool $toBase64 = false): ?string
{
if ($this->content === null) {
return $this->getContents($toBase64);
}

/**
* Get the cover contents.
*
* @param bool $toBase64 If true, the contents will be returned in base64 format.
*/
public function getContents(bool $toBase64 = false): ?string
{
if ($this->contents === null) {
return null;
}

if ($toBase64) {
return $this->content;
return $this->contents;
}

return base64_decode($this->content);
return base64_decode($this->contents);
}

public function toArray(): array
{
return [
'path' => $this->path,
'content' => $this->content,
'contents' => $this->contents,
];
}

Expand Down
Loading

0 comments on commit 884a43c

Please sign in to comment.