Contensio logo

Media lifecycle hooks

Action hooks fired when files are uploaded or deleted from the media library.

Since 1.4.0

These action hooks fire during upload and deletion in the media library. Each hook receives a Media model (or just the ID after deletion) so your plugin can react to file changes without polling the database.


contensio/media/uploaded

Type: Action
Since: 1.4.0
Source: MediaController::upload()

Fired after a file has been stored on disk and the Media database record has been created. Fires once per file — if a user uploads three files in a single batch, this hook fires three times.

For image files, the ProcessMediaVariants job is dispatched just before this hook fires, so variant generation (thumbnail, medium) may still be in progress when your callback runs.

Arguments

# Name Type Description
1 $media Media The newly created media record.

Media properties

Property Type Description
$media->id int Database ID
$media->file_name string Original filename as uploaded by the user
$media->file_path string Storage-relative path (uploads/2026/04/uuid.jpg)
$media->mime_type string MIME type (image/jpeg, application/pdf, etc.)
$media->file_size int Size in bytes
$media->width int|null Pixel width — images only
$media->height int|null Pixel height — images only
$media->disk string Laravel storage disk name (default: public)
$media->isImage() bool Helper method — true if MIME starts with image/

Example — sync to a CDN after upload

use Contensio\Models\Media;

add_action('contensio/media/uploaded', function (Media $media) {
    if (! $media->isImage()) return;

    CdnSync::push(
        storage_path('app/public/' . $media->file_path),
        $media->file_name
    );
});

Example — reject file types outside an allowlist

add_action('contensio/media/uploaded', function (Media $media) {
    $allowed = ['image/jpeg', 'image/png', 'image/webp', 'application/pdf'];

    if (! in_array($media->mime_type, $allowed)) {
        Storage::disk($media->disk)->delete($media->file_path);
        $media->delete();
    }
});

Notes

  • Variant images (thumbnail, medium) are queued before this hook fires and may not yet exist on disk when your callback runs. If your callback needs variants, listen for a later point (e.g. a custom event dispatched from your own ProcessMediaVariants replacement).
  • This hook fires for every file type — images, PDFs, videos, etc. Use $media->isImage() or check $media->mime_type if your callback is image-specific.

contensio/media/deleting

Type: Action
Since: 1.4.0
Source: MediaController::destroy()

Fired just before the file is removed from disk and the database record is deleted. All variant records are still in the database and all files are still on disk when this hook runs.

Arguments

# Name Type Description
1 $media Media The media entry about to be deleted, with variants eager-loaded.

Example

use Contensio\Models\Media;

add_action('contensio/media/deleting', function (Media $media) {
    // Remove from CDN before we lose the path
    CdnSync::delete($media->file_name);
    foreach ($media->variants as $variant) {
        CdnSync::delete($variant->path);
    }
});

Notes

  • Use this hook (not contensio/media/deleted) when you need access to the file path, filename, or variant records.
  • Both the original file and all variant files are deleted after this hook returns.

contensio/media/deleted

Type: Action
Since: 1.4.0
Source: MediaController::destroy()

Fired after the file has been removed from disk and the Media database record has been deleted. Only the original ID is available.

Arguments

# Name Type Description
1 $id int The ID of the deleted media record.

Example

add_action('contensio/media/deleted', function (int $id) {
    AuditLog::record('media.deleted', $id);
    Cache::forget("media:{$id}");
});

Notes

  • The database record and all variant records are already gone. Do not attempt Media::find($id).
  • If you need file path or filename, use contensio/media/deleting instead.

See also