Drupal is a registered trademark of Dries Buytaert
cms 2.1.2 Update released for Drupal core (2.1.2)! drupal 11.1.10 Update released for Drupal core (11.1.10)! drupal 10.5.10 Update released for Drupal core (10.5.10)! drupal 10.4.10 Update released for Drupal core (10.4.10)! drupal 11.2.12 Update released for Drupal core (11.2.12)! drupal 11.3.10 Update released for Drupal core (11.3.10)! drupal 10.6.9 Update released for Drupal core (10.6.9)! drupal 10.6.8 Update released for Drupal core (10.6.8)! drupal 11.3.9 Update released for Drupal core (11.3.9)! drupal 11.3.8 Update released for Drupal core (11.3.8)! drupal 11.3.7 Update released for Drupal core (11.3.7)! drupal 11.2.11 Update released for Drupal core (11.2.11)! drupal 10.6.7 Update released for Drupal core (10.6.7)! drupal 10.5.9 Update released for Drupal core (10.5.9)! cms 2.1.1 Update released for Drupal core (2.1.1)! drupal 11.3.6 Update released for Drupal core (11.3.6)! drupal 10.6.6 Update released for Drupal core (10.6.6)! cms 2.1.0 Update released for Drupal core (2.1.0)! linkit 7.0.15 Minor update available for module linkit (7.0.15). views_data_export 8.x-1.10 Minor update available for module views_data_export (8.x-1.10).

Automatically manages file status (temporary / permanent) and tracking (file.usage) for custom forms built with the Drupal Form API.

The Problem

When you use managed_file or text_format (CKEditor) elements in custom forms (e.g., Configuration forms, Block plugins, Custom states), uploaded files and inline images are initially saved with a temporary status.

Unlike standard Entity fields, custom Form API elements do not automatically bind files to a storage context. As a result, Drupal core unaware of their usage, and cron will eventually delete these files.

Developers usually have to write tedious boilerplate code in submitForm() using file.usage service and manual HTML parsing for CKEditor UUIDs to fix this.

The Solution

The Form File Usage module completely automates this process. It monitors targeted form elements, tracks incremental data changes (detecting newly added or removed files/images), marks them as permanent, and handles automatic cleanup via `file.usage` once they are removed from the form.

Features

  1. Zero Boilerplate: No need to write manual file tracking code in your submit handlers anymore.
  2. Automatic Config Detection: Automatically discovers configuration names for forms inheriting from ConfigFormBase.
  3. CKEditor 5 Support: Parses text formats to extract inline image UUIDs (data-entity-uuid) and tracks them natively.
  4. Garbage Collection: Safely unregisters file usage when a file or image is removed from a form, allowing Drupal cron to clean up server space.
  5. Developer-Friendly API: Provides a service with a public method to manually track files inside complex structures like Block plugins, Commerce panes, or custom DB storage.

How to Use

1. In Configuration Forms (Automatic)

Simply add #track_file_usage => TRUE to your element. The module will automatically detect your configuration object name:

$form['promo_text'] = [
  '#type' => 'text_format',
  '#title' => $this->t('Promo text'),
  '#default_value' => $config->get('promo_text.value'),
  '#format' => $config->get('promo_text.format') ?? 'full_html',
  '#track_file_usage' => TRUE, // Active file tracking enabled!
];

2. Custom Forms / Complex Storage

If your form doesn't use ConfigFormBase (e.g., saves data into State API or custom tables), specify your storage ID explicitly:

$form['badge_image'] = [
  '#type' => 'managed_file',
  '#title' => $this->t('Badge Image'),
  '#default_value' => $config->get('badge_image'),
  '#file_usage_config' => 'my_module.custom_storage_key', // Explicit tracking ID
];

3. Inside Plugins (Manual API)

For forms embedded inside Block plugins or Layout Builder where automatic tracking isn't feasible, invoke the built-in service directly in your submission method:

// Inside your plugin's submit method (e.g., blockSubmit):
\Drupal::service('form_file_usage.manager')->compareAndTrack(
  $old_value, 
  $new_value, 
  'text_format', 
  'my_module', 
  'block:' . $this->getDerivativeId()
);

Activity

Total releases
1
First release
May 2026
Latest release
1 day ago
Release cadence
Stability
0% stable

Releases

Version Type Release date
1.x-dev Dev May 20, 2026