Closed (duplicate)
Project:
Drupal core
Version:
8.0.x-dev
Component:
base system
Priority:
Major
Category:
Bug report
Assigned:
Reporter:
Created:
11 Apr 2011 at 07:26 UTC
Updated:
29 Jul 2014 at 19:29 UTC
Jump to comment: Most recent file
Comments
Comment #1
catchsubscribing.
Comment #3
chx commented*cough* that was superb dumb, wasnt it?
Comment #4
catch#1179422: hook_form_form_id_alter does not honor changes made by hook_module_implements_alter was duplicate.
Comment #5
chx commentedHere's an example of a complicated case that even my patch above does not cover (but I have code upcoming that will cover it just need to translate my skeleton tests into proper simpletests): let's say you call
drupal_alter(array('foo', 'bar'));. You have three modules, m1, m2, m3 andmodule_implements('foo_alter')returnsarray('m1', 'm2');.module_implements('bar_alter')returnsarray('m1', 'm3', 'm2');. Now the following two ordering must apply:drupal_alterThat can not be changed in 7.x. So in this case,m1_foo_altermust fire beforem1_bar_alter. We can review this in D8 but not in D7. There's a separate issue to revisit this ordering.m3_bar_alterfires some time betweenm1_bar_alterandm2_bar_alter. That's whatmodule_implementstold us. If module_implements would tell us to order in such a way that contradicts 1. the behavior is simply undefined.The only order that achieves both goals is
m1_foo_alter, m1_bar_alter, m3_bar_alter, m2_foo_alter, m2_bar_alter. What the upcoming patch is this:array('m1' => array('m1_foo_alter'), 'm2' => array('m2_foo_alter')). We will never change the ordering of these keys. We might want to insert something betweeen them, before them or after them but never change the order.m1, m3, m2list (given bymodule_implements('bar_alter')):array('m1' => array('m1_foo_alter', 'm1_bar_alter'), 'm2' => array('m2_foo_alter')).$todo = array('m3').$todobefore m2 but to do that, we would need to insert before an array key and there is no PHP function for that (array_splice does not really work for associated arrays -- it destroys the replacement keys). So instead we copy the main array one-by-one and when m2 comes, before writing it in the new main array, we iterate$todoand write those implementations down:array('m1' => array('m1_foo_alter', 'm1_bar_alter'), 'm3' => array('m3_bar_alter'))and then copy m2 over:array('m1' => array('m1_foo_alter', 'm1_bar_alter'), 'm3' => array('m3_bar_alter'), 'm2' => array('m2_foo_alter', 'm2_bar_alter'))Horribly ugly, complicated but can't find a better way.
Comment #6
chx commented#765860: drupal_alter() fails to order modules correctly in some cases is the 8.x issue. That can talk about changing the order such that all foo fires first and then all bar fires second. That is not acceptable in D7.
Comment #7
fabianx commentedHere is an attempt to solve this via a weighted sort function (not a patch, but a test case):
http://paste.pocoo.org/show/401484/
The basic idea is to cascade the module_implements by adding it to a map like:
As you can see at index 0, comparing * with m3 or m4 results in NaN (as one of them is undefined), such it goes to the next array to compare the modules.
As you can further see the sort order is conflicting, but the first order is used.
It may be possible to still combine a test case so that the sort function ends up trying to compare against NaN, but I've not yet gotten it so.
Edit: Okay, I found a test case now, which is a little problematic:
My code gives an interesting result with:
This gives the map of:
The resulting order is: m1,m3,m2,m4
As there is a conflict the absolute order is not well defined:
But on second look the partial sort order m1,m3,m2,m4 is correct, because
m1 < m2 -- OK
m1 < m3 -- OK
m3 < m2 -- OK
m1 < m4 -- OK
m2 < m4 -- OK
m3 < m4 -- FAILED, but this is due to the conflict of m3 < m2 and m3 > m2.
So the problem can be really reduced to:
Combine the above mappings into one global sorting order and use that as $module_weight keys.
I think however that the approach of cascaded search should preserve the search order even in case of conflicts.
Best Wishes,
Fabian
Comment #8
chx commentedMy code is at http://paste.pocoo.org/show/401438/ btw.
Comment #9
chx commentedThis implementation hit me while trying to fall back asleep :) It's way, way simpler than anything we came up with previously. Additionally there is one more ordering it keeps:
module_list(). We originally set up a list of module weights in the order ofmodule_list. Then, asmodule_implementsresults comes in -- this is the big trick -- we take the weights of the modules returned by m_i and swap them around so that now the weights reflect the new order. We never assign new weights, we just swap them around.Example: originally you have modules A, B, C, D, E, F weights 0,1,2,3,4,5. m_i returns E, D, B. The potential weights for these three are now 4, 3, 1. Sort the weights: 1, 3, 4. These are the new weights then: E is 1, D is 3 and B is 4.
Comment #10
chx commentedStill needs tests but the above forgot to flatten out
$implementationsinto$functions.Comment #12
fabianx commentedNice work!
Why does the Simple Test fail?
Best Wishes,
Fabian
Comment #13
chx commentedBecause i used $data accidentally there, still working on the patch and tests.
Comment #14
chx commentedHere's current version.
Comment #16
fabianx commentedThe approach in #14 is faulty, because it is assuming the weights are fixed.
Example:
Sorts: 4,3,1,5 and 4,2,0
Sort Order: 0,4,2,3,1,5
With 2 and 0 that need to be changed either the result is 0,4,2,3,1,5 or 2,4,0,3,1,5.
which is obsivously wrong.
New approach (in pseudo code):
This is our setup as sort orders. (the current code can get those)
Modules should of course be named and not numeric, so 0,1,2,3,4,5,6 are module names here, so there is that akey hack below ...
Now we sort it:
And thats it. Works of course only for one alter hook at a time, but the previous patch also had that limitation.
Best Wishes,
Fabian
Comment #17
fabianx commentedHere is the updated code for n dimensions together with an explanation.
Best Wishes,
Fabian
Comment #18
fabianx commentedAssigning to me, so I finally get back to work on this.
Comment #19
catch#1222190: hook_module_implements_alter does not work in some cases when hook is called using drupal_alter was duplicate.
Comment #20
catchBumping this to major, it is causing a lot of duplicates apparently, here's another one #1224014: form_FORM_ID_alter problem with hook_module_implements_alter.
Comment #21
xjmTagging issues not yet using summary template.
Comment #22
wzoom commentedHello Franz, is there any progress with this issue? Also for 7.x ?
Comment #23
xjmComment #24
fabianx commentedPutting on my queue for this week.
Comment #25
David_Rothstein commentedJust pointing out that since #765860: drupal_alter() fails to order modules correctly in some cases was committed to both D7 and D8, this issue may wind up being unnecessary. (But I'm not familiar enough with the code in this issue to know if that's actually the case, plus the other issue is still being heavily discussed and potentially rolled back.)
Comment #26
catchThat patch has been in for a while, and I'm pretty sure it fixes the issue here. Closing as duplicate.