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']) . '
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();
}
}