Issue #3583742: Add one-click Check Empathy field widget action and content-moderation gating

Summary

Closes #3583742

Adds a one-click Check Empathy button to text-field widgets and an optional content-moderation publish gate, so content editors can assess empathy quality without leaving the content form — and, optionally, block low-empathy content from being published.

Delivered as an optional submodule (ai_empathy_field_action) so the Field Widget Actions dependency never touches the main module.

What's included

Check Empathy field widget action (src/Plugin/FieldWidgetAction/CheckEmpathyAction.php)

  • #[FieldWidgetAction] plugin attached to text widgets (string_textfieldstring_textareatext_textfieldtext_textareatext_textarea_with_summary) / field types (stringstring_longtexttext_longtext_with_summary).
  • On click, scores the field's current text via the existing scenario-less EmpathyScoringService::scoreResponseGeneral() and shows empathy + explanation-quality scores as colour-coded badges (green / orange / red) in a modal. Nothing is written to the field.
  • Badge colours are driven by the global empathy_alignment_threshold in AI Empathy settings.

Content-moderation publish gate (src/Service/EmpathyModerationGate.php, src/Hook/AiEmpathyFieldActionHooks.php)

  • hook_form_alter validation handler blocks transitions to a published moderation state when the empathy score is below threshold.
  • Activates only when core content_moderation is installed (moduleExists guard + optional @?content_moderation.moderation_information injection) and the gate is enabled in config.
  • Fails open: if scoring is unavailable, publishing is never blocked.

Supporting pieces: settings form (FieldActionSettingsForm) + route/menu link, theme hook + Twig template + badge CSS, config schema/defaults, submodule README.md, and an "Optional integrations" note in the main README.md.

Decisions

  • Widget action and moderation gating shipped together in one submodule.
  • Badge colours and the publish gate reuse the existing global empathy_alignment_threshold (no new threshold config).

Handling of known field_widget_actions issues

  • #3567974 (required-field validation on button click) — the base class's ajax button sets suppress_required_fields_validation, so the check works on incomplete forms.
  • #3578204 (checkbox/radio widgets unsupported) — we target text widgets only.
  • Pinned to ^1.3 (stable 1.3.0), which includes the suggestion.js event fix (#3578820); deprecated multiple attribute param not used.

Testing

Automated (all passing):

  • Unit — badgeState() threshold mapping; full EmpathyModerationGate decision matrix (disabled, module absent, below/at threshold, fail-open, non-published state).
  • Kernel — check_empathy plugin discovery with correct widget/field types; result theme hook registered.
  • Functional — settings form access control + save.

Manual:

  1. composer require drupal/field_widget_actions:^1.3; enable ai_empathyai_empathy_field_actionfield_widget_actionsfield_ui; set a scoring provider/model in AI Empathy settings.
  2. Manage form display on a content type → enable Check Empathy on a text field. Edit content, click the button, confirm the modal shows scores + colour badges.
  3. Enable content_moderation on the type, enable the gate at AI Empathy → Field Action and list the field(s); confirm publishing low-empathy content is blocked and high-empathy content publishes.

This submodule builds on Field Widget Actions and requires ^1.3:

  • #3568300** — Create a stable version** (fixed, 1.3.0): provides the stable release this submodule depends on, rather than pinning a dev branch.
  • #3567974** — Action-buttons cause required-field validation errors** (open): accounted for — our action uses the ajax-callback path, so the base class's suppress_required_fields_validation lets the button work on incomplete forms.
  • #3578204** — Support for checkboxes/radio buttons** (open): the reason the Check Empathy action is scoped to text widgets only.
Edited by Joshua Fernandes

Merge request reports

Loading