3

I'm writing a module that can have some additional functionality if other modules such as Block or Menu are enabled, but I don't want to declare them as a dependency.

Currently I'm using if(module_exists($module)) { ... } to provide module-specific functionality within my custom module (in this case, defining a particular view if the module in question is present).

However I've heard that this is not the right way to provide module-specific features, and that instead I should use hooks and plugins. The only problem is that I don't really know what that means or how to get started converting my module to using those instead of if()s.

How do I define a custom view that depends on another module without using an if()?

One of the things I am trying to do is to expose that module's SQL tables to Views if the module exists, and then define a custom view with those tables.

2
  • What specific functionality are you wanting to add? You may be able use the relevant module hooks, otherwise module_exists could be a reasonable solution. Oct 15, 2013 at 21:31
  • One of the things I am trying to do is to expose that module's SQL tables to Views if the module exists, and then define a custom view with those tables.
    – beth
    Oct 15, 2013 at 21:33

3 Answers 3

1

If you want to provide Views with your module, dependent on enabled modules, you can implement

hook_views_default_views

This hook allows modules to provide their own views which can either be used as-is or as a "starter" for users to build from.

This hook should be placed in MODULENAME.views_default.inc and it will be auto-loaded. MODULENAME.views_default.inc must be in the directory specified by the 'path' key returned by MODULENAME_views_api(), or the same directory as the .module file, if 'path' is unspecified.

The $view->disabled boolean flag indicates whether the View should be enabled (FALSE) or disabled (TRUE) by default.

In that hook implementation, you can check if the relevant module is enabled with module_exists or function_exists when defining that View or component of the View and return the View definition(s) accordingly.

5
  • This is what I'm already doing, as described above.
    – beth
    Oct 15, 2013 at 21:38
  • It wasn't clear that you're using hook_views_default_views, if so that seems like a reasonable solution. Alternatively, you could use features with a dependencies[] declaration in the .info file. Oct 15, 2013 at 21:40
  • "...but I don't want to declare them as a dependency." Using hook_views_default_view()is part of exposing any custom fields to Views, and isn't really related to checking for the presence of modules like Block or Menu.
    – beth
    Oct 15, 2013 at 21:43
  • I saw you said you don't want to declare them as a dependency but it's not at all clear why, especially if it was a distinct feature module. hook_views_default_view defines the view, not custom fields, so you can return a view or not depending on available modules. Oct 15, 2013 at 21:50
  • You're right, I was thinking of hook_views_data() instead. The reason I don't want to declare dependencies is because my module is meant to describe the current state of the site, not to alter it.
    – beth
    Oct 15, 2013 at 21:53
0

I think what you are looking for (or what other people meant when they said that you shouldn't use module_exists() so much) would be to implement hooks "on behalf of" another module.

E.g. Crumbs introduces a hook_crumbs_plugins(), and then it implements this hook on behalf of other modules: menu_crumbs_plugins(), taxonomy_crumbs_plugins(), etc. These hooks will only ever be triggered if the respective other modules are enabled.

Whether this is a good idea, depends. It is ok if you are really confident that the respective module will never ever implement this hook by itself. But you need to be aware that you are intruding in the other module's "namespace".

Module names as function prefixes in D7 are quite fragile anyway compared to real namespaces, so maybe we all don't care so much in D7 and just pray that nothing blows up.

Otherwise I don't think it is all too wrong to use module_exists() where it makes sense.

Next time someone says this is best practice, ask them to explain why! There are a lot of mythical and unquestioned DOs and DONTs floating around in the community..

0

If you're using hook_views_default_views, then using if module_exists is perfectly fine.

See the example how Entityform module implements that in entityform.views_default.inc file:

/**
 * Implements hook_views_default_views().
 */
function entityform_views_default_views() {
  $view = new view;
  $view->name = 'entityforms';
  // ...
  /* Display: Master */
  $handler = $view->new_display('default', 'Master', 'default');
  $handler->display->display_options['title'] = 'List';
  // ...
  $handler->display->display_options['relationships']['uid']['required'] = 0;

  if (module_exists('views_bulk_operations')) {
    /* Field: Bulk operations: Entityform */
    $handler->display->display_options['fields']['views_bulk_operations']['id'] = 'views_bulk_operations';
    $handler->display->display_options['fields']['views_bulk_operations']['table'] = 'entityform';
    // ...
    $handler->display->display_options['fields']['views_bulk_operations']['vbo']['force_single'] = 0;
  }

  /* Field: User: Name */
  $handler->display->display_options['fields']['name']['id'] = 'name';
  $handler->display->display_options['fields']['name']['table'] = 'users';
  // ...
  $handler->display->display_options['tab_options']['name'] = 'management';
  $views[$view->name] = $view;

  return $views;
}

Then if another module wants to alter the existing view definition, it can use hook_views_default_views_alter in similar way (see example here).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.