View source
<?php
namespace Drupal\printable_pdf\Plugin\PrintableFormat;
use Drupal\Component\Utility\Unicode;
use Drupal\Core\Config\ConfigFactory;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Link;
use Drupal\Core\Messenger\MessengerInterface;
use Drupal\Core\Path\CurrentPathStack;
use Drupal\Core\StreamWrapper\PublicStream;
use Drupal\Core\Url;
use Drupal\pdf_api\PdfGeneratorPluginManager;
use Drupal\printable\LinkExtractor\LinkExtractorInterface;
use Drupal\printable\Plugin\PrintableFormatBase;
use Drupal\printable\PrintableCssIncludeInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class PdfFormat extends PrintableFormatBase {
protected $pdfGeneratorManager;
protected $pdfGenerator;
protected $filename;
protected $pathCurrent;
protected $requestStack;
protected $publicStream;
protected $messenger;
public function __construct(array $configuration, $plugin_id, array $plugin_definition, ConfigFactory $config_factory, PdfGeneratorPluginManager $pdf_generator_manager, PrintableCssIncludeInterface $printable_css_include, LinkExtractorInterface $link_extractor, CurrentPathStack $pathCurrent, RequestStack $requestStack, PublicStream $public_stream, MessengerInterface $messenger) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $config_factory, $printable_css_include, $link_extractor);
$this->pdfGeneratorManager = $pdf_generator_manager;
$this->pathCurrent = $pathCurrent;
$this->requestStack = $requestStack;
$this->publicStream = $public_stream;
$this->messenger = $messenger;
$pdf_library = (string) $this->configFactory
->get('printable.settings')
->get('pdf_tool');
if (!$pdf_library) {
$this->messenger
->addError($this
->t('A PDF generation toolkit needs to be selected. Please visit the %link.', [
'%link' => Link::fromTextAndUrl('admin interface', Url::fromRoute('printable.format_configure_pdf'))
->toString(),
]));
throw new NotFoundHttpException();
return;
}
$pdf_library = strtolower($pdf_library);
$this->pdfGenerator = $this->pdfGeneratorManager
->createInstance($pdf_library);
if ($pdf_library != 'wkhtmltopdf') {
return;
}
$options = [
'enable-local-file-access',
];
$use_xvfb_run = (string) $this->configFactory
->get('printable.settings')
->get('print_pdf_use_xvfb_run');
$path_to_xfb_run = (string) $this->configFactory
->get('printable.settings')
->get('path_to_xfb_run');
$ignore_warnings = (bool) $this->configFactory
->get('printable.settings')
->get('ignore_warnings');
if ($use_xvfb_run) {
$options = [
'use-xserver' => NULL,
'commandOptions' => [
'enableXvfb' => TRUE,
'xvfbRunBinary' => $path_to_xfb_run,
],
'ignoreWarnings' => $ignore_warnings,
'enable-local-file-access',
];
}
$this->pdfGenerator
->getObject()
->setOptions($options);
}
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($configuration, $plugin_id, $plugin_definition, $container
->get('config.factory'), $container
->get('plugin.manager.pdf_generator'), $container
->get('printable.css_include'), $container
->get('printable.link_extractor'), $container
->get('path.current'), $container
->get('request_stack'), $container
->get('stream_wrapper.public'), $container
->get('messenger'));
}
public function defaultConfiguration() {
return [
'pdf_generator' => 'wkhtmltopdf',
];
}
public function calculateDependencies() {
}
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$config = $this
->getConfiguration();
$options = [];
foreach ($this->pdfGeneratorManager
->getDefinitions() as $definition) {
$options[$definition['id']] = $definition['title'];
}
$form['pdf_generator'] = [
'#type' => 'radios',
'#title' => 'PDF Generator',
'#default_value' => $config['pdf_generator'],
'#options' => $options,
];
return $form;
}
public function submitConfigurationForm(array &$form, FormStateInterface $form_state) {
$this
->setConfiguration([
'pdf_generator' => $form_state['values']['pdf_generator'],
]);
}
public function getHeaderContent() {
$pdf_header = [
'#theme' => 'printable_pdf_header',
];
return render($pdf_header);
}
public function getFooterContent() {
$pdf_footer = [
'#theme' => 'printable_pdf_footer',
];
return render($pdf_footer);
}
public function buildPdfContent() {
$content = parent::buildContent();
$content = render($content);
$content = preg_replace([
'#printable://#',
'/\\?itok=.*"/',
], [
'',
'"',
], $content);
$rendered_page = parent::extractLinks($content);
return $rendered_page;
}
public function formattedHeaderFooter() {
$this->pdfGenerator
->getObject()
->SetFooter('This is a footer on left side||' . 'This is a footer on right side');
}
private function getHeaders($filename, $download) {
$disposition = $download ? 'attachment' : 'inline';
return [
'Content-Type' => Unicode::mimeHeaderEncode('application/pdf'),
'Content-Disposition' => $disposition . '; filename="' . $filename . '"',
'Content-Length' => filesize($filename),
'Content-Transfer-Encoding' => 'binary',
'Pragma' => 'no-cache',
'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
'Expires' => '0',
'Accept-Ranges' => 'bytes',
];
}
public function streamResponseContent() {
$this->pdfGenerator
->send();
}
public function removeImageTokens($subject) {
$next_pos = strpos($subject, DRUPAL_ROOT);
while ($next_pos !== FALSE) {
$have_matches = preg_match('/[\\s\'"]/', substr($subject, $next_pos), $matches, PREG_OFFSET_CAPTURE);
$path_end = $have_matches ? $matches[0][1] : strlen($subject) - $next_pos + 1;
$query_start = strpos(substr($subject, $next_pos, $path_end), '?');
if ($query_start !== FALSE) {
$subject = substr($subject, 0, $next_pos + $query_start) . substr($subject, $next_pos + $path_end);
}
$next_pos = strpos($subject, DRUPAL_ROOT, $next_pos + $path_end - $query_start + 1);
}
return $subject;
}
public function getResponse() {
$paper_size = (string) $this->configFactory
->get('printable.settings')
->get('paper_size');
$paper_orientation = $this->configFactory
->get('printable.settings')
->get('page_orientation');
$path_to_binary = $this->configFactory
->get('printable.settings')
->get('path_to_binary');
$save_pdf = $this->configFactory
->get('printable.settings')
->get('save_pdf');
$pdf_location = $this->configFactory
->get('printable.settings')
->get('pdf_location');
$raw_content = $this
->buildPdfContent();
$basepath = \Drupal::request()
->getBasePath();
if ($basepath) {
$raw_content = str_replace('src="' . $basepath, 'src=', $raw_content);
}
$pdf_content = $this
->removeImageTokens($raw_content);
$footer_content = $this
->getFooterContent();
$header_content = $this
->getHeaderContent();
$this->pdfGenerator
->setter($pdf_content, $pdf_location, $save_pdf, $paper_orientation, $paper_size, $footer_content, $header_content, $path_to_binary);
if (empty($pdf_location)) {
$pdf_location = str_replace("/", "_", $this->pathCurrent
->getPath()) . '.pdf';
$public_dir = $this->publicStream
->getDirectoryPath();
$pdf_location = trim($public_dir, '/') . '/' . substr($pdf_location, 1);
}
else {
$token_service = \Drupal::token();
$url_parts = explode('/', $this->pathCurrent
->getPath());
$entity = \Drupal::routeMatch()
->getParameter('entity');
$entity_type = count($url_parts) > 2 ? $url_parts[1] : NULL;
$pdf_location = $token_service
->replace($pdf_location, [
$entity_type => $entity,
]);
}
$this->filename = DRUPAL_ROOT . '/' . $pdf_location;
$this->pdfGenerator
->save($this->filename);
if ($this->pdfGenerator
->displayErrors()) {
$source_url = $this->requestStack
->getCurrentRequest()
->getRequestUri();
$pos = strpos($source_url, "printable");
$source_url = substr($source_url, 0, $pos - 1);
return new RedirectResponse($source_url);
}
return (new BinaryFileResponse($this->filename, 200, $this
->getHeaders($pdf_location, $save_pdf)))
->deleteFileAfterSend(TRUE);
}
}