martin3r / platform-media
Media Service for Platform
dev-main
2025-09-08 08:13 UTC
Requires
- intervention/image: ^3.11
- league/flysystem-aws-s3-v3: ^3.0
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
- Upload in Pool: Datei wird zentral hochgeladen
- Verwendung in Kontext: Datei wird in kontextspezifischen Pfad dupliziert
- 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