Difference between revisions of "Extension:PdfBook"

From Organic Design wiki
m (no need to preserve globals because it dies after sending pdf)
(oops, hadn't updated to server version)
Line 67: Line 67:
  
 
# Initialise PDF variables
 
# Initialise PDF variables
$layout = '--firstpage toc';
+
$layout = '--firstpage toc';
if (!xwGetProperty($properties,'pdf/left-margin',$left))    $left  = '1cm';
+
$left   = $this->setProperty('LeftMargin', '1cm');
if (!xwGetProperty($properties,'pdf/right-margin',$right))  $right  = '1cm';
+
$right   = $this->setProperty('RightMargin', '1cm');
if (!xwGetProperty($properties,'pdf/top-margin',$top))      $top    = '1cm';
+
$top     = $this->setProperty('TopMargin',   '1cm');
if (!xwGetProperty($properties,'pdf/bottom-margin',$bottom)) $bottom = '5mm';
+
$bottom = $this->setProperty('BottomMargin','1cm');
if (!xwGetProperty($properties,'pdf/font-name',$font))      $font  = 'Arial';
+
$font   = $this->setProperty('Font',       'Arial');
if (!xwGetProperty($properties,'pdf/font-size',$size))      $size  = '8';
+
$size    = $this->setProperty('FontSize',   '8');
if (!xwGetProperty($properties,'pdf/links',$links))          $links = '217A28';
+
$link    = $this->setProperty('LinkColour',  '217A28');
if (!xwGetProperty($properties,'pdf/toc-levels',$levels))    $levels = '2';
+
$levels  = $this->setProperty('TocLevels',   '2');
if (xwGetProperty($properties,'pdf/exclude',$exclude))       $exclude = split('\\s*,\\s*',$exclude); else $exclude = array();
+
$exclude = $this->setProperty('Exclude',    array());
 +
if (!is_array($exclude)) $exclude = split('\\s*,\\s*',$exclude);
 
   
 
   
 
# Select all article titles in category
 
# Select all article titles in category
$cat    = $article->getTitle()->getText();
+
$title  = $article->getTitle();
 +
$book  = $title->getText();
 +
$cat    = $title->getDBkey();
 
$db    = &wfGetDB(DB_SLAVE);
 
$db    = &wfGetDB(DB_SLAVE);
 
$cl    = $db->tableName('categorylinks');
 
$cl    = $db->tableName('categorylinks');
 
$result = $db->query("SELECT cl_from FROM $cl WHERE cl_to = '$cat' ORDER BY cl_sortkey");
 
$result = $db->query("SELECT cl_from FROM $cl WHERE cl_to = '$cat' ORDER BY cl_sortkey");
 +
 
# Format the article's as a single HTML document with absolute URL's
 
# Format the article's as a single HTML document with absolute URL's
 
$html = '';
 
$html = '';
Line 93: Line 97:
 
$wgScript      = $wgServer.$wgScript;
 
$wgScript      = $wgServer.$wgScript;
 
$article      = new Article($title);
 
$article      = new Article($title);
$text          = $article->getContent();
+
$text          = $article->fetchContent();
$opt          = new ParserOptions;
+
$opt          = ParserOptions::newFromUser($wgUser);
$opt->setRemoveComments(false); # allow HTML comments
+
# $opt->setRemoveComments(false); # allow HTML comments
 +
$text = preg_replace('/<!--([^@]+?)-->/s','@@'.'@@$1@@'.'@@',$text); # Hack so that HTML comments in the wikitext are preserved
 
$opt->setEditSection(false);    # remove section-edit links
 
$opt->setEditSection(false);    # remove section-edit links
 
$wgOut->setHTMLTitle($ttext);  # use this so DISPLAYTITLE magic works
 
$wgOut->setHTMLTitle($ttext);  # use this so DISPLAYTITLE magic works
 
$out          = $wgParser->parse($text,$title,$opt,true,true);
 
$out          = $wgParser->parse($text,$title,$opt,true,true);
 
$ttext        = $wgOut->getHTMLTitle();
 
$ttext        = $wgOut->getHTMLTitle();
$html        .= "<h1>$ttext</h1>".$out->getText()."\n";
+
$text          = $out->getText();
 +
$text = preg_replace('/@{4}([^@]+?)@{4}/s','<!--$1-->',$text); # HTML comments hack
 +
$text = preg_replace('/<table/','<table border borderwidth=2 cellpadding=3 cellspacing=0',$text);
 +
$ttext = basename($ttext);
 +
$html        .= "<h1>$ttext</h1>$text\n";
 
}
 
}
 
}
 
}
Line 106: Line 115:
 
# Write the HTML to a tmp file
 
# Write the HTML to a tmp file
 
