# Medya Yönetimi ve Görsel İşleme Altyapısı

Bu doküman, **Üst Manşet** projesinin Aşama 6 kapsamında geliştirilen Medya Kütüphanesi ve Görsel İşleme altyapısının teknik detaylarını, mimarisini, veri güvenliği önlemlerini ve kullanım detaylarını açıklamaktadır.

---

## 1. Mimari Genel Bakış

Medya yönetim altyapısı, haber görsellerinin güvenli bir şekilde saklanmasını, optimize edilmesini, duyarlı tasarım (responsive) varyantlarının asenkron olarak üretilmesini ve odak noktası (focal point) belirleme özelliklerini kapsar.

```mermaid
graph TD
    A[Kullanıcı Arayüzü / Dropzone] -->|Yükleme İsteği| B[MediaController@store]
    B -->|Upload| C[MediaUploadService]
    C -->|MIME & Boyut Doğrulama| D[Intervention Image]
    C -->|SHA-256 Hash Kontrolü| E{Mevcut Aktif Hash Var mı?}
    E -->|Evet: Conflict| F[Var Olan Medya Sayfasına Yönlendir]
    E -->|Evet: Arşivlenmiş| G[Otomatik Aktifleştir & Yönlendir]
    E -->|Hayır| H[Orijinal Dosyayı Private Diske Yaz]
    H -->|local disk: media-originals/| I[Medya DB Kaydını Oluştur]
    I -->|Pending Status| J[GenerateMediaVariantsJob Kuyruğa Ekle]
    J -->|Queue Worker| K[ImageProcessingService]
    K -->|WebP Varyantları Üret| L[Public Diske Kaydet: media/]
    L -->|Bulk Insert| M[media_variants Tablosu]
    M -->|Status: Completed| N[Kullanıma Hazır Görsel]
```

---

## 2. Orijinal Dosya Güvenliği ve Varyant Seti

### Orijinal Dosya Güvenliği
Ham orijinal görseller kesinlikle dışarıdan erişilebilir `public` dizin altında saklanmaz.
- **Private Disk (local)**: `media-originals/YYYY/MM/{uuid}/original.{extension}`
- Ham dosyalar doğrudan public URL alamaz ve ziyaretçiler tarafından indirilip taranamaz.

### Public Varyant Seti (WebP)
Görsellerin site genelinde hızlı yüklenmesi amacıyla tüm varyantlar **WebP** formatında (Kalite: 85), PNG şeffaflığı (Alpha) korunarak `public` disk altında saklanır:
- `thumbnail`: 240x160 piksel, odak noktası merkezli (cover)
- `small`: 480x270 piksel (16:9), odak noktası merkezli (cover)
- `medium`: 800x450 piksel (16:9), odak noktası merkezli (cover)
- `large`: 1280x720 piksel (16:9), odak noktası merkezli (cover)
- `social`: 1200x630 piksel (1.91:1), odak noktası merkezli (cover)
- `optimized_original`: Maksimum 1920x1920 piksel, orijinal en-boy oranı korunarak orantılı ölçekleme (Upscale korumalı - görsel hiçbir koşulda büyütülmez).

---

## 3. Veritabanı Şeması

