Problem/Motivation

I am building a recipe to for a basic startup of new projects. I want to use "minimal" profile and then enable claro and other modules. When using recipes, it seems because the installation of the extension happens in a separate step as the configuration, Drupal core will duplicate Stark's (minimal's default theme) blocks. Even by specifying the configs in recipe.yml doesn't help because in the end I have both sets of blocks

Steps to reproduce

  1. Install Drupal with the minimal profile.
  2. Apply the core/recipes/core_recommended_admin_theme recipe to the site or a simple recipe that includes that recipe.
  3. Log in and visit an administrative page. The page has both "tabs" (primary local tasks) and "primary_local_tasks" blocks.

Proposed resolution

Not sure yet, but maybe if I am importing configs provided by the extension, they could be imported during installation?

Note: the code that performs the block duplication runs after any module/theme/profile installation, except during site installation: https://git.drupalcode.org/project/drupal/-/blob/9.5.3/core/modules/bloc...

Comments

franz created an issue. See original summary.

franz’s picture

Issue summary: View changes
thejimbirch’s picture

Minimal requires Stark, and imports config: https://git.drupalcode.org/project/drupal/-/tree/9.5.3/core/profiles/min...

Could you require Stark in your recipe, and not import the config?

If that didn't work, do we need a config:remove option in addition to config:import in the recipe.yml?

franz’s picture

@thejimbirch I'm not sure how requiring stark would help. These block configs are created during site installation. If you look at the link I posted in the description, you'll see that they get duplicated when claro is installed, before its configs are imported. An option to delete configs is certainly useful but in this case it is a workaround. IMO it should be possible to install a theme via recipes with the same outcome as installing manually. Maybe this would require a patch in that code so it doesn't create block copies when installing from recipes? Would certainly be the cleanest way.

sonfd’s picture

First, I just want to add a more verbose version of what you've stated in the project description.

Recipe application installs modules and themes and imports their configuration in two steps, see An example drupal recipe in the distirbutions and recipes initiative docs.

  1. The extension is installed and its simple configuration is imported.

    During the install only simple configuration from the new modules is created. This allows the Drupal recipe control over the configuration.

  2. The configuration provided directly by the recipe is installed, along with any configuration entities provided by extensions you installed and allowed in the config section.

    A Drupal recipe can have a config directory. All configuration is this directory will be imported after the modules have been installed. Additionally, the Drupal recipe can install configuration entities provided by the modules it configures. This allows them to not have to maintain or copy this configuration.

It seems that the block module creates blocks for claro in step 1, via hook_themes_installed(), because the Claro provided blocks are not simple configuration and therefore their configuration is not imported yet). Then the claro blocks get created in step 2, if you've allowed them.

I suspect your recipe looks something like this:

# ...
install:
  - drupal:claro
# ...
config:
  import:
    claro: '*'
# ...

If we don't allow the config entities from Claro to be installed, e.g. by updating your recipe.yml and removing the entry under config, we'll only get one set of blocks, but they'll be the blocks created by the block module in step 1. Though I think we'd really rather get just the set of blocks supplied by the Claro module (if allowed in the recipe.yml), and the block module would never create the set of blocks in step 1 while a recipe is being applied.

Maybe this would require a patch in that code so it doesn't create block copies when installing from recipes?

IMO, this is the right approach. I think the block module needs to make an exception for when the theme is installed by a recipe. In the code for hook_themes_installed(), you can already see where they've made a similar exception for installation profiles:

function block_themes_installed($theme_list) {
  // Disable this functionality prior to install profile installation because
  // block configuration is often optional or provided by the install profile
  // itself. block_theme_initialize() will be called when the install profile is
  // installed.
  if (InstallerKernel::installationAttempted() && \Drupal::config('core.extension')->get('module.' . \Drupal::installProfile()) === NULL) {
    return;
  }

  // code to initialize themes with duplicate blocks omitted here... 
}
thejimbirch’s picture

