EPUB 3 Features¶
Upgrading a book to EPUB 3, landmarks and the page list, fixed layout, media overlays and plain-text extraction.
Upgrading an EPUB 2 book¶
use PhpEpub\EpubFile;
$epubFile = EpubFile::open('/path/to/old.epub');
if ($epubFile->upgradeToEpub3()) {
$epubFile->save('/path/to/new.epub');
}
EpubFile::upgradeToEpub3(): bool converts a loaded EPUB 2 book in place; save() writes the result. It returns true when the book was converted and false, changing nothing, when it already is EPUB 3. It throws an Exception when the book is not loaded or the navigation document cannot be written; the book may be partly converted then, so open it again. The conversion:
- sets the package
versionto3.0and addsdcterms:modified; - generates a navigation document (
nav.xhtmlnext to the OPF, ornav-2.xhtml, ... when that name is taken) from the NCX entries, with thenavmanifest property. A book without NCX entries gets one entry per linear XHTML document of the reading order, named after its file. The NCX stays (andspine@tocwith it) for EPUB 2 reading systems; - turns the
<guide>into the navigation document's landmarks (see below) and keeps the guide too. Guide types without an EPUB 3 equivalent, such asother.custom, are not carried over to the landmarks; - converts the
opf:*attributes, which EPUB 3 does not allow on Dublin Core elements:opf:roleandopf:file-asbecomerole(schememarc:relators) andfile-asrefinements; theopf:schemeof an ISBN or DOI identifier becomes anidentifier-typerefinement (ONIX code list 5:15ISBN-13,02ISBN-10,06DOI; other schemes are dropped); every otheropf:*attribute is removed; - keeps one
dc:date: the publication date (the one with thepublicationevent, or else the first without an event). Dates with thecreation,issuedandcopyrightevents becomedcterms:created,dcterms:issuedanddcterms:dateCopyrightedproperties; themodificationdate is replaced bydcterms:modified, and any other date is dropped; - gives the cover image the
cover-imageproperty (the<meta name="cover">stays for older readers); - adds the manifest properties XHTML documents need for their content (
svg,mathml,scripted,remote-resources), asContentManager::updateManifestProperties()does.
Content documents are not rewritten. An XHTML 1.1 document with an old DOCTYPE or obsolete elements may still draw EPUBCheck errors in EPUB 3 even though the package is valid; validate() does not report those. A book whose metadata declares xmlns:opf gets the new refinements as <opf:meta …>, which is the same XML in the same namespace.
Landmarks and the page list¶
Landmarks are the places a reading system offers as "go to cover", "go to the table of contents" or "go to the beginning": the EPUB 3 navigation document's landmarks nav and the EPUB 2 <guide>. They are read and written through TableOfContents as PhpEpub\Landmark objects (type, title, path, fragment), with the EPUB 3 epub:type as the type:
use PhpEpub\Landmark;
$toc = $epubFile->getTableOfContents();
foreach ($toc->getLandmarks() as $landmark) {
echo $landmark->type, ': ', $landmark->title, ' -> ', $landmark->path, "\n";
}
$toc->setLandmarks([
new Landmark('cover', 'Cover', 'EPUB/text/cover.xhtml'),
new Landmark('toc', 'Contents', 'EPUB/nav.xhtml'),
new Landmark('bodymatter', 'Start of the book', 'EPUB/text/chapter-1.xhtml'),
]);
$epubFile->save();
getLandmarks()returns the landmarks of the navigation document'slandmarksnav or, when it has none, those of the<guide>that have an EPUB 3 equivalent, with the type translated (textbecomesbodymatter,title-pagebecomestitlepage,acknowledgementsbecomesacknowledgments,notesbecomesendnotes;Landmark::fromGuideType()andLandmark::toGuideType()expose the mapping). Landmarks that point outside the book are left out.setLandmarks()replaces them. They are written to the navigation document'slandmarksnav, which is created when missing (hidden, after the other navs), and, for an EPUB 2 book or an EPUB 3 book that keeps a<guide>, to the guide as well, after the spine. Landmarks whose type the guide cannot express (for examplechapter) stay out of the guide.[]removes the nav and the guide. It throws anExceptionwhen a landmark has an empty type, title or path, a value is not valid XML text, a path leaves the book, or the book has neither a navigation document nor a guide.getPageList()returns the print page numbers of the navigation document'spage-listnav or, when it has none, of the NCXpageList, as a list ofTocEntry(title = the page label);[]when the book has neither. It is read-only.
The guide itself is available through Manifest::getGuideReferences() and Manifest::setGuideReferences(), which use the guide's own types.
Fixed layout and rendition¶
The rendition vocabulary tells a reading system whether a book is reflowable or fixed layout. It is EPUB 3 only: the setters throw an Exception for an EPUB 2 package, and the getters return null there.
$metadata = $epubFile->getMetadata();
$metadata->setRenditionLayout('pre-paginated'); // or 'reflowable'
$metadata->setRenditionOrientation('portrait'); // auto, landscape, portrait
$metadata->setRenditionSpread('none'); // none, auto, landscape, portrait, both
$metadata->setRenditionFlow('paginated'); // auto, paginated, scrolled-continuous, scrolled-doc
$spine = $epubFile->getSpine();
$spine->setPageSpread('page-1', 'right'); // left, right or center; null removes it
$spine->setItemRendition('page-2', 'layout', 'reflowable'); // override one page; null removes it
$spine->setItemProperties('page-3', ['page-spread-left', 'rendition:orientation-landscape']);
Metadata::getRenditionLayout()/setRenditionLayout()and the matching…Orientation(),…Spread()and…Flow()methods read and write therendition:*metadata. A value outside the vocabulary throws anException;nullremoves the property.Spine::getItemProperties($idref)/setItemProperties($idref, array $properties)read and replace the rawpropertiesof an itemref (tokens without white space).getPageSpread()/setPageSpread()handlepage-spread-left,page-spread-rightandrendition:page-spread-center;getItemRendition($idref, $aspect)/setItemRendition($idref, $aspect, $value)handle the per-item overrides (rendition:layout-pre-paginated,rendition:orientation-landscape, ...). Other properties of the entry are kept, and the item must be in the spine.- Writing any
rendition:metadata or property declares the prefix in the package element,prefix="rendition: http://www.idpf.org/vocab/rendition/#", unless the package declares it already. The prefix is reserved from EPUB 3.1 on, but a package of version3.0(which includes EPUB 3.2 and 3.3 books) and older reading systems expect the declaration, and declaring a reserved prefix with its standard URI is allowed.
Media overlays¶
A media overlay is a SMIL document that narrates a content document. Overlays are EPUB 3 only.
$manifest = $epubFile->getManifest();
$manifest->setMediaOverlay('chapter-1', 'chapter-1-smil'); // content item id, SMIL item id
echo $manifest->getMediaOverlay('chapter-1'); // 'chapter-1-smil'
$metadata = $epubFile->getMetadata();
$metadata->setMediaDuration('0:32:29'); // the whole narration
$metadata->setMediaDurationOf('chapter-1-smil', '0:16:00.5'); // one overlay
$metadata->setMediaActiveClass('-epub-media-overlay-active');
$metadata->setMediaPlaybackActiveClass('-epub-media-overlay-playing');
$metadata->setMediaNarrators(['Ann Narrator']);
Manifest::setMediaOverlay($id, $overlayId)sets themedia-overlayattribute of an XHTML or SVG item;nullremoves it. It throws anExceptionwhen an item is unknown, the content item is not XHTML or SVG, the overlay is not anapplication/smil+xmlitem, or the package is EPUB 2.getMediaOverlay($id)returns the overlay id ornull. Deleting the SMIL item clears the reference and its duration.Metadata::getMediaDuration()/setMediaDuration()handle the book's totalmedia:duration;getMediaDurationOf($overlayId)/setMediaDurationOf($overlayId, $duration)the duration of one overlay (a refinement of its SMIL item, which must be in the manifest);getMediaDurations()returns them all, keyed by SMIL item id. Durations must be SMIL clock values:0:32:29.5(hours, minutes, seconds),32:29, or a time count with an optional unit,1949.5s,1500ms,45min,3h; anything else throws anException. The library does not check that the total equals the sum of the overlays.getMediaActiveClass()/setMediaActiveClass()andgetMediaPlaybackActiveClass()/setMediaPlaybackActiveClass()take a CSS class name without white space;getMediaNarrators()/setMediaNarrators()a list of names.
Plain text¶
$text = $epubFile->getContentManager()->getText('EPUB/text/chapter-1.xhtml'); // one document
foreach ($epubFile->getText() as $path => $text) { // the whole book, in reading order
echo $path, ': ', str_word_count($text), " words\n";
}
ContentManager::getText($path)returns the text of one XHTML or HTML document: one line per paragraph, heading, list item, table row and<br>, white space collapsed, entities decoded, with scripts, styles and the document head left out. The document is read in its declared encoding (UTF-8 or UTF-16, as for conversion) and does not have to be well-formed. It throws anExceptionif the file cannot be read.EpubFile::getText(bool $linearOnly = true)returnspath => textfor the XHTML and HTML documents of the spine, in reading order. Auxiliary content (linear="no", such as notes) is skipped unless$linearOnlyisfalse; spine items that are not XHTML or HTML, or whose file is missing, are skipped.