$file = "$wgUploadPath/".uniqid('pdf-book');
 
$file = "$wgUploadPath/".uniqid('pdf-book');
 +
$file = '/var/www/extensions/PdfBook/foo';
 
$fh = fopen($file,'w+');
 
$fh = fopen($file,'w+');
 
fwrite($fh,$html);
 
fwrite($fh,$html);
Line 113: Line 123:
 
while (@ob_end_clean());
 
while (@ob_end_clean());
 
header("Content-Type: application/pdf");
 
header("Content-Type: application/pdf");
header("Content-Disposition: attachment; filename=\"$file\"");
+
header("Content-Disposition: attachment; filename=\"$book.pdf\"");
 
flush();
 
flush();
passthru("htmldoc -t pdf --left $left --right $right --top $top --bottom $bottom --header ... --footer .1. --headfootsize 8 --quiet --jpeg --color --bodyfont $font --fontsize $size --linkstyle plain --linkcolor $links --toclevels $levels --format pdf14 --numbered $layout $file");
+
$cmd =  "--left $left --right $right --top $top --bottom $bottom";
@unlink($file);
+
$cmd .= " --header ... --footer .1. --headfootsize 8 --quiet --jpeg --color";
 +
$cmd .= " --bodyfont $font --fontsize $size --linkstyle plain --linkcolor $links";
 +
$cmd .= " --toclevels $levels --format pdf14 --numbered $layout";
 +
$cmd =  "htmldoc -t pdf $cmd $file";
 +
putenv("HTMLDOC_NOCGI=1");
 +
$content = shell_exec($cmd);
 +
if (in_array('Content-Encoding: gzip',headers_list())) $content = gzencode($content);
 +
echo($content);
 +
# @unlink($file);
 
die;
 
die;
 
}
 
}
 +
}
 +
 +
# Return a property for htmldoc using global, request or passed default
 +
function setProperty($name,$default) {
 +
if (isset($_REQUEST["pdf$name"]))      return $_REQUEST["pdf$name"];
 +
if (isset($GLOBALS["wgPdfBook$name"])) return $GLOBALS["wgPdfBook$name"];
 +
return $default;
 
}
 
}
  
 
# Needed in some versions to prevent Special:Version from breaking
 
# Needed in some versions to prevent Special:Version from breaking
 
function __toString() { return 'PdfBook'; }
 
function __toString() { return 'PdfBook'; }
 +
 
  }
 
  }
  

Revision as of 22:54, 27 August 2007

<?php

  1. Extension:PdfBook
Info.svg These are the MediaWiki extensions we're using and/or developing. Please refer to the information on the mediawiki.org wiki for installation and usage details. Extensions here which have no corresponding mediawiki article are either not ready for use or have been superseded. You can also browse our extension code in our local Subversion repository or our GitHub mirror.

