MediaService.php 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. <?php
  2. namespace App\Services;
  3. use App\Enums\ApprovalStatusEnum;
  4. use App\Models\Client;
  5. use App\Models\Media;
  6. use App\Models\Provider;
  7. use App\Traits\RemoveArchiveS3;
  8. use App\Traits\UploadsFile;
  9. use Illuminate\Database\Eloquent\Collection;
  10. use Illuminate\Database\Eloquent\ModelNotFoundException;
  11. use Illuminate\Http\UploadedFile;
  12. use Illuminate\Pagination\LengthAwarePaginator;
  13. use Illuminate\Support\Facades\DB;
  14. use Illuminate\Support\Facades\Log;
  15. class MediaService
  16. {
  17. use RemoveArchiveS3, UploadsFile;
  18. public function getAll(): Collection
  19. {
  20. return Media::query()
  21. ->with(['user'])
  22. ->orderBy('created_at', 'desc')
  23. ->get();
  24. }
  25. public function findById(int $id): ?Media
  26. {
  27. return Media::with(['user'])->find($id);
  28. }
  29. public function create(array $data): Media
  30. {
  31. return Media::create($data);
  32. }
  33. public function update(int $id, array $data): ?Media
  34. {
  35. $model = $this->findById($id);
  36. if (! $model) {
  37. return null;
  38. }
  39. $model->update($data);
  40. return $model->fresh(['user']);
  41. }
  42. public function delete(int $id): bool
  43. {
  44. $model = $this->findById($id);
  45. if (! $model) {
  46. return false;
  47. }
  48. return $model->delete();
  49. }
  50. //
  51. public function getPendingProfileMedia(int $page = 1, int $perPage = 10): LengthAwarePaginator
  52. {
  53. $paginated = Media::query()
  54. ->where(function ($query) {
  55. $query->where(function ($query) {
  56. $query->where('media.source', 'provider')
  57. ->whereExists(function ($query) {
  58. $query->selectRaw('1')
  59. ->from('providers')
  60. ->whereColumn('providers.id', 'media.source_id')
  61. ->whereColumn('providers.profile_media_id', 'media.id')
  62. ->where('providers.approval_status', ApprovalStatusEnum::ACCEPTED->value)
  63. ->where('providers.selfie_verified', false)
  64. ->whereNull('providers.deleted_at');
  65. });
  66. })->orWhere(function ($query) {
  67. $query->where('media.source', 'client')
  68. ->whereExists(function ($query) {
  69. $query->selectRaw('1')
  70. ->from('clients')
  71. ->whereColumn('clients.id', 'media.source_id')
  72. ->whereColumn('clients.profile_media_id', 'media.id')
  73. ->where('clients.selfie_verified', false)
  74. ->whereNull('clients.deleted_at');
  75. });
  76. });
  77. })
  78. ->orderBy('media.created_at')
  79. ->paginate($perPage, ['media.*'], 'page', $page);
  80. $media = $paginated->getCollection();
  81. $providerIds = $media->where('source', 'provider')->pluck('source_id');
  82. $clientIds = $media->where('source', 'client')->pluck('source_id');
  83. $providers = $providerIds->isEmpty()
  84. ? collect()
  85. : Provider::query()
  86. ->with('user:id,name,email')
  87. ->whereIn('id', $providerIds)
  88. ->get()
  89. ->keyBy('id');
  90. $clients = $clientIds->isEmpty()
  91. ? collect()
  92. : Client::query()
  93. ->with('user:id,name,email')
  94. ->whereIn('id', $clientIds)
  95. ->get()
  96. ->keyBy('id');
  97. $media->each(function (Media $item) use ($clients, $providers) {
  98. $profile = match ($item->source) {
  99. 'client' => $clients->get($item->source_id),
  100. 'provider' => $providers->get($item->source_id),
  101. };
  102. $item->setRelation('user', $profile?->user);
  103. });
  104. return $paginated;
  105. }
  106. public function approveProfileMedia(string $source, int $sourceId): Media
  107. {
  108. return DB::transaction(function () use ($source, $sourceId) {
  109. $profile = match ($source) {
  110. 'client' => Client::query()->lockForUpdate()->findOrFail($sourceId),
  111. 'provider' => Provider::query()->lockForUpdate()->findOrFail($sourceId),
  112. };
  113. $profile->load('profileMedia');
  114. $media = $profile->profileMedia;
  115. if ($media === null) {
  116. throw (new ModelNotFoundException)->setModel(Media::class);
  117. }
  118. $profile->update(['selfie_verified' => true]);
  119. return $media;
  120. });
  121. }
  122. public function createFromFile(UploadedFile $file, string $folder, string $source, int $sourceId, ?string $filename = null): Media
  123. {
  124. Log::warning('[avatar-upload] MediaService::createFromFile — iniciando upload para S3', [
  125. 'folder' => $folder,
  126. 'source' => $source,
  127. 'source_id' => $sourceId,
  128. 'file_original_name' => $file->getClientOriginalName(),
  129. 'file_size' => $file->getSize(),
  130. 'file_mime' => $file->getMimeType(),
  131. 'file_extension' => $file->getClientOriginalExtension(),
  132. 'file_is_valid' => $file->isValid(),
  133. ]);
  134. $path = $this->uploadFile($file, $folder, $filename);
  135. Log::warning('[avatar-upload] MediaService::createFromFile — upload concluído, criando registro Media', [
  136. 'path_retornado' => $path,
  137. 'source' => $source,
  138. 'source_id' => $sourceId,
  139. ]);
  140. $media = Media::create([
  141. 'source' => $source,
  142. 'source_id' => $sourceId,
  143. 'name' => $file->getClientOriginalName(),
  144. 'path' => $path,
  145. ]);
  146. Log::warning('[avatar-upload] MediaService::createFromFile — Media criado no banco', [
  147. 'media_id' => $media->id,
  148. 'media_path' => $media->path,
  149. 'media_url' => $media->url ?? null,
  150. ]);
  151. return $media;
  152. }
  153. public function replaceFile(UploadedFile $newFile, string $folder, string $source, int $sourceId, ?Media $old = null, ?string $filename = null): Media
  154. {
  155. Log::warning('[avatar-upload] MediaService::replaceFile iniciado', [
  156. 'folder' => $folder,
  157. 'source' => $source,
  158. 'source_id' => $sourceId,
  159. 'has_old_media' => $old !== null,
  160. 'old_media_id' => $old?->id,
  161. 'old_path' => $old?->path,
  162. ]);
  163. if ($old) {
  164. Log::warning('[avatar-upload] Removendo arquivo antigo do S3', ['old_path' => $old->path]);
  165. $this->removeArchiveByPath($old->path);
  166. $old->delete();
  167. Log::warning('[avatar-upload] Arquivo antigo removido do S3 e Media deletado do banco');
  168. }
  169. return $this->createFromFile($newFile, $folder, $source, $sourceId, $filename);
  170. }
  171. }