(sometimes it will work just to ignore this error with --load-error-handling ignore)
*/
if ($this->getHttpUrl()) {
// $command .= ' --load-error-handling ignore';
}
$command .= ' "'.$in.'" ';
$command .= " -";
return $command;
}
/**
* Convert HTML to PDF.
*
* @todo use file cache
*
* @throws Exception
* @return string
*/
protected function _render()
{
if ($this->_have_httpurl)
{ // source is url
$input = $this->getHttpUrl();
}
// source is predefined disc file
elseif ($this->_have_htmlfile)
{
$input = $this->getHtmlPathFile();
}
// source is html string
elseif ($this->_have_html)
{
$input = $this->_tmphtmlfilename = $this->_createFile($this->getHtml());
}
else
{
throw new Exception("HTML content or source URL not set");
}
if ($this->_have_headerhtml)
{
$this->_headerfilename = $this->_createFile($this->getHeaderHtml());
}
if ($this->_have_footerhtml)
{
$this->_footerfilename = $this->_createFile($this->getFooterHtml());
}
$command = $this->_getCommand($input);
$content = $this->_pipeExec($command);
if($this->config->get('debug'))
{
dump(array(
'input' => $input,
'command' => $command,
'content' => $content
));
}
if(preg_match('/error(?! ignored)/i', $content['stderr']))
throw new Exception("System error " . $content['stderr'] . "
");
if (strlen($content['stdout']) === 0)
throw new Exception("WKHTMLTOPDF didn't return any data");
$data = $content['stdout'];
return (isset($data)?$data:false);
}
/**
* Executes the command : Deprecated - use _pipeExec
*
* @param string $cmd command to execute
* @param string $input other input (not arguments)
* @return array
*/
protected function _exec($cmd, $input = "")
{
$result = array('stdout' => '', 'stderr' => '', 'return' => '');
$proc = proc_open($cmd, array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('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;
}
/**
* Advanced execution routine.
*
* @param string $cmd The command to execute.
* @param string $input Any input not in arguments.
* @return array An array of execution data; stdout, stderr and return "error" code.
*/
private static function _pipeExec($cmd, $input='')
{
$pipes = array();
$proc = proc_open($cmd, array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w')), $pipes, null, null, array('binary_pipes'=>true));
fwrite($pipes[0], $input);
fclose($pipes[0]);
// From http://php.net/manual/en/function.proc-open.php#89338
$read_output = $read_error = false;
$buffer_len = $prev_buffer_len = 0;
$ms = 10;
$stdout = '';
$read_output = true;
$stderr = '';
$read_error = true;
stream_set_blocking($pipes[1], 0);
stream_set_blocking($pipes[2], 0);
// dual reading of STDOUT and STDERR stops one full pipe blocking the other, because the external script is waiting
while ($read_error != false or $read_output != false){
if ($read_output != false){
if(feof($pipes[1])){
fclose($pipes[1]);
$read_output = false;
} else {
$str = fgets($pipes[1], 1024);
$len = strlen($str);
if ($len){
$stdout .= $str;
$buffer_len += $len;
}
}
}
if ($read_error != false){
if(feof($pipes[2])){
fclose($pipes[2]);
$read_error = false;
} else {
$str = fgets($pipes[2], 1024);
$len = strlen($str);
if ($len){
$stderr .= $str;
$buffer_len += $len;
}
}
}
if ($buffer_len > $prev_buffer_len){
$prev_buffer_len = $buffer_len;
$ms = 10;
} else {
usleep($ms * 1000); // sleep for $ms milliseconds
if ($ms < 160){
$ms = $ms * 2;
}
}
}
$rtn = proc_close($proc);
return array(
'stdout' => $stdout,
'stderr' => $stderr,
'return' => $rtn
);
}
/**
* Return PDF with various options.
*
* @param int $mode How to output (constants from this same class - c.f. 'PDF get modes')
* @param string $filename The PDF's filename (usage depends on $mode)
*/
public function output($mode, $filename='')
{
switch ($mode) {
case self::MODE_DOWNLOAD:
if (!headers_sent()) {
$result = $this->_render();
header("Content-Description: File Transfer");
header("Cache-Control: public; must-revalidate, max-age=0"); // HTTP/1.1
header("Pragme: public");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header("Last-Modified: " . gmdate('D, d m Y H:i:s') . " GMT");
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream", false);
header("Content-Type: application/download", false);
header("Content-Type: application/pdf", false);
header('Content-Disposition: attachment; filename="' . basename($filename) .'";');
header("Content-Transfer-Encoding: binary");
header("Content-Length:" . strlen($result));
echo $result;
$this->_deleteFile();
exit();
} else {
throw new Exception("Headers already sent");
}
break;
case self::MODE_STRING:
return $this->_render();
break;
case self::MODE_EMBEDDED:
if (!headers_sent()) {
$result = $this->_render();
header("Content-type: application/pdf");
header("Cache-control: public, must-revalidate, max-age=0"); // HTTP/1.1
header("Pragme: public");
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
header("Last-Modified: " . gmdate('D, d m Y H:i:s') . " GMT");
header("Content-Length: " . strlen($result));
header('Content-Disposition: inline; filename="' . basename($filename) .'";');
echo $result;
$this->_deleteFile();
exit();
} else {
throw new Exception("Headers already sent");
}
break;
case self::MODE_SAVE:
file_put_contents($filename, $this->_render());
$this->_deleteFile();
break;
default:
throw new Exception("Mode: " . $mode . " is not supported");
}
return TRUE;
}
}