/** * Add a chapter to the book, as a chapter should not exceed 250kB, you can parse an array with multiple parts as $chapterData. * These will still only show up as a single chapter in the book TOC. * * @param String $chapterName Name of the chapter, will be use din the TOC * @param String $fileName Filename to use for the chapter, must be unique for the book. * @param String $chapter Chapter text in XHTML or array $chapterData valid XHTML data for the chapter. File should NOT exceed 250kB. * @param Bool $autoSplit Should the chapter be split if it exceeds the default split size? Default=FALSE, only used if $chapterData is a String. * @param int $externalReferences How to handle external references, EPub::EXTERNAL_REF_IGNORE, EPub::EXTERNAL_REF_ADD or EPub::EXTERNAL_REF_REMOVE_IMAGES? See documentation for <code>processChapterExternalReferences</code> for explanation. Default is EPub::EXTERNAL_REF_IGNORE. * @param String $baseDir Default is "", meaning it is pointing to the document root. NOT used if $externalReferences is set to EPub::EXTERNAL_REF_IGNORE. * @return bool $success */ function addChapter($chapterName, $fileName, $chapterData, $autoSplit = FALSE, $externalReferences = EPub::EXTERNAL_REF_IGNORE, $baseDir = "") { if ($this->isFinalized) { return FALSE; } $fileName = preg_replace('#\\\\#i', "/", $fileName); $fileName = preg_replace('#^[/\\.]+#i', "", $fileName); $htmlDir = pathinfo($fileName); $htmlDir = preg_replace('#^[/\\.]+#i', "", $htmlDir["dirname"] . "/"); $chapter = $chapterData; if ($autoSplit && is_string($chapterData) && strlen($chapterData) > $this->splitDefaultSize) { $splitter = new EPubChapterSplitter(); $chapterArray = $splitter->splitChapter($chapterData); if (count($chapterArray) > 1) { $chapter = $chapterArray; } } if (!empty($chapter) && is_string($chapter)) { if ($externalReferences !== EPub::EXTERNAL_REF_IGNORE) { $this->processChapterExternalReferences($chapter, $externalReferences, $baseDir, $htmlDir); } $this->zip->addFile($chapter, $fileName); $this->fileList[$fileName] = $fileName; $this->chapterCount++; $this->opf_manifest .= "\t\t<item id=\"chapter" . $this->chapterCount . "\" href=\"" . $fileName . "\" media-type=\"application/xhtml+xml\" />\n"; $this->opf_spine .= "\t\t<itemref idref=\"chapter" . $this->chapterCount . "\" />\n"; $this->ncx_navmap .= "\n\t\t<navPoint id=\"chapter" . $this->chapterCount . "\" playOrder=\"" . $this->chapterCount . "\">\n\t\t\t<navLabel><text>" . $chapterName . "</text></navLabel>\n\t\t\t<content src=\"" . $fileName . "\" />\n\t\t</navPoint>\n"; } else { if (is_array($chapter)) { $partCount = 0; $this->chapterCount++; $oneChapter = each($chapter); while ($oneChapter) { list($k, $v) = $oneChapter; $c = $v; if ($externalReferences !== EPub::EXTERNAL_REF_IGNORE) { $this->processChapterExternalReferences($c, $externalReferences, $baseDir); } $partCount++; $this->zip->addFile($c, $fileName . "-" . $partCount); $this->fileList[$fileName . "-" . $partCount] = $fileName . "-" . $partCount; $this->opf_manifest .= "\t\t<item id=\"chapter" . $this->chapterCount . "-" . $partCount . "\" href=\"" . $fileName . "-" . $partCount . "\" media-type=\"application/xhtml+xml\" />\n"; $this->opf_spine .= "\t\t<itemref idref=\"chapter" . $this->chapterCount . "-" . $partCount . "\" />\n"; $oneChapter = each($chapter); } $this->ncx_navmap .= "\n\t\t<navPoint id=\"chapter" . $this->chapterCount . "-1\" playOrder=\"" . $this->chapterCount . "\">\n\t\t\t<navLabel><text>" . $chapterName . "</text></navLabel>\n\t\t\t<content src=\"" . $fileName . "-1\" />\n\t\t</navPoint>\n"; } } return TRUE; }
$log->logLine("Add Chapter 3"); $book->addChapter("Chapter 3: Vivamus bibendum massa again", "Chapter003.html", $chapter3); // Autosplit a chapter: $log->logLine("Add Chapter 4"); $book->setSplitSize(15000); // For this test, we split at approx 15k. Default is 250000 had we left it alone. $book->addChapter("Chapter 4: Vivamus bibendum massa split", "Chapter004.html", $chapter4, true); $book->setSplitSize(250000); $book->subLevel(); $book->addChapter("Chapter 4B: test inlined chapter", "Chapter004.html#sub01"); $book->backLevel(); // More advanced use of the splitter: // Still using Chapter 4, but as you can see, "Chapter 4" also contains a header for Chapter 5. require_once 'EPubChapterSplitter.php'; $log->logLine("include EPubChapterSplitter.php"); $splitter = new EPubChapterSplitter(); $splitter->setSplitSize(15000); // For this test, we split at approx 15k. Default is 250000 had we left it alone. $log->logLine("new EPubChapterSplitter()"); /* Using the # as regexp delimiter here, it makes writing the regexp easier. * in this case we could have just searched for "Chapter ", or if we were using regexp '#^<h1>Chapter #i', * using regular text (no regexp delimiters) will look for the text after the first tag. Meaning had we used * "Chapter ", any paragraph or header starting with "Chapter " would have matched. The regexp equivalent of * "Chapter " is '#^<.+?>Chapter #' * Essentially, the search strnig is looking for lines starting with... */ $log->logLine("Add Chapter 5"); $html2 = $splitter->splitChapter($chapter5, true, "Chapter "); /* '#^<.+?>Chapter \d*#i'); */ $log->logLine("Split chapter 5"); $idx = 0;
/** * Create an EPUB and export to defined path * @param $dir str directory of the source file to convert * @param $src str filename of the source file to convert * @param $path str path to export the resultant EPUB to * @param $chapters array chapters to convert into a single EPUB * @param $journalId int Id of the journal(imprint) * @param $args array arguments for the conversion (e.g. Description, cover image, etc) */ function createEpub($dir = null, $src, $path, $chapters = array(), $journalId, $args = array()) { $book = new EPub(); if (isset($args['title'])) { $book->setTitle($args['title']); } else { $book->setTitle("No Title"); } $book->setLanguage("en"); $book->setPublisher(Config::getVar('general', 'base_url'), Config::getVar('general', 'base_url')); $book->setDate(time()); $book->setRights("Copyright and licence information specific for the book."); //TODO: import specific copyright/licence information $book->setSourceURL(Config::getVar('general', 'base_url')); $CBPPlatformDao =& DAORegistry::getDAO('CBPPlatformDAO'); $imprintType = $CBPPlatformDao->getImprintType($journalId); $stylesheet = $CBPPlatformDao->getImprintStylesheet($journalId); $book->addCSSFile("styles.css", "css1", file_get_contents($this->stylesheetDir . "{$stylesheet}.css")); isset($args['description']) ? $book->setDescription($args['description']) : $book->setDescription("No description"); isset($args['author']) ? $book->setAuthor($args['author'], $args['author']) : $book->setAuthor("No author", "No author"); $args['isbn'] != null ? $book->setIdentifier($args['isbn'], EPub::IDENTIFIER_URI) : $book->setIdentifier(Config::getVar('general', 'base_url'), EPub::IDENTIFIER_URI); if (isset($args['cover'])) { $cover = $args['cover']; $coverSrc = "\n\t\t\t\t\t<svg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' width='100%' height='100%' viewBox='0 0 410 597' preserveAspectRatio='xMidYMid meet'>\n\t\t\t\t\t\t<image width='410' height='597' xlink:href='images/Cover.jpg' />\n\t\t\t\t\t</svg>"; $book->addChapter("Cover Page", "Cover.html", $this->contentStart . "{$coverSrc}</body>\n</html>\n", false, EPub::EXTERNAL_REF_ADD, $this->fileDir); $book->setCoverImage("Cover.jpg", file_get_contents($args['cover'])); } else { $book->addChapter("Cover Page", "Cover.html", $this->contentStart . "<h1>" . $book->getTitle() . "</h1><h3>" . $book->getAuthor() . "</h3></body>\n</html>\n", false, EPub::EXTERNAL_REF_ADD, $this->fileDir); } $copyrightStatement = $CBPPlatformDao->getJournalCopyrightStatement($journalId); if (!empty($copyrightStatement)) { $copyrightStatement = reset($copyrightStatement); $copyrightStatement = "<div style='width: 75%; text-align: center; margin: 0 auto;'><p>" . $copyrightStatement . "</p></div>"; $book->addChapter("Copyright Notice", "notice.html", $this->contentStart . $copyrightStatement, false, EPub::EXTERNAL_REF_ADD, $this->fileDir); } if (!empty($chapters)) { $chapterCount = 0; foreach ($chapters as $chapter) { if (!isset($chapter['type']) && $chapter['type'] != "supp") { $chapterCount++; } else { $suppChapters = true; } } for ($i = 0; $i < count($chapters); $i++) { $document = new TransformDoc(); $document->setStrFile($chapters[$i]['src'], $chapters[$i]['dir']); $document->generateXHTML(); //problem, here $document->validatorXHTML(); $contentPreg = $this->stripTags($document->getStrXHTML()); if ($chapterCount == 1) { $splitter = new EPubChapterSplitter(); $xhtml = $this->contentStart . $contentPreg . "</body></html>"; $html2 = $splitter->splitChapter($xhtml, true, '@<h1[^>]*?.*?</h1>@siu'); /* '#^<.+?>Chapter \d*#i'); */ foreach ($html2 as $key => $value) { $cTitles[] = $key; $cContent[] = $value; } for ($i = 0; $i < count($cContent); $i++) { $html3[$cTitles[$i]] = $cContent[$i]; } $idx = 0; if (!empty($html3)) { foreach ($html3 as $k => $v) { $idx++; $cName = preg_replace('#<br.+?>#i', " - ", $k); // Remove any other tags $cName = preg_replace('/<[^>]*>/', '', $cName); // clean the chapter name by removing any double spaces left behind to single space. $cName = preg_replace('#\\s+#i', " ", $cName); $book->addChapter($cName, "Chapter" . $idx . ".html", $v, false, EPub::EXTERNAL_REF_ADD, $fileDir); } } if ($suppChapters == true) { $i = 0; foreach ($chapters as $chapter) { if (isset($chapter['type']) && $chapter['type'] == "supp") { $document = new TransformDoc(); $document->setStrFile($chapter['src'], $chapter['dir']); $document->generateXHTML(); $document->validatorXHTML(); $contentPreg = $this->stripTags($document->getStrXHTML()); $book->addChapter($chapter['name'], "Chapter{$i}.html", $this->contentStart . $contentPreg . "</body></html>", false, EPub::EXTERNAL_REF_ADD, $this->fileDir); } } $i++; } break; } else { if ($imprintType == "atomistic") { $book->addChapter($cName, "Chapter" . $i . ".html", $this->contentStart . $contentPreg . "</body></html>", false, EPub::EXTERNAL_REF_ADD, $fileDir); } elseif ($imprintType == "collection") { if ($chapters[$i]['description'] != "") { $book->addChapter("Introduction to " . $chapters[$i]['name'] . " by " . $chapters[$i]['author'], "Chapter" . "{$i}-I" . ".html", $this->contentStart . "<div class='submissionIntroEpub'><h1>" . $chapters[$i]['author'] . "</h1>" . $this->stripTags($chapters[$i]['description'], true) . "</div></body></html>", false, EPub::EXTERNAL_REF_ADD, $fileDir, false); } $book->addChapter($chapters[$i]['name'] . " by " . $chapters[$i]['author'], "Chapter" . $i . ".html", $this->contentStart . "{$contentPreg}</body></html>", false, EPub::EXTERNAL_REF_ADD, $fileDir); } } } } else { $content = new TransformDoc(); $splitter = new EPubChapterSplitter(); $content->setStrFile($src, $dir); $content->generateXHTML(); $content->validatorXHTML(); $contentPreg = $this->stripTags($content->getStrXHTML()); $xhtml = $this->contentStart . $contentPreg . "</body></html>"; $html2 = $splitter->splitChapter($xhtml, true, '@<h1[^>]*?.*?</h1>@siu'); foreach ($html2 as $key => $value) { $cTitles[] = $key; $cContent[] = $value; } array_shift($cContent); for ($i = 0; $i < count($cContent); $i++) { $html3[$cTitles[$i]] = $cContent[$i]; } $idx = 0; if (!empty($html3)) { foreach ($html3 as $k => $v) { $idx++; $cName = preg_replace('#<br.+?>#i', " - ", $k); // Remove any other tags $cName = preg_replace('/<[^>]*>/', '', $cName); //clean the chapter name by removing any double spaces left behind to single space. $cName = preg_replace('#\\s+#i', " ", $cName); $book->addChapter($cName, "Chapter" . $idx . ".html", $v, false, EPub::EXTERNAL_REF_ADD, $fileDir); } } else { $book->addChapter("Body Text", "Chapter1.html", $xhtml, false, EPub::EXTERNAL_REF_ADD, $fileDir); } } $book->finalize(); $zipData = $book->getBook(); file_put_contents($path, $zipData); }
/** * Add a chapter to the book, as a chapter should not exceed 250kB, you can parse an array with multiple parts as $chapterData. * These will still only show up as a single chapter in the book TOC. * * @param string $chapterName Name of the chapter, will be use din the TOC * @param string $fileName Filename to use for the chapter, must be unique for the book. * @param string $chapter Chapter text in XHTML or array $chapterData valid XHTML data for the chapter. File should NOT exceed 250kB. * @param bool $autoSplit Should the chapter be split if it exceeds the default split size? Default=FALSE, only used if $chapterData is a string. * @param int $externalReferences How to handle external references, EPub::EXTERNAL_REF_IGNORE, EPub::EXTERNAL_REF_ADD or EPub::EXTERNAL_REF_REMOVE_IMAGES? See documentation for <code>processChapterExternalReferences</code> for explanation. Default is EPub::EXTERNAL_REF_IGNORE. * @param string $baseDir Default is "", meaning it is pointing to the document root. NOT used if $externalReferences is set to EPub::EXTERNAL_REF_IGNORE. * @return mixed $success FALSE if the addition failed, else the new NavPoint. */ function addChapter($chapterName, $fileName, $chapterData = NULL, $autoSplit = FALSE, $externalReferences = EPub::EXTERNAL_REF_IGNORE, $baseDir = "") { if ($this->isFinalized) { return FALSE; } $fileName = Zip::getRelativePath($fileName); $fileName = preg_replace('#^[/\\.]+#i', "", $fileName); $fileName = $this->sanitizeFileName($fileName); $chapter = $chapterData; if ($autoSplit && is_string($chapterData) && mb_strlen($chapterData) > $this->splitDefaultSize) { $splitter = new EPubChapterSplitter(); $chapterArray = $splitter->splitChapter($chapterData); if (count($chapterArray) > 1) { $chapter = $chapterArray; } } if (!empty($chapter) && is_string($chapter)) { if ($externalReferences !== EPub::EXTERNAL_REF_IGNORE) { $htmlDirInfo = pathinfo($fileName); $htmlDir = preg_replace('#^[/\\.]+#i', "", $htmlDirInfo["dirname"] . "/"); $this->processChapterExternalReferences($chapter, $externalReferences, $baseDir, $htmlDir); } if ($this->encodeHTML === TRUE) { $chapter = $this->encodeHtml($chapter); } $this->chapterCount++; $this->addFile($fileName, "chapter" . $this->chapterCount, $chapter, "application/xhtml+xml"); $this->opf->addItemRef("chapter" . $this->chapterCount); $navPoint = new NavPoint($this->decodeHtmlEntities($chapterName), $fileName, "chapter" . $this->chapterCount); $this->ncx->addNavPoint($navPoint); $this->ncx->chapterList[$chapterName] = $navPoint; } else { if (is_array($chapter)) { $fileNameParts = pathinfo($fileName); $extension = $fileNameParts['extension']; $name = $fileNameParts['filename']; $partCount = 0; $this->chapterCount++; $oneChapter = each($chapter); while ($oneChapter) { list($k, $v) = $oneChapter; if ($this->encodeHTML === TRUE) { $v = $this->encodeHtml($v); } if ($externalReferences !== EPub::EXTERNAL_REF_IGNORE) { $this->processChapterExternalReferences($v, $externalReferences, $baseDir); } $partCount++; $partName = $name . "_" . $partCount; $this->addFile($partName . "." . $extension, $partName, $v, "application/xhtml+xml"); $this->opf->addItemRef($partName); $oneChapter = each($chapter); } $partName = $name . "_1." . $extension; $navPoint = new NavPoint($this->decodeHtmlEntities($chapterName), $partName, $partName); $this->ncx->addNavPoint($navPoint); $this->ncx->chapterList[$chapterName] = $navPoint; } else { if (!isset($chapterData) && strpos($fileName, "#") > 0) { $this->chapterCount++; //$this->opf->addItemRef("chapter" . $this->chapterCount); $navPoint = new NavPoint($this->decodeHtmlEntities($chapterName), $fileName, "chapter" . $this->chapterCount); $this->ncx->addNavPoint($navPoint); $this->ncx->chapterList[$chapterName] = $navPoint; } else { if (!isset($chapterData) && $fileName == "TOC.xhtml") { $this->chapterCount++; $this->opf->addItemRef("toc"); $navPoint = new NavPoint($this->decodeHtmlEntities($chapterName), $fileName, "chapter" . $this->chapterCount); $this->ncx->addNavPoint($navPoint); $this->ncx->chapterList[$chapterName] = $navPoint; } } } } return $navPoint; }
/** * Add a chapter to the book, as a chapter should not exceed 250kB, you can parse an array with multiple parts as $chapterData. * These will still only show up as a single chapter in the book TOC. * * @param String $chapterName Name of the chapter, will be use din the TOC * @param String $fileName Filename to use for the chapter, must be unique for the book. * @param String $chapter Chapter text in XHTML or array $chapterData valid XHTML data for the chapter. File should NOT exceed 250kB. * @param Bool $autoSplit should the chapter be split if it exceeds 250kB? Default=false, only used if $chapterData is a String. * @return void */ function addChapter($chapterName, $fileName, $chapterData, $autoSplit = false) { if ($this->isFinalized) { return; } $chapter = $chapterData; if (is_string($chapterData) && strlen($chapterData) > 100000 && $autoSplit) { include_once "EPubChapterSplitter.php"; $splitter = new EPubChapterSplitter(); $chapterArray = $splitter->splitChapter($chapterData); if (count($chapterArray) > 1) { $chapter = $chapterArray; } } if (is_string($chapter) && strlen($chapter) > 0) { $this->zip->addFile($chapter, $fileName); $this->chapterCount++; /* Keiko: Warning toc.xhtml hardcoded here. Not a good style, but that's all what we need on the other hand. */ if ($fileName === 'toc.xhtml') { $this->opf_manifest .= "\t\t<item id=\"chapter" . $this->chapterCount . "\" href=\"" . $fileName . "\" properties=\"nav\" media-type=\"application/xhtml+xml\" />\n"; } else { $this->opf_manifest .= "\t\t<item id=\"chapter" . $this->chapterCount . "\" href=\"" . $fileName . "\" media-type=\"application/xhtml+xml\" />\n"; } $this->opf_spine .= "\t\t<itemref idref=\"chapter" . $this->chapterCount . "\" />\n"; $this->ncx_navmap .= "\n\t\t<navPoint id=\"chapter" . $this->chapterCount . "\" playOrder=\"" . $this->chapterCount . "\">\n" . "\t\t\t<navLabel><text>" . $chapterName . "</text></navLabel>\n" . "\t\t\t<content src=\"" . $fileName . "\" />\n" . "\t\t</navPoint>\n"; } else { if (is_array($chapter)) { $partCount = 0; $this->chapterCount++; while (list($k, $v) = each($chapter)) { $partCount++; $this->zip->addFile($v, $fileName . "-" . $partCount . ".xhtml"); $this->opf_manifest .= "\t\t<item id=\"chapter" . $this->chapterCount . "-" . $partCount . "\" href=\"" . $fileName . "-" . $partCount . ".xhtml\" media-type=\"application/xhtml+xml\" />\n"; $this->opf_spine .= "\t\t<itemref idref=\"chapter" . $this->chapterCount . "-" . $partCount . "\" />\n"; } $this->ncx_navmap .= "\n\t\t<navPoint id=\"chapter" . $this->chapterCount . "-1\" playOrder=\"" . $this->chapterCount . "\">\n" . "\t\t\t<navLabel><text>" . $chapterName . "</text></navLabel>\n" . "\t\t\t<content src=\"" . $fileName . "-1.xhtml\" />\n" . "\t\t</navPoint>\n"; } } }