Skip to content

feat: add Insert module integration for image and file fields#21

Merged
Decipher merged 2 commits into
4.1.xfrom
feature/insert
Jun 9, 2026
Merged

feat: add Insert module integration for image and file fields#21
Decipher merged 2 commits into
4.1.xfrom
feature/insert

Conversation

@Decipher

@Decipher Decipher commented Jun 9, 2026

Copy link
Copy Markdown
Owner

Restores Insert module integration from the Drupal 7 version of Custom
Formatters. When the Insert module
is installed, custom formatters targeting image, file, or
entity_reference fields are automatically exposed as Insert styles,
allowing formatted output to be inserted directly into WYSIWYG editors.
The integration is purely opt-in — nothing changes when Insert is absent.

Insert hooks

hook_insert_styles() loads all enabled formatters and filters by field
type: image formatters are exposed for the image insert type; file and
entity_reference formatters for the file insert type. Style keys are
prefixed custom_formatters__<id> to avoid collisions.

hook_insert_render() builds a temporary field item list from the file
entity passed by Insert, instantiates the matching field formatter plugin,
and returns rendered HTML via renderInIsolation().

Both hooks are implemented in modules/insert.inc, which is loaded
automatically by the existing hook_module_implements_alter() mechanism
only when the Insert module is installed.

InsertFieldItemList

A new InsertFieldItemList class is introduced to wrap the file entity for
rendering. It extends EntityReferenceFieldItemList (not FieldItemList)
for two reasons:

  1. Drupal 11 compatibility — content entities no longer implement
    TypedDataInterface, so they cannot be passed as the $parent argument
    to FieldItemList. InsertFieldItemList stores the entity directly and
    returns it from getEntity().
  2. Core formatter compatibility — formatters such as ImageFormatterBase
    and the FormatterPreset engine type-hint against
    EntityReferenceFieldItemListInterface, which FieldItemList does not
    satisfy. Extending EntityReferenceFieldItemList provides this without
    any additional implementation.

Changes

  • modules/insert.inc — new: hook_insert_styles() and hook_insert_render()
  • src/InsertFieldItemList.php — new: field item list wrapper for Insert rendering
  • tests/src/Functional/InsertIntegrationTest.php — new: 5 functional tests
    covering style filtering, full render hook path, and node-based rendering
    for image and entity_reference fields
  • tests/src/Functional/CustomFormattersTestBase.php — add administer node form display permission
  • composer.json — add drupal/insert: ^3 to require-dev; add to suggest
  • README.md — document Insert integration in features list; remove from roadmap
  • CHANGELOG.md — add 4.1.x-dev entry

Test plan

  • DRUPAL_VERSION=11 make lint — CSpell, PHPCS, PHPStan (level 7), Rector,
    Twig CS Fixer all pass
  • DRUPAL_VERSION=11 make test — 155 tests / 1,556 assertions pass
  • Manual: installed Insert module, created image field, configured Insert
    button — custom formatters appear in the Insert styles dropdown and render
    correctly on insertion

Summary by CodeRabbit

  • New Features

    • Custom formatters can now be exposed as Insert styles for image, file, and entity_reference fields when the Insert module is installed and enabled.
  • Documentation

    • Updated CHANGELOG.md and README.md to document the new Insert module integration feature.
  • Tests

    • Added comprehensive functional tests for Insert module integration, covering style registration, field-type filtering, and rendering scenarios.

Implements hook_insert_styles() and hook_insert_render() in modules/insert.inc
so custom formatters targeting image, file, or entity_reference fields are
exposed as Insert styles.

InsertFieldItemList extends EntityReferenceFieldItemList (rather than
FieldItemList) so that core formatters such as ImageFormatter, which
type-hint against EntityReferenceFieldItemListInterface, work correctly when
invoked via the FormatterPreset engine.
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Decipher, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 30 minutes and 59 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 27bc30df-61a5-4466-9d15-b55bb0d98aa4

📥 Commits

Reviewing files that changed from the base of the PR and between 0ae0d91 and 9bbeb82.

📒 Files selected for processing (3)
  • composer.json
  • modules/insert.inc
  • tests/src/Functional/InsertIntegrationTest.php
📝 Walkthrough

Walkthrough

This pull request adds Drupal Insert module integration to Custom Formatters. Custom formatters targeting image, file, and entity_reference fields are now exposed as Insert styles for direct insertion into WYSIWYG editors when the Insert module is installed. The implementation includes two hook functions, a field item list wrapper class, and comprehensive integration tests.

Changes

Insert Module Integration

