From 87090d8ae7582708d20f3c09fb37d780af860bcd Mon Sep 17 00:00:00 2001 From: tcit Date: Thu, 24 Apr 2014 03:04:02 +0200 Subject: Added epub export function --- inc/3rdparty/libraries/PHPePub/EPub.NCX.php | 782 ++++++++++++++++++++++++++++ 1 file changed, 782 insertions(+) create mode 100644 inc/3rdparty/libraries/PHPePub/EPub.NCX.php (limited to 'inc/3rdparty/libraries/PHPePub/EPub.NCX.php') diff --git a/inc/3rdparty/libraries/PHPePub/EPub.NCX.php b/inc/3rdparty/libraries/PHPePub/EPub.NCX.php new file mode 100644 index 00000000..e5da05cd --- /dev/null +++ b/inc/3rdparty/libraries/PHPePub/EPub.NCX.php @@ -0,0 +1,782 @@ + + * @copyright 2009-2014 A. Grandt + * @license GNU LGPL, Attribution required for commercial implementations, requested for everything else. + * @version 3.20 + */ +class Ncx { + const _VERSION = 3.20; + + const MIMETYPE = "application/x-dtbncx+xml"; + + private $bookVersion = EPub::BOOK_VERSION_EPUB2; + + private $navMap = NULL; + private $uid = NULL; + private $meta = array(); + private $docTitle = NULL; + private $docAuthor = NULL; + + private $currentLevel = NULL; + private $lastLevel = NULL; + + private $languageCode = "en"; + private $writingDirection = EPub::DIRECTION_LEFT_TO_RIGHT; + + public $chapterList = array(); + public $referencesTitle = "Guide"; + public $referencesClass = "references"; + public $referencesId = "references"; + public $referencesList = array(); + public $referencesName = array(); + public $referencesOrder = NULL; + + /** + * Class constructor. + * + * @param string $uid + * @param string $docTitle + * @param string $docAuthor + * @param string $languageCode + * @param string $writingDirection + */ + function __construct($uid = NULL, $docTitle = NULL, $docAuthor = NULL, $languageCode = "en", $writingDirection = EPub::DIRECTION_LEFT_TO_RIGHT) { + $this->navMap = new NavMap($writingDirection); + $this->currentLevel = $this->navMap; + $this->setUid($uid); + $this->setDocTitle($docTitle); + $this->setDocAuthor($docAuthor); + $this->setLanguageCode($languageCode); + $this->setWritingDirection($writingDirection); + } + + /** + * Class destructor + * + * @return void + */ + function __destruct() { + unset($this->bookVersion, $this->navMap, $this->uid, $this->meta); + unset($this->docTitle, $this->docAuthor, $this->currentLevel, $this->lastLevel); + unset($this->languageCode, $this->writingDirection, $this->chapterList, $this->referencesTitle); + unset($this->referencesClass, $this->referencesId, $this->referencesList, $this->referencesName); + unset($this->referencesOrder); + } + + /** + * + * Enter description here ... + * + * @param string $bookVersion + */ + function setVersion($bookVersion) { + $this->bookVersion = is_string($bookVersion) ? trim($bookVersion) : EPub::BOOK_VERSION_EPUB2; + } + + /** + * + * @return bool TRUE if the book is set to type ePub 2 + */ + function isEPubVersion2() { + return $this->bookVersion === EPub::BOOK_VERSION_EPUB2; + } + + /** + * + * Enter description here ... + * + * @param string $uid + */ + function setUid($uid) { + $this->uid = is_string($uid) ? trim($uid) : NULL; + } + + /** + * + * Enter description here ... + * + * @param string $docTitle + */ + function setDocTitle($docTitle) { + $this->docTitle = is_string($docTitle) ? trim($docTitle) : NULL; + } + + /** + * + * Enter description here ... + * + * @param string $docAuthor + */ + function setDocAuthor($docAuthor) { + $this->docAuthor = is_string($docAuthor) ? trim($docAuthor) : NULL; + } + + /** + * + * Enter description here ... + * + * @param string $languageCode + */ + function setLanguageCode($languageCode) { + $this->languageCode = is_string($languageCode) ? trim($languageCode) : "en"; + } + + /** + * + * Enter description here ... + * + * @param string $writingDirection + */ + function setWritingDirection($writingDirection) { + $this->writingDirection = is_string($writingDirection) ? trim($writingDirection) : EPub::DIRECTION_LEFT_TO_RIGHT; + } + + /** + * + * Enter description here ... + * + * @param NavMap $navMap + */ + function setNavMap($navMap) { + if ($navMap != NULL && is_object($navMap) && get_class($navMap) === "NavMap") { + $this->navMap = $navMap; + } + } + + /** + * Add one chapter level. + * + * Subsequent chapters will be added to this level. + * + * @param string $navTitle + * @param string $navId + * @param string $navClass + * @param string $isNavHidden + * @param string $writingDirection + * @return NavPoint + */ + function subLevel($navTitle = NULL, $navId = NULL, $navClass = NULL, $isNavHidden = FALSE, $writingDirection = NULL) { + $navPoint = FALSE; + if (isset($navTitle) && isset($navClass)) { + $navPoint = new NavPoint($navTitle, NULL, $navId, $navClass, $isNavHidden, $writingDirection); + $this->addNavPoint($navPoint); + } + if ($this->lastLevel !== NULL) { + $this->currentLevel = $this->lastLevel; + } + return $navPoint; + } + + /** + * Step back one chapter level. + * + * Subsequent chapters will be added to this chapters parent level. + */ + function backLevel() { + $this->lastLevel = $this->currentLevel; + $this->currentLevel = $this->currentLevel->getParent(); + } + + /** + * Step back to the root level. + * + * Subsequent chapters will be added to the rooot NavMap. + */ + function rootLevel() { + $this->lastLevel = $this->currentLevel; + $this->currentLevel = $this->navMap; + } + + /** + * Step back to the given level. + * Useful for returning to a previous level from deep within the structure. + * Values below 2 will have the same effect as rootLevel() + * + * @param int $newLevel + */ + function setCurrentLevel($newLevel) { + if ($newLevel <= 1) { + $this->rootLevel(); + } else { + while ($this->currentLevel->getLevel() > $newLevel) { + $this->backLevel(); + } + } + } + + /** + * Get current level count. + * The indentation of the current structure point. + * + * @return current level count; + */ + function getCurrentLevel() { + return $this->currentLevel->getLevel(); + } + + /** + * Add child NavPoints to current level. + * + * @param NavPoint $navPoint + */ + function addNavPoint($navPoint) { + $this->lastLevel = $this->currentLevel->addNavPoint($navPoint); + } + + /** + * + * Enter description here ... + * + * @return NavMap + */ + function getNavMap() { + return $this->navMap; + } + + /** + * + * Enter description here ... + * + * @param string $name + * @param string $content + */ + function addMetaEntry($name, $content) { + $name = is_string($name) ? trim($name) : NULL; + $content = is_string($content) ? trim($content) : NULL; + + if ($name != NULL && $content != NULL) { + $this->meta[] = array($name => $content); + } + } + + /** + * + * Enter description here ... + * + * @return string + */ + function finalize() { + $nav = $this->navMap->finalize(); + + $ncx = "\n"; + if ($this->isEPubVersion2()) { + $ncx .= "\n"; + } + $ncx .= "languageCode . "\" dir=\"" . $this->writingDirection . "\">\n" + . "\t\n" + . "\t\tuid . "\" />\n" + . "\t\tnavMap->getNavLevels() . "\" />\n" + . "\t\t\n" + . "\t\t\n"; + + if (sizeof($this->meta)) { + foreach ($this->meta as $metaEntry) { + list($name, $content) = each($metaEntry); + $ncx .= "\t\t\n"; + } + } + + $ncx .= "\t\n\n\t\n\t\t" + . $this->docTitle + . "\n\t\n\n\t\n\t\t" + . $this->docAuthor + . "\n\t\n\n" + . $nav; + + return $ncx . "\n"; + } + + /** + * + * @param string $title + * @param string $cssFileName + * @return string + */ + function finalizeEPub3($title = "Table of Contents", $cssFileName = NULL) { + $end = "\n" + . "languageCode . "\" lang=\"" . $this->languageCode . "\" dir=\"" . $this->writingDirection . "\">\n" + . "\t\n" + . "\t\t" . $this->docTitle . "\n" + . "\t\t\n"; + if ($cssFileName !== NULL) { + $end .= "\t\t\n"; + } + $end .= "\t\n" + . "\t\n" + . "\t\t
\n" + . "\t\t\t

" . $title . "

\n" + . "\t\t
\n" + . $this->navMap->finalizeEPub3() + . $this->finalizeEPub3Landmarks() + . "\t\n" + . "\n"; + + return $end; + } + + /** + * Build the references for the ePub 2 toc. + * These are merely reference pages added to the end of the navMap though. + * + * @return string + */ + function finalizeReferences() { + if (isset($this->referencesList) && sizeof($this->referencesList) > 0) { + $this->rootLevel(); + $this->subLevel($this->referencesTitle, $this->referencesId, $this->referencesClass); + $refId = 1; + while (list($item, $descriptive) = each($this->referencesOrder)) { + if (array_key_exists($item, $this->referencesList)) { + $name = (empty($this->referencesName[$item]) ? $descriptive : $this->referencesName[$item]); + $navPoint = new NavPoint($name, $this->referencesList[$item], "ref-" . $refId++); + $this->addNavPoint($navPoint); + } + } + } + } + + /** + * Build the landmarks for the ePub 3 toc. + * @return string + */ + function finalizeEPub3Landmarks() { + $lm = ""; + if (isset($this->referencesList) && sizeof($this->referencesList) > 0) { + $lm = "\t\t\t\n"; + } + return $lm; + } +} + +/** + * ePub NavMap class + */ +class NavMap { + const _VERSION = 3.00; + + private $navPoints = array(); + private $navLevels = 0; + private $writingDirection = NULL; + + /** + * Class constructor. + * + * @return void + */ + function __construct($writingDirection = NULL) { + $this->setWritingDirection($writingDirection); + } + + /** + * Class destructor + * + * @return void + */ + function __destruct() { + unset($this->navPoints, $this->navLevels, $this->writingDirection); + } + + /** + * Set the writing direction to be used for this NavPoint. + * + * @param string $writingDirection + */ + function setWritingDirection($writingDirection) { + $this->writingDirection = isset($writingDirection) && is_string($writingDirection) ? trim($writingDirection) : NULL; + } + + function getWritingDirection() { + return $this->writingDirection; + } + + /** + * Add a navPoint to the root of the NavMap. + * + * @param NavPoint $navPoint + * @return NavMap + */ + function addNavPoint($navPoint) { + if ($navPoint != NULL && is_object($navPoint) && get_class($navPoint) === "NavPoint") { + $navPoint->setParent($this); + if ($navPoint->getWritingDirection() == NULL) { + $navPoint->setWritingDirection($this->writingDirection); + } + $this->navPoints[] = $navPoint; + return $navPoint; + } + return $this; + } + + /** + * The final max depth for the "dtb:depth" meta attribute + * Only available after finalize have been called. + * + * @return number + */ + function getNavLevels() { + return $this->navLevels+1; + } + + function getLevel() { + return 1; + } + + function getParent() { + return $this; + } + + /** + * Finalize the navMap, the final max depth for the "dtb:depth" meta attribute can be retrieved with getNavLevels after finalization + * + */ + function finalize() { + $playOrder = 0; + $this->navLevels = 0; + + $nav = "\t\n"; + if (sizeof($this->navPoints) > 0) { + $this->navLevels++; + foreach ($this->navPoints as $navPoint) { + $retLevel = $navPoint->finalize($nav, $playOrder, 0); + if ($retLevel > $this->navLevels) { + $this->navLevels = $retLevel; + } + } + } + return $nav . "\t\n"; + } + + /** + * Finalize the navMap, the final max depth for the "dtb:depth" meta attribute can be retrieved with getNavLevels after finalization + * + */ + function finalizeEPub3() { + $playOrder = 0; + $level = 0; + $this->navLevels = 0; + + $nav = "\t\t\n"; + } +} + +/** + * ePub NavPoint class + */ +class NavPoint { + const _VERSION = 3.00; + + private $label = NULL; + private $contentSrc = NULL; + private $id = NULL; + private $navClass = NULL; + private $isNavHidden = FALSE; + private $navPoints = array(); + private $parent = NULL; + + /** + * Class constructor. + * + * All three attributes are mandatory, though if ID is set to null (default) the value will be generated. + * + * @param string $label + * @param string $contentSrc + * @param string $id + * @param string $navClass + * @param bool $isNavHidden + * @param string $writingDirection + */ + function __construct($label, $contentSrc = NULL, $id = NULL, $navClass = NULL, $isNavHidden = FALSE, $writingDirection = NULL) { + $this->setLabel($label); + $this->setContentSrc($contentSrc); + $this->setId($id); + $this->setNavClass($navClass); + $this->setNavHidden($isNavHidden); + $this->setWritingDirection($writingDirection); + } + + /** + * Class destructor + * + * @return void + */ + function __destruct() { + unset($this->label, $this->contentSrc, $this->id, $this->navClass); + unset($this->isNavHidden, $this->navPoints, $this->parent); + } + + /** + * Set the Text label for the NavPoint. + * + * The label is mandatory. + * + * @param string $label + */ + function setLabel($label) { + $this->label = is_string($label) ? trim($label) : NULL; + } + + /** + * Get the Text label for the NavPoint. + * + * @return string Label + */ + function getLabel() { + return $this->label; + } + + /** + * Set the src reference for the NavPoint. + * + * The src is mandatory for ePub 2. + * + * @param string $contentSrc + */ + function setContentSrc($contentSrc) { + $this->contentSrc = isset($contentSrc) && is_string($contentSrc) ? trim($contentSrc) : NULL; + } + + /** + * Get the src reference for the NavPoint. + * + * @return string content src url. + */ + function getContentSrc() { + return $this->contentSrc; + } + /** + * Set the parent for this NavPoint. + * + * @param NavPoint or NavMap $parent + */ + function setParent($parent) { + if ($parent != NULL && is_object($parent) && + (get_class($parent) === "NavPoint" || get_class($parent) === "NavMap") ) { + $this->parent = $parent; + } + } + + /** + * Get the parent to this NavPoint. + * + * @return NavPoint, or NavMap if the parent is the root. + */ + function getParent() { + return $this->parent; + } + + /** + * Get the current level. 1 = document root. + * + * @return int level + */ + function getLevel() { + return $this->parent === NULL ? 1 : $this->parent->getLevel()+1; + } + + /** + * Set the id for the NavPoint. + * + * The id must be unique, and is mandatory. + * + * @param string $id + */ + function setId($id) { + $this->id = is_string($id) ? trim($id) : NULL; + } + + /** + * Set the class to be used for this NavPoint. + * + * @param string $navClass + */ + function setNavClass($navClass) { + $this->navClass = isset($navClass) && is_string($navClass) ? trim($navClass) : NULL; + } + + /** + * Set the class to be used for this NavPoint. + * + * @param string $navClass + */ + function setNavHidden($isNavHidden) { + $this->isNavHidden = $isNavHidden === TRUE; + } + + /** + * Set the writing direction to be used for this NavPoint. + * + * @param string $writingDirection + */ + function setWritingDirection($writingDirection) { + $this->writingDirection = isset($writingDirection) && is_string($writingDirection) ? trim($writingDirection) : NULL; + } + + function getWritingDirection() { + return $this->writingDirection; + } + + /** + * Add child NavPoints for multi level NavMaps. + * + * @param NavPoint $navPoint + */ + function addNavPoint($navPoint) { + if ($navPoint != NULL && is_object($navPoint) && get_class($navPoint) === "NavPoint") { + $navPoint->setParent($this); + if ($navPoint->getWritingDirection() == NULL) { + $navPoint->setWritingDirection($this->writingDirection); + } + $this->navPoints[] = $navPoint; + return $navPoint; + } + return $this; + } + + /** + * + * Enter description here ... + * + * @param string $nav + * @param int $playOrder + * @param int $level + * @return int + */ + function finalize(&$nav = "", &$playOrder = 0, $level = 0) { + $maxLevel = $level; + $levelAdjust = 0; + + if ($this->isNavHidden) { + return $maxLevel; + } + + if (isset($this->contentSrc)) { + $playOrder++; + + if ($this->id == NULL) { + $this->id = "navpoint-" . $playOrder; + } + $nav .= str_repeat("\t", $level) . "\t\tid . "\" playOrder=\"" . $playOrder . "\">\n" + . str_repeat("\t", $level) . "\t\t\t\n" + . str_repeat("\t", $level) . "\t\t\t\t" . $this->label . "\n" + . str_repeat("\t", $level) . "\t\t\t\n" + . str_repeat("\t", $level) . "\t\t\tcontentSrc . "\" />\n"; + } else { + $levelAdjust++; + } + + if (sizeof($this->navPoints) > 0) { + $maxLevel++; + foreach ($this->navPoints as $navPoint) { + $retLevel = $navPoint->finalize($nav, $playOrder, ($level+1+$levelAdjust)); + if ($retLevel > $maxLevel) { + $maxLevel = $retLevel; + } + } + } + + if (isset($this->contentSrc)) { + $nav .= str_repeat("\t", $level) . "\t\t\n"; + } + + return $maxLevel; + } + + /** + * + * Enter description here ... + * + * @param string $nav + * @param int $playOrder + * @param int $level + * @return int + */ + function finalizeEPub3(&$nav = "", &$playOrder = 0, $level = 0, $subLevelClass = NULL, $subLevelHidden = FALSE) { + $maxLevel = $level; + + if ($this->id == NULL) { + $this->id = "navpoint-" . $playOrder; + } + $indent = str_repeat("\t", $level) . "\t\t\t\t"; + + $nav .= $indent . "
  • id . "\""; + if (isset($this->writingDirection)) { + $nav .= " dir=\"" . $this->writingDirection . "\""; + } + $nav .= ">\n"; + + if (isset($this->contentSrc)) { + $nav .= $indent . "\tcontentSrc . "\">" . $this->label . "\n"; + } else { + $nav .= $indent . "\t" . $this->label . "\n"; + } + + if (sizeof($this->navPoints) > 0) { + $maxLevel++; + + $nav .= $indent . "\t
      navPoints as $navPoint) { + $retLevel = $navPoint->finalizeEPub3($nav, $playOrder, ($level+2), $subLevelClass, $subLevelHidden); + if ($retLevel > $maxLevel) { + $maxLevel = $retLevel; + } + } + $nav .= $indent . "\t
    \n"; + } + + $nav .= $indent . "
  • \n"; + + return $maxLevel; + } +} +?> \ No newline at end of file -- cgit v1.2.3