Another person reports this in #3436143: Duplicate blocks appear after standard recipe is applied.

The root core issue is #3105597: Stop copying block configuration from active theme when enabling a new theme.

The issue definitely exists, but you can now use the installer that is in core to install Drupal using a recipe, which bypasses the need for an install profile. This helps the issue if you are starting a new Drupal site, not if you are applying a recipe to an existing site.

php core/scripts/drupal quick-start path/to/recipe

thejimbirch’s picture

Version: 10.0.x-dev » 11.x-dev

thejimbirch’s picture

Title: Claro installed by recipes has incorrect block config » Themes installed by recipes have incorrect/duplicate block config when applied to a site that has an existing theme

Updating title, adding credits from duplicate issue.

d70rr3s’s picture

Just to shed some light on the matter. I'm facing the same issue in this case with GIn theme but, I don't have a gin: * in my recipe. This is my actual code:

name: Admin UI
type: Standard
description: Sets up a nice administrative theme and navigation.
install:
  - coffee
  - gin
  - gin_login
  - gin_toolbar
  - navigation
config:
  import:
    coffee:
      - coffee.settings
    gin:
      - gin.settings
    gin_login:
      - gin_login.settings
    navigation: "*"
  actions:
    system.theme:
      simple_config_update:
        admin: gin

Probably blocks by Gin are getting imported even if you explicitly ask for it. Probably a bug somehow?

d70rr3s’s picture

Ah, I see. @sonfd explains it in here, is how the block module behaves when installing a new theme :/

bhuvaneshwar’s picture

Assigned: Unassigned » bhuvaneshwar
prashant.c’s picture

bhuvaneshwar’s picture

Agree with #5 in order to omit duplicate blocks while initializing themes we can use:

// Get the list of themes installed and blocks to assign.
$themes = system_list('theme_enabled');

foreach ($themes as $theme => $info) {
// Get the default blocks for the theme.
$blocks = theme_get_default_blocks($theme);

// Filter out duplicates.
$unique_blocks = array_unique($blocks, SORT_REGULAR);

// Assign the unique blocks to their regions.
foreach ($unique_blocks as $block) {
// Assign the block to the region.
block_place_block($block);
}
}

As I'm also facing the same issue in this case with GIn theme but, I don't have a gin: * in my recipe too

bhuvaneshwar’s picture

Assigned: bhuvaneshwar » Unassigned
bsnodgrass’s picture

Project: Recipes Initiative » Drupal core
Component: Code » recipe system
Issue tags: +Recipes initiative
mherchel’s picture

Bumping to major.

With Drupal's focus on site templates, this becomes a blocker for that functionality.

mherchel’s picture

Priority: Normal » Major

Crap. Forgot to actually change the field!

mradcliffe’s picture

Issue summary: View changes

I stumbled on this and the other issue today working on a recipe.

I updated the steps to reproduce to use an already existing core recipe as an example (core_recommended_admin_theme).

I think that we should do the hook_themes_installed() approach and add a @todo comment linking to #3105597: Stop copying block configuration from active theme when enabling a new theme so that we're not blocked (pun intended).

thejimbirch’s picture

alexpott’s picture

I think we should do #3182716: block_theme_initialize should not create blocks during config sync which would have the by product of fixing this issue as block_theme_initialize() would no longer trigger during a recipe install.

thejimbirch’s picture

Related issues:

Removing duplicate related issue

thejimbirch’s picture

Removing this current issue as a related issue. It was relating to itself.

larowlan’s picture

catch’s picture

#3182716: block_theme_initialize should not create blocks during config sync is in 11.2 - does that mean this should be closed, or is there more to do on this issue?

thejimbirch’s picture

Status: Active » Fixed
Issue tags: -11.3.0 release priority

Yes, that issue fixed the underlying problem.

thejimbirch’s picture

Status: Fixed » Closed (duplicate)
thejimbirch’s picture