tmpl = WBClass::create('patTemplate');
$this->tmpl->setType('tex');
$this->tmpl->setDefaultAttribute('whitespace', 'keep');
$this->tmpl->setRoot('resource/latex');
if (empty($parameter['mandator'])) {
$parameter['mandator'] = WBClass::create('WBMandator', $parameter);
}
$this->mandator = $parameter['mandator'];
WBClass::load('patTemplate_Function_Config');
patTemplate_Function_Config::setMandator($this->mandator);
}
/**
* Compress Output File
*
* @param bool whether or not compress the output
*/
public function useCompression($comp = true)
{
$this->outputCompression = $comp;
}
/**
* Load Templates
*
* Auxiliary function for convinience
* @param string $tmpl
*/
public function loadTemplates($tmpl)
{
$tmpl = sprintf(self::TEMPLATE_FILE_FORMAT, $tmpl);
$this->tmpl->readTemplatesFromInput($tmpl);
}
/**
* Check if Named Template Exists
*
* @see patTemplate:exists()
* @return bool
*/
public function templateExists($name)
{
return $this->tmpl->exists($name);
}
/**
* Add Var
*
* Quote values and add to template engine
*
* @use patTemplate::addVar()
* @param string $tmpl
* @param string $name
* @param mixed
* @return bool
*/
public function addVar($tmpl, $name, $var)
{
$this->quote($var);
return $this->tmpl->addVar($tmpl, $name, $var);
}
/**
* Add Vars
*
* Data to fill placeholders, proxy for template engine.
*
* @see patTemplate::addVars()
* @param string $tmpl
* @param array $vars
* @param string $prefix
* @return bool
*/
public function addVars($tmpl, $vars, $prefix = '')
{
if (!is_array($vars)) {
return;
}
$this->quote($vars);
return $this->tmpl->addVars($tmpl, $vars, $prefix);
}
/**
* Add Rows
*
* Quote values and add to template engine
*
* @use patTemplate::addRows()
* @param string $tmpl
* @param array
*/
public function addRows($tmpl, $rows)
{
$this->quote($rows);
$this->tmpl->addRows($tmpl, $rows);
}
/**
* Add Global Vars
*
* Data to fill placeholders, proxy for template engine.
*
* @see patTemplate::addGlobalVar()
* @param string $name
* @param string $var
* @return bool
*/
public function addGlobalVar($name, $var)
{
$this->quote($var);
return $this->tmpl->addGlobalVar($name, $var);
}
/**
* Add Global Vars
*
* Data to fill placeholders, proxy for template engine.
*
* @see patTemplate::addGlobalVars()
* @param array $vars
* @param string $prefix
* @return bool
*/
public function addGlobalVars($vars, $prefix = '')
{
if (!is_array($vars)) {
return;
}
$this->quote($vars);
return $this->tmpl->addGlobalVars($vars, $prefix);
}
/**
* Fill List in Template
*
* Standard method to add rows to list template
*
* @param array list
* @param string template name stump
*/
protected function list2Template($list, $name = 'list')
{
$this->tmpl->addGlobalVar($name . '_count', count($list));
if (!$this->tmpl->exists($name . '_entry')) {
return;
}
$this->addRows($name . '_entry', $list);
$max = WBParam::get('wb/template/listtemplatemax', 10);
for ($i = 1; $i < $max; ++$i) {
if (!$this->tmpl->exists($name . '_entry_' . $i)) {
break;
}
$this->addRows($name . '_entry_' . $i, $list);
}
}
/**
* Quote Value For TeX
*
* @param mixed $var
*/
private function quote(&$var)
{
if (is_array($var)) {
// recursive
foreach ($var as &$v) {
$this->quote($v);
}
return;
}
// don't force string replace on numbers
if (is_numeric($var)) {
return;
}
// string replace
$replace = array(
'"' => "''",
"\r\n" => "\n",
'%' => '\\%',
' ' => '~',
'&' => '\\&',
'_' => '\\_',
'€' => '\\EUR',
'°' => '{\\textdegree}',
'®' => '®',
'<' => '<',
'>' => '>',
'≥' => '$\ge$',
'≤' => '$\le$',
'' => '\\-'
);
$sear = array_keys($replace);
$repl = array_values($replace);
$var = str_replace($sear, $repl, $var);
}
/**
* Render PDF
*
* Prepare LaTeX work dir, render content, use post processor
* and return path to PDF file. (Design oattern: Template Function)
*
* @return string
*/
public function render()
{
$this->tmpDir = WBClass::create('WBFile');
//$this->tmpDir->mkdir('var/tmp/tex-test');
$this->tmpDir->tempdir('tex-');
$this->renderBefore();
$this->addUserInfo();
$this->renderMandator();
$this->renderContent();
$tex = $this->tmpl->getParsedTemplate('texdoc');
$tex = WBString::replaceSuperPlaceholders($tex);
file_put_contents($this->tmpDir->realpath() . '/doc.tex', $tex);
$this->renderAfter();
$pdf = $this->processRenderedPdf($this->runLaTeX());
$this->cleanup();
return $pdf;
}
/**
* Add Current User's Info
*
*
*/
private function addUserInfo()
{
WBClass::load('WBUser');
$this->user = WBUser::getCurrent();
if (!$this->user || !$this->user->isAuthenticated()) {
return;
}
// add user data and group membership
$this->tmpl->addGlobalVars($this->user->getData(), 'user_current_');
$groups = array();
foreach ($this->user->getGroups() as $gid => $gname) {
$groups[$gname] = '1';
}
$this->tmpl->addGlobalVars($groups, 'user_current_group_');
}
/**
* Do something with
*/
protected function processRenderedPdf($pdf)
{
return $pdf;
}
/**
* Before Rendering Starts
*
*
*/
protected function renderBefore()
{
}
/**
* Actually Render Mandator Data
*
* Fill Templates LaTeX Like
*/
protected function renderMandator()
{
$data = $this->mandator->get();
$this->addGlobalVars($data, 'mandator_');
}
/**
* Actually Render Content
*
* Fill Templates LaTeX Like
*/
protected function renderContent()
{
}
/**
* After Rendering Is Done
*
*
*/
protected function renderAfter()
{
}
/**
* Execute LaTeX Commands
*
* Run LaTeX (ignore return codes) and GhostScript to optimize file size with nice image resolution
* @return string path of rendered file
*/
protected function runLaTeX()
{
$cwd = getcwd();
$path = $this->tmpDir->realpath();
chdir($path);
$resource = array();
$resource[] = '.';
$resource[] = WBParam::get('wb/dir/base') . '/resource/latex';
foreach (WBParam::get('wb/dir/resource', array()) as $r) {
$resource[] = $r . '/resource/latex';
}
// fake home folder
/** @var WBFile */
$home = WBClass::create('WBFile');
$home->mkdir('var/cache/home/laTeX');
// run ĹaTeX and ignore return code
$cmdPpdfLaTeX = WBParam::get('wb/latex/pdflatex/command', 'pdflatex');
$cmd = sprintf('HOME=%s TEXINPUTS=%s: %s --interaction=nonstopmode doc.tex', $home->realpath(), implode(':', $resource), $cmdPpdfLaTeX);
file_put_contents($path . '/cmd.log', $cmd . "\n");
$res = $this->exec($cmd);
// run twice to collect all references
file_put_contents($path . '/cmd.log', $cmd . "\n", FILE_APPEND);
$res = $this->exec($cmd);
if ($this->useCompression()) {
$cmdGS = WBParam::get('wb/latex/gs/command', 'gs');
// run ghostscript to reduce file size, ignore return code
// -dPDFSETTINGS=/screen (screen-view-only quality, 72 dpi images)
// -dPDFSETTINGS=/ebook (low quality, 150 dpi images)
// -dPDFSETTINGS=/printer (high quality, 300 dpi images)
// -dPDFSETTINGS=/prepress (high quality, color preserving, 300 dpi imgs)
// -dPDFSETTINGS=/default (almost identical to /screen)
$cmd = sprintf('%s -sDEVICE=pdfwrite -dCompatibilityLevel=1.7 -dPDFSETTINGS=/prepress -dNOPAUSE -dQUIET -dBATCH -sOutputFile=doc.small.pdf doc.pdf', $cmdGS);
file_put_contents($path . '/cmd.log', $cmd . "\n", FILE_APPEND);
$res = $this->exec($cmd);
rename($path . '/doc.small.pdf', $path . '/doc.pdf');
}
chdir($cwd);
rename($path . '/doc.pdf', $path . '.pdf');
return $path . '.pdf';
}
/**
* Tidy Up
*
* Remove temporary file
*/
public function cleanup()
{
if (0 < WBParam::get('wb/debug', 0)) {
return;
}
$this->tmpDir->removeDir();
}
/**
* Run Programm
*
* @param string
* @return bool true on success
*/
protected function exec($cmd)
{
// echo $cmd . "\n";
exec($cmd, $out, $ret);
if (0 < $ret) {
//echo "FAILED $cmd
\n";
//echo "
" . implode("\n", $out) . ""; return false; } return true; } /** * Resolve VFSFile To render image * * Create symlinks for actual image VFS file * * @see symlink() * @param string fileid * @return string filename or empty of not valid */ protected function resolveVFSFile($vfsfid) { if (0 == $vfsfid) { return; } if (!$this->vfsFile) { $this->vfsFile = WBClass::create('WBVFS_File'); } /** @var WBVFS_File */ $file = $this->vfsFile->loadById($vfsfid); if ('image' != $file->getMime(WBVFS_File::MIME_MAJOR)) { return ''; } $mime = $file->getMime(WBVFS_File::MIME_MINOR); $fileName = 'image-' . $vfsfid . '.' . $mime; switch ($mime) { case 'jpeg': case 'jpg': case 'png': if (file_exists($this->tmpDir->realpath() . '/' . $fileName)) { break; } symlink($file->getPath() . '.org', $this->tmpDir->realpath() . '/' . $fileName); break; default: $fileName = 'image-' . $vfsfid . '.png'; if (file_exists($this->tmpDir->realpath() . '/' . $fileName)) { break; } $cmd = sprintf('convert %s.org %s/image-%s.png', $file->getPath(), $this->tmpDir->realpath(), $vfsfid); $this->exec($cmd); break; } return $fileName; } }