fix pdf creation for very large exports (#1533)

This commit is contained in:
Kevin Papst
2020-03-08 00:24:49 +01:00
committed by GitHub
parent d60e738bd2
commit ace2788b57
6 changed files with 54 additions and 25 deletions

View File

@@ -34,7 +34,21 @@ class MPdfConverter implements HtmlToPdfConverter
{ {
$mpdf = new Mpdf(['tempDir' => $this->cacheDirectory]); $mpdf = new Mpdf(['tempDir' => $this->cacheDirectory]);
$mpdf->creator = Constants::SOFTWARE; $mpdf->creator = Constants::SOFTWARE;
$mpdf->WriteHTML($html);
// some OS do not follow the PHP default settings
if ((int) ini_get('pcre.backtrack_limit') < 1000000) {
@ini_set('pcre.backtrack_limit', 1000000);
}
// reduce the size of content parts that are passed to MPDF, to prevent
// https://mpdf.github.io/troubleshooting/known-issues.html#blank-pages-or-some-sections-missing
$parts = explode('<pagebreak>', $html);
for ($i = 0; $i < count($parts); $i++) {
$mpdf->WriteHTML($parts[$i]);
if ($i < count($parts) - 1) {
$mpdf->WriteHTML('<pagebreak>');
}
}
return $mpdf->Output('', Destination::STRING_RETURN); return $mpdf->Output('', Destination::STRING_RETURN);
} }

View File

@@ -10,20 +10,32 @@
<html> <html>
<head> <head>
<style> <style>
body {font-family: sans-serif; body {
font-family: sans-serif;
font-size: 10pt; font-size: 10pt;
} }
p { margin: 0pt; } p {
margin: 0;
}
table.items { table.items {
border: 0.1mm solid #000000; border: 0.1mm solid #000000;
width: 100%;
font-size: 9pt;
border-collapse: collapse;
}
td, th {
padding: 7px;
}
td {
vertical-align: top;
} }
td { vertical-align: top; }
.items td { .items td {
border-left: 0.1mm solid #000000; border-left: 0.1mm solid #000000;
border-right: 0.1mm solid #000000; border-right: 0.1mm solid #000000;
} }
.items tr.even { .items tr.even {
background-color: #e0ebff; /*background-color: #e0ebff;*/
background-color: #f5f5f5;
} }
.items tr.summary { .items tr.summary {
background-color: #efefef; background-color: #efefef;
@@ -33,22 +45,25 @@
border-top: 0.1mm solid #000000; border-top: 0.1mm solid #000000;
border-bottom: 0.1mm solid #000000; border-bottom: 0.1mm solid #000000;
} }
table thead td { table thead th {
background-color: #ececec; background-color: #ececec;
text-align: center;
border: 0.1mm solid #000000; border: 0.1mm solid #000000;
font-weight: bold; font-weight: bold;
font-size: 11pt; font-size: 10pt;
text-align: left;
} }
.items td.totals { .items td.totals {
font-weight: bold; font-weight: bold;
text-align: right;
border: 0.1mm solid #000000; border: 0.1mm solid #000000;
} }
.items .center,
.items td.duration, .items td.duration,
.items td.cost { .items td.cost {
text-align: center; text-align: center;
} }
.text-nowrap {
white-space: nowrap;
}
</style> </style>
</head> </head>
<body> <body>
@@ -82,14 +97,14 @@ mpdf-->
</p> </p>
<h3>{{ 'export.summary'|trans }}</h3> <h3>{{ 'export.summary'|trans }}</h3>
<table class="items" width="100%" style="font-size: 9pt; border-collapse: collapse; " cellpadding="8"> <table class="items">
<thead> <thead>
<tr> <tr>
<td>{{ 'label.customer'|trans }}</td> <th>{{ 'label.customer'|trans }}</th>
<td>{{ 'label.project'|trans }}</td> <th>{{ 'label.project'|trans }}</th>
<td>{{ 'label.duration'|trans }}</td> <th class="center">{{ 'label.duration'|trans }}</th>
{% if showRateColumn %} {% if showRateColumn %}
<td>{{ 'label.rate'|trans }}</td> <th class="center">{{ 'label.rate'|trans }}</th>
{% endif %} {% endif %}
</tr> </tr>
</thead> </thead>
@@ -149,17 +164,17 @@ mpdf-->
{% set duration = 0 %} {% set duration = 0 %}
{% set rate = 0 %} {% set rate = 0 %}
{% set currency = false %} {% set currency = false %}
<table class="items" width="100%" style="font-size: 9pt; border-collapse: collapse; " cellpadding="8"> <table class="items">
<thead> <thead>
<tr> <tr>
<td>{{ 'label.date'|trans }}</td> <th>{{ 'label.date'|trans }}</th>
{% if showUserColumn %} {% if showUserColumn %}
<td>{{ 'label.user'|trans }}</td> <th>{{ 'label.user'|trans }}</th>
{% endif %} {% endif %}
<td width="">{{ 'label.description'|trans }}</td> <th>{{ 'label.description'|trans }}</th>
<td>{{ 'label.duration'|trans }}</td> <th class="center">{{ 'label.duration'|trans }}</th>
{% if showRateColumn %} {% if showRateColumn %}
<td>{{ 'label.rate'|trans }}</td> <th class="center">{{ 'label.rate'|trans }}</th>
{% endif %} {% endif %}
</tr> </tr>
</thead> </thead>
@@ -173,7 +188,7 @@ mpdf-->
{% set currency = null %} {% set currency = null %}
{% endif %} {% endif %}
<tr class="{{ cycle(['odd', 'even'], loop.index0) }}"> <tr class="{{ cycle(['odd', 'even'], loop.index0) }}">
<td> <td class="text-nowrap">
{{ entry.begin|date_time }} {{ entry.begin|date_time }}
{% if entry.end %} {% if entry.end %}
<br> <br>

View File

@@ -217,7 +217,7 @@ class ExportControllerTest extends ControllerBaseTest
// poor mans assertions ;-) // poor mans assertions ;-)
$this->assertStringContainsString('export_print', $node->getIterator()[0]->getAttribute('class')); $this->assertStringContainsString('export_print', $node->getIterator()[0]->getAttribute('class'));
$this->assertStringContainsString('<h2>List of expenses</h2>', $response->getContent()); $this->assertStringContainsString('<h2>', $response->getContent());
$this->assertStringContainsString('<h3>Summary</h3>', $response->getContent()); $this->assertStringContainsString('<h3>Summary</h3>', $response->getContent());
$node = $client->getCrawler()->filter('section.export div#export-records table.dataTable tbody tr'); $node = $client->getCrawler()->filter('section.export div#export-records table.dataTable tbody tr');

View File

@@ -50,7 +50,7 @@ class HtmlRendererTest extends AbstractRendererTest
$content = $response->getContent(); $content = $response->getContent();
$this->assertStringContainsString('<h2>List of expenses</h2>', $content); $this->assertStringContainsString('<h2>', $content);
$this->assertStringContainsString('<h3>Summary</h3>', $content); $this->assertStringContainsString('<h3>Summary</h3>', $content);
$this->assertEquals(1, substr_count($content, 'id="export-summary"')); $this->assertEquals(1, substr_count($content, 'id="export-summary"'));
$this->assertEquals(1, substr_count($content, 'id="export-records"')); $this->assertEquals(1, substr_count($content, 'id="export-records"'));

View File

@@ -970,7 +970,7 @@
</trans-unit> </trans-unit>
<trans-unit id="export.document_title"> <trans-unit id="export.document_title">
<source>export.document_title</source> <source>export.document_title</source>
<target>Aufstellung zu Aufwänden</target> <target>Export von Zeiten</target>
</trans-unit> </trans-unit>
<trans-unit id="export.full_list"> <trans-unit id="export.full_list">
<source>export.full_list</source> <source>export.full_list</source>

View File

@@ -970,7 +970,7 @@
</trans-unit> </trans-unit>
<trans-unit id="export.document_title"> <trans-unit id="export.document_title">
<source>export.document_title</source> <source>export.document_title</source>
<target>List of expenses</target> <target>Export of timesheets</target>
</trans-unit> </trans-unit>
<trans-unit id="export.full_list"> <trans-unit id="export.full_list">
<source>export.full_list</source> <source>export.full_list</source>