Problem/Motivation

I think it would be useful for a recipe to say, for example, "make this change to all content types". Currently, I'm not aware of any way to do that.

Proposed resolution

In the config:actions section of recipe.yml, I'd suggest we support syntax like in #7:

config:
  actions:
    core.entity_view_display.node.*.*:
      - setComponent:
          field: field_foo
          settings: {}
    core.entity_form_display.node.*.*:
      - setComponent:
          field: field_foo
          settings: {}

In this example, if you know you have instantiated field_foo on every content type (without necessarily knowing the exact names of those content types), you might want to be sure it is visible on the form and view displays of every content type.

We identified several potential use cases for a feature like this (the actual syntax we come up with might vary):

Obviously, some of these need to be implemented differently than others. So these cases should be thought through further, and split out into their own issues.

In general, though, I see two patterns in these use cases:

  1. The ability to expand the meaning of *. This could be accomplished in a pretty straightforward manner, I think; \Drupal\Core\Recipe\RecipeRunner::processConfiguration() could convert * into a regex, and apply it against all existing configuration names to find the one(s) that the action should apply to. This would add up to a few extra lines in that method. Let's do that in #3420209: Allow config actions to be applied to multiple config entities using wildcards.
  2. New config actions that belong only to particular config entity types, allowing them to take advantage of the specific nature and superpowers of those entity types. Examples:

    Because of their specificity, I think each of these cases (or any others we think of) would need to be done in their own issues.

Comments

phenaproxima created an issue. See original summary.

phenaproxima’s picture

Issue summary: View changes
thejimbirch’s picture

I like it. Some use cases I can think of.

1. Add a field to multiple entity types using the setComponent config action.
2. Updating multiple filter.formats using the setFilterConfig config action.
3. Adding permissions to multiple user roles using the grantPermissions config action.

thejimbirch’s picture

For clarity, I think the recipe snippet in the description should be.

config:
  actions:
    media.type.*:
      simple_config_update:
        queue_thumbnail_downloads: false
wim leers’s picture

  1. Today: apply a config action to a single config entity with a particular name (and you can repeat the config action with a different ID)
  2. Proposal: apply a config action to ALL entities of a config entity type

🤔 Is this expressive enough?

I think it is, but I'm wondering if there's use cases we're not thinking of yet. It's fine to gradually expand what we can do, with one important caveat: the syntax we choose here MUST NOT prevent future evolution.

wim leers’s picture

Also: setQueueThumbnailDownloadsStatus() on media types is a pretty obscure use case. Can you expand the issue summary with some more real-world use cases? 🙏

phenaproxima’s picture

#6: You know...as I think about it, I can't find too many use cases where we'd need to, for example, do the same operation to every node type directly.

But I can easily imagine a situation where you'd want to, say, instantiate the same field on every content type. That's a completely different sort of operation, but I think we'll run into it a lot more often.

Probably the way I would expect that case to be represented in a recipe.yml is something like this:

config:
  actions:
    field.storage.node.field_foo:
      # Create this field on all bundles of its target entity type.
      # `instantiate` is an action specific to field storage config.
      - instantiateAll: {}
    core.entity_view_display.node.*.*:
      - setComponent:
          field: field_foo
          settings: {}
    core.entity_form_display.node.*.*:
      - setComponent:
          field: field_foo
          settings: {}

So, something like that would require two things:

  • Being able to apply a specific action, or set of actions, every config object with a certain prefix
  • A specialized instantiateAll action for field storages, which allows a field to be created on all bundles of the target entity type

I'll update the issue summary to reference this - "add this field to the entity view displays of every content type" is a perfect case for why this feature would be necessary.

phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Issue summary is now updated with a more realistic use case. :)

phenaproxima’s picture

Issue summary: View changes
wim leers’s picture

#7++ that seems more common for sure!

every config object with a certain prefix

… or match a certain pattern, such as node.type.* or field.field.*.*.*. Not sure which terminology is the best match to maximize recipe authoring usability.

borisson_’s picture

Would this allow us to remodel "Search api db defaults" as a recipe that can apply those (or at least some) defaults to all content types on a site?
A high level overview of what that module currently does is:
- Configures a search api server + index
- Adds and configures a view
- Adds a new view mode to basic page + article
- Adds all those bundles to search api

wim leers’s picture

I think that'd be an excellent example :)

- Adds a new view mode to basic page + article

Did you mean to all node types? 🤔

borisson_’s picture

The current implementation is only on those, but it should do all node types.

See https://git.drupalcode.org/project/search_api/-/tree/8.x-1.x/modules/sea...

phenaproxima’s picture

Another variation on this use case - what if you want to grant a polymorphic permission (such as "edit own page content", "edit own article content", etc. -- the same permission, but repeated for each bundle of an entity type) to a role?

In other words, what if you have a "super editor" role, and you want to give that role the ability to edit every possible content type, without knowing ahead of time what the content types were, and without going so far as to grant "administer nodes" (or "bypass node access")? I don't think a recipe could that right now.

It would be cool to be able to do a config action like this:

config:
  actions:
    user.role.super_editor:
      grantAllNodeTypePermissions:
        - 'edit any %bundle content'
        - 'revert %bundle revisions'

That, I imagine, would be relatively straightforward -- a whole new config action for node types. You could also have a similar one for, say, media types (grantAllMediaTypePermissions), since they're designed similarly to node types.

wim leers’s picture

Looks like we added so many needs/use cases that that warrants at least expanding this issue summary and potentially converting this to a meta/plan issue (and implementing each use case in a child issue, with cross-coordination in this issue)?

phenaproxima’s picture

Issue summary: View changes

Adding some example use cases to the issue summary.

phenaproxima’s picture

Issue summary: View changes

Fixing an HTML error in the issue summary.

phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Issue summary: View changes

Distilled my thoughts on the patterns we're seeing emerge here.

phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Title: Allow a recipe to perform a set of actions on all config that matches a particular prefix » Make config actions more dynamic
phenaproxima’s picture

Title: Make config actions more dynamic » [meta] Make config actions more dynamic
Assigned: Unassigned » phenaproxima
Status: Active » Needs work

Self-assigning to update the issue summary.

phenaproxima’s picture

Issue summary: View changes
phenaproxima’s picture

Assigned: phenaproxima » Unassigned
Issue summary: View changes
Issue tags: -Needs issue summary update
phenaproxima’s picture

Status: Needs work » Active
thejimbirch’s picture

All child and related issues have been completed. Thanks for all the work on this!

thejimbirch’s picture

Status: Active » Fixed

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.