Difference between revisions of "Extension:PdfBook"

From Organic Design wiki
m (cat)
(0.0.10 - bug preventing other action hooks from working)
Line 7: Line 7:
 
if (!defined('MEDIAWIKI')) die('Not an entry point.');
 
if (!defined('MEDIAWIKI')) die('Not an entry point.');
  
define('PDFBOOK_VERSION','0.0.9, 2007-11-01');
+
define('PDFBOOK_VERSION','0.0.10, 2008-04-16');
  
$wgPdfBookMagic         = "book";
+
$wgPdfBookMagic               = "book";
$wgExtensionFunctions[] = 'wfSetupPdfBook';
+
$wgExtensionFunctions[]       = 'wfSetupPdfBook';
 
$wgHooks['LanguageGetMagic'][] = 'wfPdfBookLanguageGetMagic';
 
$wgHooks['LanguageGetMagic'][] = 'wfPdfBookLanguageGetMagic';
  
 
$wgExtensionCredits['parserhook'][] = array(
 
$wgExtensionCredits['parserhook'][] = array(
'name' => 'Pdf Book',
+
'name'       => 'Pdf Book',
 
'author'      => '[http://www.organicdesign.co.nz/nad User:Nad]',
 
'author'      => '[http://www.organicdesign.co.nz/nad User:Nad]',
 
'description' => 'Composes a book from articles in a category and exports as a PDF book',
 
'description' => 'Composes a book from articles in a category and exports as a PDF book',
'url' => 'http://www.mediawiki.org/wiki/Extension:Pdf_Book',
+
'url'       => 'http://www.mediawiki.org/wiki/Extension:Pdf_Book',
 
'version'    => PDFBOOK_VERSION
 
'version'    => PDFBOOK_VERSION
 
);
 
);
Line 35: Line 35:
 
$wgLogHeaders['pdf']      = 'pdflogpagetext';
 
$wgLogHeaders['pdf']      = 'pdflogpagetext';
 
$wgLogActions['pdf/book'] = 'pdflogentry';
 
$wgLogActions['pdf/book'] = 'pdflogentry';
}
+
}
  
 
# Expand the book-magic
 
# Expand the book-magic
Line 44: Line 44:
 
foreach (func_get_args() as $arg) if (!is_object($arg)) {
 
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;
 
if (preg_match('/^(.+?)\\s*=\\s*(.+)$/',$arg,$match)) $argv[$match[1]] = $match[2]; else $argv[] = $arg;
}
+
}
  
 
# Return result with available parser flags
 
# Return result with available parser flags
Line 55: Line 55:
 
isHTML  => false
 
isHTML  => false
 
);
 
);
}
+
}
  
 
function onUnknownAction($action,$article) {
 
function onUnknownAction($action,$article) {
Line 92: Line 92:
 
if ($result instanceof ResultWrapper) $result = $result->result;
 
if ($result instanceof ResultWrapper) $result = $result->result;
 
while ($row = $db->fetchRow($result)) $articles[] = Title::newFromID($row[0]);
 
while ($row = $db->fetchRow($result)) $articles[] = Title::newFromID($row[0]);
}
+
}
 
else {
 
else {
 
$text = $article->fetchContent();
 
$text = $article->fetchContent();
Line 98: Line 98:
 
if (preg_match_all('/^\\*\\s*\\[{2}\\s*([^\\|\\]]+)\\s*.*?\\]{2}/m',$text,$links))
 
if (preg_match_all('/^\\*\\s*\\[{2}\\s*([^\\|\\]]+)\\s*.*?\\]{2}/m',$text,$links))
 
foreach ($links[1] as $link) $articles[] = Title::newFromText($link);
 
foreach ($links[1] as $link) $articles[] = Title::newFromText($link);
}
+
}
  
 
# 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
Line 124: Line 124:
 
$ttext  = basename($ttext);
 
$ttext  = basename($ttext);
 
$html  .= utf8_decode("<h1>$ttext</h1>$text\n");
 
$html  .= utf8_decode("<h1>$ttext</h1>$text\n");
}
 
 
}
 
}
 +
}
  
 
# If format=html in query-string, return html content directly
 
# If format=html in query-string, return html content directly
Line 133: Line 133:
 
header("Content-Disposition: attachment; filename=\"$book.html\"");
 
