Currently, before returning the list of themes, the list_themes() function does a file_exists() check on each theme's .info file. If the file doesn't exist, it removes the theme from the returned list.
Issues:
- This code is called on every non-cached page request, and can't be great for performance (especially since it calls it for every theme on your site, even disabled ones).
- Imagine some sporadic error that causes file_exists() to return FALSE (filesystem glitch, whatever - i.e. if the files are temporarily unreadable). Then any code that runs on that page request which calls list_themes() will assume your theme simply does not exist. That can have unintended consequences. For example, if you are visiting the block configuration page on that request (or clearing caches, etc), _block_rehash() will run and will disable all blocks for the theme, which isn't good.
Note that we've seen this "all blocks get disabled" bug on rare occasions in Drupal Gardens and don't know exactly what causes it, but suspect this might be the root cause. (I also have a patch at #925360: Block module sometimes disables all blocks (root cause not yet found) to treat the symptom.)
- Finally, there is really no fundamental reason why list_themes() should check that the theme data in the database is consistent with the filesystem. Code that needs to make sure that it is getting the latest data from the filesystem should already be calling (and does call) system_rebuild_theme_data() instead.
It looks like this file_exists() check has been around since at least Drupal 4.6, so it may be that it served a purpose a long time ago but no longer does.
The attached patch simply removes it.
Comment | File | Size | Author |
---|---|---|---|
list-themes-remove-file-exists.patch | 807 bytes | David_Rothstein | |
Comments
Comment #1
pwolanin CreditAttribution: pwolanin commentedThis make a lot of sense. We should hunt down and kill more such unneeded checks.
Comment #2
effulgentsia CreditAttribution: effulgentsia commentedRTBC +1. Given that the file_exists() has existed for so long, I believe it's legacy cruft rather than anything currently needed, and I fully agree with all points in the OD, and I think the first one is reason enough to do it: file_exists() is not always cheap, especially on network file systems under heavy load. It's possible this will cause a regression, so this change should be announced to the dev list, which is why I'm giving it the "API change" tag, even though this isn't technically an API change. But any such regression is indicative of faulty calling code, and can be fixed with something more appropriate, as per point 3 in the OD.
Comment #3
effulgentsia CreditAttribution: effulgentsia commentedx-post.
Comment #4
Damien Tournoud CreditAttribution: Damien Tournoud commentedOh my. +1 here as well
Comment #5
ksenzeeYes please. We should probably grep for file_exists and see just how much legacy cruft there is.
Comment #6
sunThat entire function needs an overhaul, and I'll do that ASAP, but this patch is ready to go.
Comment #7
sunAlthough badly needed, this is D8 material according to the rules (I had to learn today).
Comment #8
David_Rothstein CreditAttribution: David_Rothstein commentedAs @effulgentsia said above, the extent to which this is actually an "API change" is extremely tiny and probably nonexistent. Anyone who somehow relied on this behavior had a bug in their calling code to begin with...
Moving back to D7 for consideration.
Comment #9
Dries CreditAttribution: Dries commentedCalling this an API change is a bit of a stretch, IMO. Committed to CVS HEAD. Thanks.
Comment #10
rfaySounds like no API change announcement is required from what I read. Let me know if otherwise.
Comment #12
c960657 CreditAttribution: c960657 commentedRelated: #752730: Remove file_exists() during bootstrap