You are here

Hello hook_module_implements_alter

Categories: 

While working on a project for a client that was a perfect fit for the file_entity module, I came across an issue I didn't care for. Implementing hook_file_presave, the file_entity module assigns the file type based upon the first part of the mime type. This is a good thing technically, but my client's needs had to trump that. Instead they wanted two file types; image and files. Instead of having more specific file types/bundles, the generic would contain everything from PDF files (applications in the mime world) to text documents (text in the mime world). That means changing field displays or altering fields for non-image files would mean editing each of these bundles.

I created an issue with the file_entity project to allow a alter hook to run after file_entity_file_presave sets the type, however Dave Reid informed of me a gem of a hook I missed in Drupal 7 - hook_module_implements_alter.

First let's take a look at file_entity_file_presave:

function file_entity_file_presave($file) {
  // Always ensure the filemime property is current.
  if (!empty($file->original) || empty($file->filemime)) {
    $file->filemime = file_get_mimetype($file->uri);
  }

  // Always update file type based on filemime.
  $file->type = file_get_type($file);


  field_attach_presave('file', $file);
}

Of course the change I needed to implement was right after the $file->type line. Now this could have been handled using module weighting, but at times that can be fickle, but with the new hook_module_implements_alter, things get much better!

 

function {my_module}_module_implements_alter(&$implementations, $hook) {

  if ($hook == 'file_presave' && is_array($implementations)) {
    unset($implementations['file_entity']);

  }
}

function {my_module}_file_presave($file) {
  // Always ensure the filemime property is current.
  if (!empty($file->original) || empty($file->filemime)) {
    $file->filemime = file_get_mimetype($file->uri);
  }

  // Always update file type based on filemime.
  $file->type = file_get_type($file);

  if ($file->type != 'image') {
    $file->type = 'file';
  }
  field_attach_presave('file', $file);
}

So by basically copying the original hook over, then removing it from the registery via hook_module_implements_alter, I can now do what I want. I really see a lot of power for this hook and a much cleaner approach than dealing with module weights.