When two modules with the same name are placed in different locations (ie core vs sites) the system does some rather dumb things.

  1. Loads both install files, which results in nasty things like: Fatal error: Cannot redeclare simpletest_install() (previously declared in /home/boombatower/software/simpletest/simpletest.install:109) in /home/boombatower/software/drupal-7/modules/simpletest/simpletest.install on line 54
  2. Uses the proper .info file.
  3. Actually loads the core PHP files and ignores the ones in sites folder.
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

sun’s picture

Everything in sites/ should always have precedence.

boombatower’s picture

Right, but they don't.

boombatower’s picture

Assigned: Unassigned » boombatower

Working on this.

boombatower’s picture

So far, drupal_get_install_files() returns the proper .install file locations, and only one of them for simpletest.

boombatower’s picture

system_rebuild_module_data() seems to exhibit the behavior I noticed.

It says simpletest is in modules directory, yet picks up the .info file information from the one in sites (double whammy).

Would seem it has to do with:

  system_get_files_database($modules, 'module');
  system_update_files_database($modules, 'module');

Not updating to the proper file since the database has the wrong file, but:

$modules = drupal_system_listing('/\.module$/', 'modules', 'name', 0);

returns the right one (which is used for .info file parsing).

Not sure why this code is so extremely convoluted.

boombatower’s picture

It would seem that one function (for scanning file system) would be enough then...you update file listing ..and read .info files.

Secondly, I have no idea what the purpose of the get and then update the files database...as from scanning it would appear no change is made...the files table is simply re-written.

Dave Reid’s picture

Not sure what you mean by re-written in http://api.drupal.org/api/function/system_update_files_database/7. Old obsolete module records are deleted and new/discovered/updated (as in info in the module's .info file changed) modules are inserted/added. The point of the two functions (you should take a look at this nasty code in D6), was to re-use the functions with both themes and modules.

boombatower’s picture

The names are not clear, but either way since both modules and themes have info files they still share everything in common and should be able to use the same function, I am not seeing why the info file parsing is completely separate or if anything why they do not use the same method to seek the actual files.

Either way, the functions that seek the files do not function properly, when I get time I'll try and figure it out, otherwise it would be great if someone else had time to fix them.

boombatower’s picture

Status: Active » Needs review
FileSize
1.01 KB

Win on the "key" instead of "$key".

sun’s picture

Great.

So what we do now is:

1) Add modules/simpletest/book.module.

2) Put some completely different stuff in there. Including hook_menu() to test a callback. Perhaps also an arbitrary alter hook.

3) Add a test that enables "book" module.

4) Verify that modules/book/book.module is NOT loaded and entirely unknown to the entire system.

boombatower’s picture

That doesn't really work since it should always override. We only care about levels when modules/ vs sites/all vs sites/xyz.

And we dont' have write access to sites/[non-files] or modules/ so unless we do somethign interesting it isn't really possible since we need to gen module on the fly. (or break rules)

Status: Needs review » Needs work

The last submitted patch failed testing.

boombatower’s picture

Status: Needs work » Needs review
FileSize
2.06 KB

Double wammy, bad test as well, since $array1 == $array2 or $array1 === $array2 will only be equal if they are in the same order, which sadly the test it trying to check once in order and once not, but uses same assertion.

For example:

$array1 = array(
  'foo',
  'bar',
);

$array2 = array(
  'bar',
  'foo',
);

var_dump(array_diff($array1, $array2));
var_dump($array1 == $array2);

Results in:

array(0) {
}
bool(false)

Which is what we want.

Dave Reid’s picture

@boombatower: If you use array keys (which is what happens in module_list()), comparison does work:

$array1 = array(
  'foo' => 'foo',
  'bar' => 'bar',
);

$array2 = array(
  'bar' => 'bar',
  'foo' => 'foo',
);

var_export($array1 == $array2);

results in true

Dave Reid’s picture

