fix: #3619510 Support enum-constrained icon props without a new field setting
Issue: #3619510
An alternative to !1 (closed), same outcome with a smaller surface. Pick whichever you prefer; they are mutually exclusive.
Problem
Same as !1 (closed). A prop declaring both enum and x-canvas-icon keeps the list_string + options_select shape Canvas derived from the enum, the widget is silently ignored, and the editor renders a select list.
What this does differently
!1 (closed) forces the field to string and carries the enum forward in a new allowed_icon_ids field instance setting, which needs a config/schema addition.
This one leaves the field as list_string and reads the constraint where Canvas already put it:
- the widget declares
field_types: ['string', 'list_string'], so it is no longer discarded for an enum-constrained prop; - allowed ids come from the field's own
allowed_values_function, which is Canvas'scanvas_load_allowed_values_for_component_prop, so the enum is not copied into a second place; massageFormValues()strips thepack:prefix on a list field, so the stored value stays one of the allowed values.
Result: no new field setting, no config/schema change, and canvasStorablePropShapeAlter() is untouched. 5 files instead of 7.
Testing
Drupal CMS with the Haven site template, Drupal core 11.4.5, PHP 8.4.20, Drupal Canvas 1.10.1, UI Icons 1.1.2, Canvas Icon Picker 1.0.3, Haven's phosphor pack of 1512 icons.
A component prop with a curated enum of 4:
- before: plain
select, zero picker elements in the DOM; - after: the picker renders, the drawer reports
4 icons, and the request is/canvas-icon-picker/index?packs=phosphor&ids=info,warning,check-circle,x-circle; - a prop with no
enumis unaffected: still1512 icons, noidsparameter.
Not verified
phpstan, phpunit, eslint and stylelint were not run locally and gate on the pipeline. No test is added. tests/src/Kernel/PropShapeAlterTest.php should pass unchanged, since this branch does not touch the hook it covers, but I have not executed it.
One open question for you: reading allowed_values_function directly is the part I am least sure is the API you would want. getSettableOptions() returned nothing in this context, which is why the callback is invoked directly.
Thanks Aaron for this module.
AI-Generated: Yes
Checkpoints:
- File an issue
- Addition/Change/Update/Fix
- Testing to ensure no regression
- Automated unit testing coverage
- Automated functional testing coverage
-
UX/UI designer responsibilities— no markup or design change, reuses the existing picker UI - Readability —
phpcs,phpstan,cspellgreen - Accessibility — audited, no markup added, two pre-existing gaps reported
- Performance — index payload 60,098 → 272 bytes for a curated prop
- Security —
idsnarrows only, probed for widening and injection -
Developer Documentation— no new public API in this MR -
User Guide Documentation— no editor-facing change beyond the picker appearing - Reviewed by human
- Code review by maintainers
- Full testing and approval
- Credit contributors
-
Review with the product owner— not applicable to an upstream contrib fix - Release notes snippet
- Release