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
105 lines
3.7 KiB
PHP
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']));
|
|
}
|
|
}
|