Skip directly to content

Drupal Alters and Overrides: hook_menu_alter

on July 1st, 2011 at 12:55:43 AM

This brief tutorial will cover altering and removing items in Drupal's menu system. See my previous blog post on hook_form_alter.

hook_menu_alter

Introduced in Drupal 6, hook_menu_alter allows you to actually alter elements in Drupal's menu system. The primary links, secondary links, tabs and page callbacks are alterable in this way. For example-- using the Content Profile module, it adds an extra tab to each user's page. If I choose the option to "Show a tab at the user's page", it will then display an extra tab when visiting that profile.

The problem with this is I find the tabs a bit unclear and want to rename them; instead of "View", "Edit" and "Profile", I want them to say "View", "Edit Account Settings", and "Edit Personal Information".

In my demo module, I'll add the following:

/**
 * Implementation of hook_menu_alter().
 */
function demo_menu_alter(&$items) {
  // Change the name of user profile tabs. 
  $items['user/%user_category/edit']['title'] = 'Edit Account Settings';
  $items['user/%user/profile/profile']['title'] = 'Edit Personal Information';
}

You can, of course, also remove menu items or tabs this way. You can find and target your specific menu item with a print_r($items) or dpm($items).

/**
 * Implementation of hook_menu_alter().
 */
function demo_menu_alter(&$items) {
  // Change the name of user profile tabs. 
  $items['user/%user/profile/profile']['title'] = 'Edit Personal Information';
  unset($items['user/%user_category/edit']['title']);
}

In Drupal 6, you can also use the Tab Tamer module.

Image Uploads Using WYSIWYG and Media in Drupal 7

on May 29th, 2011 at 4:51:10 PM

Modules you'll need:

Install the WYSIWYG as instructed with CKEditor support. Enable the Media module and the dependency on File Styles. Under Configuration > Content authoring > WYSIWYG, Edit the text format of your choice. Under the Buttons and Plugins fieldset, make sure you select the Media browser checkbox. Hit Save.

Under Configure > Content authoring > Text formats, and click configure under the text format of your choice. Select the Converts Media tags to Markup checkbox.

Now, under Limit allowed HTML tags fieldset, add the img tag.

When creating a post, you'll now have an Add Media button. Select the file you want to upload and click Submit.

Drupal 7 Quick Tip: Using jQuery's once()

on May 28th, 2011 at 6:06:36 PM

In Drupal 6, many modules as well as custom jQuery required adding a "processed" class to elements in order for those elements to avoid being processed each time an AHAH/AJAX request is made on the page. In Drupal 7, you can now use the jQuery once() plugin instead.

Whereas in the past the jQuery may have looked like this:

$('.form-title:not(.title-processed)').addClass('title-processed').click(function() {
  // functionality here
});

It's now as easy as this:

$('.form-title').once('title').click(function() {
  // functionality here
});

Using once() will automatically apply a "title-processed" class to the element, processing it only once.

Tags: 

Drupal Alters and Overrides: Drupal.theme.prototype

on September 7th, 2010 at 11:30:41 PM

Recently I ran into a situation where I needed to alter the alt text of a link while using the Node relationships module. On mouse hover, it popped up the words "Search and reference..." while I wanted it to say something else, let's say, just "Search". Looking around the module's files, I found that it was embedded in a JavaScript file, node_form.js:

// Install the "Search and reference" button.
    if (fieldOptions.searchUrl) {
      var $searchButton = $(Drupal.theme('nodeRelationshipsReferenceButton', 'search', Drupal.t('Search and reference...')));
      $buttonsWrapper.append($searchButton);
...

You may notice the Drupal.theme namespace above. What Drupal.theme is doing is passing a few parameters; the first, nodeRelationshipsReferenceButton, is the name of our actual theme function:

/**
 * Theme the specified button for an autocomplete widget.
 */
Drupal.theme.prototype.nodeRelationshipsReferenceButton = function(type, title) {
  return '<a href="javascript:void(0)" class="noderelationships-nodereference-'+ type +'-button" title="'+ title +'"></a>';
};

The other parameters being passed are type and title.

Drupal.theme.prototype was introduced in Drupal 6, meant for any modules producing HTML content within their JavaScript, so that this content could be overridden properly.

In the Node relationships module, each dynamically generated button has it's alt tags created in this way. So in order to change things, I would simply add this to my custom JavaScript file:

Drupal.theme.nodeRelationshipsReferenceButton = function(type, title) {
  if (type == 'search') {
    title = 'Search';
  }
  return '<a href="javascript:void(0)" class="noderelationships-nodereference-'+ type +'-button" title="'+ title +'"></a>';
};

Note that the only real different between these functions is the removal of the prototype namespace.

You can read more about Drupal's JavaScript coding standards at http://drupal.org/node/172169

Drupal Alters and Overrides: hook_form_alter

on September 5th, 2010 at 6:17:12 PM

One of the first rules most people coming into the world of Drupal learn, hopefully, is to not hack core. I certainly didn't know about this when I first started out and hacked to pieces a lovely Drupal 4.6 site which, amusingly enough, still exists today. Since then, though, I've become more accustomed to the various ways of altering and overriding things in both Drupal core and contrib "the Drupal way".

Because Drupal is built modular with a strong hook API system, it gives us a lot of power in terms of changing things through our own custom modules. You can read more about creating a custom module at http://drupal.org/developing/modules -- there is also a useful module with some good examples you can download from http://drupal.org/project/examples

I'm going to go through a few different ways you can alter and override content in my next series of blog posts. This first one will cover one of the most popular.

hook_form_alter

One of the most common hooks used to override or alter things in Drupal is hook_form_alter. Drupal is driven by forms-- administration settings forms, content creation forms, contact forms, menu forms, user registration forms, etc., that I don't think I've ever worked on a Drupal site where this hook wasn't used.

Let's say, for example, you've got yourself a View with some exposed filters. By default the submit button says "Apply", but you've been asked to change that to "Submit".

My custom module is called demo. If I take a look at the link above from api.drupal.org, it tells me the parameters my function should have:

hook_form_alter(&$form, &$form_state, $form_id)

This is how it would appear in my module:

function demo_form_alter(&$form, &$form_state, $form_id) {

}

I need to find the $form_id in order to make sure I'm altering only that specific form and not the others. I usually do this just by printing out $form_id. For Views exposed filters, they all have the same $form_id which is 'views_exposed_form'. In order to make sure I'm only targetting this specific exposed form, I also use the $form['#id'] value. You can get these values by doing a print_r($form) or dpm($form) in your module. My alter now looks like this:

/**
 * Implementation of hook_form_alter().
 */
function demo_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'views_exposed_form' && $form['#id'] == 'views-exposed-form-content-search-page-1') {
    $form['submit']['#value'] = t('Search');
  }
}

I can do all sorts of things with forms here. I can remove elements, rename them, add new ones. I can also add or override submit and validation functions. Here are a few examples:

/**
 * Implementation of hook_form_alter().
 */
function demo_form_alter(&$form, &$form_state, $form_id) {
  if ($form_id == 'views_exposed_form' && $form['#id'] == 'views-exposed-form-content-search-page-1') {
    // Rename the submit button
    $form['submit']['#value'] = t('Search');
  }
  if ($form_id == 'search_block_form') {
    // Add default "Search" text in the searchbox
    $form['search_block_form']['#default_value'] = t('Search');
  }
  if ($form_id == 'page_node_form') {
    // Remove the "Preview" option
    unset($form['buttons']['preview']);
    // Add my extra validation function
    $form['#validate'][] = 'demo_extra_validate';
  }
}

Pages