Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
Following up on #200931: Schema not available in hook_install/hook_enable, we fixed the fact that schema information is not available in hook_enable(), but it is still the case in D7 that the schema cannot be used in hook_install (see the issue for details).
This is a less serious bug, since there are workarounds for doing what you want to do in hook_install() in hook_enable() instead - just run a check first to make sure it was not already done before. For an example, see http://api.drupal.org/api/function/shortcut_enable/7
However, it ideally should still be fixed.
Comment | File | Size | Author |
---|---|---|---|
#19 | schema-hook-install-620298-19.patch | 13.8 KB | David_Rothstein |
#19 | interdiff-14-19.txt | 4.06 KB | David_Rothstein |
#14 | schema-hook-install-620298-14.patch | 13 KB | David_Rothstein |
#7 | schema-hook-install-620298-7.patch | 12.94 KB | David_Rothstein |
#5 | schema-hook-install-620298-5.patch | 12.84 KB | David_Rothstein |
Comments
Comment #1
David_Rothstein CreditAttribution: David_Rothstein commentedSee also #568640: drupal_write_record() fails on hook_install, which was duplicate.
Comment #2
manfer CreditAttribution: manfer commentedYou mention a workaround in hook_enable, but if I need to do a drupal_write_record in hook_install (not possible by now as schema is not available), is it wrong if I use a db_query in drupal 6 or a db_insert in drupal 7?
Comment #3
David_Rothstein CreditAttribution: David_Rothstein commentedYeah, doing a direct database query definitely works also, but it can sometimes be a pain, and for certain use cases it might be important to use an API function instead of a direct database query (if the API function also triggers other behavior)...
The workaround in hook_enable() is that you can use whatever code you wanted to run in hook_install(), just that you need to do a preliminary check first to make sure that it hasn't run before (i.e., that the module has not already been installed), and then effectively it's the same thing.
Comment #4
rszrama CreditAttribution: rszrama commentedI was tracking this one down for some time and tried several different ways to manually reset the schema cache and enabled modules list. I even tried implementing hook_modules_installed() on the module as a way to get around a workaround through hook_enabled(). In the end, I just used a db_insert(), but I'm a HUGE +1 to have this fixed. It seems to me that drupal_install_schema() should mean just that... the schema has been installed and is available for any drupal_write_record() after that.
Comment #5
David_Rothstein CreditAttribution: David_Rothstein commentedTried to come up with a fix for this, and it's messier than I had hoped - it seems to be tied up to the entire way we do module installation.
Basically, right now we call hook_install() before doing anything else, so the module actually isn't "installed" yet in any meaningful way, and none of its hooks will work. To fix this essentially requires rewriting the internals of module_enable() to do this in what I think is a more sensible order:
And then, fixing some cache-clearing bugs along the way.
Let's see what the testbot thinks of this. Note that the patch also contains the obvious fix to the shortcut module so it uses this new capability - in theory that could be a followup patch, but it was useful for debugging this as I worked on it, and I'd really like to see what the testbot thinks of the entire thing.
Comment #6
David_Rothstein CreditAttribution: David_Rothstein commentedNote that one side effect of this patch is that a fatal error in a module's hook_install() will leave the system in an odd state, where Drupal thinks the module is installed and enabled but it hasn't really been yet.
However, I believe the same is true for fatal errors in hook_enable() without this patch - and in some ways worse without this patch, since it could then affect a whole list of modules rather than isolating the problem to a single one. But I thought it was worth mentioning anyway.
Comment #7
David_Rothstein CreditAttribution: David_Rothstein commentedGeez, the patch already no longer applies :)
Comment #8
moshe weitzman CreditAttribution: moshe weitzman commentedMy hard drive is litterred with half attempts at this same patch. I commend you on your skill and tenacity. This wasn't easy.
If you have enabled several modules at once with drush, you very well might have felt the pain of this bug. We need to fix it.
I reviewed the code and it looks good. The test is icing on the cake.
Comment #9
webchickQuestion about this.
Let's say my module has in its hook_requirements() in mymodule.install that in order to use it, you need the external foodybar PHP library.
At the top of my .module file is the code
require_once('/FoodyBar.baz.php');
Won't this code lead to a fatal error?
Powered by Dreditor.
Comment #10
David_Rothstein CreditAttribution: David_Rothstein commentedI think it would... however, I don't think the patch changes that one way or another. That line of code was not added by the patch, but rather just moved around a bit - e.g., notice that there are also two lines in the patch file that look like this:
Also, I think as long as you're installing modules via the UI, the hook_requirements() will be checked beforehand so you can't get into this situation that way.
Comment #11
moshe weitzman CreditAttribution: moshe weitzman commentedback to rtbc
Comment #12
moshe weitzman CreditAttribution: moshe weitzman commented#7: schema-hook-install-620298-7.patch queued for re-testing.
Comment #14
David_Rothstein CreditAttribution: David_Rothstein commentedTrivial reroll, so I'm setting straight back to RTBC assuming the testbot agrees.
Comment #16
David_Rothstein CreditAttribution: David_Rothstein commented#14: schema-hook-install-620298-14.patch queued for re-testing.
Comment #17
moshe weitzman CreditAttribution: moshe weitzman commentedall green
Comment #18
Dries CreditAttribution: Dries commentedGreat job, David. The changes to install.inc and module.inc make sense and seem to stream-line the installation process some more. It is quite grokkable actually. While I think we're really close, I still have some feedback:
I wonder if this could (and should) be moved to node module using the new _modules_installed() or _modules_enabled() hook? It would further clean-up and streamline the installer code. If not, maybe we can clarify the code comment to explain why we can't? The current code comment makes sense but at the same time, it doesn't. :P
I like this clean-up! Nice catch.
It would be good to explain why this test is useful. The help text lacks some context to help people understand the bigger picture. This seems to suggest that 'drupal_write_record()' is special but reading the patch it is not clear why.
Anyway, I think we should be able to commit this really soon.
Comment #19
David_Rothstein CreditAttribution: David_Rothstein commentedThat's a great idea about moving the node access stuff to the node module while we are in here cleaning up this function anyway... I did that in the attached patch. We should do the same thing with the node access checks in module_disable() too, but that looked a little more complicated (I think there might be a bug there) so let's save that for a followup.
I also rewrote the code comment for the test.
Finally, I realized that I had erroneously removed
include_once DRUPAL_ROOT . '/includes/install.inc'
in the previous patch (it's still needed here, just for a slightly different reason), so I've added it back with a new code comment.Comment #20
Dries CreditAttribution: Dries commentedLooks good now. Committed to CVS HEAD. Thanks.
Comment #21
David_Rothstein CreditAttribution: David_Rothstein commentedTrying to figure out how to get the node access code out of module_disable() reveals a bug in that function, and it seems like it's going to require a similar rewrite to what we did here in order to properly fix it. Initial work is here: #727876: Enabling modules one at a time works differently than enabling them all at once