Template:PhpCategory:Extensions created with Template:Extension

  1. - Licenced under LGPL (http://www.gnu.org/copyleft/lesser.html)
  2. - Author: User:Nad
  3. - Started: 2007-08-08

if (!defined('MEDIAWIKI')) die('Not an entry point.');

define('PDFBOOK_VERSION','0.0.0, 2007-08-08');

$wgPdfBookMagic = "book"; $wgExtensionFunctions[] = 'wfSetupPdfBook'; $wgHooks['LanguageGetMagic'][] = 'wfPdfBookLanguageGetMagic';

$wgExtensionCredits['parserhook'][] = array( 'name' => 'Pdf Book', 'author' => 'User:Nad', 'description' => 'Composes a book from articles in a category and exports as a PDF book', 'url' => 'http://www.mediawiki.org/wiki/Extension:Pdf_Book', 'version' => PDFBOOK_VERSION );

class PdfBook {

# Constructor function PdfBook() { global $wgHooks,$wgParser,$wgPdfBookMagic; $wgParser->setFunctionHook($wgPdfBookMagic,array($this,'magicBook')); $wgHooks['UnknownAction'][] = $this;

# Add a new pdf log type global $wgLogTypes,$wgLogNames,$wgLogHeaders,$wgLogActions; $wgLogTypes[] = 'pdf'; $wgLogNames ['pdf'] = 'pdflogpage'; $wgLogHeaders['pdf'] = 'pdflogpagetext'; $wgLogActions['pdf/book'] = 'pdflogentry'; }

# Expand the book-magic function magicBook(&$parser) {

# Populate $argv with both named and numeric parameters $argv = array(); foreach (func_get_args() as $arg) if (!is_object($arg)) { if (preg_match('/^(.+?)\\s*=\\s*(.+)$/',$arg,$match)) $argv[$match[1]] = $match[2]; else $argv[] = $arg; }

# Return result with available parser flags return array( $text, found => true, nowiki => false, noparse => false, noargs => false, isHTML => false ); }

function onUnknownAction($action,$article) { global $wgOut,$wgUser,$wgTitle,$wgParser,$wgArticlePath,$wgScriptPath,$wgUploadPath,$wgScript; if($action == 'pdfbook') {

# Log the export $msg = $wgUser->getUserPage()->getPrefixedText().' exported as a PDF book'; $log = new LogPage('pdf',false); $log->addEntry('book',$wgTitle,$msg);

# Initialise PDF variables $layout = '--firstpage toc'; $left = $this->setProperty('LeftMargin', '1cm'); $right = $this->setProperty('RightMargin', '1cm'); $top = $this->setProperty('TopMargin', '1cm'); $bottom = $this->setProperty('BottomMargin','1cm'); $font = $this->setProperty('Font', 'Arial'); $size = $this->setProperty('FontSize', '8'); $link = $this->setProperty('LinkColour', '217A28'); $levels = $this->setProperty('TocLevels', '2'); $exclude = $this->setProperty('Exclude', array()); if (!is_array($exclude)) $exclude = split('\\s*,\\s*',$exclude);

# Select all article titles in category $title = $article->getTitle(); $book = $title->getText(); $cat = $title->getDBkey(); $db = &wfGetDB(DB_SLAVE); $cl = $db->tableName('categorylinks'); $result = $db->query("SELECT cl_from FROM $cl WHERE cl_to = '$cat' ORDER BY cl_sortkey");

# Format the article's as a single HTML document with absolute URL's $html = ; while ($row = mysql_fetch_row($result)) { $title = Title::newFromID($row[0]); $ttext = $title->getPrefixedText(); if (!in_array($ttext,$exclude)) { $wgArticlePath = $wgServer.$wgArticlePath; $wgScriptPath = $wgServer.$wgScriptPath; $wgScript = $wgServer.$wgScript; $article = new Article($title); $text = $article->fetchContent(); $opt = ParserOptions::newFromUser($wgUser);

  1. $opt->setRemoveComments(false); # allow HTML comments

$text = preg_replace('//s','@@'.'@@$1@@'.'@@',$text); # Hack so that HTML comments in the wikitext are preserved $opt->setEditSection(false); # remove section-edit links $wgOut->setHTMLTitle($ttext); # use this so DISPLAYTITLE magic works $out = $wgParser->parse($text,$title,$opt,true,true); $ttext = $wgOut->getHTMLTitle(); $text = $out->getText(); $text = preg_replace('/@{4}([^@]+?)@{4}/s',,$text); # HTML comments hack $text = preg_replace('/<table/','<table border borderwidth=2 cellpadding=3 cellspacing=0',$text); $ttext = basename($ttext);

$html .= "

$ttext

$text\n";

} }

# Write the HTML to a tmp file $file = "$wgUploadPath/".uniqid('pdf-book'); $file = '/var/www/extensions/PdfBook/foo'; $fh = fopen($file,'w+'); fwrite($fh,$html); fclose($fh);

# Send the file to the client via htmldoc converter while (@ob_end_clean()); header("Content-Type: application/pdf"); header("Content-Disposition: attachment; filename=\"$book.pdf\""); flush(); $cmd = "--left $left --right $right --top $top --bottom $bottom"; $cmd .= " --header ... --footer .1. --headfootsize 8 --quiet --jpeg --color"; $cmd .= " --bodyfont $font --fontsize $size --linkstyle plain --linkcolor $links"; $cmd .= " --toclevels $levels --format pdf14 --numbered $layout"; $cmd = "htmldoc -t pdf $cmd $file"; putenv("HTMLDOC_NOCGI=1"); $content = shell_exec($cmd); if (in_array('Content-Encoding: gzip',headers_list())) $content = gzencode($content); echo($content);

  1. @unlink($file);

die; } }

# Return a property for htmldoc using global, request or passed default function setProperty($name,$default) { if (isset($_REQUEST["pdf$name"])) return $_REQUEST["pdf$name"]; if (isset($GLOBALS["wgPdfBook$name"])) return $GLOBALS["wgPdfBook$name"]; return $default; }

# Needed in some versions to prevent Special:Version from breaking function __toString() { return 'PdfBook'; }

	}
  1. Called from $wgExtensionFunctions array when initialising extensions

function wfSetupPdfBook() { global $wgPdfBook; $wgPdfBook = new PdfBook(); }

  1. Needed in MediaWiki >1.8.0 for magic word hooks to work properly

function wfPdfBookLanguageGetMagic(&$magicWords,$langCode = 0) { global $wgPdfBookMagic; $magicWords[$wgPdfBookMagic] = array(0,$wgPdfBookMagic); return true; }

?>