Problem/Motivation
Drupal currently has 3 message types:
- status
- warning
- error
These are found in MessengerInterface as constants. This interface also defines methods to directly add a message for each of these types, such as addWarning.
Any string "type" could be passed as the second argument to addMessage however there are other places in core where these 3 and only these 3 types are allowed.
For example, the render array output by StatusMessages passes an array with these 3 types to themes,
'#status_headings' => [
'status' => t('Status message'),
'error' => t('Error message'),
'warning' => t('Warning message'),
],
If a new type is used then the heading text won't display properly in themes like classy, where you find: {{ status_headings[type] }} in status-messages.html.twig
If these types were not hardcoded in Drupal core, or if there was a way to extend these 3, then new message types could be added for unique events.
Proposed resolution
Determine a way to extend the 3 message types.
Add additional info such as status headings and fallback classes. New types should be able to "fallback" to existing styles. For example, a "success" type could add messages--status class to use the existing "status" styling.
Remaining tasks
- Add option to add additional Messenger types from a module
- Make these new types discoverable for JavaScript Drupal.Message see:
getMessageTypeLabels
User interface changes
API changes
Data model changes
Release notes snippet
| Comment | File | Size | Author |
|---|---|---|---|
| #5 | interdiff_3-5.txt | 2.65 KB | zrpnr |
| #5 | 3100473-5.patch | 8.1 KB | zrpnr |
| #4 | 3100473-3.patch | 7.91 KB | gabesullice |
| #4 | interdiff.txt | 2.34 KB | gabesullice |
| #2 | 3100473-2.patch | 7.88 KB | zrpnr |
Comments
Comment #2
zrpnrI discussed this with @gabesullice and we pair programmed a bit to get a prototype working. The bulk of the credit goes to him for the idea to use YamlDiscovery to parse the "types". I added onto his code with a
base_typesproperty so that new types can have a fallback class.This patch adds a StatusMessageTypeHandler service which discovers types in [module-name].status_message_types.yml
The 3 main types are in system.status_message_types.yml while any module can add additional types.
For example, in mymodule.status_message_types.yml
This provides a type "info" which would have styling like an existing status message.
Setting to "Needs Review" to check if I missed any tests, and I'd appreciate any feedback about this approach.
This also still needs some thought around the js Message API.
Comment #4
gabesullicePaired a bit more with @zrpnr on this. He mentioned that he was not sure how a module could override or extend a type provided by another module. In the end, we added the concept of "priority" so that modules can override other statuses. That's in this interdiff.
Comment #5
zrpnrI wasn't clear if there is an order or "weight" to the loaded yml files, having a specific priority key makes sense to me to allow a module to override an existing type.
This is a much more elegant way to set the defaults than I had before!
Using
array_columnremoves the key which is needed to select the value in the template.Most of the tests were failing because of not checking for
base_types[type], and the BigPipe test failed because the extra variables added spacing to the template and it uses a strict comparison.Comment #7
tim.plunkettIt's not clear what this is doing here. Is the idea that if two modules provide the same name, then one with the higher priority will replace the existing one?
That's a departure from how Drupal usually accomplishes replacements (via alters).
Afaik this would be the 3rd usage of \Drupal\Core\Discovery\YamlDiscovery, the others being routes and permissions.
The rest of YAML discovery is done via plugins. Layouts, breakpoint, config translation, help topics, and the 4 types of links (actions, tasks, menu, contextual).
If using plugins, a lot more typical Drupalisms are easy to introduce. Alter hooks, sorting, more standardized handling of default values, translatability of properties, the option for dynamically defined message types, etc.
Finally, aside from plugins vs straight YAML: what about themes? Would it make sense for a theme to provide its own message type?
Comment #8
gabesullice@tim.plunkett, thanks for the review! This is mostly in @zrpnr's wheelhouse, but I can speak to some of the design decisions.
Precisely.
I see your point, but I'm not convinced that an alter hook makes sense. I think the API as-written is both simple and sufficient. Something Drupal needs to be better about as a whole :)
I think you're correct about usages.
Using the basic YAML discovery instead of introducing a new plugin system was done very intentionally. I'd argue that status message types are even less complex then permissions.
None of the plugin features that you describe are needed for the known use case. Turning this into a plugin system is probably premature abstraction. If those features ever become necessary, it would not be difficult to "upgrade" the proposed design to a full-blown plugin implementation in a BC compatible way (e.g. make a plugin deriver that can read the legacy yaml files).
I'll defer to w/e @zrpnr's opinion of this is. However, my gut reaction is that the answer is "no". A theme merely styles message types. It would be a pretty rare instance for A) a theme to set a message and B) the core message types to be insufficient for that message.
Comment #13
digitaldonkey commented> Would it make sense for a theme to provide its own message type?
I think it would make a lot of sense. Why we don't allow extending messages on a JS base?
Making getMessageTypeLabels() a bit less static (like providing addMessageType() or Drupal.Message.customTypes(Array) would be helpful.