Problem/Motivation
We would like to deprecate all legacy code in the file core/includes/module.inc. The function module_load_include() and module_load_install() lives in that file.
Proposed resolution
The module_load_include() function should be deprecated, and its use removed from core.
Remaining tasks
TBD
User interface changes
None
API changes
The function module_load_include() will be deprecated.
Original report by scor
This is a follow up issue on Drupal 7's #599122: Do not use module_load_include() in global context. This function is misleading and useless in some cases like in an .install file or in "global context" where a native PHP require_once call must be used instead.
The module_load_include() function provides little or no advantage over calling simpler functions directly. In #599122, several calls to require(DRUPAL_ROOT . 'file') were changed to use module_load_include() for consistency. This broke core, so after the changes were reverted, webchick commented in #599122-15:
I guess we should look at removing this stupid, confusing, and useless function in Drupal 8.
| Comment | File | Size | Author |
|---|---|---|---|
| #189 | 697946-189.patch | 27.89 KB | alexpott |
| #189 | 185-189-interdiff.txt | 2.84 KB | alexpott |
Issue fork drupal-697946
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #1
pillarsdotnet commentedAttached patch marks the
module_load_include()function as deprecated and replaces it with a combination ofrequire_once(),drupal_get_path(), andfile_exists().It may be worth investigating whether this change affects performance in any significant way.
Note that removing the function altogether would require changing the documentation (and perhaps the API) of the
drupal_build_form()function:The
form_load_include()docs would likewise need to be modified:Comment #2
pillarsdotnet commentedComment #4
pillarsdotnet commentedTrying again. using
include_once()instead ofrequire_once().Comment #6
pillarsdotnet commentedNeeded another
if (file_exists(...)).Comment #8
pillarsdotnet commentedTrying again...
Comment #10
pillarsdotnet commentedAnd again...
Comment #12
pillarsdotnet commentedAnd again...
Comment #15
pillarsdotnet commented(sigh)
EDIT: Yay!
<img src="http://drupal.org/files/happydance.gif" />EDIT: Okay, enough celebration.
Comment #16
moshe weitzman commentedThe Summary does not justify this change well. I don't yet understand the problem we are solving. Lots of functions fail if used at wrong time.
Comment #17
pillarsdotnet commentedUpdated issue summary.
Comment #18
moshe weitzman commentedI prefer to centralize including code where feasible so that you can breakpoint and understand when code is being loaded from disk. The Summary is much better now but I guess I disagree. It is possible that module_load_include() should be broken up into different functions but not removed. my .02
Comment #19
pillarsdotnet commentedIf you have any specific suggestions as to how it should be broken up (or "fixed"), I would be happy to roll a patch.
Comment #20
donquixote commentedI have one specific suggestion.
module_load_include() really helps if you have a file of the pattern "$module.something.inc".
However, if you have sth like "theme/theme.inc" in views module, then you need a stupid third argument.
A simple suggestion: Allow value of FALSE for the third argument.
Expected usage:
This quite a cheap gain.
We could also make up variations of this, where the difference to D7 would be bigger, but that might feel more sane.
----------
Of course, all of this would be only for procedural code. Anything OOP should be included with autoloading, esp. the Drupal 8 PSR0 stuff.
Comment #21
donquixote commentedHm, maybe my comment in #20 would be better placed in
#507396: Change module_load_include() parameters
or #1366026: replace module_load_include() with module_include() ?
Comment #22
alexweber commentedPersonally, I really don't think there's any point in removing this function. It's ridiculously small and simple and basically just abstracts some logic like resolving file location relative to drupal root and checking whether the file exists. IMO if we don't have a function like this we're basically gonna have the same repetitive code all over the place to achieve this.
That said, I think merging this and module_load_install() and possibly renaming it to just module_load() and clearing up parameters as suggested in #20 sounds like it could be a good thing.
Comment #23
pasquallesuggestion in #20 is not less confusing than the original function.
ctools_include() or my suggestion #1366026: replace module_load_include() with module_include() is much more usable.
Comment #23.0
pasqualleUpdate using Issue summary template.
Comment #24
areke commentedThe proposed patch is extremely old and needs a reroll. It looks like there are still quite a few usages of module_load_include() in 8.x.
Comment #25
alansaviolobo commented15: deprecate-module_load_include-697946-15.patch queued for re-testing.
Comment #27
alansaviolobo commentedComment #29
alansaviolobo commentedcorrected invalid file names passed to include.
Comment #31
alansaviolobo commentedComment #33
alansaviolobo commentedComment #35
alansaviolobo commentedComment #36
pwieck commentedComment #37
mile23Needs a reroll, and:
Use a proper @deprecated, like:
Comment #38
vaibhavjainNot sure if we should replace module_load_include with include_once.
I know about "loadInclude()" but it only works with enabled modules.
So, My query is, should we replace include_once with loadInclude() ? Or is there some thought behind using include_once ?
Attached the patch though.
Comment #39
jgeryk commentedComment #40
legolasboSome nits
This seems out of scope.
Left over from reroll?
Comment #41
legolasboComment #42
vaibhavjainFor the above 2 issues pointed.
#1 - I have removed the comment.
#2 - Thats my bad, i should have reviewed the patch better.
Comment #43
legolasbo@vaibhavjain,
If you can supply an interdiff that would make reviewing the patch a lot easier.
Comment #44
vaibhavjain@legolasbo,
Yep, I should have added that.
Attached it now though.
Comment #46
legolasbo@vaibhavjain,
The testbot automatically tests any *.patch files. Next time, please upload interdiffs in the following format: [issuenumber]-[originalcomment]-[newcomment]-interdiff.txt in your case that would have been 697946-38-42-interdiff.txt
I'm leaving this needs review for now, because I haven't had the time to actually apply the patch and go over it.
Comment #47
mile23This should be @return string|bool
https://www.drupal.org/coding-standards/docs#types
The original docs here mention sub-arrays. This info should be carried forward if it's still relevant. I couldn't find any discussion on this issue about it, so I don't know. I'm not familiar enough with how the FormState class works to know if the change is better.
Comment #48
vaibhavjainHey Mile23,
Not sure what is to be done for #2.
I am attaching the patch with #1 rectified.
Comment #49
vaibhavjainInterdiff.
Comment #50
vaibhavjainUpdating status.
Comment #51
mile23Comment #52
mile23Comment #53
pguillard commented#48 rerolled. Hope it is correct.
Comment #54
joelpittetTHanks @pguillard that is a perfect reroll.
There are a couple more references in tests and comments that could be replaced as well.
Also, maybe a stupid question but why are we using
include_onceinstead of the thing we are recommending to use which is\Drupal::moduleHandler()->loadInclude()?And last, please don't use include_once as a function, it's a statement and there should be no parenthesis, this is a nitpick but we haven't used it like that in core yet so probably shouldn't start in this patch, the parens are superfluous.
Comment #55
pguillard commentedThanks @joelpittet.
Here is the new patch applying your suggestions from #54.
I guess you are right concerning
\Drupal::moduleHandler()->loadInclude(), but in doubt, I didn't replace it.Comment #56
pguillard commentedComment #58
pguillard commentedComment #59
joelpittetThanks:) Hopefully someone else who worked on this or knows can confirm that.
Comment #60
tstoecklerRight, at the moment
module_load_include()is deprecated in favor ofModuleHandler::loadInclude(). We could decide that since module's include files are on the decline we should deprecateModuleHandler::loadInclude()as well, but then we should document that on the method.Some further thoughts:
- Seeing that this is a 20KB patch it seems there is still a lot of usage of this, so maybe we should postpone this to when we have even less include files at some point in the D9 cycle.
- At least in classes (specifically: non-test classes) using
ModuleHandler::loadInclude()is better than bothmodule_load_include()andinclude_once drupal_get_path(...) ...because theModuleHandlercan be injected making the code testable.WizardPluginBaseis one example I found in the patch (there aren't many, though). So those should in my opinion be either left alone or converted to$this->moduleHandler->loadInclude()where$this->moduleHandlerhas to be injected somehow.- The changes to
generate-d6-content.shandgenerate-d7-content.shI *think* could be fine in this particular case, but those scripts are supposed to run on a D6/D7 code base, so as a general rule of thumb those should be left alone. Just as a general note.Comment #61
almaudoh commentedWe should not introduce more usages of
drupal_get_path()since we want to remove that function as well. See #2347783: Deprecate drupal_get_path() and drupal_get_filename() and replace with ExtensionList::getPath() and ExtensionList::getPathname().With the completion of the extension system in #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList, there is a cleaner way to include files without using
drupal_get_path()that's being introduced in that patch.Comment #62
pguillard commentedI replaced
include_once drupal_get_path()withModuleHandler::loadInclude()What do you think ?
Comment #64
pguillard commentedAnother try..
Comment #68
pguillard commentedPatch re-rolled
Comment #70
douggreen commentedWas the comment in install_import_translations() accidentally changed in the last re-roll?
Comment #75
almaudoh commentedNow that #2208429: Extension System, Part III: ExtensionList, ModuleExtensionList and ProfileExtensionList is in, there should be more impetus to finish off this clean-up.
Comment #76
mile23Comment #77
harsha012 commentedPlease review the patch
Comment #79
MerryHamster commentedChanges were added for #77 patch:
1.Parameters were fixed in '\Drupal::moduleHandler()->loadInclude()'.
2.Removed changes for examples in module.inc because they for module_load_include(). They are correct.
I doubt about my changes in
/core/modules/system/src/Tests/Update/DbUpdatesTrait.php
and /core/modules/system/tests/src/Functional/Update/DbUpdatesTrait.php
are they correct or not? check please
Comment #80
MerryHamster commentedComment #82
mile23Needs a CR and a link to a CR in the deprecation message.
Comment #83
MerryHamster commentedAdded CR https://www.drupal.org/node/2948698
and some more changes to try fixing part bugs in the tests
Comment #84
MerryHamster commentedComment #85
andypostUnpublished CR cos not not commited, polished it
this kind of changes makes #507396: Change module_load_include() parameters obsolete
Looks better to introduce new "shiny" interface and stop using 3 params
Comment #88
kim.pepperReroll of #83
Comment #90
andypostFixed re-roll, mostly all places in core using long format for the method - so normalized in patch
It still needs to fix loading
.installfilesFollow-up to remove because no
views_ui.admin.incexists #3017299: Remove unused module_load_include() in view_ui moduleComment #92
andypostClosed #507396: Change module_load_include() parameters as really obsolete
Meanwhile it becomes clearer to me that loading include file and
.installshould be separate methodsLoading install happens for installed and uninstalled modules
So for not installed modules it can be executed also in context of all scanned extensions, not only installed
Comment #93
andypostTrying to decouple
Comment #94
andypostComment #95
andypostLooks we already have collision with execution of hooks for uninstalled modules
- to get schema - probably should be made only for installed modules, OTOH at install time not clear
- to get module requirements - exactly before install
Comment #96
andypostIt missing test for deprecation
this should be single line
Comment #98
pguillard commentedComment #99
andypostComment #100
rosinegrean commentedComment #101
volegerRerolled.
Fixed CS issue with a deprecation message.
Added the legacy test.
Comment #103
andypostFix broken test and few nits, I think it's fine to have module handler from
\Drupal- scope issue #3015650: Deprecate tracker_page() and allow tracker.pages.inc to be removed in Drupal 9Comment #104
andypostOne more clean-up
Comment #106
andypostFinally green!
Comment #107
berdirAt least this needs an issue summary update. The issue summary is very old and it's goal initially apparently was to remove this function completely. the patch now is "just" a 1:1 deprecation in favor of a method on a service.
not really our problem here, but this description is very outdated. There is no such thing as a menu router item file definition in Drupal 8.
And I guess that this files thing almost unused too in D8. This was necessary when form callbacks were hidden away in optional include files and needed to be loaded, but now that should mostly/completely be on classes which are autoloaded.
From a quick glance, there seems to be exactly one thing in D8 that still relies on this, and that's the theme-settings.php feature to customize the theme settings for. If there is no issue yet then lets open one to deprecate this?
can we really resolve this as a link? I doubt that, lets use interface::method?
not surprised that most of this patch is locale/content_translation, way too many include files in those modules.
yeah, this issue is pretty good at pointing out weird left-over functions :) That function and its helper things are the last things left in node.admin.inc.
That reminds me of #3015650: Deprecate tracker_page() and allow tracker.pages.inc to be removed in Drupal 9, which needs some fixes *hint* :)
this file doesn't exist anymore, so that load include is bogus and only doesn't fail because we ignore missing files (should we?)
And the description above is also bogus, there is no taxonomy_vocabulary table in D8 and the machine name now is the ID ;)
Yes, kinda off topic, but if we do a separate issue then it's weird to update those calls here?
Comment #108
andypostAbout #107.6 this file still here https://git.drupalcode.org/project/drupal/blob/HEAD/core/modules/views_u...
I recall few issues about its functions but probably it needs some meta to get rid of it
- #3017299: Remove unused module_load_include() in view_ui module
- #3035340: Deprecate core/modules/views_ui/admin.inc
Comment #109
andypostIt blocks #3012523: Convert the update.inc file functions to a class
Comment #110
andypostRerolled after #3015650: Deprecate tracker_page() and allow tracker.pages.inc to be removed in Drupal 9
Also fixed #107.2
For #107.6 there's issues already - this include still there and used
#3017299: Remove unused module_load_include() in view_ui module
#3035340: Deprecate core/modules/views_ui/admin.inc
Comment #112
volegerJust reroll with version update in the deprecation messages.
Comment #114
shaktikComment #115
shaktikComment #116
shaktikComment #117
shaktikRemoved module_load_include() from Drupal, kindly review.
Comment #118
shaktikComment #119
daffie commentedThis change is wrong. Parameters in the wrong order.
When a patch adds a
@trigger_error(), there also has to be testing for the deprecated message. See: #3038513: Move drupal_generate_test_ua() into the test system with the code:The comment is now longer then the maximum of 80 characters. See: https://www.drupal.org/docs/develop/standards/coding-standards#linelength
Comment #120
daffie commentedUpdated the the IS and the CR.
Comment #121
daffie commentedComment #122
shaktikComment #123
shaktikCould you please provide full test cast I am trying to run but not luck attach the screenshot.
Comment #124
shaktikComment #125
shaktikComment #126
daffie commented@shaktik: I think you have a syntax error in your code. You shall have to fix that first before the test will run. Also that issue has not landed. I only added it as an example of how to add testing for
@trigger_error().Comment #127
kim.pepperSorry @shaktik I couldn't work out what changes you were making from #112. Next time can you please add an interdiff as outlined in https://www.drupal.org/documentation/git/interdiff
I've basically taken #112 and simplified the legacy test and got it working.
Comment #128
shaktikThanks, @kim.pepper for quick help/fix, will be taken care of next time.
Comment #129
daffie commentedAll the code changes look good.
All my points are addressed.
Only after installing the patch and doing a code base search for "module_load_include(", I find the the function is still being used in "core/scripts/generate-d6-content.sh" and "core/scripts/generate-d7-content.sh". I should have checked for this earlier.
The patch is almost RTBC for me.
Comment #130
kim.pepperAren't those files for d6 and d7 where the function exists?
Comment #131
daffie commentedNo, the function
module_load_include()lives in:core/includes/module.inc.Comment #132
daffie commented@kim.pepper: You are right. The scripts are not to be used with a Drupal 9 site, but should be used on a Drupal 6/7 site. As stated in the docblocks of both scripts.
With that the patch is for me RTBC.
Comment #133
xjmInteresting; why aren't we using the service here? This could use an inline comment if nothing else to explain why we're not using the service.
Comment #134
ravi.shankar commentedI think we can use a service here.
So I have added a patch that uses a service to get module path.
If we can't use service here then we can ignore this patch.
Comment #135
daffie commentedWhat @xjm wants to know is why we do not use the service here. What would happen when we do:
instead of what the patch does in comment #127:
When it works with the service then use the service and when it does not, then add a comment with why it does not work in the patch.
Comment #136
sja112 commentedUpdated patch to add
instead of
--- Checking the result
Comment #138
sja112 commentedIn #92
that why
this change is included instead of use of service.
Updated patch to include the inline comment.
Comment #139
longwaveThis @todo has not been solved. This seems like an API change, if previously we could load arbitrary files from disabled modules, but now we cannot (this seems to be why
module_load_install()needs to be fixed).This doesn't really need to change, is there a preferred style here?
Comment #140
Rkumar commented@longwave
Regarding 2 points, It's good to have as like
As given name = NULL as per definition, and mostly followed the same way
public function loadInclude($module, $type, $name = NULL)Comment #142
voleger#139.1: Tried to addess this item. Currently allowed to load only install files for disabled modules (which situation may require to load any other file from the disabled module?). Reviews are welcome.
#139.2: I prefer to not use workaround of the ways how the function designed to be used. So +1 to keep this change.
Comment #144
daffie commentedAdd a number of comments on the MR, therefore changing the status to NW.
The deprecation need to be changed from 9.1.0 to 9.2.0.
Comment #145
volegerUpdated IS and CR. Also addressed review comments.
Comment #146
daffie commentedComment #147
daffie commentedAlmost RTBC.
@voleger: Thank you for working on the MR.
Comment #149
Pooja Ganjage commentedComment #150
daffie commentedThere are still unresolved threads. Back to needs work.
Comment #151
daffie commentedComment #153
tr commentedComment #154
andypostI bet fixing #2010380: Deprecate module_load_install() and replace it with ModuleHandler::loadInstall could minimize changes
Comment #155
tr commentedYes, I agree. I think it would be cleaner to keep the two changes separate. This issue was just about
module_load_include()until about 6 month ago when it was expanded, and it now conflicts with #2010380: Deprecate module_load_install() and replace it with ModuleHandler::loadInstall.The big issue with
module_load_include()IMO is that it was always used for loading code from both installed modules and uninstalled modules. That ability needs to be preserved, as contrib may depend on it. But doing a special-caseif ($type === 'install')like this patch does is really not a good thing to do as far as I'm concerned, since it special-casesmodule_load_include()just for the implementation ofmodule_load_install(). Instead, if the implementation ofmodule_load_install()needs different code, that should be inmodule_load_install().Comment #156
andypostThis brings up a question of loading includes (no matter which kind it's)
There's 2 hard coded includes - .install and tokens, views, templates and "broader"
module_load_include()it's all sounds like one method to module handlerComment #158
volegerOpened one more MR with which contains module_load_include() related changes only, left previous MR as is.
Comment #160
volegerRebased and updated MR 1222
Comment #161
volegerAddressed review comments
Comment #162
daffie commentedAll the code changes look good to me.
The method is deprecated in D10 and removed in D11.
I have updated the CR.
For me it is RTBC.
Comment #163
tr commentedI don't think this is RTBC. The concern from #139 has not been addressed:
I also expressed this same concern in #155:
Also, the CR needs to be updated.
Comment #164
volegerAddressed #163
Comment #165
daffie commentedYou are right @TR (in comment #163), that still needs to be fixed. Only now it does not work and this issue does not fix that. To me this is out of scope for this issue. I have created a followup issue for it: #3256205: \Drupal::moduleHandler()->loadInclude() should also work with disabled and/or uninstalled modules.. Changing the status back to needs work for moving the @todo to the docblock of \Drupal::moduleHandler()->loadInclude().
Comment #166
daffie commented@voleger: If we are going to address #163 in this issue can we then also add testing for it. To make sure it fixes the problem.
Comment #167
voleger#166 Sure here the test only patch
Comment #168
volegerAdded test into MR
Comment #170
volegerSo, we have proof that #139 was addressed. Needs review.
Comment #171
daffie commentedThe problem from comment #163 has been addressed and has testing for it.
Back to RTBC.
Comment #172
alexpottThe module handler loading themes should be a big red flag here. That's a massive change and not in a good direction. It points to an incorrect architecture or the method being used in the wrong places. I think it is a mistake to allow the module handler to work with anything that is not installed and anything that is not a module.
Comment #173
volegerI'd updated the test which shows that the module handler only deals with the module extensions and includes the file from the uninstalled extension only when the developer provides confirmation that is intended action.
Comment #174
daffie commentedThe testbot is not happy.
Comment #175
volegerIt is happy now, but in that case, @alexpott is right - module_load_include is used not only by module extensions.
Comment #176
daffie commentedJust one little nitpick. After that it is RTBC for me. I was not allowed to make the change myself in the MR.
Comment #177
alexpottI still think that the module handler has no business processing uninstalled modules or profiles. I think that code that works with uninstalled extensions should have to go an extra mile in order to include the code and we should not use our generic module code includer to do that.
Comment #178
alexpottI.e. all the additional logic to load uninstalled stuff should go in module_load_install() and not in ModuleHandler. And then when we refactor module_load_install() we come up with some other install-only service that does this.
Comment #179
tr commentedI am perfectly happy with this conclusion EXCEPT that it represents a reversal of what we did in D8, D7 etc. In previous versions of core, it was clearly INTENTIONAL that the module handler dealt with uninstalled module includes, and it was documented that way in the code comments.
Thus, if this behavior is going to be changed, then the change should ALSO be intentional and the change should be made explicit in the CR.
I made both of these points above: Support for uninstalled module includes was unknowingly dropped in the above patches, it was not discussed, and the patch authors clearly weren't aware of it. This change was also left out of the CR.
Comment #180
alexpott@TR the module handler doesn't exist in D7 and in D8 where it was introduce we intentionally made it only handle installed modules. This change is making it handle uninstalled modules and that's exactly what I think it should not do.
Comment #181
tr commentedDude, this issue has been open for 12 years. Instead of picking on the wording, how about interpreting my post in context? I and others were far more precise above and in the related issues. Seems like a massive waste of time to re-explain everything in every subsequent comment.
As mentioned above, this @todo about module_load_include() has been in the Drupal API documentation for a very long time:
This is precisely what the current issue is about - replacing module_load_include() with a method in the module_handler service. From this @todo, it's clear that the module_handler service was meant to preserve the functionality of module_load_include().
@longwave from #139 (May 2020):
It's a simple ask - if the behavior is going to be changed it should be intentional and documented. There are far too many core issues where this doesn't happen and we have regressions that never get fixed. Let's do a better job this time.
Comment #182
alexpottWe're adding unnecessary complexity and functionality to ModuleHandler for the benefit of only module_load_install(). Let's not do that. There's no reason to allow the ModuleHandler to include files from modules that are not installed. The @todo is not correct. We shouldn't allow the ModuleHandler to load code from uninstalled modules because that code has no business being loaded unless we're in very very specific situations which are all controlled via module_load_install().
It is a massive improvement to Drupal's architecture that the only files the can be included from uninstalled modules are .install files and we just don't support including files from uninstalled things.
Comment #183
alexpottThe patch attached is what I think we should do.
Comment #184
alexpottHmm... actually the previous patches have actually broken the legacy code's ability to include code from uninstalled modules... so I've fixed that by reverting the unnecessary changes to module_load_include(). I've also simplified module_load_install() to the mere necessary.
Comment #185
alexpottMissed a bit.
Comment #186
alexpottAmusingly even module_load_install() doesn't need to deal with uninstalled code so we can follow this up with deprecating module_load_install() with moduleHandler::loadInclude() with no changes to it.
Comment #188
daffie commentedAll code changes look good to me.
The IS and the CR are in order.
For me it is RTBC.
Comment #189
alexpottI've fixed the CR to be only about module_load_include(). Also after recent discussions with the release managers I think we should deprecate this in 9.4.x. I think Drupal 11 is the correct target for removal because there are 19 pages on http://grep.xnddx.ru/search?text=module_load_include&filename=&page=18. Given this is only a text change I've left the issue at RTBC.
We can then continue in #2010380: Deprecate module_load_install() and replace it with ModuleHandler::loadInstall
Comment #191
daffie commentedTestbot failure not related to the patch.
Back to RTBC.
Comment #194
catchThe whole problem of needing to load code from disabled modules date back to issues like #194310: Check / run updates of disabled modules. Even then, we didn't need to load code from uninstalled modules, only disabled ones. Disabled modules no longer exist as a concept, so we don't need it at all.
Agree that 19 pages of results is enough to make this a remove in Drupal 11 issue.
Committed/pushed to 10.0.x and cherry-picked to 9.4.x, thanks!