martin3r/platform-media

Media Service for Platform

dev-main 2025-09-08 08:13 UTC

This package is auto-updated.

Last update: 2025-09-08 08:15:55 UTC


README

Ein zentraler Media Service für die Platform mit Upload, Verwaltung und Wiederverwendung von Dateien über verschiedene Module hinweg.

🚀 Installation & Setup

1. Service Provider registrieren

Füge den Media Service Provider in der Zielanwendung hinzu:

// config/app.php
'providers' => [
    // ...
    Platform\Media\MediaServiceProvider::class,
],

2. Config publishen

php artisan vendor:publish --tag=media-config

3. .env Konfiguration

# Media Service Configuration
MEDIA_DISK=wasabi
MEDIA_MAX_SIZE=52428800
MEDIA_CHUNK_SIZE=1048576
MEDIA_CONCURRENT_UPLOADS=3
MEDIA_PER_PAGE=20
MEDIA_POOL_PER_PAGE=50

# Storage Configuration (bereits vorhanden)
FILESYSTEMS_DISK=wasabi
WASABI_ACCESS_KEY_ID=your_key
WASABI_SECRET_ACCESS_KEY=your_secret
WASABI_DEFAULT_REGION=eu-central-1
WASABI_BUCKET=your_bucket
WASABI_URL=https://s3.eu-central-1.wasabisys.com

4. Migrations ausführen

php artisan migrate

5. Seeder ausführen

php artisan db:seed --class=Platform\\Media\\Database\\Seeders\\MediaMimeTypeSeeder

📋 Features

Zentrale Media Pool + Kontextuelle Duplikation

Der Media Service implementiert ein intelligentes System für die Dateiverwaltung:

Konzept

  • Media Pool: Zentrale Dateiverwaltung für wiederverwendbare Medien
  • Kontextuelle Duplikation: Dateien werden in kontextspezifische Pfade dupliziert
  • Unabhängige Verwaltung: Jeder Kontext kann seine Dateien unabhängig löschen

Workflow

  1. Upload in Pool: Datei wird zentral hochgeladen
  2. Verwendung in Kontext: Datei wird in kontextspezifischen Pfad dupliziert
  3. Unabhängige Löschung: Kontext-Dateien können gelöscht werden ohne Pool zu beeinflussen

S3-Struktur

bucket/
├── {env}/media-pool/shared/          # Zentrale Dateien
│   ├── 2025/01/
│   └── 2025/02/
├── {env}/internal/                   # Kontext-Dateien
│   ├── hcm/123/2025/01/
│   ├── food-service/456/2025/01/
│   └── okr/789/2025/01/
├── {env}/public/                     # Öffentliche Dateien
└── {env}/private/                    # Private Dateien

Datenbank-Beispiel

-- Pool-Datei
INSERT INTO media_files (path, is_pool_file, category) 
VALUES ('local/media-pool/shared/2025/01/abc123.jpg', true, 'pool');

-- Kontext-Datei (dupliziert)
INSERT INTO media_files (path, is_pool_file, category, hash) 
VALUES ('local/internal/hcm/123/2025/01/def456.jpg', false, 'hcm', 'same_hash_as_pool');

Livewire Components

Media Pool Manager

  • Übersicht: Alle Pool-Dateien mit Filterung
  • Upload: Drag & Drop Upload in Pool
  • Verwendung: Dateien in Kontexte duplizieren
  • Löschung: Pool-Dateien verwalten

Media Selector (für andere Module)

  • Pool-Browse: Durchsuchen verfügbarer Pool-Dateien
  • Upload: Neue Dateien direkt hochladen
  • Duplikation: Pool-Dateien in Kontext duplizieren
  • Vorschau: Bild-Preview und Meta-Informationen

Service Functions

storeToPool()

$mediaFile = $mediaService->storeToPool($uploadedFile, [
    'description' => 'Logo für Website',
    'tags' => ['logo', 'branding']
]);

duplicateFromPool()

$contextFile = $mediaService->duplicateFromPool($poolFile, 'hcm', [
    'attached_to' => 'employee_profile',
    'employee_id' => 123
]);

Event: MediaDuplicatedFromPool

Event::listen(MediaDuplicatedFromPool::class, function ($event) {
    Log::info("Datei dupliziert", [
        'pool_file' => $event->poolFile->id,
        'context_file' => $event->contextFile->id,
        'context' => $event->context
    ]);
});

🔧 Verwendung in anderen Modulen

HCM Module

use Platform\Media\Traits\HasMedia;

class Employee extends Model
{
    use HasMedia;
    
    public function mediaStorageModelSegment(): string
    {
        return 'hcm';
    }
    
    public function mediaStorageIdSegment(): string
    {
        return $this->id;
    }
}

// Verwendung
$employee = Employee::find(1);
$mediaFile = $mediaService->duplicateFromPoolToModel($poolFile, $employee);

Food Service Module

class Recipe extends Model
{
    use HasMedia;
    
