simedkom/app/Filament/Pages/Media/Services/MediaSaveService.php

215 lines
7.1 KiB
PHP

<?php
namespace App\Filament\Pages\Media\Services;
use App\Enums\DataChangeStatus;
use App\Filament\Resources\Manage\DataChanges\DataChangesResource;
use App\Filament\Support\CheerfulNotification;
use App\Models\DataChangeRequest;
use App\Models\PartnerMedia;
use App\Models\User;
use App\Notifications\BroadcastNotification;
use BackedEnum;
use Filament\Actions\Action;
use Filament\Support\Contracts\HasLabel;
use Illuminate\Support\Facades\Storage;
use UnitEnum;
class MediaSaveService
{
public static function handle(
?PartnerMedia $existingMedia,
int $companyId,
array $formState,
array $pageData,
array $originalDocuments,
bool $needsReview,
array $actionData = [],
): ?PartnerMedia {
if ($needsReview && $existingMedia) {
self::createDataChangeRequest(
media: $existingMedia,
formState: $formState,
pageData: $pageData,
originalDocuments: $originalDocuments,
actionData: $actionData,
);
return $existingMedia;
}
return self::saveMediaDirectly(
existingMedia: $existingMedia,
companyId: $companyId,
formState: $formState,
pageData: $pageData,
);
}
private static function createDataChangeRequest(
PartnerMedia $media,
array $formState,
array $pageData,
array $originalDocuments,
array $actionData,
): void {
$existingRequest = DataChangeRequest::where('entity_type', PartnerMedia::class)
->where('entity_id', $media->id)
->where('status', DataChangeStatus::PENDING)
->exists();
if ($existingRequest) {
CheerfulNotification::warning(
CheerfulNotification::getByKey('data_change.existing.title'),
CheerfulNotification::getByKey('data_change.existing.body')
)->send();
return;
}
$data = array_merge($formState, $actionData);
$fieldLabels = PartnerMedia::dataChangeEntryLabels();
$editableFields = [
'name',
'link',
'address',
'type',
'classification',
'journalism_organization',
'press_council_certificate',
];
$changedFields = [];
$oldDataArr = [];
$casts = $media->getCasts();
foreach ($editableFields as $field) {
$val = $data[$field] ?? null;
$oldVal = $media->{$field};
if (isset($casts[$field]) && ! ($val instanceof BackedEnum) && enum_exists($casts[$field])) {
/** @var class-string<UnitEnum> $enumClass */
$enumClass = $casts[$field];
$val = $enumClass::tryFrom($val) ?? $val;
}
$displayVal = ($val instanceof HasLabel) ? $val->getLabel() : ($val instanceof BackedEnum ? $val->value : $val);
$displayOldVal = ($oldVal instanceof HasLabel) ? $oldVal->getLabel() : ($oldVal instanceof BackedEnum ? $oldVal->value : $oldVal);
if ($displayOldVal !== $displayVal) {
$label = $fieldLabels[$field] ?? $field;
$changedFields[$label] = $displayVal;
$oldDataArr[$label] = $displayOldVal;
}
}
$documents = [
'journalism_organization_docs',
'press_council_certificate_docs',
];
foreach ($documents as $field) {
$newValue = $pageData[$field] ?? [];
$oldValue = $originalDocuments[$field] ?? [];
if (json_encode($newValue) !== json_encode($oldValue)) {
$label = $fieldLabels[$field] ?? $field;
$changedFields[$label] = $newValue;
$oldDataArr[$label] = $oldValue;
}
}
if (empty($changedFields)) {
CheerfulNotification::info(
CheerfulNotification::getByKey('data_change.no_change.title'),
CheerfulNotification::getByKey('data_change.no_change.body')
)->send();
return;
}
$dataChangeRequest = DataChangeRequest::create([
'user_id' => auth()->id(),
'entity_type' => PartnerMedia::class,
'entity_id' => $media->id,
'old_data' => $oldDataArr,
'new_data' => $changedFields,
'change_reason' => $data['change_reason'] ?? null,
]);
CheerfulNotification::success(
CheerfulNotification::getByKey('data_change.success.title'),
CheerfulNotification::getByKey('data_change.success.body')
)->send();
User::superAdmin()
->get()
->each(function ($admin) use ($dataChangeRequest): void {
$admin->notify(new BroadcastNotification([
'title' => CheerfulNotification::getByKey('data_change.admin_notify.title'),
'body' => CheerfulNotification::getByKey('data_change.admin_notify.body', ['name' => auth()->user()->name]),
'action' => [
Action::make('view')
->label('Lihat')
->url(DataChangesResource::getUrl('view', ['record' => $dataChangeRequest->id])),
],
]));
});
}
private static function saveMediaDirectly(
?PartnerMedia $existingMedia,
int $companyId,
array $formState,
array $pageData,
): PartnerMedia {
$media = PartnerMedia::updateOrCreate([
'id' => $existingMedia?->id,
], [
'company_id' => $companyId,
'name' => $formState['name'],
'link' => $formState['link'],
'address' => $formState['address'],
'type' => $formState['type'],
'classification' => $formState['classification'],
'journalism_organization' => $formState['journalism_organization'],
'press_council_certificate' => $formState['press_council_certificate'],
]);
$documents = [
'journalism_organization_docs',
'press_council_certificate_docs',
];
foreach ($documents as $field) {
if (empty($pageData[$field])) {
continue;
}
foreach ((array) $pageData[$field] as $filePath) {
$fullPath = Storage::disk(config('filesystems.default'))->path($filePath);
if (! file_exists($fullPath)) {
continue;
}
$media
->addMediaFromDisk($filePath, config('filesystems.default'))
->preservingOriginal()
->withCustomProperties([
'feature' => 'media',
'date' => now()->toDateString(),
'doc_type' => str($field)
->replace('_docs', '')
->slug('-'),
])
->toMediaCollection('partnerMedia');
}
}
return $media;
}
}