Files
hoshpoint-backend/app/Services/TemplateFillService.php
soheil khaledabadi ae974c2afa feat: add ApiResponse trait for standardized API responses
chore: update composer dependencies to include phppresentation

chore: update composer.lock after adding phppresentation

feat: create categories migration for category management

feat: create templates migration for template storage

feat: create template generations migration for tracking template usage

feat: create template keys migration for template customization

feat: create notifications migration for user notifications

feat: update API routes for categories, templates, and user profile management

docs: update API documentation to include new endpoints for profile and wallet
2026-07-07 01:03:12 +03:30

105 lines
3.7 KiB
PHP

<?php
namespace App\Services;
use App\Enums\TemplateKeyType;
use App\Models\TemplateGeneration;
use Illuminate\Support\Facades\Storage;
use PhpOffice\PhpPresentation\IOFactory;
use PhpOffice\PhpPresentation\PhpPresentation;
use PhpOffice\PhpPresentation\Shape\Drawing\File as FileDrawing;
use PhpOffice\PhpPresentation\Shape\Drawing\Gd as GdDrawing;
use PhpOffice\PhpPresentation\Shape\RichText;
use RuntimeException;
class TemplateFillService
{
public function fill(TemplateGeneration $generation): string
{
$template = $generation->template;
$sourcePath = Storage::disk('local')->path($template->file_path);
$presentation = IOFactory::load($sourcePath);
$values = $generation->values ?? [];
foreach ($template->keys as $key) {
if (! array_key_exists($key->key, $values)) {
continue;
}
match ($key->type) {
TemplateKeyType::Text => $this->fillText($presentation, $key->key, (string) $values[$key->key]),
TemplateKeyType::Image => $this->fillImage($presentation, $key->shape_name, Storage::disk('local')->path($values[$key->key])),
TemplateKeyType::Chart => throw new RuntimeException('پرکردن کلید از نوع چارت هنوز پشتیبانی نمی‌شود.'),
};
}
$outputRelativePath = 'templates/generations/'.$generation->uuid.'.pptx';
$outputAbsolutePath = Storage::disk('local')->path($outputRelativePath);
Storage::disk('local')->makeDirectory('templates/generations');
$writer = IOFactory::createWriter($presentation, 'PowerPoint2007');
$writer->save($outputAbsolutePath);
return $outputRelativePath;
}
private function fillText(PhpPresentation $presentation, string $key, string $value): void
{
$placeholder = '{{'.$key.'}}';
foreach ($presentation->getAllSlides() as $slide) {
foreach ($slide->getShapeCollection() as $shape) {
if (! $shape instanceof RichText) {
continue;
}
foreach ($shape->getParagraphs() as $paragraph) {
foreach ($paragraph->getRichTextElements() as $element) {
if (str_contains($element->getText(), $placeholder)) {
$element->setText(str_replace($placeholder, $value, $element->getText()));
}
}
}
}
}
}
private function fillImage(PhpPresentation $presentation, ?string $shapeName, string $imagePath): void
{
if ($shapeName === null || $shapeName === '') {
return;
}
foreach ($presentation->getAllSlides() as $slide) {
foreach ($slide->getShapeCollection() as $shape) {
if ($shape->getName() !== $shapeName) {
continue;
}
if ($shape instanceof GdDrawing) {
$this->replaceGdImage($shape, $imagePath);
} elseif ($shape instanceof FileDrawing) {
$shape->setPath($imagePath);
}
}
}
}
private function replaceGdImage(GdDrawing $shape, string $imagePath): void
{
$info = getimagesize($imagePath);
$image = imagecreatefromstring(file_get_contents($imagePath));
if ($info === false || $image === false) {
throw new RuntimeException('فایل تصویر ارسالی معتبر نیست.');
}
$shape->setImageResource($image);
$shape->setMimeType($info['mime']);
$shape->setRenderingFunction(str_replace('/', '', $info['mime']));
}
}