Update of /cvsroot/php-blog/serendipity/plugins/serendipity_event_blogpdf
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv8724/plugins/serendipity_event_blogpdf
Modified Files:
serendipity_event_blogpdf.php
Log Message:
* Adjusted footer to display on more reasonable pages, including event hook
* Pimped up PDF export: Per-entry (including comments), Per-Month,
Per-Category)
* Added TODO-List for PDF-export. If someone wants to have a go, I won't put
much more work into this...
Index: serendipity_event_blogpdf.php
===================================================================
RCS file: /cvsroot/php-blog/serendipity/plugins/serendipity_event_blogpdf/serendipity_event_blogpdf.php,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- serendipity_event_blogpdf.php 9 Jul 2004 11:58:23 -0000 1.2
+++ serendipity_event_blogpdf.php 12 Jul 2004 12:47:41 -0000 1.3
@@ -1,12 +1,27 @@
<?php # $Id$
+/* TODO:
+- Use Links inside entries
+- Put images
+- Build a nice TOC
+- Insert nice formatting, maybe user-defined? (Color, Font face)
+- Parse attributes like STRONG, BOLD, ...
+*/
+
switch ($serendipity['lang']) {
case 'de':
@define('PLUGIN_EVENT_BLOGPDF_NAME', 'Blog als PDF exportieren');
@define('PLUGIN_EVENT_BLOGPDF_DESC', 'Exportiert alle Einträge des Blogs in eine PDF-Datei');
- @define('PLUGIN_EVENT_BLOGPDF_DOWNLOAD', 'Download des Blogs als plaintext-PDF!');
+ @define('PLUGIN_EVENT_BLOGPDF_DOWNLOAD', 'Download des Blogs als PDF!');
@define('PLUGIN_EVENT_BLOGPDF_PAGE', 'Seite');
@define('PLUGIN_EVENT_BLOGPDF_EXPORT', 'Blog Export');
+
+ @define('PLUGIN_EVENT_BLOGPDF_VIEW', 'Als PDF ansehen: ');
+ @define('PLUGIN_EVENT_BLOGPDF_VIEW_FULL', 'Vollständiges Blog');
+ @define('PLUGIN_EVENT_BLOGPDF_VIEW_ENTRY', 'Dieser Artikel');
+ @define('PLUGIN_EVENT_BLOGPDF_VIEW_CATEGORY', 'Kategorie %s');
+ @define('PLUGIN_EVENT_BLOGPDF_VIEW_MONTH', 'Dieser Monat');
+ @define('PLUGIN_EVENT_BLOGPDF_MISSING', 'Ungültiger Plugin-Modus %s');
break;
case 'en':
@@ -14,21 +29,29 @@
default:
@define('PLUGIN_EVENT_BLOGPDF_NAME', 'Export blog as PDF');
@define('PLUGIN_EVENT_BLOGPDF_DESC', 'Exports your full blog as a PDF file');
- @define('PLUGIN_EVENT_BLOGPDF_DOWNLOAD', 'Download this blog as plaintext-PDF!');
+ @define('PLUGIN_EVENT_BLOGPDF_DOWNLOAD', 'Download this blog as PDF!');
@define('PLUGIN_EVENT_BLOGPDF_PAGE', 'Page');
@define('PLUGIN_EVENT_BLOGPDF_EXPORT', 'Blog Export');
+ @define('PLUGIN_EVENT_BLOGPDF_VIEW', 'View as PDF: ');
+ @define('PLUGIN_EVENT_BLOGPDF_VIEW_FULL', 'Full blog');
+ @define('PLUGIN_EVENT_BLOGPDF_VIEW_ENTRY', 'This entry');
+ @define('PLUGIN_EVENT_BLOGPDF_VIEW_CATEGORY', 'Category %s');
+ @define('PLUGIN_EVENT_BLOGPDF_VIEW_MONTH', 'This month');
+ @define('PLUGIN_EVENT_BLOGPDF_MISSING', 'Invalid plugin operator %s');
break;
}
define('FPDF_FONTPATH','plugins/serendipity_event_blogpdf/font/');
require('fpdf.php');
class PDF extends FPDF {
+ var $TOC = array();
+
function Header() {
global $serendipity;
$this->SetFont('Arial', 'B', 15);
- $this->Cell(0, 10, PLUGIN_EVENT_BLOGPDF_EXPORT .' :' . $serendipity['blogTitle'] . ', ' . $serendipity['baseURL'], 1, 0, 'C');
+ $this->Cell(0, 10, PLUGIN_EVENT_BLOGPDF_EXPORT .': ' . $serendipity['blogTitle'] . ', ' . $serendipity['baseURL'], 1, 0, 'C');
$this->Ln(20);
}
@@ -39,10 +62,86 @@
$this->SetFont('Arial', 'I', 8);
$this->Cell(0, 10, PLUGIN_EVENT_BLOGPDF_PAGE . ' ' . $this->PageNo() . ' / {nb}', 0, 0, 'C');
}
+
+ function TOC_Add($header) {
+ $this->TOC[] = array(
+ 'header' => $header,
+ 'page' => $this->PageNo(),
+ 'pos' => $this->GetY()
+ );
+ }
+
+ function TOC_Build() {
+ $cnt = count($this->TOC);
+ if ($cnt < 1) {
+ return;
+ }
+
+ $first = $this->n+1;
+ $last = $first + $cnt;
+
+ foreach($this->TOC AS $ti => $toc) {
+ $this->_newobj();
+ $this->_out('<</Title ' . $this->_textstring($toc['header']));
+
+ // This ob has to be the obj reference to the last Outline-Type.
+ $this->_out('/Parent ' . ($first + $cnt) . ' 0 R');
+ if ($this->n > $first) {
+ $this->_out('/Prev ' . ($this->n - 1) . ' 0 R');
+ }
+
+ if ($this->n < $last && isset($TOC[$ti+1])) {
+ $this->_out('/Next ' . ($this->n + 1) . ' 0 R');
+ }
+
+ $this->_out(
+ sprintf(
+ '/Dest [%d 0 R /XYZ 0 %.2f null]',
+
+ 1 + (2*$toc['page']),
+ ($this->h - $toc['pos']) * $this->k
+ )
+ );
+ $this->_out('/Count 0>>');
+ $this->_out('endobj');
+ }
+
+ $this->_newobj();
+ $this->OutlineRoot = $this->n;
+ $this->_out('<</Type /Outlines /First ' . $first . ' 0 R');
+ $this->_out('/Last ' . ($this->n - 1) . ' 0 R>>');
+ $this->_out('endobj');
+ }
+
+ function _putresources() {
+ parent::_putresources();
+ $this->TOC_Build();
+ }
+
+ function _putcatalog() {
+ parent::_putcatalog();
+ if(count($this->TOC) > 0) {
+ $this->_out('/Outlines '. $this->OutlineRoot . ' 0 R');
+ $this->_out('/PageMode /UseOutlines');
+ }
+ }
+}
+
+if (!function_exists('html_entity_decode')) {
+ function html_entity_decode($given_html, $quote_style = ENT_QUOTES) {
+ $trans_table = get_html_translation_table(HTML_SPECIALCHARS, $quote_style);
+ if ($trans_table["'"] != ''') { # some versions of PHP match single quotes to '
+ $trans_table["'"] = ''';
+ }
+
+ return (strtr($given_html, array_flip($trans_table)));
+ }
}
class serendipity_event_blogpdf extends serendipity_event
{
+ var $pdf;
+
function introspect(&$propbag)
{
global $serendipity;
@@ -50,8 +149,9 @@
$propbag->add('name', PLUGIN_EVENT_BLOGPDF_NAME);
$propbag->add('description', PLUGIN_EVENT_BLOGPDF_DESC);
$propbag->add('event_hooks', array(
- 'external_plugin' => true,
- 'entries_footer' => true
+ 'external_plugin' => true,
+ 'entries_footer' => true,
+ 'frontend_display' => true
));
}
@@ -63,36 +163,114 @@
global $serendipity;
$hooks = &$bag->get('event_hooks');
+ $links = array();
+ $article_show = false;
if (isset($hooks[$event])) {
switch($event) {
+ case 'frontend_display':
+ if (isset($serendipity['GET']['id']) && is_numeric($serendipity['GET']['id'])) {
+ $article_show = true;
+ $year = date('Y', $eventData['timestamp']);
+ $month = date('m', $eventData['timestamp']);
+ } else {
+ break;
+ }
+
case 'entries_footer':
- echo '<br /><a href="' . $serendipity['baseURL'] . 'plugin/blogpdf">' . PLUGIN_EVENT_BLOGPDF_DOWNLOAD . '</a>';
+ if (isset($serendipity['GET']['id']) && is_numeric($serendipity['GET']['id'])) {
+ $links[] = '<a href="' . $serendipity['baseURL'] . 'plugin/articlepdf_' . $serendipity['GET']['id'] . '">' . PLUGIN_EVENT_BLOGPDF_VIEW_ENTRY . '</a>';
+ }
+
+ if (isset($serendipity['GET']['category'])) {
+ $cid = explode('_', $serendipity['GET']['category']);
+ if (is_numeric($cid[0])) {
+ $cat = serendipity_fetchCategoryInfo($cid[0]);
+ $links[] = '<a href="' . $serendipity['baseURL'] . 'plugin/categorypdf_' . $cid[0] . '">' . sprintf(PLUGIN_EVENT_BLOGPDF_VIEW_CATEGORY, $cat['category_name']) . '</a>';
+ }
+ }
+
+ if (empty($year) && empty($month) && isset($serendipity['GET']['range']) && is_numeric($serendipity['GET']['range'])) {
+ $year = substr($serendipity['GET']['range'], 0, 4);
+ $month = substr($serendipity['GET']['range'], 4, 2);
+ }
+
+ if (empty($year)) {
+ $year = date('Y');
+ }
+
+ if (empty($month)) {
+ $month = date('m');
+ }
+
+ $links[] = '<a href="' . $serendipity['baseURL'] . 'plugin/monthpdf_' . $year . $month . '">' . PLUGIN_EVENT_BLOGPDF_VIEW_MONTH . '</a>';
+ $links[] = '<a href="' . $serendipity['baseURL'] . 'plugin/blogpdf">' . PLUGIN_EVENT_BLOGPDF_VIEW_FULL . '</a>';
+
+ if ($article_show) {
+ $eventData['add_footer'] = '<br />' . PLUGIN_EVENT_BLOGPDF_VIEW . implode(' | ', $links);
+ } else {
+ echo '<br />' . PLUGIN_EVENT_BLOGPDF_VIEW . implode(' | ' , $links);
+ }
+
+
return true;
break;
case 'external_plugin':
- if (stristr($eventData, 'blogpdf')) {
- $feedcache = $serendipity['serendipityPath'] . 'archives/blog.pdf';
- $cachetime = 60*60*24; // one day
+ $cachetime = 60*60*24; // one day
- $pdf = new PDF();
- $pdf->AliasNbPages();
+ $parts = explode('_', $eventData);
+ if (!empty($parts[1])) {
+ $param = (int) $parts[1];
+ } else {
+ $param = null;
+ }
- if (!file_exists($feedcache) || filesize($feedcache) == 0 || filemtime($feedcache) < (time() - $cachetime)) {
- $this->print_entries(serendipity_fetchEntries(), $pdf);
- $pdf->Close();
- $fp = fopen($feedcache, 'wb');
- fwrite($fp, $pdf->buffer);
- fclose($fp);
- } else {
- $pdf->buffer = file_get_contents($feedcache);
- $pdf->state = 3; // fake closed document to insert cached PDF
- }
+ $this->pdf = new PDF();
+ $this->pdf->AliasNbPages();
- $pdf->Output();
+ switch($parts[0]) {
+ case 'blogpdf':
+ $feedcache = $serendipity['serendipityPath'] . 'archives/blog.pdf';
+ $this->process(
+ $feedcache,
+ serendipity_fetchEntries()
+ );
+ break;
+
+ case 'articlepdf':
+ $feedcache = $serendipity['serendipityPath'] . 'archives/article' . $param . '.pdf';
+ $this->single = true;
+ $this->process(
+ $feedcache,
+ serendipity_fetchEntry('id', $param)
+ );
+ break;
+
+ case 'monthpdf':
+ $feedcache = $serendipity['serendipityPath'] . 'archives/month' . $param . '.pdf';
+ $this->process(
+ $feedcache,
+ serendipity_fetchEntries($param)
+ );
+ break;
+
+ case 'categorypdf':
+ $feedcache = $serendipity['serendipityPath'] . 'archives/category' . $param . '.pdf';
+ $serendipity['GET']['category'] = $param . '_category';
+ $this->process(
+ $feedcache,
+ serendipity_fetchEntries()
+ );
+ break;
+
+ default:
+ printf(PLUGIN_EVENT_BLOGPDF_MISSING, $eventData);
+ break;
}
+ $this->pdf->Output();
+
return true;
break;
@@ -105,7 +283,108 @@
}
}
- function print_entries($entries, &$pdf) {
+ function process($feedcache, $entries) {
+ if (!file_exists($feedcache) || filesize($feedcache) == 0 || filemtime($feedcache) < (time() - $cachetime)) {
+ if ($this->single) {
+ $this->print_entry(0, $entries, serendipity_formatTime(DATE_FORMAT_ENTRY, $entries['timestamp']));
+ } else {
+ $this->print_entries($entries);
+ }
+ $this->pdf->Close();
+ $fp = fopen($feedcache, 'wb');
+ fwrite($fp, $this->pdf->buffer);
+ fclose($fp);
+ } else {
+ $this->pdf->buffer = file_get_contents($feedcache);
+ $this->pdf->state = 3; // fake closed document to insert cached PDF
+ }
+
+ return true;
+ }
+
+ function print_entry($x, &$entry, $header = false) {
+ if ($header) {
+ $this->pdf->AddPage();
+ $this->pdf->SetFont('Courier','',12);
+ $this->pdf->TOC_Add($header);
+ $this->pdf->Cell(0, 10, $header, 1);
+ $this->pdf->Ln();
+ $this->pdf->Ln();
+ }
+
+ $entryLink = serendipity_archiveURL($entry['id'], $entry['title'], 'serendipityHTTPPath', false);
+ serendipity_plugin_api::hook_event('frontend_display', $entry, array('no_scramble' => true));
+
+ $posted_by = ' ' . POSTED_BY . ' ' . htmlspecialchars($entry['username']);
+ if (is_array($entry['categories']) && sizeof($entry['categories']) > 0) {
+ $posted_by .= ' ' . IN . ' ';
+ $cats = array();
+ foreach ($entry['categories'] as $cat) {
+ $cats[] = $cat['category_name'];
+ }
+ $posted_by .= implode(', ', $cats);
+ }
+
+ $posted_by .= ' ' . AT . ' ' . date('H:i', $entry['timestamp']);
+
+ $this->pdf->SetFont('Arial', 'B', 11);
+ $this->pdf->Write(4, $this->prep_out($entry['title']) . "\n");
+ $this->pdf->Ln();
+
+ $this->pdf->SetFont('Arial', '', 10);
+ $this->pdf->Write(4, $this->prep_out($entry['body'] . $entry['extended']) . "\n");
+ $this->pdf->Ln();
+
+ $this->pdf->SetFont('Courier', '', 9);
+ $this->pdf->Write(4, $this->prep_out($posted_by) . "\n");
+ $this->pdf->Ln();
+
+ if ($this->single) {
+ $this->printComments(serendipity_fetchComments($entry['id']));
+ }
+
+ }
+
+ function printComments($comments) {
+ if (!is_array($comments) || count($comments) < 1) {
+ return;
+ }
+
+ foreach ($comments as $i => $comment) {
+ $comment['comment'] = htmlspecialchars(strip_tags($comment['body']));
+ if (!empty($comment['url']) && substr($comment['url'], 0, 7) != 'http://' && substr($comment['url'], 0, 8) != 'https://') {
+ $comment['url'] = 'http://' . $comment['url'];
+ }
+
+ serendipity_plugin_api::hook_event('frontend_display', $comment);
+
+ /* Protect submitted mails against spam, by replacing @ with [at]*/
+ if (!empty($comment['email'])) {
+ $comment['email'] = str_replace('@', '[at]', $comment['email']);
+ }
+
+ $name = empty($comment['author']) ? ANONYMOUS : $comment['author'];
+ $body = $comment['comment'];
+
+ $this->pdf->SetFont('Arial', '', 9);
+ $this->pdf->Write(
+ 3,
+ $this->prep_out(
+ $body . "\n" .
+ ' ' . $name .
+ ' ' . ON . ' ' . ucfirst(strftime('%b %e %Y, %H:%M', $comment['timestamp']))
+ ) . "\n"
+ );
+ $this->pdf->Ln();
+ $this->pdf->Ln();
+ }
+ }
+
+ function prep_out($string) {
+ return strip_tags(html_entity_decode($string));
+ }
+
+ function print_entries($entries) {
$extended = true;
$preview = false;
@@ -125,39 +404,10 @@
}
foreach ($bydate as $date => $ents) {
- $pdf->AddPage();
- $pdf->SetFont('Courier','',12);
- $pdf->Cell(0, 10, $date, 1);
- $pdf->Ln();
- $pdf->Ln();
-
+ $header = $date;
foreach ($ents as $x => $entry) {
- $entryLink = serendipity_archiveURL($entry['id'], $entry['title'], 'serendipityHTTPPath', false);
- serendipity_plugin_api::hook_event('frontend_display', $entry, array('no_scramble' => true));
-
- $posted_by = ' ' . POSTED_BY . ' ' . htmlspecialchars($entry['username']);
- if (is_array($entry['categories']) && sizeof($entry['categories']) > 0) {
- $posted_by .= ' ' . IN . ' ';
- $cats = array();
- foreach ($entry['categories'] as $cat) {
- $cats[] = $cat['category_name'];
- }
- $posted_by .= implode(', ', $cats);
- }
-
- $posted_by .= ' ' . AT . ' ' . date('H:i', $entry['timestamp']);
-
- $pdf->SetFont('Arial', 'B', 11);
- $pdf->Write(4, strip_tags($entry['title']) . "\n");
- $pdf->Ln();
-
- $pdf->SetFont('Arial', '', 10);
- $pdf->Write(4, strip_tags($entry['body'] . $entry['extended']) . "\n");
- $pdf->Ln();
-
- $pdf->SetFont('Courier', '', 9);
- $pdf->Write(4, strip_tags($posted_by) . "\n");
- $pdf->Ln();
+ $this->print_entry($x, $entry, $header);
+ $header = false;
} // end for-loop (entries)
} // end for-loop (dates)
} // end function serendipity_printEntries
|