PMCORE-3540 BE: Generate a output document using the header, footer and pagination defined

This commit is contained in:
Roly Gutierrez
2022-01-17 09:44:48 -04:00
parent a65ea8cd92
commit beacac5a5b
9 changed files with 1788 additions and 3 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,173 @@
<?php
namespace ProcessMaker\PDF;
use stdClass;
use Tests\TestCase;
/**
* @covers ProcessMaker\PDF\TCPDFHeaderFooter
* @test
*/
class TCPDFHeaderFooterTest extends TestCase
{
/**
* TCPDFHeaderFooter object.
* @var TCPDFHeaderFooter
*/
protected $object;
/**
* setUp method.
*/
protected function setUp()
{
parent::setUp();
$this->object = new TCPDFHeaderFooter('P', PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
$this->object->SetCreator(PDF_CREATOR);
$this->object->SetAuthor('admin');
$this->object->SetTitle('test');
$this->object->SetSubject('test.pdf');
$this->object->SetCompression(true);
$this->setHeaderData();
$this->setFooterData();
}
/**
* tearDown method.
*/
protected function tearDown()
{
parent::tearDown();
}
/**
* Setting data for header configuration.
*/
private function setHeaderData()
{
$header = new stdClass();
$header->logo = PATH_TRUNK . "/vendor/tecnickcom/tcpdf/examples/images/logo_example.jpg";
$header->logoWidth = 10;
$header->logoPositionX = 50;
$header->logoPositionY = 0;
$header->title = "Test1 Test1";
$header->titleFontSize = 60;
$header->titleFontPositionX = 10;
$header->titleFontPositionY = 0;
$header->pageNumber = true;
$header->pageNumberTitle = "Pages";
$header->pageNumberTotal = true;
$header->pageNumberPositionX = 10;
$header->pageNumberPositionY = 0;
$struct = $this->object->getHeaderStruct();
$struct->setLogo($header->logo);
$struct->setLogoWidth($header->logoWidth);
$struct->setLogoPositionX($header->logoPositionX);
$struct->setLogoPositionY($header->logoPositionY);
$struct->setTitle($header->title);
$struct->setTitleFontSize($header->titleFontSize);
$struct->setTitleFontPositionX($header->titleFontPositionX);
$struct->setTitleFontPositionY($header->titleFontPositionY);
$struct->setPageNumber($header->pageNumber);
$struct->setPageNumberTitle($header->pageNumberTitle);
$struct->setPageNumberTotal($header->pageNumberTotal);
$struct->setPageNumberPositionX($header->pageNumberPositionX);
$struct->setPageNumberPositionY($header->pageNumberPositionY);
}
/**
* Setting data for footer configuration.
*/
private function setFooterData()
{
$footer = new stdClass();
$footer->logo = PATH_TRUNK . "/vendor/tecnickcom/tcpdf/examples/images/logo_example.jpg";
$footer->logoWidth = 15;
$footer->logoPositionX = 10;
$footer->logoPositionY = 0;
$footer->title = "Hola mundo como estas";
$footer->titleFontSize = 20;
$footer->titleFontPositionX = 0;
$footer->titleFontPositionY = 5;
$footer->pageNumber = true;
$footer->pageNumberTitle = "Pages";
$footer->pageNumberTotal = true;
$footer->pageNumberPositionX = 40;
$footer->pageNumberPositionY = 5;
$struct = $this->object->getFooterStruct();
$struct->setLogo($footer->logo);
$struct->setLogoWidth($footer->logoWidth);
$struct->setLogoPositionX($footer->logoPositionX);
$struct->setLogoPositionY($footer->logoPositionY);
$struct->setTitle($footer->title);
$struct->setTitleFontSize($footer->titleFontSize);
$struct->setTitleFontPositionX($footer->titleFontPositionX);
$struct->setTitleFontPositionY($footer->titleFontPositionY);
$struct->setPageNumber($footer->pageNumber);
$struct->setPageNumberTitle($footer->pageNumberTitle);
$struct->setPageNumberTotal($footer->pageNumberTotal);
$struct->setPageNumberPositionX($footer->pageNumberPositionX);
$struct->setPageNumberPositionY($footer->pageNumberPositionY);
}
/**
* This test the getHeaderStruct() method.
* @covers ProcessMaker\PDF\TCPDFHeaderFooter::getHeaderStruct()
* @test
*/
public function it_should_test_the_getHeaderStruct()
{
$result = $this->object->getHeaderStruct();
$this->assertNotNull($result);
$this->assertEquals(HeaderStruct::class, get_class($result));
}
/**
* This test the getFooterStruct() method.
* @covers ProcessMaker\PDF\TCPDFHeaderFooter::getFooterStruct()
* @test
*/
public function it_should_test_the_getFooterStruct()
{
$result = $this->object->getFooterStruct();
$this->assertNotNull($result);
$this->assertEquals(FooterStruct::class, get_class($result));
}
/**
* This test the Header() method override.
* @covers ProcessMaker\PDF\TCPDFHeaderFooter::Header()
* @covers ProcessMaker\PDF\TCPDFHeaderFooter::buildHeaderLogo()
* @covers ProcessMaker\PDF\TCPDFHeaderFooter::buildHeaderTitle()
* @covers ProcessMaker\PDF\TCPDFHeaderFooter::buildHeaderPageNumber()
* @test
*/
public function it_should_test_the_Header()
{
$this->object->AddPage();
$result = $this->object->Header();
$this->assertEmpty($result);
}
/**
* @covers ProcessMaker\PDF\TCPDFHeaderFooter::Footer()
* @covers ProcessMaker\PDF\TCPDFHeaderFooter::buildFooterLogo()
* @covers ProcessMaker\PDF\TCPDFHeaderFooter::buildFooterTitle()
* @covers ProcessMaker\PDF\TCPDFHeaderFooter::buildFooterPageNumber()
* @test
*/
public function it_should_test_the_Footer()
{
$this->object->AddPage();
$result = $this->object->Footer();
$this->assertEmpty($result);
}
}

View File

@@ -2,6 +2,7 @@
use Illuminate\Filesystem\Filesystem;
use ProcessMaker\Core\System;
use ProcessMaker\PDF\TCPDFHeaderFooter;
class OutputDocument extends BaseOutputDocument
{
@@ -879,7 +880,7 @@ class OutputDocument extends BaseOutputDocument
$content = str_replace("margin-left", "text-indent", $content);
// Instance the TCPDF library
$pdf = new TCPDF($orientation, PDF_UNIT, $media, true, 'UTF-8', false);
$pdf = new TCPDFHeaderFooter($orientation, PDF_UNIT, $media, true, 'UTF-8', false);
// Set document information
$pdf->SetCreator(PDF_CREATOR);
@@ -896,8 +897,10 @@ class OutputDocument extends BaseOutputDocument
$margins["bottom"] = ($margins["bottom"] >= 0) ? $margins["bottom"] : PDF_MARGIN_BOTTOM;
// Set margins configuration
$pdf->setPrintHeader(false);
$pdf->setPrintFooter(false);
$headerOptions = $this->setHeaderOptions($pdf);
$footerOptions = $this->setFooterOptions($pdf);
$pdf->setPrintHeader($headerOptions);
$pdf->setPrintFooter($footerOptions);
$pdf->SetLeftMargin($margins['left']);
$pdf->SetTopMargin($margins['top']);
$pdf->SetRightMargin($margins['right']);
@@ -1362,4 +1365,68 @@ class OutputDocument extends BaseOutputDocument
// Save the CSS file
file_put_contents(K_PATH_FONTS . 'fonts.css', $css);
}
/**
* Set and build if header options exist.
* @param TCPDFHeaderFooter $pdf
* @return bool
*/
private function setHeaderOptions(TCPDFHeaderFooter $pdf): bool
{
if (empty($this->out_doc_header)) {
return false;
}
$header = json_decode($this->out_doc_header);
$struct = $pdf->getHeaderStruct();
$struct->setLogo($header->logo);
$struct->setLogoWidth($header->logoWidth);
$struct->setLogoPositionX($header->logoPositionX);
$struct->setLogoPositionY($header->logoPositionY);
$struct->setTitle($header->title);
$struct->setTitleFontSize($header->titleFontSize);
$struct->setTitleFontPositionX($header->titleFontPositionX);
$struct->setTitleFontPositionY($header->titleFontPositionY);
$struct->setPageNumber($header->pageNumber);
$struct->setPageNumberTitle($header->pageNumberTitle);
$struct->setPageNumberTotal($header->pageNumberTotal);
$struct->setPageNumberPositionX($header->pageNumberPositionX);
$struct->setPageNumberPositionY($header->pageNumberPositionY);
return true;
}
/**
* Set and build if footer options exist.
* @param TCPDFHeaderFooter $pdf
* @return bool
*/
private function setFooterOptions(TCPDFHeaderFooter $pdf): bool
{
if (empty($this->out_doc_footer)) {
return false;
}
$footer = json_decode($this->out_doc_footer);
$struct = $pdf->getFooterStruct();
$struct->setLogo($footer->logo);
$struct->setLogoWidth($footer->logoWidth);
$struct->setLogoPositionX($footer->logoPositionX);
$struct->setLogoPositionY($footer->logoPositionY);
$struct->setTitle($footer->title);
$struct->setTitleFontSize($footer->titleFontSize);
$struct->setTitleFontPositionX($footer->titleFontPositionX);
$struct->setTitleFontPositionY($footer->titleFontPositionY);
$struct->setPageNumber($footer->pageNumber);
$struct->setPageNumberTitle($footer->pageNumberTitle);
$struct->setPageNumberTotal($footer->pageNumberTotal);
$struct->setPageNumberPositionX($footer->pageNumberPositionX);
$struct->setPageNumberPositionY($footer->pageNumberPositionY);
return true;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,11 @@
<?php
namespace ProcessMaker\PDF;
class FooterStruct
{
/**
* Using basic struct for footer properties.
*/
use BasicStruct;
}

View File

@@ -0,0 +1,11 @@
<?php
namespace ProcessMaker\PDF;
class HeaderStruct
{
/**
* Using basic struct for header properties.
*/
use BasicStruct;
}

View File

@@ -0,0 +1,242 @@
<?php
namespace ProcessMaker\PDF;
use TCPDF;
class TCPDFHeaderFooter extends TCPDF
{
/**
* Property for configure header element.
* @var HeaderStruct
*/
private $headerStruct;
/**
* Property for configure footer element.
* @var FooterStruct
*/
private $footerStruct;
/**
* Save the original margins configured in the page.
* @var array
*/
private $originalMargins;
/**
* Constructor of the class.
* @param string $orientation
* @param string $unit
* @param string $format
* @param bool $unicode
* @param string $encoding
* @param bool $diskcache
* @param bool $pdfa
*/
public function __construct($orientation = 'P', $unit = 'mm', $format = 'A4', $unicode = true, $encoding = 'UTF-8', $diskcache = false, $pdfa = false)
{
parent::__construct($orientation, $unit, $format, $unicode, $encoding, $diskcache, $pdfa);
$this->headerStruct = new HeaderStruct();
$this->footerStruct = new FooterStruct();
}
/**
* Destructor of the class.
*/
public function __destruct()
{
parent::__destruct();
}
/**
* Gets an object that contains the properties of the header.
* @return HeaderStruct
*/
public function getHeaderStruct(): HeaderStruct
{
return $this->headerStruct;
}
/**
* Gets an object that contains the properties of the footer.
* @return FooterStruct
*/
public function getFooterStruct(): FooterStruct
{
return $this->footerStruct;
}
/**
* This method is used to render the page header.
* This method has been overwritten.
*/
public function Header()
{
$heights = [];
$struct = $this->getHeaderStruct();
if (empty($this->originalMargins)) {
$this->originalMargins = $this->getMargins();
}
$margins = $this->originalMargins;
$this->buildHeaderLogo($struct, $margins, $heights);
$this->buildHeaderTitle($struct, $margins, $heights);
$this->buildHeaderPageNumber($struct, $margins, $heights);
//page adjust
$newHeight = max($heights);
$this->SetTopMargin($newHeight);
}
/**
* Build header logo.
* @param HeaderStruct $struct
* @param array $margins
* @param array $heights
* @return void
*/
private function buildHeaderLogo(HeaderStruct $struct, array $margins, array &$heights): void
{
$path = $struct->getLogo();
if (!file_exists($path)) {
return;
}
$pathinfo = pathinfo($path);
$imageSize = getimagesize($path);
$extension = $pathinfo['extension'];
$x = $struct->getLogoPositionX() + $margins['left'];
$y = $struct->getLogoPositionY() + $margins['top'];
$width = $struct->getLogoWidth();
$this->Image($path, $x, $y, $width, 0, $extension, '', '', false, 300, '', false, false, 0, false, false, false);
$newImageHeight = ($width * $imageSize[0] / $imageSize[1]);
$heights[] = $margins['top'] + $newImageHeight;
}
/**
* Build header title.
* @param HeaderStruct $struct
* @param array $margins
* @param array $heights
* @return void
*/
private function buildHeaderTitle(HeaderStruct $struct, array $margins, array &$heights): void
{
$string = $struct->getTitle();
$x = $struct->getTitleFontPositionX() + $margins['left'];
$y = $struct->getTitleFontPositionY() + $margins['top'];
$fontSize = $struct->getTitleFontSize();
$this->SetXY($x, $y);
$this->SetFont('helvetica', 'B', $fontSize);
$this->MultiCell(0, 0, $string, 0, 'L', false, 1, '', '', true, 0, false, true, 0, 'T', false);
$heights[] = $margins['top'] + ($this->getCellHeight($fontSize, false)) / 2;
}
/**
* Build header page number.
* @param HeaderStruct $struct
* @param array $margins
* @param array $heights
* @return void
*/
private function buildHeaderPageNumber(HeaderStruct $struct, array $margins, array &$heights): void
{
if ($struct->getPageNumber() === true) {
$pageString = empty($struct->getPageNumberTitle()) ? 'Page ' : $struct->getPageNumberTitle() . ' ';
$pageNumberTotal = $struct->getPageNumberTotal() === true ? ' / ' . $this->getAliasNbPages() : '';
$string = $pageString . $this->getAliasNumPage() . $pageNumberTotal;
$x = $struct->getPageNumberPositionX() + $margins['left'];
$y = $struct->getPageNumberPositionY() + $margins['top'];
$fontSize = 8;
$this->SetXY($x, $y);
$this->SetFont('helvetica', 'I', $fontSize);
$this->Cell(0, 0, $string, 0, 0, '', false, '', 0, false, 'T', 'M');
$heights[] = $margins['top'] + ($this->getCellHeight($fontSize, false)) / 2;
}
}
/**
* This method is used to render the page footer.
* This method has been overwritten.
*/
public function Footer()
{
$struct = $this->getFooterStruct();
if (empty($this->originalMargins)) {
$this->originalMargins = $this->getMargins();
}
$margins = $this->originalMargins;
//page adjust
$this->SetY(-1 * ($margins['bottom']));
$currentY = $this->GetY();
$this->buildFooterLogo($margins, $currentY, $struct);
$this->buildFooterTitle($margins, $currentY, $struct);
$this->buildFooterPageNumber($margins, $currentY, $struct);
}
/**
* Build footer logo.
* @param array $margins
* @param float $currentY
* @param HeaderStruct $struct
* @return void
*/
private function buildFooterLogo(array $margins, float $currentY, FooterStruct $struct): void
{
$path = $struct->getLogo();
if (!file_exists($path)) {
return;
}
$pathinfo = pathinfo($path);
$extension = $pathinfo['extension'];
$x = $struct->getLogoPositionX() + $margins['left'];
$y = $struct->getLogoPositionY() + $currentY;
$width = $struct->getLogoWidth();
$this->Image($path, $x, $y, $width, 0, $extension, '', '', false, 300, '', false, false, 0, false, false, false);
}
/**
* Build footer title.
* @param array $margins
* @param float $currentY
* @param HeaderStruct $struct
* @return void
*/
private function buildFooterTitle(array $margins, float $currentY, FooterStruct $struct): void
{
$string = $struct->getTitle();
$x = $struct->getTitleFontPositionX() + $margins['left'];
$y = $struct->getTitleFontPositionY() + $currentY;
$fontSize = $struct->getTitleFontSize();
$this->SetXY($x, $y);
$this->SetFont('helvetica', 'B', $fontSize);
$this->MultiCell(0, 0, $string, 0, 'L', false, 1, '', '', true, 0, false, true, 0, 'T', false);
}
/**
* Build footer page number.
* @param array $margins
* @param float $currentY
* @param HeaderStruct $struct
* @return void
*/
private function buildFooterPageNumber(array $margins, float $currentY, FooterStruct $struct): void
{
if ($struct->getPageNumber() === true) {
$pageString = empty($struct->getPageNumberTitle()) ? 'Page ' : $struct->getPageNumberTitle() . ' ';
$pageNumberTotal = $struct->getPageNumberTotal() === true ? ' / ' . $this->getAliasNbPages() : '';
$string = $pageString . $this->getAliasNumPage() . $pageNumberTotal;
$x = $struct->getPageNumberPositionX() + $margins['left'];
$y = $struct->getPageNumberPositionY() + $currentY;
$fontSize = 8;
$this->SetXY($x, $y);
$this->SetFont('helvetica', 'I', $fontSize);
$this->Cell(0, 0, $string, 0, 0, '', false, '', 0, false, 'T', 'M');
}
}
}