1<?php 2 3require_once './Services/PDFGeneration/classes/class.ilPDFGenerationConstants.php'; 4require_once './Services/PDFGeneration/interfaces/interface.ilRendererConfig.php'; 5require_once './Services/PDFGeneration/interfaces/interface.ilPDFRenderer.php'; 6 7class ilPhantomJSRenderer implements ilRendererConfig, ilPDFRenderer 8{ 9 const PAGE = 0; 10 const VIEWPORT = 1; 11 12 /** @var ilLanguage $lng */ 13 protected $lng; 14 15 /** @var string */ 16 protected $path_to_rasterize = './Services/PDFGeneration/js/rasterize.js'; 17 18 public function __construct($phpunit = false) 19 { 20 if (!$phpunit) { 21 global $DIC; 22 $this->setLanguage($DIC['lng']); 23 } 24 } 25 26 /** 27 * @param $lng 28 */ 29 protected function setLanguage($lng) 30 { 31 $this->lng = $lng; 32 } 33 34 /** 35 * @var bool 36 */ 37 protected $use_default_config; 38 39 /** 40 * @var string 41 */ 42 protected $page_size; 43 44 /** 45 * @var string 46 */ 47 protected $orientation; 48 49 /** 50 * @var string 51 */ 52 protected $margin; 53 54 /** 55 * @var int 56 */ 57 protected $javascript_delay; 58 59 /** 60 * @var string 61 */ 62 protected $viewport; 63 64 /** 65 * @var int 66 */ 67 protected $header_type; 68 69 /** 70 * @var int 71 */ 72 protected $footer_type; 73 74 /** 75 * @var string 76 */ 77 protected $header_text; 78 79 /** 80 * @var string 81 */ 82 protected $header_height; 83 84 /** 85 * @var bool 86 */ 87 protected $header_show_pages; 88 89 /** 90 * @var string 91 */ 92 protected $footer_text; 93 94 /** 95 * @var string 96 */ 97 protected $footer_height; 98 99 /** 100 * @var bool 101 */ 102 protected $footer_show_pages; 103 104 /** 105 * @var string 106 */ 107 protected $path; 108 109 /** 110 * @var int 111 */ 112 protected $page_type = self::PAGE; 113 114 /** 115 * @return string 116 */ 117 public function getPluginName() 118 { 119 return $this->lng->txt('pdfgen_renderer_dummyrender_plugname'); 120 } 121 122 /** 123 * @var string 124 */ 125 protected $do_not_validate_ssl = ' --ssl-protocol=any --ignore-ssl-errors=true '; 126 127 /** 128 * from ilRendererConfig 129 * 130 * @param \ilPropertyFormGUI $form 131 * @param string $service 132 * @param string $purpose 133 * 134 * @return \ilPropertyFormGUI|void 135 */ 136 public function addConfigElementsToForm(\ilPropertyFormGUI $form, $service, $purpose) 137 { 138 $path = new ilTextInputGUI($this->lng->txt('path'), 'path'); 139 $path->setValue($this->path); 140 $form->addItem($path); 141 142 $item_group = new ilRadioGroupInputGUI($this->lng->txt('page_settings'), 'page_type'); 143 144 $op = new ilRadioOption($this->lng->txt('page'), self::PAGE); 145 $op->addSubItem($this->buildMarginForm()); 146 $op->addSubItem($this->buildOrientationForm()); 147 $op->addSubItem($this->buildPageSizesForm()); 148 $header_select = new ilRadioGroupInputGUI($this->lng->txt('header_type'), 'header_select'); 149 $header_select->addOption(new ilRadioOption($this->lng->txt('none'), ilPDFGenerationConstants::HEADER_NONE, '')); 150 $header_text = new ilRadioOption($this->lng->txt('text'), ilPDFGenerationConstants::HEADER_TEXT, ''); 151 $header_text->addSubItem($this->buildHeaderTextForm()); 152 $header_text->addSubItem($this->buildHeaderHeightForm()); 153 $header_text->addSubItem($this->buildHeaderPageNumbersForm()); 154 $header_select->addOption($header_text); 155 $header_select->setValue($this->header_type); 156 $op->addSubItem($header_select); 157 $footer_select = new ilRadioGroupInputGUI($this->lng->txt('footer_type'), 'footer_select'); 158 $footer_select->addOption(new ilRadioOption($this->lng->txt('none'), ilPDFGenerationConstants::FOOTER_NONE, '')); 159 $footer_text = new ilRadioOption($this->lng->txt('text'), ilPDFGenerationConstants::FOOTER_TEXT, ''); 160 $footer_text->addSubItem($this->buildFooterTextForm()); 161 $footer_text->addSubItem($this->buildFooterHeightForm()); 162 $footer_text->addSubItem($this->buildFooterPageNumbersForm()); 163 $footer_select->addOption($footer_text); 164 $footer_select->setValue($this->footer_type); 165 $op->addSubItem($footer_select); 166 $item_group->addOption($op); 167 168 $op = new ilRadioOption($this->lng->txt('viewport'), self::VIEWPORT); 169 $op->addSubItem($this->buildViewPortForm()); 170 $item_group->addOption($op); 171 $item_group->setValue($this->page_type); 172 $form->addItem($item_group); 173 174 $form->addItem($this->buildJavascriptDelayForm()); 175 } 176 177 /** 178 * from ilRendererConfig 179 * 180 * @param \ilPropertyFormGUI $form 181 * @param string $service 182 * @param string $purpose 183 * @param array $config 184 * 185 * @return void 186 */ 187 public function populateConfigElementsInForm(\ilPropertyFormGUI $form, $service, $purpose, $config) 188 { 189 $form->getItemByPostVar('path')->setValue($config['path']); 190 $form->getItemByPostVar('page_size')->setValue($config['page_size']); 191 $form->getItemByPostVar('margin')->setValue($config['margin']); 192 $form->getItemByPostVar('javascript_delay')->setValue($config['javascript_delay']); 193 $form->getItemByPostVar('viewport')->setValue($config['viewport']); 194 $form->getItemByPostVar('orientation')->setValue($config['orientation']); 195 $form->getItemByPostVar('header_select')->setValue($config['header_type']); 196 $form->getItemByPostVar('header_text')->setValue($config['header_text']); 197 $form->getItemByPostVar('header_height')->setValue($config['header_height']); 198 $form->getItemByPostVar('header_show_pages')->setChecked($config['header_show_pages']); 199 $form->getItemByPostVar('footer_select')->setValue($config['footer_type']); 200 $form->getItemByPostVar('footer_text')->setValue($config['footer_text']); 201 $form->getItemByPostVar('footer_height')->setValue($config['footer_height']); 202 $form->getItemByPostVar('footer_show_pages')->setChecked($config['footer_show_pages']); 203 $form->getItemByPostVar('page_type')->setValue($config['page_type']); 204 205 ilPDFGeneratorUtils::setCheckedIfTrue($form); 206 } 207 208 /** 209 * from ilRendererConfig 210 * 211 * @param \ilPropertyFormGUI $form 212 * @param string $service 213 * @param string $purpose 214 * 215 * @return bool 216 */ 217 public function validateConfigInForm(\ilPropertyFormGUI $form, $service, $purpose) 218 { 219 if (true) { 220 return true; 221 } 222 return false; 223 } 224 225 /** 226 * from ilRendererConfig 227 * 228 * @param \ilPropertyFormGUI $form 229 * @param string $service 230 * @param string $purpose 231 * 232 * @return array 233 */ 234 public function getConfigFromForm(\ilPropertyFormGUI $form, $service, $purpose) 235 { 236 $config = array(); 237 $config['path'] = $form->getItemByPostVar('path')->getValue(); 238 $config['page_size'] = $form->getItemByPostVar('page_size')->getValue(); 239 $config['margin'] = $form->getItemByPostVar('margin')->getValue(); 240 $config['javascript_delay'] = $form->getItemByPostVar('javascript_delay')->getValue(); 241 $config['viewport'] = $form->getItemByPostVar('viewport')->getValue(); 242 $config['orientation'] = $form->getItemByPostVar('orientation')->getValue(); 243 $config['header_type'] = $form->getItemByPostVar('header_select')->getValue(); 244 $config['header_text'] = $form->getItemByPostVar('header_text')->getValue(); 245 $config['header_height'] = $form->getItemByPostVar('header_height')->getValue(); 246 $config['header_show_pages'] = $form->getItemByPostVar('header_show_pages')->getChecked(); 247 $config['footer_type'] = $form->getItemByPostVar('footer_select')->getValue(); 248 $config['footer_text'] = $form->getItemByPostVar('footer_text')->getValue(); 249 $config['footer_height'] = $form->getItemByPostVar('footer_height')->getValue(); 250 $config['footer_show_pages'] = $form->getItemByPostVar('footer_show_pages')->getChecked(); 251 $config['page_type'] = $form->getItemByPostVar('page_type')->getValue(); 252 253 return $config; 254 } 255 256 /** 257 * from ilRendererConfig 258 * 259 * @param string $service 260 * @param string $purpose 261 * 262 * @return array 263 */ 264 public function getDefaultConfig($service, $purpose) 265 { 266 $config = array(); 267 if (PATH_TO_PHANTOMJS !== '') { 268 $config['path'] = PATH_TO_PHANTOMJS; 269 } else { 270 $config['path'] = '/usr/local/bin/phantomjs'; 271 } 272 273 $config['page_size'] = 'A4'; 274 $config['margin'] = '1cm'; 275 $config['javascript_delay'] = 200; 276 $config['viewport'] = ''; 277 $config['orientation'] = 'Portrait'; 278 $config['header_type'] = 0; 279 $config['header_text'] = ''; 280 $config['header_height'] = '0cm'; 281 $config['header_show_pages'] = 0; 282 $config['footer_type'] = 0; 283 $config['footer_text'] = ''; 284 $config['footer_height'] = '0cm'; 285 $config['footer_show_pages'] = 0; 286 $config['page_type'] = self::PAGE; 287 288 return $config; 289 } 290 291 292 /** 293 * Prepare the content processing at the beginning of a PDF generation request 294 * Should be used to initialize the processing of latex code 295 * The PDF renderers require different image formats generated by the MathJax service 296 * 297 * @param string $service 298 * @param string $purpose 299 * @return void 300 */ 301 public function prepareGenerationRequest($service, $purpose) 302 { 303 ilMathJax::getInstance() 304 ->init(ilMathJax::PURPOSE_PDF) 305 ->setRendering(ilMathJax::RENDER_SVG_AS_XML_EMBED); 306 } 307 308 309 /** 310 * from ilPDFRenderer 311 * 312 * @param string $service 313 * @param string $purpose 314 * @param array $config 315 * @param \ilPDFGenerationJob $job 316 * 317 * @return string|void 318 */ 319 public function generatePDF($service, $purpose, $config, $job) 320 { 321 $html_file = $this->getHtmlTempName(); 322 file_put_contents($html_file, implode('', $job->getPages())); 323 $this->createPDFFileFromHTMLFile($html_file, $config, $job); 324 } 325 326 /** 327 * @param $a_path_to_file 328 * @param $config 329 * @param ilPDFGenerationJob $job 330 */ 331 public function createPDFFileFromHTMLFile($a_path_to_file, $config, $job) 332 { 333 /** @var ilLog $ilLog */ 334 global $ilLog; 335 336 if (file_exists($a_path_to_file)) { 337 $temp_file = $this->getPdfTempName(); 338 339 $args = ' ' . $a_path_to_file . ' ' . $temp_file . ' ' . $this->getCommandLineConfig($config); 340 $return_value = ilUtil::execQuoted($config['path'], $this->do_not_validate_ssl . ' ' . $this->path_to_rasterize . ' ' . $args); 341 342 $ilLog->write('ilPhantomJSRenderer command line config: ' . $args); 343 foreach ($return_value as $key => $value) { 344 $ilLog->write('ilPhantomJSRenderer return value line ' . $key . ' : ' . $value); 345 } 346 347 if (file_exists($temp_file)) { 348 $ilLog->write('ilPhantomJSRenderer file exists: ' . $temp_file . ' file size is :' . filesize($temp_file) . ' bytes, will be renamed to ' . $job->getFilename()); 349 ilFileUtils::rename($temp_file, $job->getFilename()); 350 } else { 351 $ilLog->write('ilPhantomJSRenderer error: ' . print_r($return_value, true)); 352 } 353 } 354 } 355 356 /** 357 * @return ilTextInputGUI 358 */ 359 protected function buildHeaderTextForm() 360 { 361 $header_text = new ilTextInputGUI($this->lng->txt('head_text'), 'header_text'); 362 $header_text->setValue($this->header_text); 363 return $header_text; 364 } 365 366 /** 367 * @return ilTextInputGUI 368 */ 369 protected function buildHeaderHeightForm() 370 { 371 $header_height = new ilTextInputGUI($this->lng->txt('header_height'), 'header_height'); 372 $header_height->setValue($this->header_height); 373 return $header_height; 374 } 375 376 /** 377 * @return ilTextInputGUI 378 */ 379 protected function buildViewPortForm() 380 { 381 $viewport = new ilTextInputGUI($this->lng->txt('viewport'), 'viewport'); 382 $viewport->setValue($this->viewport); 383 $viewport->setInfo($this->lng->txt('viewport_info')); 384 return $viewport; 385 } 386 387 /** 388 * @return ilCheckboxInputGUI 389 */ 390 protected function buildHeaderPageNumbersForm() 391 { 392 $header_show_pages = new ilCheckboxInputGUI($this->lng->txt('header_show_pages'), 'header_show_pages'); 393 if ($this->header_show_pages == true || $this->header_show_pages == 1) { 394 $header_show_pages->setChecked(true); 395 } 396 return $header_show_pages; 397 } 398 399 /** 400 * @return ilTextInputGUI 401 */ 402 protected function buildFooterTextForm() 403 { 404 $footer_text = new ilTextInputGUI($this->lng->txt('footer_text'), 'footer_text'); 405 $footer_text->setValue($this->footer_text); 406 return $footer_text; 407 } 408 409 /** 410 * @return ilTextInputGUI 411 */ 412 protected function buildFooterHeightForm() 413 { 414 $footer_height = new ilTextInputGUI($this->lng->txt('footer_height'), 'footer_height'); 415 $footer_height->setValue($this->footer_height); 416 return $footer_height; 417 } 418 419 /** 420 * @return ilCheckboxInputGUI 421 */ 422 protected function buildFooterPageNumbersForm() 423 { 424 $footer_show_pages = new ilCheckboxInputGUI($this->lng->txt('footer_show_pages'), 'footer_show_pages'); 425 if ($this->footer_show_pages == true || $this->footer_show_pages == 1) { 426 $footer_show_pages->setChecked(true); 427 } 428 return $footer_show_pages; 429 } 430 431 /** 432 * @return ilSelectInputGUI 433 */ 434 protected function buildPageSizesForm() 435 { 436 $page_size = new ilSelectInputGUI($this->lng->txt('page_size'), 'page_size'); 437 $page_size->setOptions(ilPDFGenerationConstants::getPageSizesNames()); 438 $page_size->setValue($this->page_size); 439 return $page_size; 440 } 441 442 /** 443 * @return ilSelectInputGUI 444 */ 445 protected function buildOrientationForm() 446 { 447 $orientation = new ilSelectInputGUI($this->lng->txt('orientation'), 'orientation'); 448 $orientation->setOptions(ilPDFGenerationConstants::getOrientations()); 449 $orientation->setValue($this->orientation); 450 return $orientation; 451 } 452 453 /** 454 * @return ilTextInputGUI 455 */ 456 protected function buildMarginForm() 457 { 458 $margin = new ilTextInputGUI($this->lng->txt('margin'), 'margin'); 459 $margin->setValue($this->margin); 460 return $margin; 461 } 462 463 /** 464 * @return ilTextInputGUI 465 */ 466 protected function buildJavascriptDelayForm() 467 { 468 $javascript_delay = new ilTextInputGUI($this->lng->txt('javascript_delay'), 'javascript_delay'); 469 $javascript_delay->setInfo($this->lng->txt('javascript_delay_info')); 470 $javascript_delay->setValue($this->javascript_delay); 471 return $javascript_delay; 472 } 473 474 /** 475 * @return string 476 */ 477 public function getPdfTempName() 478 { 479 return $this->getTempFileName('pdf'); 480 } 481 482 /** 483 * @return string 484 */ 485 public function getHtmlTempName() 486 { 487 return $this->getTempFileName('html'); 488 } 489 490 /** 491 * @param $file_type 492 * @return string 493 */ 494 protected function getTempFileName($file_type) 495 { 496 if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' && $file_type == 'html') { 497 return 'file:///' . str_replace(':/', '://', ilUtil::ilTempnam()) . '.' . $file_type; 498 } else { 499 return ilUtil::ilTempnam() . '.' . $file_type; 500 } 501 } 502 503 /** 504 * @param $config 505 * 506 * @return string 507 */ 508 protected function getCommandLineConfig($config) 509 { 510 $r_config = array(); 511 512 if ($config['header_type'] == ilPDFGenerationConstants::HEADER_TEXT) { 513 $h_config = array( 514 'text' => $config['header_text'], 515 'height' => $config['header_height'], 516 'show_pages' => $config['header_show_pages']); 517 } else { 518 $h_config = null; 519 } 520 521 if ($config['footer_type'] == ilPDFGenerationConstants::FOOTER_TEXT) { 522 $f_config = array( 523 'text' => $config['footer_text'], 524 'height' => $config['footer_height'], 525 'show_pages' => $config['footer_show_pages']); 526 } else { 527 $f_config = null; 528 } 529 530 $r_config['page_size'] = $config['page_size']; 531 $r_config['orientation'] = $config['orientation']; 532 $r_config['margin'] = $config['margin']; 533 $r_config['delay'] = $config['javascript_delay']; 534 $r_config['viewport'] = $config['viewport']; 535 $r_config['header'] = $h_config; 536 $r_config['footer'] = $f_config; 537 $r_config['page_type'] = $config['page_type']; 538 539 return json_encode(json_encode($r_config)); 540 } 541} 542