chore: remove deprecations

This commit is contained in:
Björn Fromme
2025-07-08 15:06:44 +02:00
parent 8e27cc990b
commit 70e477073b
7 changed files with 123 additions and 26 deletions
+1
View File
@@ -20,6 +20,7 @@ add('shared_files', [
// Rsync options, mainly files/dirs to exclude
$rsyncOptions = [
'exclude' => [
'.cursor',
'.idea',
'.vscode',
'.DS_Store',
+5 -5
View File
@@ -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);
+3 -3
View File
@@ -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);
+8 -8
View File
@@ -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
View File
@@ -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');
}
}
+2 -1
View File
@@ -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();
+4 -2
View File
@@ -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);