Problem

  1. When creating a distribution profile that only specifies e.g. Block module as a dependency, then installation succeeds, but when visiting the site, you get the following fatal error on /user/1:

    Fatal error: Class 'Drupal\entity\Entity\EntityViewDisplay' not found
    in \core\lib\Drupal\Core\Entity\EntityViewBuilder.php on line 225

Cause

  1. Entity module does not get installed.

  2. This happens, because install_profile_info() assumes that the array returned by drupal_required_modules() would include the installation profile as the first element, so it uses array_shift() to remove the element.

  3. But when installing with a distribution profile, install_profile_info() happens to get invoked before $install_state['parameters']['profile'] is set, so drupal_get_profile() does not return a "current" profile (yet).

  4. In turn, the array_shift() causes the Entity module to get removed instead of the assumed installation profile module.

Proposed solution

  1. Use array_diff() instead of array_shift().

CommentFileSizeAuthor
distro.profile-info-required.0.patch1.17 KBsun
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tstoeckler’s picture

Makes the code much clearer. Nice!

sun’s picture

Was that an RTBC? :)

FWIW, even though I'd have an idea for testing this, that would be an extremely narrow DUTB test, which would only test for this particular bug... — Therefore, I thought it wouldn't be worth to add that test here.

Instead of such a too narrow test, I think we need to (1) revamp the architecture of install profile [info] and (2) introduce proper test coverage as part of #2186491: [meta] D8 Extension System: Discovery/Listing/Info

That is, because only after cowboy-debugging this via debug_backtrace(), I learned that the entire surrounding code is some giant plate of spaghetti, sans sauce.

tstoeckler’s picture

Well, I'd want to either step through this with a debugger or at least have another pair of eyes look at this so it was intentional that I didn't RTBC (yet).

sun’s picture

When stepping through this with a debugger, note that you might need an actual distribution profile in your filesystem.

The code path is triggered by install_begin_request() on line 392:

  if ($profile = _install_select_profile($install_state)) {
    $install_state['parameters']['profile'] = $profile;

Where _install_select_profile() performs:

  foreach ($install_state['profiles'] as $profile) {
    $profile_info = install_profile_info($profile->getName());

install_profile_info() calls into drupal_required_modules(), which contains:

  // Unless called by the installer, an installation profile is required and
  // must always be loaded. drupal_get_profile() also returns the installation
  // profile in the installer, but only after it has been selected.
  if ($profile = drupal_get_profile()) {
    $required[] = $profile;
  }

→ But as visible in the first snippet, the 'profile' parameter is not set yet, so drupal_get_profile() returns no profile name and thus the resulting list does not contain a profile.

Instead, the first element in the returned array is simply the first 'required' module that has been discovered.

sun’s picture

Berdir’s picture

Status: Needs review » Reviewed & tested by the community

Yeah, we did run into this with an actual distributation, can confirm that the patch fixes it.

Core currently doesn't have a distribution and I guess can't (otherwise it would override the other install profiles ;)) so this can't be tested. I will certainly notice now if it will break again ;)

catch’s picture

Status: Reviewed & tested by the community » Fixed

Committed/pushed to 8.x, thanks!

  • Commit 3e26810 on 8.x by catch:
    Issue #2218955 by sun: Install_profile_info() removes required module...

Status: Fixed » Closed (fixed)

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