epub_template)); $this->epub = new ZipArchive; if (($err = $this->epub->open($path)) !== true) { unlink($path); throw new lencrierException('Unable to open EPUB archive (code '.$err.'), message: '.$this->epub->getStatusString()); } $this->epub->addEmptyDir('META-INF'); $this->epub->addEmptyDir('OEBPS'); $this->epub->addEmptyDir('OEBPS/articles'); $this->epub->addEmptyDir('OEBPS/articles/images'); $this->epub->addFromString('META-INF/container.xml', ' '); return $this->epub; } protected function epub_mediaTypeFromFileExtension($ext) { switch (strtolower($ext)) { case 'gif': return 'image/gif'; case 'jpg': case 'jpeg': case 'jpe': return 'image/jpeg'; case 'png': return 'image/png'; case 'svg': return 'image/svg+xml'; case 'html': case 'xhtml': return 'application/xhtml+xml'; case 'css': return 'text/css'; default: return false; } } protected function epub_appendFile($local_path, $distant_path, $id) { $local_dir = dirname($local_path); if (!in_array($local_dir, $this->epub_dirs)) { $this->epub->addEmptyDir('OEBPS/' . $local_dir); $this->epub_dirs[] = $local_dir; } $ext = strtolower(substr($distant_path, strrpos($distant_path, '.')+1)); $type = $this->epub_mediaTypeFromFileExtension($ext); $this->epub_files[$local_path] = ['id' => $id, 'type' => $type]; return $this->epub->addFile($distant_path, 'OEBPS/' . $local_path); } protected function epub_appendFileFromString($local_path, $content, $id) { $ext = strtolower(substr($local_path, strrpos($local_path, '.')+1)); $type = $this->epub_mediaTypeFromFileExtension($ext); $this->epub_files[$local_path] = ['id' => $id, 'type' => $type]; return $this->epub->addFromString('OEBPS/' . $local_path, $content); } protected function html_header($title) { return ' '.htmlspecialchars($title, ENT_QUOTES, 'UTF-8').' '; } protected function html_footer() { return ' '; } protected function html_Article($article) { $text = $article['texte_html']; $text = preg_replace('!image:\[([^\]]+)\]!', 'images/$1', $text); // TODO: for the time being documents are not included (privacy issues?) //$texte = preg_replace('!document:\[([^\]]+)\]!', utils::getJournalDatasURL($journal, 'documents') . '$1', $texte); $text = preg_replace_callback('!href="(\d+)"!', function ($match) { return 'href="'.sprintf('%010d.xhtml', (int)$match[1]).'"'; }, $text); $text = strip_tags($text, $this->allowed_tags); $text = Rendu_Modifiers::formatter_texte($text); $text = tidy_repair_string($text, array('wrap' => 100, 'output-xhtml' => true, 'show-body-only' => true), 'utf8'); $html = $this->html_header($article['titre']); $html .= '

'.htmlspecialchars($article['titre'], ENT_QUOTES, 'UTF-8').'

'.$this->dateFormat($article['date']).'

'.$text.'
'; $html .= $this->html_footer(); return $html; } protected function html_titlePage() { $journal = $this->getJournalResume(); $url = utils::getJournalURL($this->id); $text = Rendu_Modifiers::formatter_texte($journal['texte']); $html = $this->html_header($journal['titre']); $html .= '

' . htmlspecialchars($journal['titre']) . '

' . $url . '

E-Book créé le '.$this->dateFormat(time()).'

' . $text . '
'; $html .= $this->html_footer(); return $html; } protected function epub_TOC() { $journal = $this->getJournalResume(); $url = utils::getJournalURL($this->id); $toc = ' '.$this->escape($journal['titre']).' '; $i = 1; foreach ($this->epub_toc as $month=>$articles) { $ts = strtotime($month . '-15'); $first = current($articles); $toc .= ' '.$this->escape($this->dateFormat($ts, 'F Y')).' '; $j = 1; foreach ($articles as $id => $art) { $toc .= ' '.$this->escape($this->dateFormat($art['date'], 'l j') . ' — ' . $art['title']).' '; } $toc .= ' '; $i++; } $toc .= ' '; return $toc; } protected function epub_close() { $journal = $this->getJournalResume(); $url = utils::getJournalURL($this->id); // Generate OPF file $manifest = ''; foreach ($this->epub_files as $path => $attrs) { $manifest .= ' '; } $spine = ''; foreach ($this->epub_spine as $id) { $spine .= ' '; } // TODO: dc:language according to blog lang $this->epub->addFromString('OEBPS/book.opf', ' '.$this->escape($journal['titre']).' fr '.$this->escape($url).' '.date('Y-m-d').' '.$this->escape(strip_tags($journal['texte'])).' '.$this->escape(LENCRIER_HOME_NAME).' '.$manifest.' '.$spine.' '); $this->epub->addFromString('OEBPS/toc.ncx', $this->epub_TOC()); $this->epub->close(); } public function export($path=false) { if (!$path) { $path = LENCRIER_DATA_ROOT . '/documents/'.$this->id.'/export-journal-'.$this->id.'.epub'; } loadLib('rendu_modifiers'); $epub = $this->epub_init($path); if (!$epub) return false; $this->epub_appendFileFromString('articles/index.xhtml', $this->html_titlePage(), 'titlepage'); $this->epub_appendFile('articles/style.css', LENCRIER_ROOT . '/ecrire/style/corps.css', 'style'); // Add images $images_path = utils::getJournalDatasPath($this->id, 'documents') . '/images/'; $files = utils::recurseListFiles($images_path); if (!empty($files)) { foreach ($files as $file) { $local_file = 'articles/images/' . str_replace($images_path, '', $file); $local_file = str_replace('//', '/', $local_file); $this->epub_appendFile($local_file, $file, 'img-' . sha1($file)); } } require_once LENCRIER_ROOT . '/include/garbage2xhtml/lib.garbage2xhtml.php'; $this->g2x = new garbage2xhtml; // There is no reason to include those in an EPUB (at least in v2) unset($this->g2x->block_tags['audio'], $this->g2x->block_tags['video'], $this->g2x->block_tags['object'], $this->g2x->block_tags['iframe']); $this->allowed_tags = array_merge( array_keys($this->g2x->block_tags), array_keys($this->g2x->inline_tags) ); // Compile a list of allowed tags in article content $this->allowed_tags = '<' . implode('><', $this->allowed_tags) . '>'; $this->resetEcrits(); while ($article = $this->getEcrit()) { $epub_id = 'art-' . (int)$article['id']; $epub_file = sprintf('articles/%010d.xhtml', (int)$article['id']); $this->epub_appendFileFromString($epub_file, $this->html_Article($article), $epub_id); $this->epub_spine[] = $epub_id; $month = date('Y-m', $article['date']); if (!array_key_exists($month, $this->epub_toc)) { $this->epub_toc[$month] = []; } $this->epub_toc[$month][$epub_id] = [ 'title' => $article['titre'], 'date' => $article['date'], 'file' => $epub_file ]; } return $this->epub_close(); } }