As contributer to the image CAPTCHA module, I'd like to add a pre-install check if the GD library is availiable with FreeType support.
I thought that hook_requirements would be the right place to do this, but it appears that I can't hook into the 'install' phase, only the 'runtime' phase is available.

I did some research and found out that the install phase only looks for hook_requirements implementations in .install files in the 'modules' directory, and not in 'sites/all/modules' and friends, where contributed modules should live.

Before installation of a module (in modules/system/system.module::system_modules_submit()), drupal_check_module() (defined in includes/instal.inc) is called, which looks for the .install file of the module with drupal_get_install_files():

function drupal_get_install_files($module_list = array()) {
  $installs = array();
  foreach ($module_list as $module) {
    $installs = array_merge($installs, file_scan_directory('./modules', "^$module.install$", array('.', '..', 'CVS'), 0, TRUE, 'name', 0));
  }
  return $installs;
}

This returns nothing for (contributed) modules outside the core modules directory, so the .install file is not found, so the desired hook_requirements() is not called.

Is this intended behaviour (I'd prefer not) or is this a bug?

If it is a bug I guess the file_scan_directory() thing should be replaced with the right drupal_system_listing() call?

Comments

Anonymous’s picture

Based on http://api.drupal.org/api/function/file_scan_directory/5 I think it looks wrong.

function drupal_get_install_files($module_list = array()) {
  $installs = array();
  foreach ($module_list as $module) {
    $installs = array_merge($installs, file_scan_directory('./', "^modules/$module.install$", array('.', '..', 'CVS'), 0, TRUE, 'name', 0));
  }
  return $installs;
}

Does the above change work for you?

soxofaan’s picture

Status: Active » Needs review
StatusFileSize
new783 bytes

Does the above change work for you?

No, still nothing is returned, I guess you meant something like "$module.install$" instead of "^modules/$module.install$".

But anyway, I think usage of a bare file_scan_directory() won't cut it because several directories like 'modules/', 'sites/all/modules/' and 'sites/example.com/modules/' need to be searched and some directories like 'sites/otherexample.com/modules/' should not be searched.
The function drupal_system_listing() is very handy here to search through the right directories:

function drupal_get_install_files($module_list = array()) {
  $installs = array();
  foreach ($module_list as $module) {
    $installs = array_merge($installs, drupal_system_listing("$module.install$", 'modules', 'name'));
  }
  return $installs;
}

This works nicely.
see attached patch

Anonymous’s picture

Status: Needs review » Needs work

I think this

+    $installs = array_merge($installs, drupal_system_listing("$module.install$", 'modules', 'name'));

should be

+    $installs = array_merge($installs, drupal_system_listing("$module.install$", 'modules', 'name', 0));

to make it match the original intention for the min_depth parameter.

-    $installs = array_merge($installs, file_scan_directory('./modules', "^$module.install$", array('.', '..', 'CVS'), 0, TRUE, 'name', 0));

Otherwise I think it is the correct patch but I need to test it.

soxofaan’s picture

Status: Needs work » Needs review
StatusFileSize
new775 bytes

at #3:

I think the min_depth=0 in the original drupal_get_install_files() implementation is a leftover from the time (drupal 4.x) that modules did not reside in their own directory. But since Drupal 5 that's not the case anymore and it is considered good style to put each module in its own directory. That's why min_depth of drupal_system_listing() defaults to 1, I guess. drupal_system_listing() was introduced in Drupal 5, while file_scan_directory() goes back to D4.6.

Considering argument defaults, even the $key='name' argument can be dropped, because that's the default:

function drupal_get_install_files($module_list = array()) {
  $installs = array();
  foreach ($module_list as $module) {
    $installs = array_merge($installs, drupal_system_listing("$module.install$", 'modules'));
  }
  return $installs;
}

see attached patch

soxofaan’s picture

at #3:

I think the min_depth=0 in the original drupal_get_install_files() implementation is a leftover from the time (drupal 4.x) that modules did not reside in their own directory. But since Drupal 5 that's not the case anymore and it is considered good style to put each module in its own directory. That's why min_depth of drupal_system_listing() defaults to 1, I guess. drupal_system_listing() was introduced in Drupal 5, while file_scan_directory() goes back to D4.6.

Considering argument defaults, even the $key='name' argument can be dropped, because that's the default:

function drupal_get_install_files($module_list = array()) {
  $installs = array();
  foreach ($module_list as $module) {
    $installs = array_merge($installs, drupal_system_listing("$module.install$", 'modules'));
  }
  return $installs;
}

see attached patch

(the first submission of this post failed in some strange way, I hope this is not a duplicate post)

soxofaan’s picture

StatusFileSize
new775 bytes

at #3:

I think the min_depth=0 in the original drupal_get_install_files() implementation is a leftover from the time (drupal 4.x) that modules did not reside in their own directory. But since Drupal 5 that's not the case anymore and it is considered good style to put each module in its own directory. That's why min_depth of drupal_system_listing() defaults to 1, I guess. drupal_system_listing() was introduced in Drupal 5, while file_scan_directory() goes back to D4.6.

Considering argument defaults, even the $key='name' argument can be dropped, because that's the default:

function drupal_get_install_files($module_list = array()) {
  $installs = array();
  foreach ($module_list as $module) {
    $installs = array_merge($installs, drupal_system_listing("$module.install$", 'modules'));
  }
  return $installs;
}

see attached patch

(the first submissions of this post failed in some strange way, I hope this is not a duplicate post)

soxofaan’s picture

sorry about the duplicate posts :)

drumm’s picture

Version: 5.x-dev » 6.x-dev
Status: Needs review » Reviewed & tested by the community

This looks okay.

It does apply cleanly to 6.x, where I would like to see it committed first.

drumm’s picture

Status: Reviewed & tested by the community » Needs work

Actually, I tested this and it breaks install. Common.inc, which has that function, is not included early in the install process.

soxofaan’s picture

Since I'm not very familiar with Drupal core development, what would you suggest?

moving drupal_system_listing() to install.inc?
including common.inc earlier?
emulating drupal_system_listing in drupal_get_install_files()?
something else?

drumm’s picture

Status: Needs work » Closed (duplicate)

This is a duplicate of http://drupal.org/node/110981.