Untitled
unknown
plain_text
2 years ago
11 kB
8
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