chore: remove deprecations
This commit is contained in:
@@ -20,6 +20,7 @@ add('shared_files', [
|
||||
// Rsync options, mainly files/dirs to exclude
|
||||
$rsyncOptions = [
|
||||
'exclude' => [
|
||||
'.cursor',
|
||||
'.idea',
|
||||
'.vscode',
|
||||
'.DS_Store',
|
||||
|
||||
@@ -27,16 +27,16 @@ class ContractRenderer extends AbstractPdfRenderer
|
||||
|
||||
// Current date
|
||||
$date = (new \DateTimeImmutable())->format('d.m.Y');
|
||||
$pdf->Text(164,43, utf8_decode($date));
|
||||
$pdf->Text(164,43, $pdf->encodeString($date));
|
||||
|
||||
// Name
|
||||
$pdf->Text(45,67.75, utf8_decode($teamer));
|
||||
$pdf->Text(45,67.75, $pdf->encodeString($teamer));
|
||||
|
||||
// Address
|
||||
$pdf->Text(45,77.75, utf8_decode($teamer->getAddress()));
|
||||
$pdf->Text(45,77.75, $pdf->encodeString($teamer->getAddress()));
|
||||
|
||||
// Jobprofile
|
||||
$pdf->Text(21,104.5, utf8_decode($assignment->getJobProfile()->getName()));
|
||||
$pdf->Text(21,104.5, $pdf->encodeString($assignment->getJobProfile()->getName()));
|
||||
|
||||
// Period
|
||||
$dateFrom = $assignment->getEffectivePeriod()->start->format('d.m.Y');
|
||||
@@ -45,7 +45,7 @@ class ContractRenderer extends AbstractPdfRenderer
|
||||
$pdf->Text(57,113, $period);
|
||||
|
||||
// Destination
|
||||
$pdf->Text(57,121.5, utf8_decode(sprintf('%s, %s', $destination->getProduct(), $destination->getHotel())));
|
||||
$pdf->Text(57,121.5, $pdf->encodeString(sprintf('%s, %s', $destination->getProduct(), $destination->getHotel())));
|
||||
|
||||
// Set pointer to last page to include all
|
||||
$pdf->setPage($numberOfPages);
|
||||
|
||||
@@ -39,19 +39,19 @@ class InvoiceApprover extends AbstractPdfRenderer
|
||||
// Cost unit job profile
|
||||
if (null !== $costUnit = $assignment->getJobProfile()->getCostUnit()) {
|
||||
$pdf->SetFont('Arial', '', 11);
|
||||
$pdf->Text(20,20, utf8_decode('Kostenstelle 1: '.$costUnit));
|
||||
$pdf->Text(20,20, $pdf->encodeString('Kostenstelle 1: '.$costUnit));
|
||||
}
|
||||
|
||||
// Cost unit destination/hotel
|
||||
if (null !== $costUnit = $assignment->getDestination()->getCostUnit()) {
|
||||
$pdf->SetFont('Arial', '', 11);
|
||||
$pdf->Text(20,25, utf8_decode('Kostenstelle 2: '.$costUnit));
|
||||
$pdf->Text(20,25, $pdf->encodeString('Kostenstelle 2: '.$costUnit));
|
||||
}
|
||||
|
||||
// Approval
|
||||
$pdf->SetFont('Arial', '', 11);
|
||||
$pdf->SetTextColor(0, 128, 0);
|
||||
$pdf->Text(20,30, utf8_decode('geprüft: '.$invoice->getApprovedBy()));
|
||||
$pdf->Text(20,30, $pdf->encodeString('geprüft: '.$invoice->getApprovedBy()));
|
||||
|
||||
$this->createBackup($filepath);
|
||||
|
||||
|
||||
@@ -26,15 +26,15 @@ class InvoiceRenderer extends AbstractPdfRenderer
|
||||
$assignment = $disposition->getAssignment();
|
||||
|
||||
// Name
|
||||
$pdf->Text(135,28.5, utf8_decode($teamer->getFullName()));
|
||||
$pdf->Text(135,28.5, $pdf->encodeString($teamer->getFullName()));
|
||||
|
||||
// Address
|
||||
$address = $teamer->getAddress();
|
||||
$pdf->Text(135,39, utf8_decode($address->getStreet()));
|
||||
$pdf->Text(135,51, utf8_decode($address->getPostCode(). ' '.$address->getCity()));
|
||||
$pdf->Text(135,39, $pdf->encodeString($address->getStreet()));
|
||||
$pdf->Text(135,51, $pdf->encodeString($address->getPostCode(). ' '.$address->getCity()));
|
||||
|
||||
// Tax ID
|
||||
$pdf->Text(144,62, utf8_decode($teamer->getTaxId()));
|
||||
$pdf->Text(144,62, $pdf->encodeString($teamer->getTaxId()));
|
||||
|
||||
// Invoice number
|
||||
$pdf->SetFont('Arial', '', 12);
|
||||
@@ -45,14 +45,14 @@ class InvoiceRenderer extends AbstractPdfRenderer
|
||||
|
||||
// Bank account
|
||||
$bankAccount = $teamer->getBankAccount();
|
||||
$pdf->Text(36,233.5, utf8_decode($bankAccount->getIban()));
|
||||
$pdf->Text(36,241, utf8_decode($bankAccount->getBic()));
|
||||
$pdf->Text(36,248.5, utf8_decode($bankAccount->getBank()));
|
||||
$pdf->Text(36,233.5, $pdf->encodeString($bankAccount->getIban()));
|
||||
$pdf->Text(36,241, $pdf->encodeString($bankAccount->getBic()));
|
||||
$pdf->Text(36,248.5, $pdf->encodeString($bankAccount->getBank()));
|
||||
|
||||
|
||||
// Current date
|
||||
$date = (new \DateTimeImmutable())->format('d.m.Y');
|
||||
$pdf->Text(38,264, utf8_decode($date));
|
||||
$pdf->Text(38,264, $pdf->encodeString($date));
|
||||
|
||||
return $pdf;
|
||||
}
|
||||
|
||||
+100
-7
@@ -7,13 +7,18 @@ use setasign\Fpdi\PdfParser\PdfParserException;
|
||||
use setasign\Fpdi\PdfReader\PdfReaderException;
|
||||
|
||||
/**
|
||||
* Functionality to center image on PDF page adapted from
|
||||
* https://gist.github.com/benshimmin/4088493?permalink_comment_id=2398423#gistcomment-2398423.
|
||||
* Extended PDF manipulation class providing image centering and PDF merging capabilities.
|
||||
*
|
||||
* Functionality to append pages from external PDF file adapted from
|
||||
* https://stackoverflow.com/questions/22404601/merging-pdf-files-with-php-fpdi/29552294#29552294
|
||||
* This class extends FPDI to provide enhanced PDF functionality including automatic
|
||||
* image centering on pages, PDF file merging, and proper UTF-8 string encoding for
|
||||
* FPDF compatibility. It handles image resizing to fit within specified containers
|
||||
* while maintaining aspect ratios and provides error handling for PDF parsing issues.
|
||||
*
|
||||
* Requires commercial FPDI PDF-Parser addon to parse compressed PDF files.
|
||||
* The class implements functionality adapted from external sources for image centering
|
||||
* and PDF merging, with additional error handling and UTF-8 support for German text.
|
||||
*
|
||||
* @see https://gist.github.com/benshimmin/4088493?permalink_comment_id=2398423#gistcomment-2398423 Image centering functionality
|
||||
* @see https://stackoverflow.com/questions/22404601/merging-pdf-files-with-php-fpdi/29552294#29552294 PDF merging functionality
|
||||
*/
|
||||
class Pdf extends Fpdi
|
||||
{
|
||||
@@ -24,11 +29,33 @@ class Pdf extends Fpdi
|
||||
public const MARGIN_X = 10;
|
||||
public const MARGIN_Y = 10;
|
||||
|
||||
/**
|
||||
* Sets the current page number for PDF operations.
|
||||
*
|
||||
* Allows manual control of the current page position within the PDF document.
|
||||
* This is useful for positioning operations or when working with specific pages.
|
||||
*
|
||||
* @param int $pageNumber The page number to set as current
|
||||
*/
|
||||
public function setPage(int $pageNumber): void
|
||||
{
|
||||
$this->page = $pageNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends all pages from an external PDF file to the current document.
|
||||
*
|
||||
* Imports and merges all pages from a source PDF file into the current document.
|
||||
* Each page is imported with its original dimensions and orientation. If parsing
|
||||
* fails, a fallback page with error information is added instead.
|
||||
*
|
||||
* @param string $sourceFile Path to the source PDF file to append
|
||||
*
|
||||
* @return int The number of pages successfully appended, or 1 if an error occurred
|
||||
*
|
||||
* @throws PdfParserException When the source PDF cannot be parsed
|
||||
* @throws PdfReaderException When the source PDF cannot be read
|
||||
*/
|
||||
public function appendPdf(string $sourceFile): int
|
||||
{
|
||||
try {
|
||||
@@ -50,6 +77,16 @@ class Pdf extends Fpdi
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new page with a centered image and optional title.
|
||||
*
|
||||
* Creates a new page and places an image in the center with proper margins.
|
||||
* The image is automatically resized to fit within the available space while
|
||||
* maintaining its aspect ratio. An optional title can be added at the top.
|
||||
*
|
||||
* @param string $sourceFile Path to the image file to display
|
||||
* @param string $pageTitle Optional title text to display at the top of the page
|
||||
*/
|
||||
public function appendImage(string $sourceFile, string $pageTitle = ''): void
|
||||
{
|
||||
$this->AddPage();
|
||||
@@ -65,10 +102,23 @@ class Pdf extends Fpdi
|
||||
|
||||
if ($pageTitle) {
|
||||
$this->SetFont('Arial', '', 10);
|
||||
$this->Text(self::MARGIN_X, self::MARGIN_Y, utf8_decode($pageTitle));
|
||||
$this->Text(self::MARGIN_X, self::MARGIN_Y, $this->encodeString($pageTitle));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Centers an image within specified container dimensions.
|
||||
*
|
||||
* Calculates the optimal size for an image to fit within the given container
|
||||
* while maintaining aspect ratio, then positions it in the center. Handles
|
||||
* image loading errors gracefully by displaying an error message.
|
||||
*
|
||||
* @param string $imgPath Path to the image file
|
||||
* @param int $x X-coordinate of the container's top-left corner
|
||||
* @param int $y Y-coordinate of the container's top-left corner
|
||||
* @param int $containerWidth Width of the container area
|
||||
* @param int $containerHeight Height of the container area
|
||||
*/
|
||||
public function centerImage(
|
||||
string $imgPath,
|
||||
int $x = 0,
|
||||
@@ -92,16 +142,43 @@ class Pdf extends Fpdi
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts pixel values to millimeters based on DPI setting.
|
||||
*
|
||||
* @param mixed $val Pixel value to convert
|
||||
*
|
||||
* @return int Millimeter value rounded to nearest integer
|
||||
*/
|
||||
protected function pixelsToMm($val): int
|
||||
{
|
||||
return (int) (round($val * $this::MM_IN_INCH / self::DPI));
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts millimeter values to pixels based on DPI setting.
|
||||
*
|
||||
* @param mixed $val Millimeter value to convert
|
||||
*
|
||||
* @return int Pixel value rounded to nearest integer
|
||||
*/
|
||||
protected function mmToPixels($val): int
|
||||
{
|
||||
return (int) (round($this::DPI * $val / self::MM_IN_INCH));
|
||||
return (int) (round($this::DPI * $val / $this::MM_IN_INCH));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates optimal image dimensions to fit within specified maximum bounds.
|
||||
*
|
||||
* Analyzes the original image dimensions and calculates the largest possible
|
||||
* size that fits within the maximum width and height while preserving the
|
||||
* aspect ratio. Returns dimensions in millimeters for PDF placement.
|
||||
*
|
||||
* @param string $imgPath Path to the image file
|
||||
* @param int $maxWidth Maximum allowed width in millimeters
|
||||
* @param int $maxHeight Maximum allowed height in millimeters
|
||||
*
|
||||
* @return array Array containing [width, height] in millimeters
|
||||
*/
|
||||
protected function resizeToFit(
|
||||
string $imgPath,
|
||||
int $maxWidth = self::A4_WIDTH,
|
||||
@@ -117,4 +194,20 @@ class Pdf extends Fpdi
|
||||
$this->pixelsToMm($scale * $height),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts UTF-8 string to ISO-8859-1 for FPDF compatibility.
|
||||
*
|
||||
* FPDF has limited Unicode support and works best with ISO-8859-1 encoding.
|
||||
* This method ensures proper character encoding for German umlauts and other
|
||||
* special characters when adding text to PDF documents.
|
||||
*
|
||||
* @param string $string UTF-8 encoded string to convert
|
||||
*
|
||||
* @return string ISO-8859-1 encoded string suitable for FPDF
|
||||
*/
|
||||
public function encodeString(string $string): string
|
||||
{
|
||||
return mb_convert_encoding($string, 'ISO-8859-1', 'UTF-8');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,8 @@ class ContractRendererTest extends WebTestCase
|
||||
public function testRendersContract(): void
|
||||
{
|
||||
$projectDir = static::getContainer()->getParameter('kernel.project_dir');
|
||||
$translator = $this->createMock(TranslatorInterface::class);
|
||||
/** @var TranslatorInterface $translator */
|
||||
$translator = static::getContainer()->get(TranslatorInterface::class);
|
||||
$renderer = new ContractRenderer($translator, ['project_dir' => $projectDir]);
|
||||
|
||||
$address = new Address();
|
||||
|
||||
@@ -25,6 +25,7 @@ class InvoiceRendererTest extends WebTestCase
|
||||
{
|
||||
$projectDir = static::getContainer()->getParameter('kernel.project_dir');
|
||||
$translator = $this->createMock(TranslatorInterface::class);
|
||||
/** @var TranslatorInterface $translator */
|
||||
$renderer = new InvoiceRenderer($translator, ['project_dir' => $projectDir]);
|
||||
|
||||
$address = new Address();
|
||||
@@ -93,19 +94,20 @@ class InvoiceRendererTest extends WebTestCase
|
||||
$pdf = $renderer->render($disposition);
|
||||
$this->assertInstanceOf(Pdf::class, $pdf);
|
||||
|
||||
$pdf->Output('F', $projectDir.'/uploads/invoice/Honorarnote.pdf');
|
||||
$pdf->Output('F', $projectDir.'/uploads/invoice/a/abcdef0123456789.pdf');
|
||||
|
||||
$invoice = new Upload();
|
||||
$invoice
|
||||
->setType(Upload::TYPE_INVOICE)
|
||||
->setMimeType('application/pdf')
|
||||
->setFilename('Honorarnote.pdf')
|
||||
->setFilename('abcdef0123456789.pdf')
|
||||
->setApprovedBy('FOO')
|
||||
->setApprovedAt(new \DateTimeImmutable())
|
||||
->setStatus(Upload::STATUS_PAID)
|
||||
;
|
||||
$disposition->addDocument($invoice);
|
||||
|
||||
/** @var TranslatorInterface $translator */
|
||||
$approver = new InvoiceApprover($translator, ['project_dir' => $projectDir]);
|
||||
$pdf = $approver->render($disposition);
|
||||
$this->assertInstanceOf(Pdf::class, $pdf);
|
||||
|
||||
Reference in New Issue
Block a user