#134 - fill users data for resume #144
							
								
								
									
										140
									
								
								app/Domain/ResumeGenerator.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								app/Domain/ResumeGenerator.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | declare(strict_types=1); | ||||||
|  |  | ||||||
|  | namespace Toby\Domain; | ||||||
|  |  | ||||||
|  | use Illuminate\Support\Carbon; | ||||||
|  | use Illuminate\Support\Collection; | ||||||
|  | use Illuminate\Support\Str; | ||||||
|  | use PhpOffice\PhpWord\TemplateProcessor; | ||||||
|  | use Toby\Eloquent\Models\Resume; | ||||||
|  |  | ||||||
|  | class ResumeGenerator | ||||||
|  | { | ||||||
|  |     public function generate(Resume $resume): string | ||||||
|  |     { | ||||||
|  |         $uid = Str::uuid(); | ||||||
|  |  | ||||||
|  |         $path = storage_path("${uid}.docx"); | ||||||
|  |  | ||||||
|  |         $processor = new TemplateProcessor($this->getTemplate()); | ||||||
|  |  | ||||||
|  |         $processor->setValue("id", $resume->id); | ||||||
|  |         $processor->setValue("name", $resume->user ? $resume->user->profile->full_name : $resume->name); | ||||||
|  |  | ||||||
|  |         $this->fillTechnologies($processor, $resume); | ||||||
|  |         $this->fillLanguages($processor, $resume); | ||||||
|  |         $this->fillEducation($processor, $resume); | ||||||
|  |         $this->fillProjects($processor, $resume); | ||||||
|  |  | ||||||
|  |         $processor->saveAs($path); | ||||||
|  |  | ||||||
|  |         return $path; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     public function getTemplate(): string | ||||||
|  |     { | ||||||
|  |         return resource_path("views/docx/resume_eng.docx"); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function fillTechnologies(TemplateProcessor $processor, Resume $resume): void | ||||||
|  |     { | ||||||
|  |         if ($resume->technologies->count() <= 0) { | ||||||
|  |             $processor->deleteBlock("technologies"); | ||||||
|  |  | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $processor->cloneBlock("technologies", 0, true, false, $this->getTechnologies($resume)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     protected function fillLanguages(TemplateProcessor $processor, Resume $resume): void | ||||||
|  |     { | ||||||
|  |         if ($resume->education->count() <= 0) { | ||||||
|  |             $processor->deleteBlock("languages"); | ||||||
|  |  | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $processor->cloneBlock("languages", 0, true, false, $this->getLanguages($resume)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function fillEducation(TemplateProcessor $processor, Resume $resume): void | ||||||
|  |     { | ||||||
|  |         if ($resume->education->count() <= 0) { | ||||||
|  |             $processor->deleteBlock("education"); | ||||||
|  |  | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $processor->cloneBlock("education", 0, true, false, $this->getEducation($resume)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function fillProjects(TemplateProcessor $processor, Resume $resume): void | ||||||
|  |     { | ||||||
|  |         if ($resume->projects->count() <= 0) { | ||||||
|  |             $processor->deleteBlock("projects"); | ||||||
|  |  | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |  | ||||||
|  |         $processor->cloneBlock("projects", $resume->projects->count(), true, true); | ||||||
|  |  | ||||||
|  |         foreach ($resume->projects as $index => $project) { | ||||||
|  |             $index += 1; | ||||||
|  |             $processor->setValues($this->getProject($project, $index)); | ||||||
|  |  | ||||||
|  |             $processor->cloneBlock("project_technologies#{$index}", 0, true, false, $this->getProjectTechnologies($project, $index)); | ||||||
|  |  | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function getProject(array $project, int $index): array | ||||||
|  |     { | ||||||
|  |         return [ | ||||||
|  |             "index#{$index}" => $index, | ||||||
|  |             "start_date#{$index}" => Carbon::create($project["startDate"])->toDisplayString(), | ||||||
|  |             "end_date#{$index}" => Carbon::create($project["endDate"])->toDisplayString(), | ||||||
|  |             "description#{$index}" => $project["description"], | ||||||
|  |             "tasks#{$index}" => $project["tasks"], | ||||||
|  |         ]; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function getProjectTechnologies(array $project, int $index): array | ||||||
|  |     { | ||||||
|  |         $technologies = new Collection($project["technologies"] ?? []); | ||||||
|  |  | ||||||
|  |         return $technologies->map(fn(string $name) => [ | ||||||
|  |            "technology#{$index}" => $name, | ||||||
|  |         ])->all(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function getTechnologies(Resume $resume): array | ||||||
|  |     { | ||||||
|  |         return $resume->technologies->map(fn(array $technology): array => [ | ||||||
|  |             "technology_name" => $technology["name"], | ||||||
|  |             "technology_level" => $technology["level"], | ||||||
|  |         ])->all(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function getLanguages(Resume $resume): array | ||||||
|  |     { | ||||||
|  |         return $resume->languages->map(fn(array $language): array => [ | ||||||
|  |             "language_name" => $language["name"], | ||||||
|  |             "language_level" => $language["level"], | ||||||
|  |         ])->all(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     protected function getEducation(Resume $resume): array | ||||||
|  |     { | ||||||
|  |         return $resume->education->map(fn(array $project, int $index): array => [ | ||||||
|  |             "start_date" => Carbon::create($project["startDate"])->toDisplayString(), | ||||||
|  |             "end_date" => Carbon::create($project["endDate"])->toDisplayString(), | ||||||
|  |             "school" => $project["school"], | ||||||
|  |             "field_of_study" => $project["fieldOfStudy"], | ||||||
|  |             "degree" => $project["degree"], | ||||||
|  |         ])->all(); | ||||||
|  |     } | ||||||
|  | } | ||||||
| @@ -6,6 +6,8 @@ namespace Toby\Infrastructure\Http\Controllers; | |||||||
|  |  | ||||||
| use Illuminate\Http\RedirectResponse; | use Illuminate\Http\RedirectResponse; | ||||||
| use Inertia\Response; | use Inertia\Response; | ||||||
|  | use Symfony\Component\HttpFoundation\BinaryFileResponse as BinaryFileResponseAlias; | ||||||
|  | use Toby\Domain\ResumeGenerator; | ||||||
| use Toby\Eloquent\Models\Resume; | use Toby\Eloquent\Models\Resume; | ||||||
| use Toby\Eloquent\Models\Technology; | use Toby\Eloquent\Models\Technology; | ||||||
| use Toby\Eloquent\Models\User; | use Toby\Eloquent\Models\User; | ||||||
| @@ -39,6 +41,15 @@ class ResumeController extends Controller | |||||||
|         ]); |         ]); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     public function show(Resume $resume, ResumeGenerator $generator): BinaryFileResponseAlias | ||||||
|  |     { | ||||||
|  |         $path = $generator->generate($resume); | ||||||
|  |  | ||||||
|  |         return response() | ||||||
|  |             ->download($path, "resume-{$resume->id}.docx") | ||||||
|  |             ->deleteFileAfterSend(); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     public function store(ResumeRequest $request): RedirectResponse |     public function store(ResumeRequest $request): RedirectResponse | ||||||
|     { |     { | ||||||
|         $resume = new Resume(); |         $resume = new Resume(); | ||||||
|   | |||||||
| @@ -19,6 +19,7 @@ | |||||||
|         "laravel/telescope": "^4.6", |         "laravel/telescope": "^4.6", | ||||||
|         "laravel/tinker": "^2.5", |         "laravel/tinker": "^2.5", | ||||||
|         "maatwebsite/excel": "^3.1", |         "maatwebsite/excel": "^3.1", | ||||||
|  |         "phpoffice/phpword": "^0.18.3", | ||||||
|         "rackbeat/laravel-ui-avatars": "^1.0", |         "rackbeat/laravel-ui-avatars": "^1.0", | ||||||
|         "spatie/laravel-google-calendar": "^3.5", |         "spatie/laravel-google-calendar": "^3.5", | ||||||
|         "spatie/laravel-model-states": "^2.1" |         "spatie/laravel-model-states": "^2.1" | ||||||
|   | |||||||
							
								
								
									
										176
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										176
									
								
								composer.lock
									
									
									
										generated
									
									
									
								
							| @@ -4,7 +4,7 @@ | |||||||
|         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", |         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", | ||||||
|         "This file is @generated automatically" |         "This file is @generated automatically" | ||||||
|     ], |     ], | ||||||
|     "content-hash": "414a1fc13e0731e59605248bd4e39de6", |     "content-hash": "3e4ab38084e10e25b26a11dc275dd007", | ||||||
|     "packages": [ |     "packages": [ | ||||||
|         { |         { | ||||||
|             "name": "asm89/stack-cors", |             "name": "asm89/stack-cors", | ||||||
| @@ -1731,6 +1731,68 @@ | |||||||
|             ], |             ], | ||||||
|             "time": "2021-12-16T16:49:26+00:00" |             "time": "2021-12-16T16:49:26+00:00" | ||||||
|         }, |         }, | ||||||
|  |         { | ||||||
|  |             "name": "laminas/laminas-escaper", | ||||||
|  |             "version": "2.10.0", | ||||||
|  |             "source": { | ||||||
|  |                 "type": "git", | ||||||
|  |                 "url": "https://github.com/laminas/laminas-escaper.git", | ||||||
|  |                 "reference": "58af67282db37d24e584a837a94ee55b9c7552be" | ||||||
|  |             }, | ||||||
|  |             "dist": { | ||||||
|  |                 "type": "zip", | ||||||
|  |                 "url": "https://api.github.com/repos/laminas/laminas-escaper/zipball/58af67282db37d24e584a837a94ee55b9c7552be", | ||||||
|  |                 "reference": "58af67282db37d24e584a837a94ee55b9c7552be", | ||||||
|  |                 "shasum": "" | ||||||
|  |             }, | ||||||
|  |             "require": { | ||||||
|  |                 "ext-ctype": "*", | ||||||
|  |                 "ext-mbstring": "*", | ||||||
|  |                 "php": "^7.4 || ~8.0.0 || ~8.1.0" | ||||||
|  |             }, | ||||||
|  |             "conflict": { | ||||||
|  |                 "zendframework/zend-escaper": "*" | ||||||
|  |             }, | ||||||
|  |             "require-dev": { | ||||||
|  |                 "infection/infection": "^0.26.6", | ||||||
|  |                 "laminas/laminas-coding-standard": "~2.3.0", | ||||||
|  |                 "maglnet/composer-require-checker": "^3.8.0", | ||||||
|  |                 "phpunit/phpunit": "^9.5.18", | ||||||
|  |                 "psalm/plugin-phpunit": "^0.16.1", | ||||||
|  |                 "vimeo/psalm": "^4.22.0" | ||||||
|  |             }, | ||||||
|  |             "type": "library", | ||||||
|  |             "autoload": { | ||||||
|  |                 "psr-4": { | ||||||
|  |                     "Laminas\\Escaper\\": "src/" | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             "notification-url": "https://packagist.org/downloads/", | ||||||
|  |             "license": [ | ||||||
|  |                 "BSD-3-Clause" | ||||||
|  |             ], | ||||||
|  |             "description": "Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs", | ||||||
|  |             "homepage": "https://laminas.dev", | ||||||
|  |             "keywords": [ | ||||||
|  |                 "escaper", | ||||||
|  |                 "laminas" | ||||||
|  |             ], | ||||||
|  |             "support": { | ||||||
|  |                 "chat": "https://laminas.dev/chat", | ||||||
|  |                 "docs": "https://docs.laminas.dev/laminas-escaper/", | ||||||
|  |                 "forum": "https://discourse.laminas.dev", | ||||||
|  |                 "issues": "https://github.com/laminas/laminas-escaper/issues", | ||||||
|  |                 "rss": "https://github.com/laminas/laminas-escaper/releases.atom", | ||||||
|  |                 "source": "https://github.com/laminas/laminas-escaper" | ||||||
|  |             }, | ||||||
|  |             "funding": [ | ||||||
|  |                 { | ||||||
|  |                     "url": "https://funding.communitybridge.org/projects/laminas-project", | ||||||
|  |                     "type": "community_bridge" | ||||||
|  |                 } | ||||||
|  |             ], | ||||||
|  |             "time": "2022-03-08T20:15:36+00:00" | ||||||
|  |         }, | ||||||
|         { |         { | ||||||
|             "name": "laravel/framework", |             "name": "laravel/framework", | ||||||
|             "version": "v9.7.0", |             "version": "v9.7.0", | ||||||
| @@ -3958,6 +4020,118 @@ | |||||||
|             }, |             }, | ||||||
|             "time": "2022-02-18T12:57:07+00:00" |             "time": "2022-02-18T12:57:07+00:00" | ||||||
|         }, |         }, | ||||||
|  |         { | ||||||
|  |             "name": "phpoffice/phpword", | ||||||
|  |             "version": "0.18.3", | ||||||
|  |             "source": { | ||||||
|  |                 "type": "git", | ||||||
|  |                 "url": "https://github.com/PHPOffice/PHPWord.git", | ||||||
|  |                 "reference": "be0190cd5d8f95b4be08d5853b107aa4e352759a" | ||||||
|  |             }, | ||||||
|  |             "dist": { | ||||||
|  |                 "type": "zip", | ||||||
|  |                 "url": "https://api.github.com/repos/PHPOffice/PHPWord/zipball/be0190cd5d8f95b4be08d5853b107aa4e352759a", | ||||||
|  |                 "reference": "be0190cd5d8f95b4be08d5853b107aa4e352759a", | ||||||
|  |                 "shasum": "" | ||||||
|  |             }, | ||||||
|  |             "require": { | ||||||
|  |                 "ext-xml": "*", | ||||||
|  |                 "laminas/laminas-escaper": "^2.2", | ||||||
|  |                 "php": "^5.3.3 || ^7.0 || ^8.0" | ||||||
|  |             }, | ||||||
|  |             "require-dev": { | ||||||
|  |                 "dompdf/dompdf": "0.8.* || 1.0.*", | ||||||
|  |                 "ext-gd": "*", | ||||||
|  |                 "ext-zip": "*", | ||||||
|  |                 "friendsofphp/php-cs-fixer": "^2.2", | ||||||
|  |                 "mpdf/mpdf": "5.7.4 || 6.* || 7.* || 8.*", | ||||||
|  |                 "php-coveralls/php-coveralls": "1.1.0 || ^2.0", | ||||||
|  |                 "phploc/phploc": "2.* || 3.* || 4.* || 5.* || 6.* || 7.*", | ||||||
|  |                 "phpmd/phpmd": "2.*", | ||||||
|  |                 "phpunit/phpunit": "^4.8.36 || ^7.0", | ||||||
|  |                 "squizlabs/php_codesniffer": "^2.9 || ^3.5", | ||||||
|  |                 "tecnickcom/tcpdf": "6.*" | ||||||
|  |             }, | ||||||
|  |             "suggest": { | ||||||
|  |                 "dompdf/dompdf": "Allows writing PDF", | ||||||
|  |                 "ext-gd2": "Allows adding images", | ||||||
|  |                 "ext-xmlwriter": "Allows writing OOXML and ODF", | ||||||
|  |                 "ext-xsl": "Allows applying XSL style sheet to headers, to main document part, and to footers of an OOXML template", | ||||||
|  |                 "ext-zip": "Allows writing OOXML and ODF" | ||||||
|  |             }, | ||||||
|  |             "type": "library", | ||||||
|  |             "extra": { | ||||||
|  |                 "branch-alias": { | ||||||
|  |                     "dev-develop": "0.19-dev" | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             "autoload": { | ||||||
|  |                 "psr-4": { | ||||||
|  |                     "PhpOffice\\PhpWord\\": "src/PhpWord" | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             "notification-url": "https://packagist.org/downloads/", | ||||||
|  |             "license": [ | ||||||
|  |                 "LGPL-3.0" | ||||||
|  |             ], | ||||||
|  |             "authors": [ | ||||||
|  |                 { | ||||||
|  |                     "name": "Mark Baker" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "name": "Gabriel Bull", | ||||||
|  |                     "email": "me@gabrielbull.com", | ||||||
|  |                     "homepage": "http://gabrielbull.com/" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "name": "Franck Lefevre", | ||||||
|  |                     "homepage": "https://rootslabs.net/blog/" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "name": "Ivan Lanin", | ||||||
|  |                     "homepage": "http://ivan.lanin.org" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "name": "Roman Syroeshko", | ||||||
|  |                     "homepage": "http://ru.linkedin.com/pub/roman-syroeshko/34/a53/994/" | ||||||
|  |                 }, | ||||||
|  |                 { | ||||||
|  |                     "name": "Antoine de Troostembergh" | ||||||
|  |                 } | ||||||
|  |             ], | ||||||
|  |             "description": "PHPWord - A pure PHP library for reading and writing word processing documents (OOXML, ODF, RTF, HTML, PDF)", | ||||||
|  |             "homepage": "http://phpoffice.github.io", | ||||||
|  |             "keywords": [ | ||||||
|  |                 "ISO IEC 29500", | ||||||
|  |                 "OOXML", | ||||||
|  |                 "Office Open XML", | ||||||
|  |                 "OpenDocument", | ||||||
|  |                 "OpenXML", | ||||||
|  |                 "PhpOffice", | ||||||
|  |                 "PhpWord", | ||||||
|  |                 "Rich Text Format", | ||||||
|  |                 "WordprocessingML", | ||||||
|  |                 "doc", | ||||||
|  |                 "docx", | ||||||
|  |                 "html", | ||||||
|  |                 "odf", | ||||||
|  |                 "odt", | ||||||
|  |                 "office", | ||||||
|  |                 "pdf", | ||||||
|  |                 "php", | ||||||
|  |                 "reader", | ||||||
|  |                 "rtf", | ||||||
|  |                 "template", | ||||||
|  |                 "template processor", | ||||||
|  |                 "word", | ||||||
|  |                 "writer" | ||||||
|  |             ], | ||||||
|  |             "support": { | ||||||
|  |                 "issues": "https://github.com/PHPOffice/PHPWord/issues", | ||||||
|  |                 "source": "https://github.com/PHPOffice/PHPWord/tree/0.18.3" | ||||||
|  |             }, | ||||||
|  |             "time": "2022-02-17T15:40:03+00:00" | ||||||
|  |         }, | ||||||
|         { |         { | ||||||
|             "name": "phpoption/phpoption", |             "name": "phpoption/phpoption", | ||||||
|             "version": "1.8.1", |             "version": "1.8.1", | ||||||
|   | |||||||
| @@ -1,5 +1,5 @@ | |||||||
| <template> | <template> | ||||||
|   <InertiaHead title="Dodawanie CV" /> |   <InertiaHead title="Edycja CV" /> | ||||||
|   <div class="mx-auto w-full max-w-7xl bg-white shadow-md"> |   <div class="mx-auto w-full max-w-7xl bg-white shadow-md"> | ||||||
|     <div class="p-4 sm:px-6"> |     <div class="p-4 sm:px-6"> | ||||||
|       <h2 class="text-lg font-medium leading-6 text-gray-900"> |       <h2 class="text-lg font-medium leading-6 text-gray-900"> | ||||||
|   | |||||||
							
								
								
									
										
											BIN
										
									
								
								resources/views/docx/resume_eng.docx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								resources/views/docx/resume_eng.docx
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Reference in New Issue
	
	Block a user