@boombatower: Not sure what you mean by array_combine not working. "array_combine — Creates an array by using one array for keys and another for its values". $expected_values = array_combine($expected_values, $expected_values); basically works like drupal_map_assoc().

boombatower’s picture

Here are the arrays the test has when it runs.

$a1 = array ( 'block' => 'block', 'color' => 'color', 'comment' => 'comment', 'dashboard' => 'dashboard', 'dblog' => 'dblog', 'default' => 'default', 'field' => 'field', 'field_sql_storage' => 'field_sql_storage', 'field_ui' => 'field_ui', 'file' => 'file', 'filter' => 'filter', 'help' => 'help', 'image' => 'image', 'list' => 'list', 'menu' => 'menu', 'node' => 'node', 'number' => 'number', 'options' => 'options', 'path' => 'path', 'rdf' => 'rdf', 'search' => 'search', 'shortcut' => 'shortcut', 'system' => 'system', 'taxonomy' => 'taxonomy', 'text' => 'text', 'toolbar' => 'toolbar', 'user' => 'user', );
$a2 = array ( 'block' => 'block', 'color' => 'color', 'comment' => 'comment', 'dashboard' => 'dashboard', 'dblog' => 'dblog', 'field' => 'field', 'field_sql_storage' => 'field_sql_storage', 'field_ui' => 'field_ui', 'file' => 'file', 'filter' => 'filter', 'help' => 'help', 'image' => 'image', 'list' => 'list', 'menu' => 'menu', 'node' => 'node', 'number' => 'number', 'options' => 'options', 'path' => 'path', 'rdf' => 'rdf', 'search' => 'search', 'shortcut' => 'shortcut', 'system' => 'system', 'taxonomy' => 'taxonomy', 'text' => 'text', 'toolbar' => 'toolbar', 'user' => 'user', 'default' => 'default', );

var_dump($a1 === $a2); // Result: false

var_dump(array_diff($a1, $a2)); // Result: empty array

ksort($a1);
ksort($a2);

var_dump($a1 === $a2); // Result: true

var_dump(array_diff($a1, $a2)); // Result: empty array

Only difference is default is in a new location.

Looking into this.

boombatower’s picture

Ah, yes @Dave Reid: your example uses "==" when assertIdentical() uses "===".

I'll update test to use == and then we don't need array_diff().

boombatower’s picture

FileSize
2.05 KB
boombatower’s picture

chx said it was worthy of a phpwtf: http://www.phpwtf.org/identical-arrays-vs-equal-arrays.

rfay’s picture

Subscribing. I too have spent pain on this issue.

In my case:

  • Two modules of the same name in different directories, both in sites/all/modules.
  • Remove the bad one, which also happened to be the one already in the system table.
  • Try to update cache and get the table rebuilt, but a cache rebuild caused fatal error.
boombatower’s picture

For clarification, #19 works great for me at solving the problem, just need someone to "review" the patch.

chx’s picture

Status: Needs review » Reviewed & tested by the community

Bugfix and a PHP ouch in the test. Please understand that this is a serious regression. The capability of site specific core hacks by copying a module and hacking there is rather important.

sun’s picture

+++ modules/system/system.module	9 Nov 2009 20:17:21 -0000
@@ -2122,6 +2122,9 @@
   foreach ($modules as $key => $module) {
+    // Filename key is used in system table so copy value.
+    $modules[$key]->filename = $module->uri;

Could we quickly clarify/improve this inline comment a bit? I don't get what it wants to tell me by reading it.

I'm on crack. Are you, too?

webchick’s picture

Status: Reviewed & tested by the community » Needs work
boombatower’s picture

Status: Needs work » Reviewed & tested by the community
FileSize
2.13 KB

Here ya go.

boombatower’s picture

oo...lets get this in.

webchick’s picture

Status: Reviewed & tested by the community » Fixed

Committed to HEAD.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.