Moving a custom profile to its own repo

State can be weird in Drupal 8.

I recently experienced a situation where the project had a profile—let’s call it theprof—that got moved into its own repository, beefed up (various modules and themes moved to it, etc.), and included in the implementing project via `composer.json`.

We then ran into a weird problem: rebuilding the cache successfully found all of the enabled modules again, but the theme was no longer active. Not only was it inactive, but Drupal couldn’t even find it!

What in the world was going on?

It turns out that Drupal 8 discovers themes differently than modules. When discovering modules, it first actively discovers profiles and then passes a list of these to the class used for discovering “extensions” (a general term used to refer to both modules and themes).

However, when discovering themes, it simply delegates the job of finding profiles to Drupal itself. And Drupal, reasonably, retrieves the path to a profile it has seen before from the State subsystem (generally, the `key_value` table in the database).

Note: It retrieves the path to a profile “it has seen before” this way.

That means that when we moved theprof from profiles/theprof to profiles/contrib/theprof, Drupal still had its path set to the old path in the system.profile.files State key. The solution in the end was simple:

/**
 * Clear profile path cache so that theme discovery works.
 */
function mymodule_update_8004() {
  $state = Drupal::state();
  $state->delete('system.profile.files');

  // Rebuild module and theme data.
  // @see drupal_flush_all_caches()
  $module_data = \Drupal::service('extension.list.module')->reset()->getList();
  /** @var \Drupal\Core\Extension\ThemeHandlerInterface $theme_handler */
  $theme_handler = \Drupal::service('theme_handler');
  $theme_handler->refreshInfo();
  // In case the active theme gets requested later in the same request we need
  // to reset the theme manager.
  \Drupal::theme()->resetActiveTheme();
}