entity_print_chrome-1.0.0/src/Plugin/EntityPrint/PrintEngine/Chrome.php
src/Plugin/EntityPrint/PrintEngine/Chrome.php
<?php
namespace Drupal\entity_print_chrome\Plugin\EntityPrint\PrintEngine;
use Drupal\Core\File\FileSystemInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\entity_print\Plugin\ExportTypeInterface;
use Drupal\entity_print\Plugin\PrintEngineBase;
use HeadlessChromium\BrowserFactory;
use HeadlessChromium\Page;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\HeaderUtils;
use Symfony\Component\HttpFoundation\Response;
/**
* An Entity Print plugin for a Chromium-based PDF generator.
*
* @PrintEngine(
* id = "chrome",
* label = @Translation("Chrome"),
* export_type = "pdf"
* )
*/
class Chrome extends PrintEngineBase {
/**
* The Chrome browser factory.
*
* @var \HeadlessChromium\BrowserFactory
*/
protected $browserFactory;
/**
* The file system helper.
*
* @var \Drupal\Core\File\FileSystemInterface
*/
protected $fileSystem;
/**
* Keep track of HTML pages as they're added.
*
* @var string
*/
protected string $html = '';
/**
* {@inheritdoc}
*/
public function __construct(array $configuration, $plugin_id, $plugin_definition, ExportTypeInterface $export_type, FileSystemInterface $file_system) {
parent::__construct($configuration, $plugin_id, $plugin_definition, $export_type);
$this->fileSystem = $file_system;
$this->browserFactory = new BrowserFactory($this->configuration['binary_location']);
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration,
$plugin_id,
$plugin_definition,
$container->get('plugin.manager.entity_print.export_type')->createInstance($plugin_definition['export_type']),
$container->get('file_system'),
);
}
/**
* {@inheritdoc}
*/
public static function getInstallationInstructions() {
return t('Please install with: @command', ['@command' => 'composer require chrome-php/chrome']);
}
/**
* {@inheritdoc}
*/
public function defaultConfiguration() {
return parent::defaultConfiguration() + [
'binary_location' => '/usr/bin/google-chrome',
'print_background' => FALSE,
];
}
/**
* {@inheritdoc}
*/
public function buildConfigurationForm(array $form, FormStateInterface $form_state) {
$form = parent::buildConfigurationForm($form, $form_state);
$form['binary_location'] = [
'#type' => 'textfield',
'#title' => $this->t('Path to the Chrome/Chromium binary'),
'#default_value' => $this->configuration['binary_location'],
'#description' => $this->t("For example, /usr/bin/google-chrome or /usr/local/bin/chromium."),
];
$form['print_background'] = [
'#type' => 'checkbox',
'#title' => $this->t('Print background images'),
'#description' => $this->t("If checked, the PDF will include background images."),
'#default_value' => $this->configuration['print_background'],
];
return $form;
}
/**
* {@inheritdoc}
*/
public function addPage($content) {
$this->html .= $content;
return $this;
}
/**
* {@inheritdoc}
*/
public function send($filename, $force_download = TRUE) {
$data = $this->getBlob();
// Build up a Symfony response.
$disposition = $force_download ? HeaderUtils::DISPOSITION_ATTACHMENT : HeaderUtils::DISPOSITION_INLINE;
$response = new Response($data, 200, [
'Content-Type' => 'application/pdf',
'Content-Length' => mb_strlen($data, '8bit'),
'Content-Disposition' => HeaderUtils::makeDisposition($disposition, $filename),
]);
$response->send();
}
/**
* {@inheritdoc}
*/
public function getBlob() {
$temp_file = $this->fileSystem->tempnam('temporary://', 'entity_print');
$html_file = $temp_file . '.html';
if (!@rename($temp_file, $html_file)) {
throw new \RuntimeException("Temporary file '$temp_file' could not be renamed.");
}
if (file_put_contents($html_file, $this->html) === FALSE) {
throw new \RuntimeException("Temporary file '$html_file' could not be created.");
}
$html_uri = 'file://' . $this->fileSystem->realpath($html_file);
$browser = $this->browserFactory->createBrowser([
'noSandbox' => TRUE,
]);
try {
$page = $browser->createPage();
$page->navigate($html_uri)->waitForNavigation(Page::NETWORK_IDLE);
// Allow 10s timeout when generating PDF; default is 2s.
$timeout = 10 * 1000;
$pdf = $page->pdf(['printBackground' => $this->configuration['print_background']])->getBase64($timeout);
return base64_decode($pdf);
}
finally {
$browser->close();
$this->fileSystem->unlink($html_file);
}
}
/**
* {@inheritdoc}
*/
public static function dependenciesAvailable() {
return class_exists(BrowserFactory::class) && !drupal_valid_test_ua();
}
/**
* {@inheritdoc}
*/
public function getPrintObject() {
return $this->browserFactory;
}
}