    public function mediaStorageModelSegment(): string
    {
        return 'food-service';
    }
    
    public function mediaStorageExtraSegments(): array
    {
        return ['recipes'];
    }
}

OKR Module

class Objective extends Model
{
    use HasMedia;
    
    public function mediaStorageModelSegment(): string
    {
        return 'okr';
    }
}

🎨 UI Integration

Media Selector Component

// In anderen Livewire Components
use Platform\Media\Livewire\MediaSelector;

class EmployeeForm extends Component
{
    public function render()
    {
        return view('livewire.employee.form', [
            'mediaSelector' => MediaSelector::class
        ]);
    }
}

Blade Template

<div>
    <h3>Profilbild</h3>
    @livewire('media-selector', [
        'model' => $employee,
        'role' => 'profile_image'
    ])
</div>

📁 Datenbank-Schema

media_mime_types

CREATE TABLE media_mime_types (
    id BIGINT PRIMARY KEY,
    mime_type VARCHAR(255) UNIQUE,
    description VARCHAR(255),
    extension VARCHAR(10),
    is_image BOOLEAN,
    is_video BOOLEAN,
    is_document BOOLEAN,
    is_audio BOOLEAN,
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);

media_files

CREATE TABLE media_files (
    id BIGINT PRIMARY KEY,
    disk VARCHAR(50),
    path VARCHAR(500),
    original_name VARCHAR(255),
    hash VARCHAR(64) UNIQUE,
    mime_type_id BIGINT,
    file_size BIGINT,
    meta JSON,
    width INTEGER,
    height INTEGER,
    is_pool_file BOOLEAN,
    category VARCHAR(100),
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);

media_attachments

CREATE TABLE media_attachments (
    id BIGINT PRIMARY KEY,
    attachable_type VARCHAR(255),
    attachable_id BIGINT,
    media_file_id BIGINT,
    role VARCHAR(100),
    position INTEGER,
    realm VARCHAR(50),
    access_scope_type VARCHAR(255),
    access_scope_id BIGINT,
    meta JSON,
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);

media_image_variants

CREATE TABLE media_image_variants (
    id BIGINT PRIMARY KEY,
    media_file_id BIGINT,
    variant_name VARCHAR(100),
    file_path VARCHAR(500),
    file_size BIGINT,
    width INTEGER,
    height INTEGER,
    format VARCHAR(10),
    quality INTEGER,
    meta JSON,
    created_at TIMESTAMP,
    updated_at TIMESTAMP
);

🔧 Konfiguration

config/media.php

return [
    'storage' => [
        'disk' => env('MEDIA_DISK', 'wasabi'),
        'prefixes' => [
            'public' => '{env}/public',
            'internal' => '{env}/internal',
            'private' => '{env}/private',
            'pool' => '{env}/media-pool/shared',
        ],
        'image_variants' => [
            'formats' => [
                '4_3' => [300, 225, 800, 600, 1200, 900, 2400, 1800],
                '16_9' => [300, 169, 800, 450, 1200, 675, 2400, 1350],
                '1_1' => [300, 300, 800, 800, 1200, 1200, 2400, 2400],
                '9_16' => [300, 533, 800, 1422, 1200, 2133, 2400, 4267],
                '3_1' => [300, 100, 900, 300, 1500, 500, 3000, 1000],
                'original' => [300, null, 800, null, 1200, null, 2400, null],
            ],
            'format' => 'webp',
            'quality' => 90,
        ],
    ],
    'upload' => [
        'max_size' => env('MEDIA_MAX_SIZE', 50 * 1024 * 1024),
        'allowed_mimes' => [
            'image/jpeg', 'image/png', 'image/gif', 'image/webp',
            'video/mp4', 'video/avi', 'video/mov',
            'audio/mpeg', 'audio/wav', 'audio/ogg',
            'application/pdf', 'application/msword',
            // ... weitere MIME-Types
        ],
    ],
];

🚀 Roadmap

Phase 1: Basis-Funktionalität ✅

  • Service-Architektur mit Contracts
  • Upload-Funktionalität (Pool + Kontext)
  • Bildvarianten-Generierung
  • Livewire Upload-Komponente
  • Dashboard und UI

Phase 2: Erweiterte Features

  • FilePond-ähnliche Upload-Experience
  • Image Cropping und Editing
  • Batch-Uploads und Chunked Uploads
  • Drag & Drop zwischen Modulen
  • Erweiterte Suche und Filterung

Phase 3: Advanced Features

  • AI-basierte Bildanalyse
  • Automatische Tagging
  • Duplikatserkennung mit visueller Ähnlichkeit
  • CDN-Integration
  • Backup und Recovery

📝 Changelog

v1.0.0

  • Initiale Version mit Service-Architektur
  • Upload-Funktionalität (Pool + Kontext)
  • Bildvarianten-Generierung
  • Livewire Integration
  • Dashboard und UI
  • MIME-Type Management
  • Polymorphe Beziehungen