#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 Inertia\Response; | ||||
| use Symfony\Component\HttpFoundation\BinaryFileResponse as BinaryFileResponseAlias; | ||||
| use Toby\Domain\ResumeGenerator; | ||||
| use Toby\Eloquent\Models\Resume; | ||||
| use Toby\Eloquent\Models\Technology; | ||||
| 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 | ||||
|     { | ||||
|         $resume = new Resume(); | ||||
|   | ||||
| @@ -19,6 +19,7 @@ | ||||
|         "laravel/telescope": "^4.6", | ||||
|         "laravel/tinker": "^2.5", | ||||
|         "maatwebsite/excel": "^3.1", | ||||
|         "phpoffice/phpword": "^0.18.3", | ||||
|         "rackbeat/laravel-ui-avatars": "^1.0", | ||||
|         "spatie/laravel-google-calendar": "^3.5", | ||||
|         "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", | ||||
|         "This file is @generated automatically" | ||||
|     ], | ||||
|     "content-hash": "414a1fc13e0731e59605248bd4e39de6", | ||||
|     "content-hash": "3e4ab38084e10e25b26a11dc275dd007", | ||||
|     "packages": [ | ||||
|         { | ||||
|             "name": "asm89/stack-cors", | ||||
| @@ -1731,6 +1731,68 @@ | ||||
|             ], | ||||
|             "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", | ||||
|             "version": "v9.7.0", | ||||
| @@ -3958,6 +4020,118 @@ | ||||
|             }, | ||||
|             "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", | ||||
|             "version": "1.8.1", | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| <template> | ||||
|   <InertiaHead title="Dodawanie CV" /> | ||||
|   <InertiaHead title="Edycja CV" /> | ||||
|   <div class="mx-auto w-full max-w-7xl bg-white shadow-md"> | ||||
|     <div class="p-4 sm:px-6"> | ||||
|       <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