/ app / Http / Livewire / Eml.php
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  }