Layer / File(s) Summary
Documentation and dependencies
CHANGELOG.md, README.md, composer.json
Updated project documentation describing the new Insert integration feature for all supported field types. Added drupal/insert and drupal/token to development dependencies and suggested packages.
Insert integration hooks
modules/insert.inc
Implemented custom_formatters_insert_styles() to enumerate enabled formatter entities and filter style definitions by insert type compatibility. Implemented custom_formatters_insert_render() to resolve formatters, build field contexts using InsertFieldItemList, instantiate formatter plugins, and return rendered HTML strings.
Field item list wrapper
src/InsertFieldItemList.php
Introduced InsertFieldItemList class extending EntityReferenceFieldItemList to wrap FileInterface entities separately and expose them via getEntity(), providing the context needed for formatter rendering without entity reference field storage.
Integration tests
tests/src/Functional/CustomFormattersTestBase.php, tests/src/Functional/InsertIntegrationTest.php
Created InsertIntegrationTest suite covering style filtering across insert types, direct hook rendering with file and entity_reference fields, formatter plugin instantiation via FieldItemList objects, and manage display UI page access. Updated test base class to grant the admin user additional permissions for field display administration.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

A rabbit hops through insert fields with glee,
Exposing formatters for all to see—
Images and files now dance in WYSIWYG,
With tests that hop and hooks configured big! 🐰✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically summarizes the main change: adding Insert module integration for image and file fields, which is the central feature introduced across all modified files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/insert

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov

codecov Bot commented Jun 9, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.54%. Comparing base (3471d6b) to head (9bbeb82).
⚠️ Report is 1 commits behind head on 4.1.x.

Additional details and impacted files
@@            Coverage Diff             @@
##            4.1.x      #21      +/-   ##
==========================================
+ Coverage   78.49%   78.54%   +0.04%     
==========================================
  Files          24       25       +1     
  Lines        1725     1729       +4     
  Branches       64       64              
==========================================
+ Hits         1354     1358       +4     
  Misses        368      368              
  Partials        3        3              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@composer.json`:
- Line 32: The package description for "drupal/insert" is inconsistent with docs
and implementation: update the composer.json description string so it mentions
that custom formatters target image/file AND entity_reference fields (matching
README and CHANGELOG and the behavior in modules/insert.inc which exposes
entity_reference formatters for the 'file' insert type).

In `@modules/insert.inc`:
- Around line 124-141: Wrap the formatter instantiation and rendering pipeline
in a try/catch that catches Throwable so plugin creation failures and runtime
formatter errors don't bubble to a 500; specifically guard the call to
$plugin_manager->createInstance('custom_formatters:' . $formatter_id, ...) and
subsequent $formatter_instance->viewElements(...) and
\Drupal::service('renderer')->renderInIsolation(...) so that any exception
returns the current fail-closed value '' (and optionally logs the exception via
Drupal::logger or $this->logger->error for diagnostics) while still asserting
the $formatter_instance instanceof FormatterInterface before calling
viewElements.
- Around line 82-90: The code currently defaults $field_type to
'entity_reference' which lets unrelated formatters proceed; instead initialize
$field_type to NULL and only set it when one of the allowed types is found from
$formatter->get('field_types') (the loop that checks
['image','file','entity_reference']). After the loop, if $field_type is still
NULL, reject/skip this formatter path (e.g., return or continue) so it doesn't
fall through into the render path—apply this change around the logic handling
$formatter and ensure behavior aligns with custom_formatters_insert_styles()
compatibility checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: c25ca258-02ae-44a7-94dc-056e6c2946b2

📥 Commits

Reviewing files that changed from the base of the PR and between 9b552ba and 0ae0d91.

📒 Files selected for processing (7)
  • CHANGELOG.md
  • README.md
  • composer.json
  • modules/insert.inc
  • src/InsertFieldItemList.php
  • tests/src/Functional/CustomFormattersTestBase.php
  • tests/src/Functional/InsertIntegrationTest.php

Comment thread composer.json Outdated
Comment thread modules/insert.inc
Comment thread modules/insert.inc Outdated
- composer.json: mention entity_reference in drupal/insert suggest description
- insert.inc: initialise $field_type to NULL and bail early if the formatter
  does not target an Insert-compatible field type (prevents unintended fallback
  to entity_reference for non-file formatters)
- insert.inc: wrap formatter instantiation and render pipeline in try/catch
  Throwable so plugin failures and runtime errors return '' instead of a 500
  (with logger::error for diagnostics)
@Decipher
Decipher merged commit 2655e80 into 4.1.x Jun 9, 2026
19 checks passed
@Decipher
Decipher deleted the feature/insert branch June 9, 2026 05:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant