In D8, implementsHook
calls $this->loadInclude($module, 'inc', $module . '.' . $hook_info[$hook]['group']);
which happily tries to do $this->moduleList[$module]
without any check in either method whether the $module
is enabled.
In D7, it's even more funny:
module_hook
module_load_include
drupal_get_path
drupal_get_filename
which reads{system}
regardless of status.- The include file of the disabled module is loaded and happily processed.
This is rarely hit because module_implements
will iterate the module list and call implementsHook
only with module names that happen to exist (in D7 the module_load_include call is inlined into module_implements).
But. In D8, field_views_data
will iterate the existing fields and call the modules from there for views data and if you happen to have a disabled module which provided a field type, then boom! you get a notice. If you have a stray modulename.type in your DRUPAL_ROOT that gets loaded. Yes, that's an idiot edge case, but hey, it's me.
I have hit this during the update path where disabled modules are frequent which, alas, makes this critical. Of course, fixing ModuleHandler is not hard at all. I already patched this, still need to write a test, will post a patch soon.
I will file a separate issue for Views to get rid of (pseudohook)_field_views_data because it's not necessary, there's an alter already and we can change that to an alter of array types.
Comment | File | Size | Author |
---|---|---|---|
#29 | 1948702-29.patch | 1.45 KB | David_Rothstein |
#29 | 1948702-29-TESTS-ONLY.patch | 849 bytes | David_Rothstein |
#22 | 1948702-22.patch | 633 bytes | David_Rothstein |
#14 | 1948702_14.patch | 716 bytes | jibran |
#8 | Selection_106.png | 41.18 KB | chx |
Comments
Comment #1
chx CreditAttribution: chx commentedAsserts are for wusses :P The test only patch beautifully will fail (it does locally at least) because of the notice while the patched version passes.
Comment #2
msonnabaum CreditAttribution: msonnabaum commentedLooks quite good to me. Love the test.
Comment #3
chx CreditAttribution: chx commentedFor D7, this is just normal IMO but will need profiling before it can get in although I believe that the cost is really, really small but it does get called a lot of times and adds a userspace function call. In D8, the performance cost is negligible because there is no userspace function call added, just a simple isset.
Comment #4
BerdirShould be new ModuleHandler() I think.
Wouldn't care much but the test-only patch did not fail so it might need a change anyway...
Also tried locally and same result. Does it have something to do with PHPUnit?
Comment #5
jibran#1 That awkward moment when test only patch is green.
Comment #6
amateescu CreditAttribution: amateescu commentedThe same fix is RTBC here for over a week.. #1940954: ModuleHandler::loadInclude() can trigger notices
Comment #7
yched CreditAttribution: yched commentedyup, #1940954: ModuleHandler::loadInclude() can trigger notices was the exact same problem with field_views_data.
Comment #8
chx CreditAttribution: chx commentedThe pass is due to faulty phpunit integration and has nothing to do with my most excellent and really complicated test :P The linked issue is a duplicate that has no test.
Comment #9
chx CreditAttribution: chx commented#1949266: phpunit errors are silently eaten
Comment #10
yched CreditAttribution: yched commentedSimilar / tangentially related (ok, shameless plug) : #1941000: update_module_enable() does not update ModuleHandler::$moduleList
Comment #11
Dries CreditAttribution: Dries commentedCommitted to 8.x. Thanks chx. Moving to 7.x.
Comment #12
webchickComment #13
chx CreditAttribution: chx commentedPatch is in #3
Comment #14
jibranRe-uploading #3 for testing.
Comment #16
jibran#14: 1948702_14.patch queued for re-testing.
Comment #17.0
(not verified) CreditAttribution: commentedUpdated issue summary.
Comment #20
David_Rothstein CreditAttribution: David_Rothstein as a volunteer commentedThe patch changes module_load_include(), but shouldn't it change module_hook() instead? I don't think there's anything that says you can't load a file from a disabled module if you really need to.
For module_hook(), however, the function documentation says it returns "TRUE if the module is both installed and enabled, and the hook is implemented in that module", but the code is sometimes ignoring the first half of that sentence. So it's definitely a bug. Still seems a bit scary to fix (code out there could be relying on the current behavior), but it's probably worth fixing. This is also leading to subtle bugs in some contrib modules - see the related issue.
Comment #21
David_Rothstein CreditAttribution: David_Rothstein as a volunteer commentedThat issue is related also, but here is the one I actually meant to add.
Comment #22
David_Rothstein CreditAttribution: David_Rothstein as a volunteer commentedHere's a patch that fixes it in module_hook().
I guess ideally we could use a test for it too.
Comment #23
David_Rothstein CreditAttribution: David_Rothstein as a volunteer commentedComment #24
David_Rothstein CreditAttribution: David_Rothstein as a volunteer commentedComment #25
Neograph734Marking this RTBC as well. I see no harm in this implementation and the missing module errors during installation are gone.
Comment #27
stefan.r CreditAttribution: stefan.r commentedComment #28
David_Rothstein CreditAttribution: David_Rothstein as a volunteer commentedI put this as Drupal 7.60 target because I was worried it could break things. For example, any code that calls module_hook() (or module_implements(), which in turn calls module_hook()) in an update function and then gets run on a disabled module.... Invoking hooks in update functions is generally a bad idea but in practice it can happen, especially indirectly.
In any case this could still use a test.
Comment #29
David_Rothstein CreditAttribution: David_Rothstein as a volunteer commentedI guess something like this should work as a test.
Comment #32
stefan.r CreditAttribution: stefan.r commentedComment #35
joseph.olstadBumping to 7.70. This didn't make it into 7.60
Comment #36
poker10 CreditAttribution: poker10 at ActivIT s.r.o. commentedJust for the reference, the test in #29 is failing because the
module_test
module was enabled before this test code is hit and the file withmodule_test_test_hook
is therefore already included in PHP. So inmodule_hook()
we will not reach this desired part (which was modified by the patch):Instead the first IF condition will return TRUE (because the file with the function is already loaded from before):
So either the test needs to be fixed, or the
testModuleInvoke()
function needs to be moved more upper.I think it will be better to create a separate issue for D7 fix, because this still needs work.