private function createNavPoint(\DOMDocument $document, ManifestItem $item, &$index) { $child = $document->createElement('navPoint'); $child->setAttribute('id', sprintf('navpoint-%d', $index)); $child->setAttribute('playOrder', $index); $dom = new \DOMDocument('1.0'); @$dom->loadHTML($item->getContent()); $title = $dom->getElementsByTagName('title')->item(0); if (!$title) { $title = basename($item->href, '.html'); } else { $title = $title->nodeValue; } $label = $document->createElement('navLabel'); $text = $document->createElement('text', $title); $label->appendChild($text); $child->appendChild($label); $content = $document->createElement('content'); $content->setAttribute('src', $item->href); $child->appendChild($content); $xpath = new \DOMXPath($dom); $headers = $xpath->query('//h3/a[@id]'); $createNavPoint = function ($id, $class, $title, $src, $playOrder) use($document) { $child = $document->createElement('navPoint'); $child->setAttribute('id', $id); $child->setAttribute('class', $class); $child->setAttribute('playOrder', $playOrder); $label = $document->createElement('navLabel'); $text = $document->createElement('text', $title); $label->appendChild($text); $child->appendChild($label); $content = $document->createElement('content'); $content->setAttribute('src', $src); $child->appendChild($content); return $child; }; if ($headers) { foreach ($headers as $node) { // only add 2nd level headers if (!preg_match('/^\\d+\\.\\d+$/', $node->nodeValue)) { continue; } $ref = $node->getAttribute('id'); $title = $node->nextSibling->nodeValue; $child->appendChild($createNavPoint(str_replace('.', '_', $ref), 'h2', $title, sprintf('%s#%s', $item->href, $ref), ++$index)); } } return $child; }
protected function execute(InputInterface $input, OutputInterface $output) { $destination = $input->getArgument('output'); // use realpath because we need the absolute location $filename = realpath(dirname($destination)) . '/' . basename($destination); $workingDir = sys_get_temp_dir() . uniqid('build-epub-'); mkdir($workingDir); $converter = new Txt2HtmlConverter(realpath($input->getArgument('input')), $workingDir); $converter->convert(); $sourceFiles = $converter->getFiles(); $this->workingDir = $workingDir; $package = new Package(); $metadata = array('title' => 'HTTP Protocol', 'identifier' => 'http-protocol', 'language' => 'en'); foreach ($metadata as $name => $value) { $item = new MetadataItem(); $item->name = $name; $item->value = $value; $package->metadata->add($item); } $toc = new ManifestItem(); $toc->type = 'application/x-dtbncx+xml'; $toc->href = 'toc.ncx'; $toc->id = 'ncx'; $toc->setContent(function () use($package) { $dumper = new TocResourceDumper($package); return $dumper->dump(); }); $package->manifest->add($toc); foreach ($sourceFiles as $name => $file) { $item = new ManifestItem(); $item->href = $name; // fix the filenames for sorting purposes if (preg_match('/rfc(\\d+)-sec(\\d+)\\.html/', $item->href, $match)) { $item->href = sprintf('x-rfc%s-sec%04s.html', $match[1], $match[2]); } $item->type = 'application/xhtml+xml'; $item->id = basename($item->href, '.html'); $item->setContent($this->repairSpecHTML(file_get_contents($file))); unlink($file); $package->manifest->add($item); $package->spine->add($item); } $this->addFromString('mimetype', 'application/epub+zip'); $this->addFromString('META-INF/container.xml', <<<EOT <?xml version="1.0"?> <container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container"> <rootfiles> <rootfile full-path="content.opf" media-type="application/oebps-package+xml"/> </rootfiles> </container> EOT ); $dumper = new OpfResourceDumper($package); $this->addFromString('content.opf', $dumper->dump()); foreach ($package->manifest->all() as $item) { $this->addFromString($item->href, $item->getContent()); } exec(sprintf('(cd %s && zip -q0Xj %s %s)', escapeshellarg($workingDir), escapeshellarg($filename), 'mimetype')); exec(sprintf('(cd %s && zip -Xur9D %s *)', escapeshellarg($workingDir), escapeshellarg($filename))); exec(sprintf('rm -rf %s', escapeshellarg($workingDir))); }