Eml.php
1 <?php 2 3 namespace App\Http\Livewire; 4 5 use App\Helpers\EmlBuilder; 6 use App\Http\Livewire\Dossiers\Dossier\OutPut\Create as OutputCreate; 7 use App\Http\Livewire\Traits\LivewireDownload; 8 use App\Http\Services\EMLService; 9 use App\Models\Document; 10 use App\Models\Dossier; 11 use App\Models\EMLTemplate; 12 use App\Models\Entity; 13 use App\Models\Meet; 14 use App\Models\Stage; 15 use App\Models\User; 16 use Blade; 17 use Exception; 18 use Illuminate\Foundation\Auth\Access\AuthorizesRequests; 19 use Illuminate\Support\Collection; 20 use Illuminate\Support\Facades\Auth; 21 use Livewire\Component; 22 use Livewire\WithFileUploads; 23 use Log; 24 use phpDocumentor\Reflection\PseudoTypes\False_; 25 use PhpOffice\PhpWord\Element\Bookmark; 26 use WireUi\Traits\Actions; 27 28 class Eml extends Component 29 { 30 use AuthorizesRequests, Actions, WithFileUploads, LivewireDownload; 31 32 public int $entityId; // dossier id 33 34 public ?int $stageId = null; 35 public ?string $template = null; 36 public bool $encrypt = true; 37 public $uploadedFiles = []; 38 public array $localDocuments = []; 39 public array $usersTo = []; 40 41 public array $usersCC = []; 42 43 public array $usersBCC = []; 44 45 public string $subject = ''; 46 47 public array $params; 48 49 public bool $btnIsDisabled = false; 50 51 public array $rules = [ 52 'usersTo' => 'nullable|array', 53 'usersCC' => 'nullable|array', 54 'usersBCC' => 'nullable|array', 55 'template' => 'required', 56 'encrypt' => 'required|boolean', 57 ]; 58 59 public function mount(): void 60 { 61 $this->setData(); 62 } 63 64 public function getDossierProperty() 65 { 66 return Dossier::find($this->entityId); 67 } 68 69 public function getStagesProperty() 70 { 71 return $this->dossier->stages()->select('id', 'name')->get()->toArray(); 72 } 73 74 public function getStageProperty() 75 { 76 return Stage::find($this->stageId); 77 } 78 79 public function getTemplatesProperty() 80 { 81 $locale = strtolower($this->dossier->language ?? $this->getDefaultLanguage()); 82 83 $templates = EMLService::getTemplateNames(null, $locale); 84 if (!$this->stageId) { 85 return $templates; 86 } 87 88 $stageNumber = ($this->stage->getNumber()); 89 return array_filter($templates, function ($template) use ($stageNumber) { 90 $templateStageNumber = self::getStageNumber($template['filter']); 91 return $stageNumber === $templateStageNumber; 92 }); 93 } 94 95 public function getUsersProperty() 96 { 97 return $this->dossier->getPointsOfContact()->map(function ($poc) { 98 return [ 99 'id' => $poc->id, 100 'name' => $poc->fullname, 101 'description' => $poc->email, 102 ]; 103 }); 104 } 105 106 public function getDossierDocumentsProperty() 107 { 108 return $this->dossier->documents->map(function ($document) { 109 $description = '<strong>' . $document->head->name . '</strong><br>' . $document->head->description; 110 return [ 111 'id' => $document->id, 112 'name' => $document->name, 113 'description' => $description, 114 ]; 115 })->toArray(); 116 } 117 118 public function updatedStageId($value) 119 { 120 if (empty($this->templates)) { 121 $this->subject = ""; 122 } 123 } 124 125 public function updatedTemplate($value): void 126 { 127 if (!$this->template) { 128 return; 129 } 130 131 try { 132 $filter = collect($this->templates)->where('id', $this->template)->first()['filter']; 133 $filter = '/' . $this->dossier->language . '/' . $filter . '.blade.php'; 134 135 $this->getDataFromEmailsMapper($filter); 136 137 $this->subject = Blade::render( 138 EMLTemplate::find($value)->subject, 139 [ 140 'dossier' => $this->dossier, 141 'meet' => $this->getMeet(), 142 ] 143 ); 144 $this->btnIsDisabled = false; 145 } catch (Exception $e) { 146 $this->btnIsDisabled = true; 147 $this->addError('template', __('eml.errors.template-tokens')); 148 Log::error($e->getMessage()); 149 } 150 } 151 152 private static function getStageNumber(string $stageName): int 153 { 154 $matches = []; 155 $pattern = '/\d+/'; 156 preg_match($pattern, $stageName, $matches); 157 158 if (isset($matches[0])) { 159 return max(0, min(12, (int)$matches[0])); 160 } else { 161 return -1; 162 } 163 } 164 165 private function getDataFromEmailsMapper(string $filter): void 166 { 167 EMLService::getDataFromEmailsParser( 168 $this->dossier, 169 $filter, 170 $this->encrypt, 171 $this->usersTo, 172 $this->usersCC, 173 $this->usersBCC 174 ); 175 176 $this->usersTo = array_unique($this->usersTo); 177 $this->usersCC = array_unique($this->usersCC); 178 $this->usersBCC = array_unique($this->usersBCC); 179 } 180 181 public function create() 182 { 183 $this->validate(); 184 185 if ($this->encrypt) { 186 $missing = $this->findUsersMissingGpg(); 187 if ($missing->count() > 0) { 188 $this->missingGpgDialog($missing); 189 return; 190 } 191 } 192 193 $this->commitCreate(); 194 } 195 196 private function findUsersMissingGpg() 197 { 198 return $this->recipients->filter(function ($user) { 199 return !$user->gpg_keys()->exists(); 200 }); 201 } 202 203 private function setData(): void 204 { 205 $this->stageId = $this->dossier->stage->id; 206 207 $users = []; 208 if (isset($this->params['meetId'])) { 209 $meet = Meet::findOrFail($this->params['meetId']); 210 $users = $meet->participants->pluck('id'); 211 } else { 212 $users = $this->getUsersByTemplate()->pluck('id'); 213 } 214 $this->userIds = $users->toArray(); 215 } 216 217 private function getUsersByTemplate(): Collection 218 { 219 // TODO: get users by EML TEMPLATE @jgallardo 220 return collect(); 221 } 222 223 public function getRecipientsProperty(): Collection 224 { 225 $userIds = array_merge($this->usersTo, $this->usersCC, $this->usersBCC); 226 227 return User::whereIn('id', $userIds)->get(); 228 } 229 230 private function missingGpgDialog(Collection $users) 231 { 232 $message = __('eml.dialog.description_a') . '<br>'; 233 foreach ($users as $user) { 234 $message .= $user->fullName . ' ' . $user->email . '<br>'; 235 } 236 $message .= __('eml.dialog.description_b'); 237 238 $this->dialog()->confirm([ 239 'title' => __('eml.dialog.title'), 240 'description' => $message, 241 'acceptLabel' => __('eml.dialog.yes'), 242 'rejectLabel' => __('eml.dialog.cancel'), 243 'method' => 'commitCreate', 244 ]); 245 } 246 247 public function getFingerprintsProperty() 248 { 249 return $this->recipients->map(function ($user) { 250 return $user->gpg_keys()->latest()->first()?->key_fingerprint; 251 })->filter()->toArray(); 252 } 253 254 private function getEmails() 255 { 256 return $this->recipients 257 ->map(function ($user) { 258 return [ 259 'name' => $user->fullName, 260 'address' => $user->email, 261 'type' => EMLService::getTypeOfReceiver($this->usersTo, $this->usersCC, $this->usersBCC, $user) 262 ]; 263 })->toArray(); 264 } 265 266 public function resetData(): void 267 { 268 $this->usersTo = []; 269 $this->usersCC = []; 270 $this->usersBCC = []; 271 } 272 273 public function commitCreate() 274 { 275 $user = Auth::user(); 276 $meet = $this->getMeet(); 277 278 try { 279 $eml = new EmlBuilder($this->template, $this->dossier, ['meet' => $meet], textSubject: $this->subject); 280 $eml 281 ->addSender($user) 282 ->addReceiversArray($this->getEmails()) 283 ->addLocalAttachmentsArray(Document::whereIn('id', $this->localDocuments)->get()) 284 ->addAttachmentsArray($this->uploadedFiles); 285 286 if ($this->encrypt) { 287 try { 288 $cab_key = Entity::cab()->keys()->first()->key_id; 289 $eml->addFingerprint($cab_key); 290 } catch (\Exception $e) { 291 $this->notification()->error('Error', __('eml.errors.sgoc-missing-public-key')); 292 logger()->error($e); 293 return; 294 } 295 296 $eml->addFingerprintsArray($this->fingerprints); 297 } 298 299 $result = $eml->build(); 300 $emlDocument = $result->saveAsDocument($this->template); 301 $this->dispatchBrowserEvent('reset-file'); 302 $this->livewireDownload($emlDocument->head->name, $result->toString()); 303 } catch (\Exception $e) { 304 if (str_contains($e->getMessage(), 'Attempt to read property "meet_date"')) { 305 $this->notification()->error('Error', __('eml.errors.meet-missing')); 306 } else { 307 $this->notification()->error('Error', $e->getMessage()); 308 } 309 $this->resetData(); 310 logger()->error($e); 311 return; 312 } 313 314 if (config('app.env') !== 'testing') { 315 sleep(1); 316 } 317 318 $this->emit('openPanel', __('out-puts.panel.title.create'), OutputCreate::class, $this->dossier->id, Dossier::class, '', [ 319 'isAutomatic' => true, 320 'isDocument' => true, 321 'documentIds' => $this->localDocuments, 322 'userIds' => $this->recipients->pluck('id')->toArray(), 323 ]); 324 325 $this->notification()->success('Success', __('eml.success.created')); 326 } 327 328 private function getMeet() 329 { 330 if (isset($this->params['meetId'])) { 331 return Meet::findOrFail($this->params['meetId']); 332 } 333 return null; 334 } 335 336 public function render() 337 { 338 return view('livewire.eml'); 339 } 340 }