header("Content-Disposition: attachment; filename=\"$book.html\"");
 
print $html;
 
print $html;
}
+
}
 
else {
 
else {
 
# Write the HTML to a tmp file
 
# Write the HTML to a tmp file
Line 153: Line 153:
 
passthru($cmd);
 
passthru($cmd);
 
@unlink($file);
 
@unlink($file);
}
 
 
}
 
}
 
+
return false;
return false;
 
 
}
 
}
 +
 +
return true;
 +
}
  
 
# Return a property for htmldoc using global, request or passed default
 
# Return a property for htmldoc using global, request or passed default
Line 164: Line 165:
 
if (isset($GLOBALS["wgPdfBook$name"])) return $GLOBALS["wgPdfBook$name"];
 
if (isset($GLOBALS["wgPdfBook$name"])) return $GLOBALS["wgPdfBook$name"];
 
return $default;
 
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'; }
 
+
}
}
 
  
 
# Called from $wgExtensionFunctions array when initialising extensions
 
# Called from $wgExtensionFunctions array when initialising extensions
Line 175: Line 175:
 
global $wgPdfBook;
 
global $wgPdfBook;
 
$wgPdfBook = new PdfBook();
 
$wgPdfBook = new PdfBook();
}
+
}
  
 
# Needed in MediaWiki >1.8.0 for magic word hooks to work properly
 
# Needed in MediaWiki >1.8.0 for magic word hooks to work properly
Line 182: Line 182:
 
$magicWords[$wgPdfBookMagic] = array(0,$wgPdfBookMagic);
 
$magicWords[$wgPdfBookMagic] = array(0,$wgPdfBookMagic);
 
return true;
 
return true;
}
+
}

Revision as of 10:11, 16 April 2008

<?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:NadCategory:Extensions in progress
  3. - Started: 2007-08-08

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

define('PDFBOOK_VERSION','0.0.10, 2008-04-16');

$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; global $wgServer,$wgArticlePath,$wgScriptPath,$wgUploadPath,$wgUploadDirectory,$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 articles from members if a category or links in content if not $articles = array(); $title = $article->getTitle(); $opt = ParserOptions::newFromUser($wgUser); if ($title->getNamespace() == NS_CATEGORY) { $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"); if ($result instanceof ResultWrapper) $result = $result->result; while ($row = $db->fetchRow($result)) $articles[] = Title::newFromID($row[0]); } else { $text = $article->fetchContent(); $text = $wgParser->preprocess($text,$title,$opt); if (preg_match_all('/^\\*\\s*\\[{2}\\s*([^\\|\\]]+)\\s*.*?\\]{2}/m',$text,$links)) foreach ($links[1] as $link) $articles[] = Title::newFromText($link); }

# Format the article's as a single HTML document with absolute URL's $book = $title->getText(); $html = ; $wgArticlePath = $wgServer.$wgArticlePath; $wgScriptPath = $wgServer.$wgScriptPath; $wgUploadPath = $wgServer.$wgUploadPath; $wgScript = $wgServer.$wgScript; foreach ($articles as $title) { $ttext = $title->getPrefixedText(); if (!in_array($ttext,$exclude)) { $article = new Article($title); $text = $article->fetchContent(); $text = preg_replace('//s','@@'.'@@$1@@'.'@@',$text); # preserve HTML comments $text .= ; $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('|(<img[^>]+?src=")(/.+?>)|',"$1$wgServer$2",$text); $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 .= utf8_decode("

$ttext

$text\n");

} }

# If format=html in query-string, return html content directly if (isset($_REQUEST['format']) && $_REQUEST['format'] == 'html') { $wgOut->disable(); header("Content-Type: text/html"); header("Content-Disposition: attachment; filename=\"$book.html\""); print $html; } else { # Write the HTML to a tmp file $file = "$wgUploadDirectory/".uniqid('pdf-book'); $fh = fopen($file,'w+'); fwrite($fh,$html); fclose($fh);

# Send the file to the client via htmldoc converter $wgOut->disable(); header("Content-Type: application/pdf"); header("Content-Disposition: attachment; filename=\"$book.pdf\""); $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 --charset iso-8859-1 $cmd $file"; putenv("HTMLDOC_NOCGI=1"); passthru($cmd); @unlink($file); } return false; }

return true; }

# 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; }