Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Mediable Laravel Package

plank/laravel-mediable

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require plank/laravel-mediable:^7.0

Publish the config and migrations:

php artisan vendor:publish --provider="Plank\Mediable\MediableServiceProvider"
php artisan migrate
  1. First Use Case (Updated for Security): Upload a file with enhanced security checks:

    use Plank\Mediable\HasMediable;
    use Plank\Mediable\MediaUploader;
    use Plank\Mediable\Enum\OnDuplicateBehaviour;
    
    class Post extends Model
    {
        use HasMediable;
    }
    
    // In your controller:
    $post = Post::find(1);
    $media = MediaUploader::fromRequest($request, 'image')
        ->toDestination('public', 'posts/thumbnails')
        ->onDuplicate(OnDuplicateBehaviour::RENAME) // Use enum instead of constant
        ->upload();
    $post->addMedia($media)->usingCollection('thumbnails')->save();
    
  2. Key Files (Updated):

    • config/mediable.php: Configure new security settings (remote hosts, schemes, forbidden extensions/MIME types, sanitizers).
    • app/Models/Media.php: Base model for media records (extend if needed).
    • app/Models/Mediable.php: Trait for polymorphic media relationships.
    • New: Plank\Mediable\MediaUploaderConfiguration class for cleaner config handling.

Implementation Patterns

Core Workflows

1. Uploading Media (Security-Focused)

  • Basic Upload with Security:
    $media = MediaUploader::fromRequest($request, 'image')
        ->toDestination('public', 'uploads')
        ->setForbiddenExtensions(['php', 'exe']) // Block dangerous extensions
        ->setForbiddenMimeTypes(['text/x-php', 'application/x-httpd-php'])
        ->upload();
    
  • Remote URL Upload (Restricted Hosts):
    // config/mediable.php
    'allowed_remote_hosts' => ['*.example.com', 'cdn.example.org'],
    'allowed_remote_schemes' => ['https'],
    
    // In code:
    $media = MediaUploader::fromRemoteUrl('https://example.com/image.jpg')
        ->toDestination('public', 'remote')
        ->upload(); // Will reject non-whitelisted hosts
    
  • SVG Sanitization (Auto-Enabled): SVG files are now automatically sanitized to prevent XSS. Disable in config/mediable.php:
    'sanitizers' => [
        // 'Plank\Mediable\Sanitizers\SvgSanitizer' => false, // Disable
    ],
    

2. Attaching Media to Models

  • Polymorphic Relationships (Unchanged):
    $post->addMedia($media)->usingCollection('featured')->save();
    
  • Tagging Media (Unchanged):
    $media->tags()->sync(['thumbnail', 'primary']);
    

3. Retrieving Media (Unchanged)

  • By Collection:
    $post->getMedia('thumbnails');
    
  • URL Generation:
    $media->getUrl();
    

4. Image Manipulation (Unchanged)

  • Generate Variants:
    $media->generateVariant(['width' => 300, 'height' => 200], 'thumbnail');
    

5. Deleting Media (Unchanged)

  • From Model:
    $post->deleteMedia($media, 'thumbnails');
    

Integration Tips

1. Customizing Media Model (Unchanged)

Extend the Media model as before.

2. Custom Upload Logic (Updated)

Use MediaUploaderConfiguration for cleaner config:

$config = new MediaUploaderConfiguration([
    'disk' => 's3',
    'destination_path' => 'custom/path',
    'forbidden_extensions' => ['php', 'exe'],
]);
$uploader = new MediaUploader($config);
$media = $uploader->fromRequest($request, 'file')->upload();

3. Filesystem Configuration (Updated)

Configure new security settings in config/mediable.php:

'disks' => ['public', 's3'],
'allowed_remote_hosts' => ['*.trusted.com'],
'allowed_remote_schemes' => ['https'],
'forbidden_file_extensions' => ['php', 'exe', 'pl', 'bat'],
'forbidden_mime_types' => ['text/x-php', 'application/x-httpd-php'],
'sanitizers' => [
    'Plank\Mediable\Sanitizers\SvgSanitizer' => true,
],

4. API Responses (Unchanged)

Serialize media with relationships as before.

5. Testing (Updated)

Test security restrictions:

// Test forbidden extension rejection
$this->expectException(\Plank\Mediable\Exceptions\ForbiddenFileExtension::class);
MediaUploader::fromSource(fake()->createFile('script.php.jpg'))
    ->toDestination('public', 'test')
    ->upload();

Gotchas and Tips

Pitfalls

  1. SSRF Protection (New)

    • Remote URL uploads now block private IPs and localhost by default (CVE-2026-49969).
    • Configure allowed_remote_hosts to whitelist trusted domains:
      'allowed_remote_hosts' => ['*.yourdomain.com'],
      
    • Wildcards supported: *.sub.example.com.
  2. Directory Traversal (Fixed)

    • Paths are now sanitized to strip . characters (CVE-2026-49970).
    • Example: ../../evil.phpevil.php (blocked).
    • No longer possible to bypass with ../ or hidden files.
  3. Forbidden Extensions/MIME Types (New)

    • Default blacklist includes php, exe, pl, bat, etc.
    • Double extensions are sanitized: script.php.jpgscript-php.jpg.
    • Configure in config/mediable.php:
      'forbidden_file_extensions' => ['php', 'exe', 'phtml'],
      'forbidden_mime_types' => ['text/x-php', 'application/x-httpd-php'],
      
  4. SVG Sanitization (New)

    • All SVG uploads are sanitized by default to prevent XSS.
    • Disable in config/mediable.php if needed (not recommended):
      'sanitizers' => [
          'Plank\Mediable\Sanitizers\SvgSanitizer' => false,
      ],
      
  5. Breaking Changes

    • ON_DUPLICATE_* constants → Plank\Mediable\Enum\OnDuplicateBehaviour enum. Update calls like:
      // Old:
      ->onDuplicate(MediaUploader::ON_DUPLICATE_RENAME)
      
      // New:
      ->onDuplicate(OnDuplicateBehaviour::RENAME)
      
    • MediaUploader now accepts MediaUploaderConfiguration instead of raw arrays.
  6. Large Files (Unchanged)

    • Adjust php.ini (upload_max_filesize, post_max_size) and Laravel’s MAX_FILE_SIZE in forms.
  7. Tagging Quirks (Unchanged)

    • Tags remain case-sensitive.

Debugging Tips

  1. Log Security Rejections Add logging for blocked uploads:

    $uploader->beforeUpload(function ($file) {
        if ($file->isValid()) {
            \Log::debug('Upload allowed', ['file' => $file->getClientOriginalName()]);
        } else {
            \Log::warning('Upload blocked', [
                'file' => $file->getClientOriginalName(),
                'reason' => $file->getError(),
            ]);
        }
    });
    
  2. Check Remote URL Restrictions Verify allowed_remote_hosts and allowed_remote_schemes:

    $uploader = MediaUploader::fromRemoteUrl('https://untrusted.com/file.jpg');
    // Will throw \Plank\Mediable\Exceptions\ForbiddenRemoteHost if untrusted.
    
  3. Inspect Sanitized Paths Debug path sanitization:

    $path = $uploader->getDestinationPath();
    \Log::debug('Sanitized path', ['path' => $path]);
    
  4. Validate Forbidden Extensions Test extension blocking

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky