-6

So, here's the skinny.

I have an HTML form (of which there will be many depending on the Letter template) that passes the form data into a Letter Template via PHP. THIS...I have successfully done.

However, what I need is to pass the data INTO the template, THEN turn that template INTO a PDF.

Any suggestions? AND......GO

Aaron B
  • 69
  • 11

1 Answers1

1

I've recently use pdftk (server) to do so: https://www.pdflabs.com/tools/pdftk-server/

First, install it on a webserver or locally.

Then, here's a PHP class I adapted from the web (copy it and name it PdfFormToPdftk.php):

<?php

class PdfFormToPdftk {
    /*
     * Path to raw PDF form
     * @var string
     */
    private $pdfurl;

     /*
     * Path to PDFKTK
     * @var string
     */
    private $pdftkpath;

    /*
     * Path to temp files
     * @var string
     */
    private $tmppath;

    /*
     * Errors
     * @var string
     */
    private $errors;

    /*
     * Last command done
     * @var string
     */
    private $lastcmd;

    /*
     * Form data
     * @var array
     */
    private $data;

    /*
     * Path to filled PDF form
     * @var string
     */
    private $output;

    /*
     * Flag for flattening the file
     * @var string
     */
    private $flatten;

    public function __construct($pdfurl, $data, $tmppath, $pdftkpath = '/usr/bin/pdftk') {
        $this->pdfurl = $pdfurl;
        $this->data = $data;
        $this->tmppath = $tmppath;
        $this->pdftkpath = $pdftkpath;
    }

    private function tempfile() {
        return tempnam($this->tmppath, gethostname());
    }

    public function fields($pretty = false) {
        $tmp = $this->tempfile();

        exec("{$this->pdftkpath} {$this->pdfurl} dump_data_fields > {$tmp}");
        $con = file_get_contents($tmp);

        unlink($tmp);
        return $pretty == true ? nl2br($con) : $con;
    }

    private function makeFdf() {
        $fdf = '%FDF-1.2
        1 0 obj<</FDF<< /Fields[';

        foreach ($this->data as $key => $value) {
            $fdf .= '<</T(' . $key . ')/V(' . $value . ')>>';
        }

        $fdf .= "] >> >>
        endobj
        trailer
        <</Root 1 0 R>>
        %%EOF";

        $fdf_file = $this->tempfile();
        file_put_contents($fdf_file, $fdf);

        return $fdf_file;
    }

    public function flatten() {
        $this->flatten = ' flatten';
        return $this;
    }

    private function generate() {

        $fdf = $this->makeFdf();
        $this->output = $this->tempfile();
        $cmd = "{$this->pdftkpath} {$this->pdfurl} fill_form {$fdf} output {$this->output}{$this->flatten} 2>&1";
        $this->lastcmd = $cmd;
        exec($cmd, $outputAndErrors, $returnValue);
        $this->errors = $outputAndErrors;
        unlink($fdf);
    }

    public function save($path = null) {
        if (is_null($path)) {
            return $this;
        }

        if (!$this->output) {
            $this->generate();
        }

        $dest = pathinfo($path, PATHINFO_DIRNAME);
        if (!file_exists($dest)) {
            mkdir($dest, 0775, true);
        }

        if (!copy($this->output, $path)) {
            echo "failed to copy $path...\n";
        }
        unlink($this->output);

        $this->output = $path;

        return $this;
    }

    public function download() {
        if (!$this->output) {
            $this->generate();
        }

        $filepath = $this->output;
        if (file_exists($filepath)) {

            header('Content-Description: File Transfer');
            header('Content-Type: application/pdf');
            header('Content-Disposition: attachment; filename=' . uniqid(gethostname()) . '.pdf');
            header('Expires: 0');
            header('Cache-Control: must-revalidate');
            header('Pragma: public');
            header('Content-Length: ' . filesize($filepath));

            readfile($filepath);

            exit;
        }
    }

}

You could use it like this in some script:

<?php
require_once 'PdfFormToPdftk.php';

$datas = ['firstname' => 'Foo', 'lastname' => 'Bar'];
$output_file = 'yourfile.pdf';
$template_pdf_file = 'templatefile.pdf'; //where your virgin pdf template contains at least 'firstname' and 'lastname' as editable fields. You might want to use Adobe Acrobat Pro and save it as a Adobe Static PDF Form
$path_to_pdftk_server = '/opt/pdflabs/pdftk/bin/pdftk'; // type 'which pdftk' in your console to find yours

$pdf = new PdfFormToPdftk($template_pdf_file, $datas, '/', $path_to_pdftk_server);
$file = $pdf->save($output_file);
F3L1X79
  • 2,367
  • 2
  • 25
  • 40
  • Okay, so...it KINDA works, not sure if it's because I'm running the Free version locally or not, but it creates the PDF but when I try to open it, it says that it cannot be opened because the file may be damaged or corrupted. – Aaron B Oct 06 '17 at 11:23
  • you can do : var_dump($file); to see if there is any errors during the generation of the PDF. There is no paid version for pdftk server only. – F3L1X79 Oct 06 '17 at 13:13
  • And if you are developping on mac OS x, you should install this version : https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/pdftk_server-2.02-mac_osx-10.11-setup.pkg (source : https://stackoverflow.com/questions/32505951/pdftk-server-on-os-x-10-11) – F3L1X79 Oct 06 '17 at 14:50
  • Forgive the N00B question here, but in the lines for things like `private $pdfurl;` or `private $pdftkpath;` Do I set these variables or are these defaults? Again, sorry about the question. – Aaron B Oct 07 '17 at 12:23
  • the $pdfurl var corresponds to the path where your empty template lies. You'd better set it to an an absolute URL. the $pdftkpath is the path where you intsalled pdftk. There's a default to /usr/bin/pdftk - but you may want to change it. If you prefer, there's a more complete API written in PHP for pdftk here: https://github.com/mikehaertl/php-pdftk – F3L1X79 Oct 09 '17 at 07:15
  • I don't know what I'm doing wrong. `Warning: copy(/completed/): failed to open stream: No such file or directory in C:\xampp\htdocs\temp\PdfFormToPdftk.php on line 122 failed to copy 10-10-2017.pdf ` – Aaron B Oct 10 '17 at 11:03
  • And `Warning: unlink(/completed/): No such file or directory in C:\xampp\htdocs\temp\PdfFormToPdftk.php on line 125 object(PdfFormToPdftk)#1 (8) { ["pdfurl":"PdfFormToPdftk":private]=> string(28) "Form.pdf" ["pdftkpath":"PdfFormToPdftk":private]=> string(15) "PDFtk/bin/pdftk" ["tmppath":"PdfFormToPdftk":private]=> string(1) "/" ["errors":"PdfFormToPdftk":private]=> string(8) "/errors/" ["lastcmd":"PdfFormToPdftk":private]=> NULL ` (cont'd on next comment) – Aaron B Oct 10 '17 at 11:05
  • `["data":"PdfFormToPdftk":private]=> array(4) { ["County"]=> string(7) "Jackson" ["JD"]=> string(4) "22nd" ["Person1"]=> string(8) "Joe Blow" ["Person2"]=> string(11) "Sally Schmo" } ["output":"PdfFormToPdftk":private]=> string(23) "10-10-2017.pdf" ["flatten":"PdfFormToPdftk":private]=> NULL } ` – Aaron B Oct 10 '17 at 11:05
  • Your ['lastcmd'] argument shouldn't be NULL at all. You maybe should open your permissions folders to 777? + set all URL to absolute; example : ABSPATH . '/yourfile.pdf' – F3L1X79 Oct 10 '17 at 12:08