Update Spatie versi 4
This commit is contained in:
@@ -4,10 +4,12 @@ namespace App\Http\Controllers\Web\Konfigurasi;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Konfigurasi\FilterLogAktivitasRequest;
|
||||
use App\Models\Konfigurasi\LogAktivitas;
|
||||
use App\Models\Pertanian\Petani;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Spatie\Activitylog\Models\Activity;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class LogAktivitasController extends Controller
|
||||
{
|
||||
@@ -38,21 +40,24 @@ class LogAktivitasController extends Controller
|
||||
{
|
||||
$filter = $request->validated();
|
||||
|
||||
// Ambil log sesuai filter
|
||||
$aktivitas = Activity::query()
|
||||
->with(['causer', 'subject'])
|
||||
// Ambil log sesuai filter (tanpa COUNT total)
|
||||
$aktivitas = LogAktivitas::query()
|
||||
->with('causer:id,name,role')
|
||||
->when($filter['jenis'] ?? null, fn ($q, $jenis) => $q->where('log_name', $jenis))
|
||||
->when($filter['dari'] ?? null, fn ($q, $tgl) => $q->where('created_at', '>=', $tgl))
|
||||
->when($filter['sampai'] ?? null, fn ($q, $tgl) => $q->where('created_at', '<', Carbon::parse($tgl)->addDay()))
|
||||
->when($filter['search'] ?? null, fn ($q, $cari) => $this->cari($q, '%' . mb_strtolower($cari) . '%'))
|
||||
->latest('id')
|
||||
->paginate((int) ($filter['per_page'] ?? self::PER_PAGE[0]))
|
||||
->simplePaginate((int) ($filter['per_page'] ?? self::PER_PAGE[0]))
|
||||
->withQueryString();
|
||||
|
||||
// Nama petani untuk log tab petani (satu query)
|
||||
$namaPetani = Petani::withoutGlobalScopes()->withTrashed()
|
||||
->whereIn('id', $aktivitas->getCollection()->pluck('properties.petani_id')->filter()->unique())
|
||||
->pluck('nama', 'id');
|
||||
// Nama petani untuk log yang belum menyimpan nama (satu query)
|
||||
$idPetani = $aktivitas->getCollection()
|
||||
->map(fn ($a) => $a->properties['petani_id'] ?? ($a->subject_type === Petani::class ? $a->subject_id : null))
|
||||
->filter()
|
||||
->unique();
|
||||
|
||||
$namaPetani = $idPetani->isEmpty() ? collect() : Petani::withoutGlobalScopes()->whereIn('id', $idPetani)->pluck('nama', 'id');
|
||||
|
||||
return view('konfigurasi.log-aktivitas.index', [
|
||||
'aktivitas' => $aktivitas,
|
||||
@@ -62,15 +67,16 @@ class LogAktivitasController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
// Cari di aktivitas, nama pengguna, dan nama petani
|
||||
private function cari($query, string $cari): void
|
||||
// Cari di aktivitas, nama pengguna, dan nama petani (memakai index)
|
||||
private function cari(Builder $query, string $cari): void
|
||||
{
|
||||
$petani = Petani::withoutGlobalScopes()->select('id')->whereRaw('lower(nama) like ?', [$cari]);
|
||||
$pengguna = User::withoutGlobalScopes()->select('id')->whereRaw('lower(name) like ?', [$cari]);
|
||||
|
||||
$query->where(fn ($q) => $q
|
||||
->whereRaw('lower(description) like ?', [$cari])
|
||||
->orWhereHasMorph('causer', [User::class], fn ($q) => $q->whereRaw('lower(name) like ?', [$cari]))
|
||||
->orWhereRaw(
|
||||
"coalesce((properties->>'petani_id')::bigint, case when subject_type = ? then subject_id end) in (select id from petani where lower(nama) like ?)",
|
||||
[Petani::class, $cari]
|
||||
));
|
||||
->orWhere(fn ($q) => $q->where('causer_type', User::class)->whereIn('causer_id', $pengguna))
|
||||
->orWhere(fn ($q) => $q->where('subject_type', Petani::class)->whereIn('subject_id', $petani))
|
||||
->orWhereIn(DB::raw("(properties->>'petani_id')::bigint"), $petani));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Services\Konfigurasi\BufferLogAktivitas;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
class SimpanLogAktivitas
|
||||
{
|
||||
public function __construct(private BufferLogAktivitas $buffer) {}
|
||||
|
||||
public function handle(Request $request, Closure $next): Response
|
||||
{
|
||||
$this->buffer->mulai();
|
||||
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
// Simpan log setelah respons terkirim; request gagal (5xx) tidak dicatat
|
||||
public function terminate(Request $request, Response $response): void
|
||||
{
|
||||
$response->getStatusCode() >= 500 ? $this->buffer->buang() : $this->buffer->simpan();
|
||||
}
|
||||
}
|
||||
@@ -2,10 +2,10 @@
|
||||
|
||||
namespace App\Models\Concerns;
|
||||
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Str;
|
||||
use Spatie\Activitylog\Models\Concerns\LogsActivity;
|
||||
use Spatie\Activitylog\Support\LogOptions;
|
||||
use Spatie\Activitylog\Contracts\Activity;
|
||||
use Spatie\Activitylog\LogOptions;
|
||||
use Spatie\Activitylog\Traits\LogsActivity;
|
||||
|
||||
trait CatatAktivitas
|
||||
{
|
||||
@@ -36,15 +36,19 @@ trait CatatAktivitas
|
||||
->logExcept([...self::$kolomTidakDicatat, ...$this->getHidden()])
|
||||
->dontLogIfAttributesChangedOnly(self::$kolomTidakDicatat)
|
||||
->logOnlyDirty()
|
||||
->dontLogEmptyChanges()
|
||||
->dontSubmitEmptyLogs()
|
||||
->setDescriptionForEvent(fn (string $event) => $label . ' ' . (self::$kataEvent[$event] ?? $event));
|
||||
}
|
||||
|
||||
// Tandai petani terkait
|
||||
public function beforeActivityLogged(Model $activity, string $event): void
|
||||
// Simpan nama data & petani terkait di log (halaman log tak perlu memuat data asli)
|
||||
public function tapActivity(Activity $activity, string $eventName): void
|
||||
{
|
||||
if ($petaniId = $this->getAttribute('petani_id')) {
|
||||
$activity->properties = $activity->properties->put('petani_id', (int) $petaniId);
|
||||
}
|
||||
$label = $this->getAttribute('nama') ?? $this->getAttribute('name');
|
||||
$petaniId = $this->getAttribute('petani_id');
|
||||
|
||||
$activity->properties = $activity->properties->merge(array_filter([
|
||||
'label' => is_string($label) ? Str::limit($label, 100) : null,
|
||||
'petani_id' => $petaniId ? (int) $petaniId : null,
|
||||
]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Konfigurasi;
|
||||
|
||||
use App\Services\Konfigurasi\BufferLogAktivitas;
|
||||
use Spatie\Activitylog\Models\Activity;
|
||||
|
||||
class LogAktivitas extends Activity
|
||||
{
|
||||
// Saat request web/API, log ditampung lalu disimpan sekaligus di akhir request
|
||||
public function save(array $options = []): bool
|
||||
{
|
||||
$buffer = app(BufferLogAktivitas::class);
|
||||
|
||||
if ($this->exists || ! $buffer->aktif()) {
|
||||
return parent::save($options);
|
||||
}
|
||||
|
||||
$this->updateTimestamps();
|
||||
$buffer->tambah($this->getAttributes());
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,8 @@ use Dedoc\Scramble\Support\Generator\OpenApi;
|
||||
use Dedoc\Scramble\Support\Generator\SecurityScheme;
|
||||
|
||||
use App\Models\Ekosistem\TabelBasisData;
|
||||
use Spatie\Activitylog\Support\ActivityLogStatus;
|
||||
use App\Services\Konfigurasi\BufferLogAktivitas;
|
||||
use Spatie\Activitylog\ActivityLogStatus;
|
||||
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
@@ -24,7 +25,7 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function register(): void
|
||||
{
|
||||
//
|
||||
$this->app->scoped(BufferLogAktivitas::class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Konfigurasi;
|
||||
|
||||
use App\Models\Konfigurasi\LogAktivitas;
|
||||
|
||||
class BufferLogAktivitas
|
||||
{
|
||||
private bool $aktif = false;
|
||||
|
||||
private array $antrean = [];
|
||||
|
||||
public function mulai(): void
|
||||
{
|
||||
$this->aktif = true;
|
||||
}
|
||||
|
||||
public function aktif(): bool
|
||||
{
|
||||
return $this->aktif;
|
||||
}
|
||||
|
||||
private const KOLOM = [
|
||||
'log_name', 'description', 'subject_type', 'subject_id', 'event',
|
||||
'causer_type', 'causer_id', 'properties', 'batch_uuid', 'created_at', 'updated_at',
|
||||
];
|
||||
|
||||
// Samakan kolom tiap baris supaya bisa di-insert sekaligus
|
||||
public function tambah(array $baris): void
|
||||
{
|
||||
$this->antrean[] = array_merge(array_fill_keys(self::KOLOM, null), array_intersect_key($baris, array_flip(self::KOLOM)));
|
||||
}
|
||||
|
||||
// Simpan semua log dalam satu insert
|
||||
public function simpan(): void
|
||||
{
|
||||
foreach (array_chunk($this->antrean, 500) as $potongan) {
|
||||
LogAktivitas::query()->insert($potongan);
|
||||
}
|
||||
|
||||
$this->buang();
|
||||
}
|
||||
|
||||
public function buang(): void
|
||||
{
|
||||
$this->antrean = [];
|
||||
$this->aktif = false;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user