Extension:Pdf Export Dompdf

From MediaWiki.org
Jump to: navigation, search
MediaWiki extensions manual - list
Crystal Clear action run.png
Pdf Export Dompdf

Release status: beta

Description Converts current page to PDF and sends to browser, using dompdf (a html to pdf converter written in php5)
Author(s) Andreas Hagmann (AhTalk)

DumpydoobyTalk

MediaWiki 1.12+
License No license specified
Download Code

Check usage (experimental)

Contents

[edit] Overview

This extension is a modified version of the Pdf_Export Extension. See Extension:Pdf_Export for details.

I modified it because I wanted to do pdf-export on my shared hosting server. It was impossible to install htmldoc on it because I dont't have root access.

Searching the web, I found dompdf, an html to pdf converter written in php5.

[edit] Installation

Follow each step in order, and review the linked items as needed.

 require_once("$IP/extensions/PdfExport/PdfExport.php");
 $PdfExportUseHtmlDoc = false;
  • Note: The above value can be changed to true if you would like to revert to using HtmlDoc (I use is_executable() as a failsafe, just in case this value set to true, but HtmlDoc is not installed.

[edit] Code

Create or edit the following files accordingly.

[edit] PdfExport_body.php

Put the following into $IP/extensions/PdfExport/PdfExport_body.php:

<?php
# This file has been modified by DumpyDooby.
if ( !defined( 'MEDIAWIKI' ) ) 
        die();
 
# <Craig>
$PdfExportUseHtmlDoc = isset($PdfExportUseHtmlDoc) ? $PdfExportUseHtmlDoc : false;
# </Craig>

$wgPdfExportAttach = false; // set to true if you want output as an attachment
$wgPdfExportHttpsImages = false; // set to true if page is on a HTTPS server and contains images that are on the HTTPS server and also 
//                                  reachable with HTTP
 
class SpecialPdf extends SpecialPage {
        var $title;
        var $article;
        var $html;
        var $parserOptions;
        var $bhtml;
        public $iswindows;
 
        function SpecialPdf() {
                global $iswindows;
                SpecialPage::SpecialPage( 'PdfPrint' );
                $os = getenv ("SERVER_SOFTWARE");
                $iswindows = strstr ($os, "Win32");
        }
 
        public function write1file ($text) {
                // make a temporary directory with an unique name
                // NOTE: If no PDF file is created and you get message "ERROR: No HTML files!", 
                //       try using a temporary directory that is within web server space.
                //       For example (assuming the web server root directory is /var/www/html):
                //           $mytemp = "/var/html/www/tmp/f" .time(). "-" .rand() . ".html";
 
 
                # <Craig>
         $mytemp=tempnam(sys_get_temp_dir(), 'PdfExport');
                # </Craig>
         $article_f = fopen($mytemp,'w');
                if($article_f === FALSE){
                        error_log("Failed opening temporary HTML file to \"$mytemp\" failed", 0);
                        return;
                }
                fwrite($article_f, $text);
                # <Craig>
         fseek($article_f, 0);
                # </Craig>
         fclose($article_f);
                return $mytemp;
        }
 
        public function save1page ( $page ) {
                global $wgUser;
                global $wgParser;
                global $wgScriptPath;
                global $wgServer;
                global $wgPdfExportHttpsImages;
 
                $title = Title::newFromText( $page );
                if( is_null( $title ) || !$title->userCanRead() )
                        return null;
                $article = new Article ($title);
                $parserOptions = ParserOptions::newFromUser( $wgUser );
                $parserOptions->setEditSection( false );
                $parserOptions->setTidy(true);
                $wgParser->mShowToc = false;
                $parserOutput = $wgParser->parse( $article->preSaveTransform( $article->getContent() ) ."\n\n", $title, $parserOptions );
 
                $bhtml = $parserOutput->getText();
                // Hack to thread the EUR sign correctly
                $bhtml = str_replace(chr(0xE2) . chr(0x82) . chr(0xAC), chr(0xA4), $bhtml);
                $bhtml = utf8_decode($bhtml);
 
                $bhtml = str_replace ($wgScriptPath, $wgServer . $wgScriptPath, $bhtml);
                $bhtml = str_replace ('/w/',$wgServer . '/w/', $bhtml);
                if ($wgPdfExportHttpsImages)
                        $bhtm = str_replace('img src=\"https:\/\/','img src=\"http:\/\/', $bhtml);
 
                $html = "<html><head><title>" . utf8_decode($page) . "</title></head><body>" . $bhtml . "</body></html>";
                return $this->write1file ($html);
        }
 
        function outputpdf ($pages, $landscape, $size) {
                global $iswindows;
                global $wgPdfExportAttach;
                $returnStatus = 0;
                $pagestring = "";
                $pagefiles = array();
                $foundone = false;
 
                foreach ($pages as $pg) {
                        $f = $this->save1page ($pg);
                        if ($f == null)   continue;
                        $foundone = true;
                        if ($iswindows) $pagestring .= "\"" . $f . "\" ";
                        else $pagestring .= $f . " ";
                        $pagefiles[] = $f;
                }
                if ($foundone == false)   return;
 
                putenv("HTMLDOC_NOCGI=1");
 
                # Write the content type to the client...
         header("Content-Type: application/pdf");
 
                if ($wgPdfExportAttach)
                        header(sprintf('Content-Disposition: attachment; filename="%s.pdf"', $page));
 
                # <Craig>
         global $PdfExportUseHtmlDoc;
                if($PdfExportUseHtmlDoc == true && is_executable('htmldoc')){
                        # Run HTMLDOC to provide the PDF file to the user...
                 passthru("htmldoc -t pdf14 --charset iso-8859-15 --color --quiet --jpeg --size " . $size . " " . $landscape . "--webpage " . $pagestring, $returnStatus);
                        if($returnStatus == 1)
                                error_log("Generating PDF failed. Return status was:" . $returnStatus, 0);
                }
                else{
                        $PdfContent = '';
                        foreach ($pagefiles as &$pagefile){
                                $PdfContent .= file_get_contents($pagefile);
                        }
                        //Note: Create PdfExport_headfoot.php if necessary (it can be blank).
                        $PdfHeaderFooter = '<script type="text/php">include_once("'.realpath(dirname(__FILE__)).'/PdfExport_headfoot.php");</script>';  
                        $PdfContent = str_replace('</body></html>',$PdfHeaderFooter.'</body></html>',$PdfContent); // Insert inline header/footer script.
                        $PdfContent = str_replace('</head>','<style type="text/css">body{padding:10px 10px 35px;}</style></head>',$PdfContent); // Insert styling to make room for header/footer.
                        $orientation = stristr($landscape,'landscape') ? 'landscape' : 'portrait';
                        // Required API for alternative method.
                        // Download here: http://www.digitaljunkies.ca/dompdf/downloads.php
                        require_once( realpath(dirname(__FILE__)) . "/dompdf/dompdf_config.inc.php" );
                        spl_autoload_register( 'DOMPDF_autoload' );
                        $domPDF = new DOMPDF();
                        $domPDF->set_base_path(realpath(dirname(__FILE__)).'/tmp');
                        $domPDF->set_paper(mb_strtolower($size), mb_strtolower($orientation));
                        $domPDF->load_html($PdfContent);
                        $domPDF->render();
                        $domPDF->stream(utf8_decode($page) . ".pdf", array('Attachment'=>0));
                }
                # </Craig>
         flush();
                foreach ($pagefiles as $pgf) {
                        unlink ($pgf);
                }
        }
 
        function execute( $par ) {
                global $wgRequest;
                global $wgOut; 
 
                wfLoadExtensionMessages ('PdfPrint');
                $dopdf = false;
                if ($wgRequest->wasPosted()) {
                        $pagel = $wgRequest->getText ('pagel');
                        $pages = array_filter( explode( "\n", $pagel ), 'wfFilterPage1' );
                        $size = $wgRequest->getText ('Size', 'Letter');
                        $orientations = $wgRequest->getVal ('orientation');
                        $orientation = ($orientations == 'landscape') ? " --landscape --browserwidth 1200 " : " --portrait ";
                        $dopdf = true;
                }
                else {
                        $page = isset( $par ) ? $par : $wgRequest->getText( 'page' );
                        if ($page != "") $dopdf = true; 
                        $pages = array ($page);
                        $orientation = " --portrait ";
                        $size = "Letter";
                }
                if ($dopdf) {
                        $wgOut->setPrintable();
                        $wgOut->disable();
 
                        $this->outputpdf ($pages, $orientation, $size);
                        return;
                }
 
                $self = SpecialPage::getTitleFor( 'PdfPrint' );
                $wgOut->addHtml( wfMsgExt( 'pdf_print_text', 'parse' ) );
 
                $form = Xml::openElement( 'form', array( 'method' => 'post',
                'action' => $self->getLocalUrl( 'action=submit' ) ) );
 
                $form .= Xml::openElement( 'textarea', array( 'name' => 'pagel', 'cols' => 40, 'rows' => 10 ) );
                $form .= Xml::closeElement( 'textarea' );
                $form .= '<br />';
                $form .= Xml::radioLabel(wfMsg ('pdf_portrait'), 'orientation' , 'portrait' , 'portrait', true);  
                $form .= Xml::radioLabel(wfMsg ('pdf_landscape'), 'orientation' , 'landscape' , 'landscape', false);  
                $form .= '<br />' . wfMsg('pdf_size');
                $form .= Xml::listDropDown ('Size', wfMsg ('pdf_size_options'),'', wfMsg('pdf_size_default'));
                $form .= Xml::submitButton( wfMsg( 'pdf_submit' ) );
                $form .= Xml::closeElement( 'form' );
                $wgOut->addHtml( $form );
 
        }
 
}
 
function wfFilterPage1( $page ) {
        return $page !== '' && $page !== null;
}
?>

[edit] PdfExport_headfoot.php

Put the following into $IP/extensions/PdfExport/PdfExport_headfoot.php:

<?php
if(isset($pdf)){
        $font = Font_Metrics::get_font("verdana");
        $size = 10;
        $color = array(0,0,0);
        $text_height = Font_Metrics::get_font_height($font, $size);
        $foot = $pdf->open_object();
        $w = $pdf->get_width();
        $h = $pdf->get_height();
        $y = $h - 2 * $text_height - 24;
        $pdf->line(16, $y, $w - 16, $y, $color, 1);
        $y += $text_height;
        $text = "My Awesome Website! (edit PdfExport_headfoot.php to change this text) | " . date("F j, Y");
        $pdf->text(16, $y, $text, $font, $size, $color);
        $pdf->close_object();
        $pdf->add_object($foot, "all");
        $text = "Page {PAGE_NUM}/{PAGE_COUNT}";
        $width = Font_Metrics::get_text_width($text, $font, $size);
        $pdf->page_text($w-5 - $width, $y, $text, $font, $size, $color);
}
?>

[edit] See also

  • Extension:Collection - allows to build collections from a number of pages. Collections can be edited, persisted and retrieved as PDF. No need to install dompdf or htmldoc.
Personal tools
Namespaces
Variants
Actions
Site
Support
Download
Development
Communication
Print/export
Toolbox