It is expected that module hook_update_N() implementations should not use the module's own APIs, but that is not for the module's hook_schema(), hook_install() or hook_enable() implementations.

Drupal 7's module_enable()'s workflow is roughly as follows:

  1. Load mymodule.module file.
  2. Load mymodule.install file.
  3. Update the {system} table to mark the module as being enabled.
  4. Reset the cached list of system files.
  5. Clear the cached list of module files.
  6. Clear the cached list of hook implementations.
  7. Reload the system registry to include all files identified in the previous steps.
  8. Clear the cached schema.
  9. Clear the entity info cache.
  10. Install the new module's schema.
  11. Update the module's schema_revision value to the numerically highest hook_update_N() implementation.
  12. Run the module's hook_install() implementation, if present.
  13. Run the module's hook_enable() implementation, if present.

It's worth noting that step 7 causes any implementations of hook_registry_files_alter() to execute, which can lead to unexpected problems, like Media module not installing or the same with Styles module.

What I would recommend is changing the installation process to not load the module file, rely on the hook_install() to instead deal with any custom logic on its own and only run registry_update() after the module has been properly installed.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

DamienMcKenna’s picture

exratione’s picture

Here's a patch for module_enable() (in 7.10) that works for my profile installation situation, which had issues with both registry_update() and drupal_get_schema() for much the same reasons. Your mileage may vary, of course.

nedjo’s picture

Status: Active » Needs work

Indeed there are many issues out there that relate to the problem of a module's methods being called before it is fully installed.

However, updating the registry before a module is enabled seems to be by design and required. Modules frequently use their own methods at install time. For this to work, their own code needs to be available. Therefore the registry needs to be updated before their install hooks are called.

The solution to this seems to be that modules need to conditionally skip certain API calls at install time (when Drupal or a module or theme is being installed). We may need a convenience method equivalent to drupal_installation_attempted() but that returns TRUE also when a module or theme is being installed.

nedjo’s picture

Issue summary: View changes

Correct Media module issue URL.

rlmumford’s picture

I agree, the .module file should not be included until the module's install function has run. Any other functions could still be used if they were in other includes that could then be embedded.

rlmumford’s picture

Priority: Normal » Critical

I think this bug should be marked as critical as currently it stops lots of entity providing modules from being used in install profiles. We should either document that modules need to check whether tables exist in some functions OR fix this in drupal core.

rlmumford’s picture

GuyPaddock’s picture

GuyPaddock’s picture

azovsky’s picture

Clean the patch file (can apply for D7.34 from now).

azovsky’s picture

Status: Needs review » Needs work
hefox’s picture

Status: Needs work » Needs review
FileSize
923 bytes

Here's a patch that purely moves register_update. What is the purpose of also moving drupal_get_schema?

GuyPaddock’s picture

GuyPaddock’s picture

#13 works for me! Sooooo glad to finally have a solution.

Dane Powell’s picture

#13 fixes a number of entity-related modules breaking during installation with install profiles (such as Paragraphs: #2412747: Fatal error: Class 'ParagraphsItemMetadataController' not found). I haven't noticed any side effects.

grom358’s picture

Status: Needs review » Reviewed & tested by the community

I also can confirm this worked in resolving an issue with paragraphs as per #17

David_Rothstein’s picture

Status: Reviewed & tested by the community » Needs work

@nedjo's comment in #3 looks valid to me and has not been addressed. We shouldn't break modules that are currently using their own API in hook_install()...

Because of that, I'm not sure this is a bug core can or should fix, but perhaps at least it can do something (as @nedjo suggested) to make sure that contrib modules have an easy way to distinguish between a fully-installed module and one that is still in the process of being installed (if that doesn't already exist).

gbangban’s picture

Looks like this should be closed out. The patch is #13 is already in core 7.43.

David_Rothstein’s picture

HLopes’s picture

An implementation of hook_module_implements_alter removing the offending hook if the table doesn't exist seems to work as well.

For paragraphs (in my case) it would be something like

function MYMOD_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'entity_info') {
    if (!db_table_exists('paragraphs_bundle')) {
      unset($implementations['paragraphs']);
    }
  }
}
stephencamilo’s picture

Status: Needs work » Closed (won't fix)
hestenet’s picture

Status: Closed (won't fix) » Needs work

Reset issue status.