Fix: Menampilkan media Galeri berbasis link (Google Drive & YouTube) di Web dan Admin - #1766
Merged
Merged
Conversation
Contributor
|
🔄 AI PR Review sedang antri di server...
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull Request: Fix: Menampilkan media Galeri berbasis link (Google Drive & YouTube) di Web dan Admin
Description
Galeri dengan
jenis = urlhanya mengenali tautan YouTube, sehingga tautan Google Drive untuk foto maupun video tidak pernah ditampilkan, dan halaman detail galeri mengabaikanlinksama sekali. PR ini menambahkan resolusi link media (Google Drive, YouTube, Vimeo, serta berkas foto/video langsung) beserta tipe medianya, lalu merender<img>,<video>, atau<iframe>yang sesuai pada Admin maupun halaman web.Changes made:
app/Services/MediaLinkService.phpuntuk resolusi link media (deteksi + probing HTTP saat perlu)app/ValueObjects/MediaLink.phpdanapp/Enums/TipeMedia.phpsebagai kontrak tipe media2026_09_28_000001_add_media_type_to_galeris_table.php(kolomgaleris.media_type)app/Models/Galeri.php— menambahkanmedia_type,media_url,media_embed_urlpada$appendsagar tersedia di APIapp/Http/Controllers/Publikasi/GaleriController.php— deteksi & penyimpananmedia_typepadastore()/update(), serta kolom Media pada DataTableapp/Http/Requests/GaleriRequest.php— validasilinkharus URL http(s) danmedia_typeharus salah satu tipe yang diizinkanresources/views/components/galeri-media.blade.php(renderer media bersama) danresources/views/publikasi/galeri/parts/media-cell.blade.phpresources/views/publikasi/galeri/_form.blade.php— menambahkan select Tipe Media (Otomatis/Foto/Video/YouTube) dan pratinjau media pada form Tambah/Ubahpublic/js/custom.js— menambahkanrenderGaleriMedia()danisGaleriPlayable()yang dipakai kedua temathemes/opendk/default&themes/opendk/buen— halaman detail galeri kini merender media berbasis link, bukan hanya arraygambarthemes/opendk/default&themes/opendk/buen— halaman daftar galeri menampilkan thumbnail + badge Video/YouTube sesuai tipeapp/Http/Middleware/SecurityHeaders.php— CSP dipisah keapp/Support/CspPolicy.php, ditambahkanmedia-src https: blob:danframe-src https://drive.google.comagar media eksternal tidak diblokir di productionReason for change:
Galeri::getGambarPathAttribute()hanya memiliki regex YouTube. Tautan Google Drive tidak pernah dikenali sehingga selalu jatuh keno-image.png.galeri_detail.blade.phphanya melakukan iterasigaleri.gambar. Untuk galerijenis = url, nilai tersebutnull, sehingga selalu menampilkan "Tidak ada gambar yang ditampilkan!" di kedua tema.media-src 'self'danframe-srctanpadrive.google.commembuat video eksternal tidak dapat diputar di environment production.Impact of change:
✅ Video Google Drive & YouTube tampil di halaman detail galeri (Web) dan dapat diputar langsung dari admin
✅ Konsistensi tampilan: media berbasis link kini diperlakukan sama dengan media hasil upload di Admin maupun Web
✅ Deteksi otomatis: admin tidak wajib memilih tipe untuk tautan yang ekstensinya jelas (
.jpg,.mp4, YouTube)✅ Penanganan kasus Drive: foto Drive dipetakan ke
uc?export=view, video Drive dipetakan ke previewfile/d/ID/previewyang mendukung pemutaran✅ Validasi lebih ketat: tautan yang bukan URL http(s) ditolak saat menyimpan, bukan gagal diam-diam saat tampil
✅ CSP lebih dirawat: directive CSP kini berada di kelas terpisah dan dapat diuji per directive
Related Issue
Steps to Reproduce
Before fix (problem):
keclongikis.paserkab.go.idno-image.png; video Drive tidak pernah bisa diputarAfter fix (solution):
videodan diputar lewat preview resmi Drive)HEADke Google Drive dipakai untuk memastikan apakah isinya foto atau video; bila probing gagal, admin dapat memilih Tipe Media → Video secara manualTesting on related features:
gambar_pathuntukjenis = filetetap memakai storage lokaljenis = file(upload banyak foto) ✅ kompatibel penuhjenis = urlnon-media (mis. tautan biasa) ✅ tetap disimpan, hanya menampilkan tautan tanpa embed/api/frontend/v1/galeri✅ respons kini memuatmedia_type,media_url,media_embed_urldefaultdanbuen✅ keduanya sudah disesuaikanvalid_file✅ tidak berubahChecklist
Technical Details
Technical Explanation
Alur resolusi link
MediaLinkService::resolve()bersifat murni (tanpa jaringan) dan mengubah link menjadiMediaLinkberisitype,id,url,embedUrl,thumbnail:url(src)embedUrl(iframe)thumbnailwatch,youtu.be,embed,shorts,live)youtubeyoutube.com/embed/{id}img.youtube.com/vi/{id}/hqdefault.jpgimagedrive.google.com/uc?export=view&id=urlvideodrive.google.com/uc?export=download&id=drive.google.com/file/d/{id}/previewvideoplayer.vimeo.com/video/{id}*.jpg/.png/.gif/.webp/...image*.mp4/.webm/.ogv/.mov/...videounknownMengapa ada probing HTTP
probe()mengirimHEAD(timeout 5 detik, maksimal 3 redirect) dan membacaContent-Type; bila generik (application/octet-stream, hal yang sering terjadi pada Drive), ia jatuh keContent-Dispositionuntuk melihat ekstensi nama berkas. Untuk link Drive, target probing adalahuc?export=download&id=karena/file/d/ID/viewhanya menyajikan halaman HTML. Kegagalan probing tidak menggagalkan penyimpanan — tipe kembali ke hasil resolusi.Probing tidak pernah dijalankan bila admin memilih tipe secara manual, sehingga form tetap berfungsi di lingkungan tanpa akses jaringan keluar.
Model
Kolom
media_typeyang tersimpan selalu lebih dipercaya daripada menebak ulang dari URL;gambar_pathkini diturunkan darimedia()->thumbnailsehingga tetap kompatibel dengan tema lama.Rendering
<x-galeri-media :galeri="$galeri" variant="thumb|full" />renderGaleriMedia(galeri, options)dipublic/js/custom.js, dipakai kedua tema sehingga tidak ada duplikasi logikaPerbaikan URL storage
asset('storage/publikasi/galeri/')membuang garis miring di akhir, sehingga penggabungan langsung dengan nama berkas akan menghasilkan.../galerifoto.jpg. Sekarang base URL dihitung terpisah dan pemisah ditambahkan eksplisit:Configuration changes
Tidak ada perubahan pada file
.envatauconfig/. CSP dipindahkan dari string satu baris di middleware ke konstantaApp\Support\CspPolicy::DIRECTIVESdengan dua directive yang diperluas:Dependencies added
No new dependencies
Testing
Manual Testing
.mp4/.jpg— tampil sesuai tipelinkdengan teks bukan URL — ditolak dengan pesan validasifilekeurl— gambar lama terhapus,media_typeterisiurlkefile—linkdanmedia_typedikosongkandefaultdanbuenAutomated Testing
tests/Unit/Services/MediaLinkServiceTest.php— 27 test (YouTube, Google Drive, file langsung, Vimeo, fallback, probing,detectType)tests/Unit/Models/GaleriTest.php— 8 test (accessormedia_type/media_url/media_embed_urldan serialisasi API)tests/Unit/Support/CspPolicyTest.php— 5 test (per directive CSP)tests/Feature/GaleriControllerTest.php— 19 test (9 test baru: Drive video/foto, manual override, validasi, perpindahanfile↔url, pratinjau form, kolom DataTable)tests/Feature/Api/Frontend/GaleriControllerTest.php— 4 test baru (bentuk payload media pada API)tests/Feature/PublikasiGaleriPublikTest.php— 4 test baru (render halaman publik, URL storage tanpa regresi separator)Total: 95 test lulus, 273 assertion pada 9 file yang relevan.
Catatan: terdapat 13 kegagalan test yang sudah ada sebelumnya dan tidak berkaitan dengan PR ini (
ModelScopesTest,InternalApiTest,FileUploadTest,ArtikelControllerTest,AuthorizationTest,FilePreviewFeatureTest,PendudukExportTest) — sudah diverifikasi menghasilkan output identik ketika seluruh kode PR ini dihapus.Browser Compatibility
Screenshots / Video
Belum tersedia. Disarankan menyertakan perekaman layar untuk: (1) form Tambah Galeri dengan pratinjau link video Google Drive, (2) halaman detail galeri di Web yang memutar video, (3) tampilan tema
buen.Before:
After:
Breaking Changes
None secara fungsional — kolom
galeris.media_typebersifat nullable dan seluruh field lama (gambar_path,link,jenis) tetap tidak berubah perilakunya.linkkini memerlukan URLhttp/https. Galeri lama yang menyimpanlinknon-URL tidak ikut terhapus, namun tidak dapat diedit tanpa memperbaikinya lebih dahulu.Migration Guide
Wajib menjalankan migration pada server yang telah terpasang:
Migration menambahkan kolom
galeris.media_type(nullable, panjang 20). Tidak ada data yang diubah atau dihapus.📝 Catatan untuk data lama: baris galeri yang sudah ada akan bernilai
NULLpadamedia_type.Baris yang tidak ada di kategori tersebut dapat dibiarkan
NULL(bermapped keunknown).References
media-src<video>elementAdditional notes:
albums.gambar) sengaja tidak diubah — hanya galeri yang menjadi objek laporan. Dapat dijadikan PR terpisah bila diperlukan.MediaLinkService::probe()melakukan outbound HTTP saat penyimpanan galeri. Mohon konfirmasi apakah server desa diizinkan melakukan request keluar kedrive.google.com.