Untitled
unknown
plain_text
2 years ago
11 kB
10
Indexable
public function processElementPlacementOnDoc(Deed $deed, Collection $deedDocuments): Fpdi
{
$pdf = new Fpdi('P');
foreach ($deedDocuments as $deedDocument) {
$deedElements = $this->getDeedElements($deed->id, $deedDocument->id);
$tempPdfFilePath = tempnam(sys_get_temp_dir(), 'deed_');
$tempPdfContent = file_get_contents($deedDocument->path);
file_put_contents($tempPdfFilePath, $tempPdfContent);
$pageCount = $pdf->setSourceFile($tempPdfFilePath);
for ($pageNumber = 1; $pageNumber <= $pageCount; $pageNumber++) {
$this->injectElementsOnPage($pdf, $deedElements, $pageNumber);
}
unlink($tempPdfFilePath);
}
return $pdf;
}
/**
* @return mixed
*/
protected function getDeedElements(int $deedId, int $deedDocumentId): Collection
{
return DeedElement::where([
'deed_id' => $deedId,
'deed_document_id' => $deedDocumentId,
])->get();
}
/**
* @throws GenericErrorException
* @throws PdfParserException
* @throws PdfReaderException
* @throws CrossReferenceException
* @throws FilterException
* @throws PdfTypeException
* @throws Exception
*/
private function injectElementsOnPage(Fpdi $pdf, Collection $deed_elements, int $pageNumber): void
{
$templateId = $pdf->importPage($pageNumber);
$size = $pdf->getTemplateSize($templateId);
$pdf->AddPage(Arr::get($size, 'orientation'), [Arr::get($size, 'width'), Arr::get($size, 'height')]);
$pdf->SetAutoPageBreak(0, 0);
$pdf->useTemplate($templateId, 0, 0, Arr::get($size, 'width'), Arr::get($size, 'height'), true);
$elementsOnPage = $this->pdfService->getCurrentPageElement($deed_elements->toArray(), $pageNumber);
foreach ($elementsOnPage as $element) {
$this->pdfService->addElementByType($pdf, ElementType::tryFrom(Arr::get($element, 'element_type')), $element);
}
}
public function download(string $modifiedFilePath): BinaryFileResponse
{
$response = new BinaryFileResponse($modifiedFilePath);
$response->headers->set('Content-Type', 'application/pdf');
$response->headers->set('Content-Disposition', 'attachment; filename="modified_deed.pdf"');
return $response;
}
public function getCurrentPageElement(array $elements, int $pageNumber): array
{
return array_filter($elements, function ($element) use ($pageNumber) {
$element = $element['response_meta'];
return $element['page'] == $pageNumber;
});
}
/**
* @throws Exception
*/
public function addElementByType(Fpdi $pdf, ElementType $element_type, array $element_meta): void
{
$element_data = Arr::get($element_meta, 'response_meta');
$x = Arr::get($element_data, 'cord.x');
$y = Arr::get($element_data, 'cord.y');
$width = Arr::get($element_data, 'area.width', '');
$height = Arr::get($element_data, 'area.height', '');
$element = new Element($pdf);
match ($element_type) {
ElementType::TEXT,ElementType::DROPDOWN, ElementType::DATE => $element->addTextElement($x, $y, $width, $height, Arr::get($element_data, 'value'), Arr::get($element_data, 'font_family'), Arr::get($element_data, 'font_size')),
ElementType::STAMP,ElementType::INITIAL, ElementType::SIGNATURE => $element->addImageElement($x, $y, $width, $height, $element_data),
ElementType::CHECKBOX => $element->addCheckBoxes($x, $y, Arr::get($element_data, 'is_checked')),
ElementType::RADIO => $element->addRadioButtons($x, $y, Arr::get($element_data, 'options')),
default => throw new Exception('Invalid element type', code: Response::HTTP_BAD_REQUEST)
};
}
<?php
namespace App\Services\Pdf;
use App\DTO\Coordinate;
use App\DTO\Dimension;
use App\Enums\SignatureType;
use Illuminate\Support\Arr;
use setasign\Fpdi\Fpdi;
class Element
{
private Fpdi $pdf;
private string $font_family = 'Arial';
private int $font_size = 12;
public function __construct(Fpdi $pdf)
{
$this->pdf = $pdf;
}
public function addImageElement(int $x, int $y, float $width, float $height, array $element_data): void
{
// if it is text type signature and initial then call textElement
if (Arr::get($element_data, 'type') === SignatureType::Text->value) {
// Call addTextElement and return
$this->addTextElement($x, $y, $width, $height, Arr::get($element_data, 'value'), Arr::get($element_data, 'font_family') ?? $this->font_family, Arr::get($element_data, 'font_size') ?? $this->font_size);
return;
}
$coordinate = $this->calculateCoordinates($x, $y);
$dimension = $this->calculateDimension($height, $width);
// Assuming $img_src needs to be extracted from $element_data
$img_src = Arr::get($element_data, 'img_src', ''); // Adjust this based on your actual data structure
$this->pdf->Image(
$img_src,
$coordinate->x,
$coordinate->y,
$dimension->width,
$dimension->height
);
}
public function addTextElement(float $x, float $y, float $width, float $height, string $text, ?string $font_family, ?int $font_size): void
{
$coordinate = $this->calculateCoordinates($x, $y);
$dimension = $this->calculateDimension($height, $width);
$this->setPdfProperties($font_family, $font_size);
$this->pdf->SetXY($coordinate->x, $coordinate->y);
$this->pdf->MultiCell(
$dimension->width,
$dimension->height,
$text,
1,
'C',
false
);
}
private function calculateCoordinates(float $x, float $y): Coordinate
{
$x = $x * 25.4 / 72;
$y = $y * 25.4 / 72;
return make_dto(Coordinate::class, ['x' => $x, 'y' => $y]);
}
/**
* @return float[]
*/
private function calculateDimension(float $height, float $width): Dimension
{
$height = $height * 25.4 / 72;
$width = $width * 25.4 / 72;
return make_dto(Dimension::class, ['width' => $width, 'height' => $height]);
}
private function setPdfProperties(?string $font_family, ?int $font_size): void
{
$this->pdf->SetFont($font_family ?? $this->font_family, '', $font_size ?? $this->font_size);
// Additional properties specific to elements can be set here if necessary
}
// public function addCheckBoxes(int $x, int $y, bool $is_checked): void
// {
// $coordinate = $this->calculateCoordinates($x, $y);
//
// $checkboxHeight = 5; // Define the reduced height of the checkbox
// $checkboxWidth = 5; // Define the reduced width of the checkbox
// $checkboxSpacing = 5; // Define the spacing between checkboxes
// $textOffsetY = 3.5; // Adjust the Y-axis positioning for the text
//
// $y = $coordinate->y;
//
// // Draw a smaller checkbox at each option's specified coordinates
// $this->pdf->Rect($coordinate->x, $y, $checkboxWidth, $checkboxHeight);
//// $this->pdf->Text($coordinate->x + $checkboxWidth + 2, $y + $textOffsetY, ''); // Add option label with adjusted Y-axis
//
// $y += $checkboxHeight + $checkboxSpacing; // Move to the next line for the next checkbox
//
// }
public function addCheckBoxes(int $x, int $y, bool $is_checked, float $width = 20, float $height = 20): void
{
$coordinate = $this->calculateCoordinates($x, $y);
$checkboxWidth = $width * 25.4 / 72;
$checkboxHeight = $height * 25.4 / 72;
// Draw a checkbox at the specified coordinates
$this->pdf->Rect($coordinate->x, $coordinate->y, $checkboxWidth, $checkboxHeight);
// If $is_checked is true, draw a proportional checkmark inside the checkbox
if ($is_checked) {
$this->drawProportionalCheckmark($coordinate->x, $coordinate->y, $checkboxWidth, $checkboxHeight);
}
}
private function drawProportionalCheckmark(float $x, float $y, float $width, float $height): void
{
// Calculate checkmark size and position
$checkSize = min($width, $height) * 0.8; // Adjust the proportion as needed
$xCenter = $x + ($width - $checkSize) / 2;
$yCenter = $y + ($height - $checkSize) / 2;
// Calculate checkmark coordinates
$x1 = $xCenter + 0.2 * $checkSize;
$y1 = $yCenter + 0.5 * $checkSize;
$x2 = $xCenter + 0.4 * $checkSize;
$y2 = $yCenter + 0.7 * $checkSize;
$x3 = $xCenter + 0.8 * $checkSize;
$y3 = $yCenter + 0.3 * $checkSize;
// Draw the checkmark
$this->pdf->Line($x1, $y1, $x2, $y2);
$this->pdf->Line($x2, $y2, $x3, $y3);
}
public function addRadioButtons(int $x, int $y, array $options): void
{
$coordinate = $this->calculateCoordinates($x, $y);
$radioDiameter = 5; // Define the diameter of the radio button
$radioSpacing = 7; // Define the spacing between radio buttons
$textOffsetX = 1; // Adjust this value to align text with the radio button horizontally
$textOffsetY = 1; // Adjust this value to align text with the radio button vertically
$y = $coordinate->y;
foreach ($options as $option) {
// Draw the circle for the radio button
$this->drawRadioCircle($coordinate->x, $y, $radioDiameter);
// Add text for the radio button option
$this->pdf->Text(x: $coordinate->x + $radioDiameter + $textOffsetX, y: $y + $textOffsetY, txt: $option);
$y += $radioSpacing; // Move to the next line for the next radio button
}
}
private function drawRadioCircle(int $x, int $y, int $diameter): void
{
$segments = 360; // Number of segments to approximate a circle
for ($i = 0; $i < $segments; $i++) {
$angle = ($i / $segments) * 2 * M_PI;
$nextAngle = (($i + 1) / $segments) * 2 * M_PI;
$x1 = $x + ($diameter / 2 * cos($angle));
$y1 = $y + ($diameter / 2 * sin($angle));
$x2 = $x + ($diameter / 2 * cos($nextAngle));
$y2 = $y + ($diameter / 2 * sin($nextAngle));
$this->pdf->Line($x1, $y1, $x2, $y2); // Draw a line segment
}
}
}
Editor is loading...
Leave a Comment