Skip to content

Instantly share code, notes, and snippets.

@burzum
Last active December 10, 2015 15:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save burzum/1875af8478afe6dcfd0b to your computer and use it in GitHub Desktop.
Save burzum/1875af8478afe6dcfd0b to your computer and use it in GitHub Desktop.
src/Pdf/Engine/TexToPdfEngine.php
<?php
namespace App\Pdf\Engine;
use CakePdf\Pdf\CakePdf;
use CakePdf\Pdf\Engine\AbstractPdfEngine;
use Cake\Core\Exception\Exception;
use Cake\Utility\Text;
/**
* TexToPdfEngine for the CakePdf Plugin
*
* @copyright 2015 PSA Publishers
* @author Florian Krämer
* @license MIT
*/
class TexToPdfEngine extends AbstractPdfEngine
{
/**
* Path to the wkhtmltopdf executable binary
*
* @access protected
* @var string
*/
protected $_binary = '/usr/bin/latexpdf';
/**
* Constructor
*
* @param CakePdf $Pdf CakePdf instance
*/
public function __construct(CakePdf $Pdf)
{
parent::__construct($Pdf);
$this->_defaultConfig['options']['output-directory'] = TMP . 'pdf';
}
protected function _writeTexFile()
{
$output = $this->_Pdf->html();
$file = sha1($output);
$texFile = $this->config('options.output-directory') . DS . $file;
file_put_contents($texFile, $output);
return $texFile;
}
protected function _cleanUpTexFiles($texFile)
{
unlink($texFile);
unlink($texFile . '.aux');
unlink($texFile . '.log');
unlink($texFile . '.pdf');
}
/**
* Generates Pdf from html
*
* @throws \Cake\Core\Exception\Exception
* @return string raw pdf data
*/
public function output()
{
$texFile = $this->_writeTexFile();
$content = $this->_exec($this->_getCommand(), $texFile);
if (strpos(mb_strtolower($content['stderr']), 'error')) {
throw new Exception("System error <pre>" . $content['stderr'] . "</pre>");
}
if (mb_strlen($content['stdout'], $this->_Pdf->encoding()) === 0) {
throw new Exception("TeX compiler binary didn't return any data");
}
if ((int)$content['return'] !== 0 && !empty($content['stderr'])) {
throw new Exception("Shell error, return code: " . (int)$content['return']);
}
$result = file_get_contents($texFile . '.pdf');
$this->_cleanUpTexFiles($texFile);
return $result;
}
/**
* Execute the latex binary commands for rendering pdfs
*
* @param string $cmd the command to execute
* @param string $input Html to pass to wkhtmltopdf
* @return string the result of running the command to generate the pdf
*/
protected function _exec($cmd, $input)
{
$cmd .= ' ' . $input;
$result = ['stdout' => '', 'stderr' => '', 'return' => ''];
$proc = proc_open($cmd, [0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']], $pipes);
fwrite($pipes[0], $input);
fclose($pipes[0]);
$result['stdout'] = stream_get_contents($pipes[1]);
fclose($pipes[1]);
$result['stderr'] = stream_get_contents($pipes[2]);
fclose($pipes[2]);
$result['return'] = proc_close($proc);
return $result;
}
/**
* Get the command to render a pdf
*
* @return string the command for generating the pdf
* @throws \Cake\Core\Exception\Exception
*/
protected function _getCommand()
{
$binary = $this->config('binary');
if ($binary) {
$this->_binary = $binary;
}
if (!is_executable($this->_binary)) {
throw new Exception(sprintf('TeX compiler binary is not found or not executable: %s', $this->_binary));
}
$options = (array)$this->config('options');
if (!is_dir($options['output-directory'])) {
mkdir($options['output-directory']);
}
$command = $this->_binary;
foreach ($options as $key => $value) {
if (empty($value)) {
continue;
} elseif ($value === true) {
$command .= ' --' . $key;
} else {
$command .= sprintf(' --%s %s', $key, escapeshellarg($value));
}
}
return $command;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment