Plugin Directory

Changeset 489024


Ignore:
Timestamp:
01/12/2012 09:26:07 PM (14 years ago)
Author:
divinenephron
Message:

Made it create pdfs for taxonomy terms.

Location:
latex-everything/trunk
Files:
2 edited
1 copied
1 moved

Legend:

Unmodified
Added
Removed
  • latex-everything/trunk/latex-document.php

    r489023 r489024  
    22
    33define( 'PLUGIN_DIR', plugin_dir_path( __FILE__ ) );            // Plugin directory with trailing slash
    4 define( 'PDFLATEX', '/usr/texbin/pdflatex' );
    5 
    6 define( 'LE_POST_TYPE', 1 );
     4
     5define( 'LE_SINGLE_TYPE', 1 );
    76define( 'LE_TERM_TYPE', 2 );
    87
     
    1413    var $doc_type;
    1514
    16     var $latex_file;
     15    var $pdflatex_path;
     16    var $pdftk_path;
     17
     18    var $latex_files;
    1719    var $pdf_file;
    1820    var $uploaded_file;
     21    var $tmp_files;
    1922
    2023    var $unwanted_filter_functions = Array( 'wptexturize', 'convert_chars', 'esc_html', 'ent2ncr', '_wp_specialchars', 'sanitize_text_field', 'capital_P_dangit' );
    2124    var $removed_filters;
    2225
     26    var $combine_latex_files_callback;
     27
    2328    function __construct ( $id, $taxonomy='' ) {
     29        $this->tmp_files = array();
     30        $this->latex_files = array();
     31        $this->combine_latex_files_callback = array( &$this, 'concatenate_latex_files' );
     32
     33        if ( !$this->pdflatex_path = exec( 'which pdflatex' ) )
     34            return new WP_Error( 'LE_Latex_Document::__construct', 'pdflatex not found' );
     35        if ( !$this->pdftk_path = exec( 'which pdftk' ) )
     36            return new WP_Error( 'LE_Latex_Document::__construct', 'pdftk not found' );
     37
    2438        if ( !$taxonomy ) { // Have post
    25             $this->doc_type = LE_POST_TYPE;
     39            $this->doc_type = LE_SINGLE_TYPE;
    2640            $source = get_post( $id );
    2741        } else {            // Have term
     
    3751    function __destruct () {
    3852        // Unlink temporary files
    39         /*
    40         unlink( $this->latex_file );
    41         unlink( $this->pdf_file );
    42         unlink( $this->latex_file . '.aux' );
    43         unlink( $this->latex_file . '.log' );
    44         */
    45     }
    46 
     53        if ( ! WP_DEBUG ) {
     54            array_map( 'unlink', $this->latex_files );
     55            array_map( 'unlink', $this->tmp_files );
     56        }
     57    }
    4758
    4859    function generate() {
    4960   
    50         $latex_result = $this->make_latex_file();
    51         if ( is_wp_error( $latex_result ) ) {
    52             return $latex_result;
    53         }
    54    
    55         error_log( "Before latex_file_to_pdf_file()" );
    56         $pdf_result = $this->latex_file_to_pdf_file();
    57         if ( is_wp_error( $pdf_result ) ) {
    58             return $pdf_result;
    59         }
    60    
    61         $attach_id = $this->attach_pdf_file();
    62         if ( is_wp_error( $attach_id ) ) {
    63             return $attach_id;
    64         }
    65         error_log( "After attach_pdf_file()" );
    66         return 0; // Return no error
    67     }
    68 
    69     function make_latex_file () {
    70         $template = $this->_get_latex_template();
    71 
    72         // Render the template       
    73         if ( $this->doc_type == LE_POST_TYPE ) {
    74             $args = array(  'orderby'        => 'date',
    75                             'order'          => 'DESC',
    76                             'posts_per_pate' => -1,
    77                             );
    78             if ( $this->source->post_type == 'page' )
    79                 $args['page_id'] = $this->source->ID;
    80             else
    81                 $args['p'] = $this->source->ID;
     61        // Generate latex file(s).
     62        if ( $this->doc_type == LE_SINGLE_TYPE ) {
     63            $posts = array ( $this->source );
    8264        } else {
     65            // Generate single latex files for each of a term's posts, because Latex
     66            // wasn't designed to generate multi-article documents.
    8367            $args = array( 'tax_query'      => array( array(
    8468                                                'taxonomy' => $this->source->taxonomy,
     
    8872                           'order'          => 'DESC',
    8973                           'posts_per_page' => -1,
     74                           'post_type'      => null,
    9075                           );
    91         }
     76            $posts = get_posts( $args );
     77        }
     78        foreach ( $posts as $post ) {
     79            $latex_result = $this->make_latex_file( $post->ID, $post->post_type );
     80            if ( is_wp_error( $latex_result ) )
     81                return $latex_result;
     82            else
     83                $this->latex_files[] = $latex_result;
     84        }
     85   
     86        // Typset latex file(s)
     87        if ( $this->doc_type == LE_SINGLE_TYPE ) {
     88            $pdf_file = $this->typeset_file( $this->latex_files[0] );
     89        } else {
     90            if ( is_callable( $this->combine_latex_files_callback ) )
     91                $pdf_file = call_user_func( $this->combine_latex_files_callback, &$this );
     92        }
     93        if ( !$pdf_file )
     94            return new WP_Error( 'LE_Latex_Document::generate', "Error: No pdf file generated." );
     95        else if ( is_wp_error( $pdf_file ) )
     96            return $pdf_file;
     97        else
     98            $this->pdf_file = $pdf_file;
     99   
     100        $attach_id = $this->attach_pdf_file();
     101        if ( is_wp_error( $attach_id ) ) {
     102            return $attach_id;
     103        }
     104        return 0; // Return no error
     105    }
     106
     107    /* Writes a latex file for a single post.
     108     */
     109    function make_latex_file ($id, $post_type ) {
     110        $template = $this->_get_latex_template( );
     111
     112        // Query the post
     113        $args = array(  'orderby'        => 'date',
     114                        'order'          => 'DESC',
     115                        );
     116        if ( $post_type == 'page' )
     117            $args['page_id'] = $id;
     118        else
     119            $args['p'] = $id;
    92120        query_posts( $args );
     121
     122        // Render the template
    93123        $this->_set_up_latex_filters();
    94124        ob_start();
     
    96126        $latex = ob_get_clean();
    97127        $this->_undo_latex_filters();
     128
    98129        wp_reset_query();
    99130
    100131        // Get the name of a temporary file.
    101 
    102         if ( !$this->latex_file = tempnam( sys_get_temp_dir(), 'le-' ) ) // Should fall back on system's temp dir if /tmp does not exist
     132        if ( !$latex_file = tempnam( sys_get_temp_dir(), 'le-' ) )
    103133        return new WP_Error( 'tempnam', 'Could not create temporary file.' );
    104         $dir = dirname( $this->latex_file );
     134        $dir = dirname( $latex_file );
    105135
    106136        // Open and write the latex the temporary file.
    107137        if ( !WP_DEBUG )
    108             $f = @fopen( $this->latex_file, 'w' );
    109         else
    110             $f = fopen( $this->latex_file, 'w' );
     138            $f = @fopen( $latex_file, 'w' );
     139        else
     140            $f = fopen( $latex_file, 'w' );
    111141    if ( !$f )
    112142        return new WP_Error( 'fopen', 'Could not open temporary file for writing' );
     
    119149    fclose($f);
    120150
    121         return $this->latex_file;
     151        return $latex_file;
    122152    }
    123153
    124154    function _get_latex_template () {
     155        $templates = array();
     156        $templates[] = 'latex';
     157        if ( $this->doc_type == LE_SINGLE_TYPE ) {
     158            $templates[] = "latex-single";
     159            $templates[] = "latex-single-{$this->source->post_type}";
     160            $templates[] = "latex-single-{$this->source->post_type}-{$this->source->post_name}";
     161            $templates[] = "latex-single-{$this->source->post_type}-{$this->source->ID}";
     162        } else {
     163            $templates[] = "latex-term";
     164            $templates[] = "latex-term-{$this->source->taxonomy}";
     165            $templates[] = "latex-term-{$this->source->taxonomy}-{$this->source->slug}";
     166            $templates[] = "latex-term-{$this->source->taxonomy}-{$this->source->term_id}";
     167        }
    125168        $template = get_query_template('latex');
    126169        if ( empty( $template) ) {
    127             $template = PLUGIN_DIR . 'default-template.php';
     170            if ( $this->doc_type == LE_SINGLE_TYPE )
     171                $template = PLUGIN_DIR . 'default-latex-single.php';
     172            else
     173                $template = PLUGIN_DIR . 'default-latex-term.php';
    128174        }
    129175        return $template;
     
    157203    }
    158204   
    159     function latex_file_to_pdf_file () {
    160         error_log( "latex_file_to_pdf_file" );
    161         $dir = dirname( $this->latex_file );
     205    /* Calls pdflatex once on $latex_file, returning the path to the generated pdf, or a WP_Error.
     206     * The optional $latex_cmd argument can be used when a command other than the default
     207     * "[path/to/pdflatex] --interaction=nonstopmode [filename]" is needed.
     208     */
     209    function typeset_file ( $latex_file, $latex_cmd='' ) {
     210        $dir = dirname( $latex_file );
    162211
    163212        // Tell Latex to search in the theme directory for class/style files.
    164213        putenv('TEXINPUTS=.:' . get_stylesheet_directory() . ':' . get_template_directory() . ':');
    165         $cmd = sprintf( 'cd %s; %s --interaction=nonstopmode %s 2>&1', $dir, PDFLATEX, $this->latex_file);
     214        if ( !$latex_cmd )
     215            $latex_cmd = sprintf( "%s --interaction=nonstopmode %s", $this->pdflatex_path, $latex_file );
     216        $cmd = sprintf( 'cd %s; %s 2>&1', $dir, $latex_cmd );
    166217
    167218        exec( $cmd, $latex_output, $v );
    168219
    169220        if ( $v != 0 ) { // There was an error
    170             $latex_output = join( "\n", $latex_output );
     221            $latex_output = implode( "\n", $latex_output );
    171222            return new WP_Error( 'pdflatex', $latex_output );
    172223        }
    173224
    174         $this->pdf_file = $dir . '/' . basename($this->latex_file, '.tex') . '.pdf';
    175         return $this->pdf_file;
     225        $pdf_file = $dir . '/' . basename($latex_file, '.tex') . '.pdf';
     226
     227        $this->tmp_files[] = "{$latex_file}.log";
     228        $this->tmp_files[] = "{$latex_file}.aux";
     229        $this->tmp_files[] = $pdf_file;
     230
     231        return $pdf_file;
     232    }
     233
     234    /* Typsets the latex files in $doc seperately then concatenates them with
     235     * pdftk. Also ensures the page numbering is corret for each file.
     236     */
     237    function concatenate_latex_files ( $doc ) {
     238        // Get a temporary filename for the concatenated pdf.
     239        if ( !$tmp_file = tempnam( sys_get_temp_dir(), 'le-' ) )
     240        return new WP_Error( 'tempnam', 'Could not create temporary file.' );
     241        $concatenated_pdf = "{$tmp_file}.pdf";
     242        unlink( $tmp_file );
     243
     244        // Typset all of the latex files to be concatenated, fixing page numbers.
     245        $pdf_files = array();
     246        $current_page = 1;
     247        foreach ( $doc->latex_files as $latex_file ) {
     248            $latex_cmd = "{$doc->pdflatex_path} --interaction=nonstopmode \"\AtBeginDocument{\setcounter{page}{{$current_page}}}\input{{$latex_file}}\"";
     249            $pdf_files[] = $doc->typeset_file( $latex_file, $latex_cmd );
     250            $current_page += $this->_pages_in_pdf( end( $pdf_files ) );
     251        }
     252
     253        // Concatenate with pdftk
     254        $cmd = sprintf( '%s %s cat output %s', $this->pdftk_path, implode( ' ', $pdf_files ), $concatenated_pdf );
     255        exec( $cmd, $pdftk_output, $v );
     256        if ( $v != 0 ) { // There was an error
     257            $pdftk_output = implode( "\n", $pdftk_output );
     258            return new WP_Error( 'pdftk', $pdftk_output );
     259        }
     260
     261        $doc->tmp_files[] = $concatenated_pdf;
     262        return $concatenated_pdf;
     263    }
     264
     265    function _pages_in_pdf ( $pdf ) {
     266        $cmd = "{$this->pdftk_path} {$pdf} dump_data";
     267        exec( $cmd, $pdftk_output, $v );
     268        $pdftk_output = implode( "\n", $pdftk_output );
     269        if ( preg_match('/NumberOfPages: (\d+)/', $pdftk_output, $matches ) ){
     270            return (int) $matches[1];
     271        }
     272        return 0;
    176273    }
    177274
    178275    function attach_pdf_file () {
    179         error_log( "attach_pdf_file()" );
    180         if ( $this->doc_type == LE_POST_TYPE ) {
    181             $filename = $this->source->post_name . '.pdf';
     276        if ( $this->doc_type == LE_SINGLE_TYPE ) {
     277            $filename = "{$this->source->post_name}.pdf";
    182278            $title = $this->source->post_title;
    183279            $parent = $this->source->ID;
    184             error_log( "Filename: {$filename}" );
    185             error_log( "Title: {$title}" );
    186             error_log( "Parent: {$parent}" );
    187280        } else {
    188             $filename = $this->source->slug . '.pdf';
    189             $title = "{$this->source->taxonomy} {$this->source->name}";
     281            $filename = "{$this->source->taxonomy}-{$this->source->slug}.pdf";
     282            $tax_name = ucwords( $this->source->taxonomy );
     283            $title = "{$tax_name} {$this->source->name}";
    190284            $parent = 0;
    191285        }
     
    202296        // Check whether this post has an older file and attachment
    203297        // object we can update
    204         if ( $this->doc_type == LE_POST_TYPE ) {
    205             $args = array( 'post_type' => 'attachment',
    206                            'numberposts' => -1,
    207                            'post_status' => null,
    208                            'post_parent' => $this->source->ID );
    209             $attachments = get_posts($args);
    210             if ($attachments) {
    211                 foreach ( $attachments as $attachment ) {
    212                     $attached_file = get_attached_file( $attachment->ID );
    213                     if ( basename( $attached_file ) == $filename ) {
    214                         $this->uploaded_file = $attached_file;
    215                         $attachment_data['ID'] = $attachment->ID;
    216                     }
     298        $args = array( 'post_type' => 'attachment',
     299                       'numberposts' => -1,
     300                       'post_status' => null, );
     301        if ( $this->doc_type == LE_SINGLE_TYPE )
     302            $args['post_parent'] = $this->source->ID;
     303        else
     304            $args['post_parent'] = 0;
     305        $attachments = get_posts($args);
     306        if ($attachments) {
     307            foreach ( $attachments as $attachment ) {
     308                $attached_file = get_attached_file( $attachment->ID );
     309                if ( basename( $attached_file ) == $filename ) {
     310                    $this->uploaded_file = $attached_file;
     311                    $attachment_data['ID'] = $attachment->ID;
    217312                }
    218313            }
  • latex-everything/trunk/latex-everything.php

    r489023 r489024  
    1111
    1212// TODO: Make documentation of API and install process.
    13 // TODO: Extend generation to object other than posts - pages? categories? You'd just need to extend the
    14 //       templating and the "get latex stuff" API. You might also have to use WP-Cron more (more PDF
    15 //       being written at once), and hence improve the error handling to actually save error messages.
     13// TODO: Oh fsck, Latex wasn't supposed to typeset multiple papers. Find a way around it. Probably just typset the buggers seperately and glueing them together with combine.
    1614
    1715global $latex_everything;
     
    8785            $this->create_document( $post_id );
    8886        }
    89         /*
    9087        foreach( $this->taxonomies as $taxonomy ) {
    9188            if( $terms = get_the_terms( $post_id, $taxonomy ) ) {
     
    9794            }
    9895        }
    99         */
    10096    }
    10197        /* If le_error is in the query, a previous post save created an error
Note: See TracChangeset for help on using the changeset viewer.