### `media` Tablosu
Her yüklenen ana görseli ve onun meta/telif bilgilerini tutar:
- `id`: primary key
- `uuid`: char(36), benzersiz görsel kimliği
- `disk`: varchar(30), orijinal dosyanın tutulduğu disk ('local')
- `directory`: varchar(255), varyantların saklandığı göreli dizin
- `filename`: varchar(255), orijinal dosyanın adı (`original.ext`)
- `original_filename`: varchar(255), kullanıcının yüklediği dosyanın gerçek adı
- `mime_type`: varchar(100), 'image/jpeg', 'image/png' vb.
- `extension`: varchar(10), orijinal dosya uzantısı
- `size`: unsigned bigint, byte cinsinden boyut
- `width` / `height`: unsigned int, piksel cinsinden çözünürlük
- `hash`: char(64), SHA-256 dosya hash'i (mükerrer yükleme tespiti için)
- `status`: enum('active', 'archived'), varsayılan 'active'
- `processing_status`: enum('pending', 'processing', 'completed', 'failed')
- `processing_error`: text, nullable (işleme hata aldığında kaydedilir)
- `focal_point_x` / `focal_point_y`: decimal(5,4), varsayılan 0.5000 (0.0000 - 1.0000 arası)
- `title` / `alt_text` / `caption` / `description`: metin alanları (SEO ve erişilebilirlik için)
- `credit` / `source` / `copyright` / `license_type`: telif ve kaynak sahipliği bilgileri
- `taken_at`: timestamp, nullable (çekim tarihi - EXIF'ten otomatik alınabilir)
- `uploaded_by`: foreign key (users)

### `media_variants` Tablosu
Üretilen optimize edilmiş alt varyantların dosya yollarını ve boyutlarını tutar:
- `id`: primary key
- `media_id`: foreign key (media.id - cascade on delete)
- `variant`: varchar(50), varyant adı ('thumbnail', 'small' vb.)
- `disk`: varchar(30), 'public'
- `path`: varchar(255), dosya yolu
- `mime_type`: varchar(100), 'image/webp'
- `extension`: varchar(10), 'webp'
- `size`: unsigned bigint
- `width` / `height`: unsigned int

---

## 4. Odak Noktası (Focal Point) ve Kırpma Teknolojisi

Odak noktası, görselin responsive kırpılması esnasında kadraj dışı kalmaması gereken ana unsuru (insan yüzü, bina vb.) korumak için tasarlanmıştır.

- **Frontend Arayüzü**: Kullanıcı düzenleme sayfasında görsel üzerinde bir noktaya tıklar. Tıklanan nokta Alpine.js ile 0.0000 ile 1.0000 arasında X ve Y koordinatlarına dönüştürülür.
- **Backend Entegrasyonu**: Koordinatlar [0.0, 1.0] aralığında doğrulanır. Eğer koordinatlar değişirse, görselin tüm varyantlarının kırpma konumları yeniden hesaplanır ve arka plan job'ı tetiklenir.
- **Intervention Image Entegrasyonu**: Koordinatlar `ImageProcessingService` tarafından Intervention Image'in cover pozisyon parametrelerine (`top-left`, `top`, `top-right`, `left`, `center`, `right`, `bottom-left`, `bottom`, `bottom-right`) map edilir:
  - X < 0.35: `left` | X > 0.65: `right` | aksi halde: `center`
  - Y < 0.35: `top` | Y > 0.65: `bottom` | aksi halde: boşluk

---

## 5. Mükerrer Görsel Yükleme (Duplicate Hash) Engelleme

Gereksiz disk kullanımını ve sunucu yükünü engellemek için yüklenen her görselin SHA-256 hash'i alınır ve veritabanında taranır.

1. **Aktif Eşleşme**: Eğer görsel sistemde zaten aktif olarak bulunuyorsa, yeni dosya yazılmaz ve yeni kayıt oluşturulmaz. Kullanıcı, mevcut medyanın detay düzenleme sayfasına yönlendirilir ve Türkçe bilgilendirme mesajı gösterilir.
2. **Arşivlenmiş Eşleşme**: Eğer görsel sistemde bulunuyor ancak daha önce arşivlenmiş ise, kayıt otomatik olarak arşivden çıkarılarak `active` durumuna getirilir ve kullanıcı düzenleme sayfasına yönlendirilir.

---

## 6. Asenkron İşleme ve Hata Yönetimi

Görsel boyutlandırma ve WebP dönüştürme işlemleri yüksek işlemci (CPU) kaynağı tükettiği için kuyruk (Queue) üzerinden asenkron yürütülür:
- Kuyruk Kanalı: `media` kuyruğu öncelikli olmak üzere `php artisan queue:work --queue=media,default`.
- **Eşzamanlılık Koruması**: `GenerateMediaVariantsJob`, aynı medya kaydı için birden fazla işleyicinin çalışmasını önlemek amacıyla `lockForUpdate()` kullanarak durum kontrolü yapar.
- **Dosya Güvenliği (Rollback)**: İşleme adımlarından herhangi biri hata verirse, o adıma kadar oluşturulmuş tüm kısmi dosyalar sunucudan silinerek yetim (orphan) dosyaların birikmesi engellenir. Hata detayı veritabanında `processing_error` alanına kaydedilir ve durum `failed` olarak işaretlenir.

---

## 7. Arayüz Bileşenleri

### `<x-ui.file-dropzone>`
- Sürükle-bırak desteği.
- İstemci tarafında anlık görsel önizleme, isim ve boyut gösterimi.
- Boyut (>10MB) ve MIME (yalnızca JPEG, PNG, WebP) kısıtlamalarının istemci tarafında Alpine.js ile hızlı kontrolü.
- Klavye odaklanma ve klavye kısayolları (Space/Enter) ile erişilebilirlik.

### `<x-ui.media-picker>`
- Yazar, haber vb. formlarda profil/kapak resmi seçmek için tasarlanmış minimalist modüler seçici.
- "Görsel Seç" butonu tıklandığında açılan arama ve sayfalama destekli asenkron modal.
- Seçim yapıldığında önizleme gösterme ve seçimi tek tıkla kaldırma olanağı.

---

## 8. Yetkilendirme (Permissions)

Medya işlemleri için Spatie Permission üzerinde 7 yeni yetki tanımlanmış ve rollere dağıtılmıştır:
- `media.view`: Kütüphaneyi görüntüleme ve listeleme.
- `media.upload`: Yeni görsel yükleme.
- `media.update`: Görsel meta verilerini güncelleme.
- `media.archive`: Görseli arşivleme (yeni içeriklerde kullanılmasını engelleme).
- `media.restore`: Arşivlenmiş görseli tekrar kullanıma açma.
- `media.manage_all`: Diğer kullanıcıların yüklediği görselleri de yönetebilme.
- `media.manage_metadata`: Odak noktası (focal point) belirleme yetkisi.
