mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-11-22 11:20:37 +08:00
PDF: Added implmentation of command PDF option
Tested quickly manually but not yet covered by PHPUnit tests.
This commit is contained in:
parent
40200856af
commit
1c7128c2cb
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
namespace BookStack\Entities\Tools;
|
namespace BookStack\Entities\Tools;
|
||||||
|
|
||||||
|
use BookStack\Exceptions\PdfExportException;
|
||||||
use Knp\Snappy\Pdf as SnappyPdf;
|
use Knp\Snappy\Pdf as SnappyPdf;
|
||||||
use Dompdf\Dompdf;
|
use Dompdf\Dompdf;
|
||||||
|
use Symfony\Component\Process\Process;
|
||||||
|
|
||||||
class PdfGenerator
|
class PdfGenerator
|
||||||
{
|
{
|
||||||
|
@ -13,19 +15,15 @@ class PdfGenerator
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate PDF content from the given HTML content.
|
* Generate PDF content from the given HTML content.
|
||||||
|
* @throws PdfExportException
|
||||||
*/
|
*/
|
||||||
public function fromHtml(string $html): string
|
public function fromHtml(string $html): string
|
||||||
{
|
{
|
||||||
$engine = $this->getActiveEngine();
|
return match ($this->getActiveEngine()) {
|
||||||
|
self::ENGINE_COMMAND => $this->renderUsingCommand($html),
|
||||||
if ($engine === self::ENGINE_WKHTML) {
|
self::ENGINE_WKHTML => $this->renderUsingWkhtml($html),
|
||||||
return $this->renderUsingWkhtml($html);
|
default => $this->renderUsingDomPdf($html)
|
||||||
} else if ($engine === self::ENGINE_COMMAND) {
|
};
|
||||||
// TODO - Support PDF command
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
return $this->renderUsingDomPdf($html);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -34,6 +32,10 @@ class PdfGenerator
|
||||||
*/
|
*/
|
||||||
public function getActiveEngine(): string
|
public function getActiveEngine(): string
|
||||||
{
|
{
|
||||||
|
if (config('exports.pdf_command')) {
|
||||||
|
return self::ENGINE_COMMAND;
|
||||||
|
}
|
||||||
|
|
||||||
if ($this->getWkhtmlBinaryPath() && config('app.allow_untrusted_server_fetching') === true) {
|
if ($this->getWkhtmlBinaryPath() && config('app.allow_untrusted_server_fetching') === true) {
|
||||||
return self::ENGINE_WKHTML;
|
return self::ENGINE_WKHTML;
|
||||||
}
|
}
|
||||||
|
@ -63,6 +65,46 @@ class PdfGenerator
|
||||||
return (string) $domPdf->output();
|
return (string) $domPdf->output();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws PdfExportException
|
||||||
|
*/
|
||||||
|
protected function renderUsingCommand(string $html): string
|
||||||
|
{
|
||||||
|
$command = config('exports.pdf_command');
|
||||||
|
$inputHtml = tempnam(sys_get_temp_dir(), 'bs-pdfgen-html-');
|
||||||
|
$outputPdf = tempnam(sys_get_temp_dir(), 'bs-pdfgen-output-');
|
||||||
|
|
||||||
|
$replacementsByPlaceholder = [
|
||||||
|
'{input_html_path}' => $inputHtml,
|
||||||
|
'{output_html_path}' => $outputPdf,
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($replacementsByPlaceholder as $placeholder => $replacement) {
|
||||||
|
$command = str_replace($placeholder, escapeshellarg($replacement), $command);
|
||||||
|
}
|
||||||
|
|
||||||
|
file_put_contents($inputHtml, $html);
|
||||||
|
|
||||||
|
$process = Process::fromShellCommandline($command);
|
||||||
|
$process->setTimeout(15);
|
||||||
|
$process->run();
|
||||||
|
|
||||||
|
if (!$process->isSuccessful()) {
|
||||||
|
throw new PdfExportException("PDF Export via command failed with exit code {$process->getExitCode()}, stdout: {$process->getOutput()}, stderr: {$process->getErrorOutput()}");
|
||||||
|
}
|
||||||
|
|
||||||
|
$pdfContents = file_get_contents($outputPdf);
|
||||||
|
unlink($outputPdf);
|
||||||
|
|
||||||
|
if ($pdfContents === false) {
|
||||||
|
throw new PdfExportException("PDF Export via command failed, unable to read PDF output file");
|
||||||
|
} else if (empty($pdfContents)) {
|
||||||
|
throw new PdfExportException("PDF Export via command failed, PDF output file is empty");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $pdfContents;
|
||||||
|
}
|
||||||
|
|
||||||
protected function renderUsingWkhtml(string $html): string
|
protected function renderUsingWkhtml(string $html): string
|
||||||
{
|
{
|
||||||
$snappy = new SnappyPdf($this->getWkhtmlBinaryPath());
|
$snappy = new SnappyPdf($this->getWkhtmlBinaryPath());
|
||||||
|
|
7
app/Exceptions/PdfExportException.php
Normal file
7
app/Exceptions/PdfExportException.php
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace BookStack\Exceptions;
|
||||||
|
|
||||||
|
class PdfExportException extends \Exception
|
||||||
|
{
|
||||||
|
}
|
|
@ -51,6 +51,7 @@
|
||||||
<server name="LOG_FAILED_LOGIN_MESSAGE" value=""/>
|
<server name="LOG_FAILED_LOGIN_MESSAGE" value=""/>
|
||||||
<server name="LOG_FAILED_LOGIN_CHANNEL" value="testing"/>
|
<server name="LOG_FAILED_LOGIN_CHANNEL" value="testing"/>
|
||||||
<server name="WKHTMLTOPDF" value="false"/>
|
<server name="WKHTMLTOPDF" value="false"/>
|
||||||
|
<server name="EXPORT_PDF_COMMAND" value="false"/>
|
||||||
<server name="APP_DEFAULT_DARK_MODE" value="false"/>
|
<server name="APP_DEFAULT_DARK_MODE" value="false"/>
|
||||||
<server name="IP_ADDRESS_PRECISION" value="4"/>
|
<server name="IP_ADDRESS_PRECISION" value="4"/>
|
||||||
</php>
|
</php>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user