From 234beee61b8cf4c8c27eb76a81f443614d938c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Tue, 25 Aug 2020 10:51:49 +0200 Subject: [PATCH 1/8] Enable injecting print CSS into document --- app/Services/PdfMaker/PdfMaker.php | 14 ++++-- app/Services/PdfMaker/PdfMakerUtilities.php | 35 ++++++++++++++- tests/Feature/PdfMaker/PdfMakerTest.php | 48 +++++++++++++++++---- 3 files changed, 83 insertions(+), 14 deletions(-) diff --git a/app/Services/PdfMaker/PdfMaker.php b/app/Services/PdfMaker/PdfMaker.php index 7640b4d95c1b..6118c6854685 100644 --- a/app/Services/PdfMaker/PdfMaker.php +++ b/app/Services/PdfMaker/PdfMaker.php @@ -32,9 +32,15 @@ class PdfMaker '' => '', ]; + private $options; + public function __construct(array $data) { $this->data = $data; + + if (array_key_exists('options', $data)) { + $this->options = $data['options']; + } } public function design(string $design) @@ -61,14 +67,16 @@ class PdfMaker public function getCompiledHTML($final = false) { + $this->processOptions(); + if ($final) { $html = $this->document->saveXML(); - + $filtered = strtr($html, $this->filters); - + return $filtered; } - + return $this->document->saveXML(); } } diff --git a/app/Services/PdfMaker/PdfMakerUtilities.php b/app/Services/PdfMaker/PdfMakerUtilities.php index 6a20c3fe66a5..f0f16e09a180 100644 --- a/app/Services/PdfMaker/PdfMakerUtilities.php +++ b/app/Services/PdfMaker/PdfMakerUtilities.php @@ -47,7 +47,11 @@ trait PdfMakerUtilities public function updateElementProperties(array $elements) { foreach ($elements as $element) { - $node = $this->document->getElementById($element['id']); + if (isset($element['tag'])) { + $node = $this->document->getElementsByTagName($element['tag'])->item(0); + } else { + $node = $this->document->getElementById($element['id']); + } if (isset($element['properties'])) { foreach ($element['properties'] as $property => $value) { @@ -104,7 +108,6 @@ trait PdfMakerUtilities public function createElementContent($element, $children) { foreach ($children as $child) { - $_child = $this->document->createElement($child['element'], $child['content']); $element->appendChild($_child); @@ -149,4 +152,32 @@ trait PdfMakerUtilities return $element; } + + public function processOptions() + { + if (isset($this->options['print_css']) && $this->options['print_css']) { + $this->insertPrintCSS(); + } + } + + public function insertPrintCSS() + { + $css = '.page-header,.page-header-space{height:100px}.page-footer,.page-footer-space{height:50px}.page-footer{position:fixed;bottom:0;width:100%;border-top:1px solid #000;background:#ff0}.page-header{position:fixed;top:0;width:100%;border-bottom:1px solid #000;background:#ff0}.page{page-break-after:always}@page{margin:20mm}@media print{thead{display:table-header-group}tfoot{display:table-footer-group}button{display:none}body{margin:0}}'; + + $css_node = $this->document->createTextNode($css); + + $style = $this->document->getElementsByTagName('style')->item(0); + + if ($style) { + return $style->appendChild($css_node); + } + + $head = $this->document->getElementsByTagName('head')->item(0); + + if ($head) { + $style_node = $this->document->createElement('style', $css); + + return $head->appendChild($style_node); + } + } } diff --git a/tests/Feature/PdfMaker/PdfMakerTest.php b/tests/Feature/PdfMaker/PdfMakerTest.php index cbe58711d325..09f30e16ce6f 100644 --- a/tests/Feature/PdfMaker/PdfMakerTest.php +++ b/tests/Feature/PdfMaker/PdfMakerTest.php @@ -18,7 +18,7 @@ class PdfMakerTest extends TestCase public function testDesignLoadsCorrectly() { - $this->markTestSkipped('STUB broken tests'); + $this->markTestSkipped('STUB broken tests'); $maker = new PdfMaker($this->state); @@ -29,7 +29,7 @@ class PdfMakerTest extends TestCase public function testHtmlDesignLoadsCorrectly() { - $this->markTestSkipped('STUB broken tests'); + $this->markTestSkipped('STUB broken tests'); $maker = new PdfMaker($this->state); @@ -42,7 +42,7 @@ class PdfMakerTest extends TestCase public function testGetSectionUtility() { - $this->markTestSkipped('STUB broken tests'); + $this->markTestSkipped('STUB broken tests'); $maker = new PdfMaker($this->state); @@ -55,7 +55,7 @@ class PdfMakerTest extends TestCase public function testTableAttributesAreInjected() { - $this->markTestSkipped('STUB broken tests'); + $this->markTestSkipped('STUB broken tests'); $state = [ 'template' => [ @@ -93,7 +93,7 @@ class PdfMakerTest extends TestCase public function testVariablesAreReplaced() { - $this->markTestSkipped('STUB broken tests'); + $this->markTestSkipped('STUB broken tests'); $state = [ @@ -133,7 +133,7 @@ class PdfMakerTest extends TestCase public function testElementContentIsGenerated() { - $this->markTestSkipped('STUB broken tests'); + $this->markTestSkipped('STUB broken tests'); $state = [ @@ -184,7 +184,7 @@ class PdfMakerTest extends TestCase public function testConditionalRenderingOfElements() { - $this->markTestSkipped('STUB broken tests'); + $this->markTestSkipped('STUB broken tests'); $maker1 = new PdfMaker([ @@ -226,7 +226,7 @@ class PdfMakerTest extends TestCase public function testOrderingElements() { - $this->markTestSkipped('STUB broken tests'); + $this->markTestSkipped('STUB broken tests'); $maker = new PdfMaker([ @@ -286,7 +286,7 @@ class PdfMakerTest extends TestCase public function testGeneratingPdf() { - $this->markTestSkipped('STUB broken tests'); + $this->markTestSkipped('STUB broken tests'); $state = [ @@ -356,4 +356,34 @@ class PdfMakerTest extends TestCase $this->assertStringContainsString('id="product-table"', $html); } + + public function testWrapperHTMLWorks() + { + $design = new ExampleDesign(); + + $html = $design + ->document() + ->getSectionHTML('product-table'); + + $state = [ + 'template' => [], + 'variables' => [ + 'labels' => [], + 'values' => [], + ], + 'options' => [ + 'print_css' => true, + ], + ]; + + $maker = new PdfMaker($state); + + $maker + ->design(ExampleDesign::class) + ->build(); + + exec('echo "" > storage/logs/laravel.log'); + + info($maker->getCompiledHTML(true)); + } } From e965aded062af48ec799799c0d390e6f9f0afa51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Wed, 26 Aug 2020 09:02:38 +0200 Subject: [PATCH 2/8] engine for repeating headers --- app/Services/PdfMaker/PdfMaker.php | 4 +- app/Services/PdfMaker/PdfMakerUtilities.php | 81 ++++++++++++++++++++- tests/Feature/PdfMaker/PdfMakerTest.php | 17 +++-- tests/Feature/PdfMaker/example-design.html | 3 +- 4 files changed, 92 insertions(+), 13 deletions(-) diff --git a/app/Services/PdfMaker/PdfMaker.php b/app/Services/PdfMaker/PdfMaker.php index 6118c6854685..7e0e793fcbcd 100644 --- a/app/Services/PdfMaker/PdfMaker.php +++ b/app/Services/PdfMaker/PdfMaker.php @@ -62,13 +62,13 @@ class PdfMaker $this->updateVariables($this->data['variables']); } + $this->processOptions(); + return $this; } public function getCompiledHTML($final = false) { - $this->processOptions(); - if ($final) { $html = $this->document->saveXML(); diff --git a/app/Services/PdfMaker/PdfMakerUtilities.php b/app/Services/PdfMaker/PdfMakerUtilities.php index f0f16e09a180..dd35daf90b51 100644 --- a/app/Services/PdfMaker/PdfMakerUtilities.php +++ b/app/Services/PdfMaker/PdfMakerUtilities.php @@ -13,6 +13,7 @@ namespace App\Services\PdfMaker; use DOMDocument; +use DOMDomError; use DOMXPath; trait PdfMakerUtilities @@ -155,14 +156,27 @@ trait PdfMakerUtilities public function processOptions() { - if (isset($this->options['print_css']) && $this->options['print_css']) { + if (isset($this->options['repeat_header_and_footer']) && $this->options['repeat_header_and_footer']) { $this->insertPrintCSS(); + $this->wrapIntoTable(); } } public function insertPrintCSS() { - $css = '.page-header,.page-header-space{height:100px}.page-footer,.page-footer-space{height:50px}.page-footer{position:fixed;bottom:0;width:100%;border-top:1px solid #000;background:#ff0}.page-header{position:fixed;top:0;width:100%;border-bottom:1px solid #000;background:#ff0}.page{page-break-after:always}@page{margin:20mm}@media print{thead{display:table-header-group}tfoot{display:table-footer-group}button{display:none}body{margin:0}}'; + $css = <<document->createTextNode($css); @@ -180,4 +194,67 @@ trait PdfMakerUtilities return $head->appendChild($style_node); } } + + public function wrapIntoTable() + { + $markup = << + + + + + + + + + + + + + + + + + + + + + + + EOT; + + $document = new DOMDocument(); + $document->loadHTML($markup); + + $table = $document->getElementById('page-container'); + + $this->document->getElementsByTagName('body') + ->item(0) + ->appendChild($this->document->importNode($table, true)); + + foreach ($this->data['template'] as $element) { + if ($element['id'] == 'header' || $element['id'] == 'footer') { + continue; + } + + $node = $this->document->getElementById($element['id']); + $node->parentNode->removeChild($node); + + $this->document->getElementById('repeat-content')->appendChild($node); + } + + if ($header = $this->document->getElementById('header')) { + $header = $this->document->getElementById('header'); + $header->parentNode->removeChild($header); + + $this->document->getElementById('repeat-header')->appendChild($header); + } + + if ($footer = $this->document->getElementById('footer')) { + $footer = $this->document->getElementById('footer'); + $footer->parentNode->removeChild($footer); + + $this->document->getElementById('repeat-footer')->appendChild($footer); + } + } } diff --git a/tests/Feature/PdfMaker/PdfMakerTest.php b/tests/Feature/PdfMaker/PdfMakerTest.php index 09f30e16ce6f..a0bff13208dc 100644 --- a/tests/Feature/PdfMaker/PdfMakerTest.php +++ b/tests/Feature/PdfMaker/PdfMakerTest.php @@ -361,18 +361,21 @@ class PdfMakerTest extends TestCase { $design = new ExampleDesign(); - $html = $design - ->document() - ->getSectionHTML('product-table'); - $state = [ - 'template' => [], + 'template' => [ + 'product-table' => [ + 'id' => 'product-table', + 'elements' => [ + ['element' => 'p', 'content' => 'Example paragraph'], + ], + ], + ], 'variables' => [ 'labels' => [], 'values' => [], ], 'options' => [ - 'print_css' => true, + 'repeat_header_and_footer' => true, ], ]; @@ -382,8 +385,6 @@ class PdfMakerTest extends TestCase ->design(ExampleDesign::class) ->build(); - exec('echo "" > storage/logs/laravel.log'); - info($maker->getCompiledHTML(true)); } } diff --git a/tests/Feature/PdfMaker/example-design.html b/tests/Feature/PdfMaker/example-design.html index b2c0c81a2b06..305f12a1762f 100644 --- a/tests/Feature/PdfMaker/example-design.html +++ b/tests/Feature/PdfMaker/example-design.html @@ -2,6 +2,7 @@ - +
+ \ No newline at end of file From 09dc17d3dc8d85d7bf741a269cac78ff5a2e7a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Benjamin=20Beganovi=C4=87?= Date: Wed, 26 Aug 2020 12:51:54 +0200 Subject: [PATCH 3/8] Separate header section on templates --- resources/views/pdf-designs/bold.html | 2 +- resources/views/pdf-designs/business.html | 2 +- resources/views/pdf-designs/clean.html | 2 +- resources/views/pdf-designs/creative.html | 2 +- resources/views/pdf-designs/elegant.html | 7 +++++-- resources/views/pdf-designs/hipster.html | 2 +- resources/views/pdf-designs/modern.html | 2 +- resources/views/pdf-designs/plain.html | 2 +- resources/views/pdf-designs/playful.html | 2 +- 9 files changed, 13 insertions(+), 10 deletions(-) diff --git a/resources/views/pdf-designs/bold.html b/resources/views/pdf-designs/bold.html index 66b172cff9b7..e73a4251a459 100644 --- a/resources/views/pdf-designs/bold.html +++ b/resources/views/pdf-designs/bold.html @@ -19,7 +19,7 @@ -
+