Skip directly to content

Brenda Boggs's blog

Working with Arrays and Objects in Drupal with print_r() and dpm()

on July 1st, 2011 at 4:33:43 PM

When customizing things in Drupal, whether we like it or not, there often comes the need to dive in and alter or override things. Because of Drupal's API, we're given a lot of wonderful hooks and theme functions to take advantage of without touching Drupal core. Instead we can modify most things the way we want within our own custom module or theme, without ever having to worry about our changes getting overwritten when doing an update to our web site.

Great! There's plenty of tutorials, blog posts, forum posts and issues both on drupal.org and throughout the interwebs on how to work with data in order to bend it to our wills, but it's not always clear on how exactly to work with the data in the first place.

Understanding print_r()

PHP provides us with a handy (if not a bit "dirty") function called print_r. What it does is print readable information about PHP objects and arrays that assist with debugging and figuring out what value we're trying to target. Here is a partial output of me doing a print_r($form) in a hook_form_alter of a blog post. What we need to understand is I am printing the full output of $form, which is an array. Each piece of the array contains a key and a value, where the value can be another array, an object, or a string.

Take a look at the screenshot above. When I am manipulating this form, I need to target the keys of the array(s) in order to manipulate any of the values. Each indent shows us the tree. We know that this is printing out $form. In order to target any of the keys within that, we need to use $form['nid'] or $form['type'] or $form['uid'], and deeper than that is $form['nid']['#type'], $form['type']['#value'], or $form['uid']['#value'].

Now we understand that arrays are handled with brackets: [ ]

But PHP objects are a little different. Below is a screenshot of another part of the $form array I posted above. This portion is accessed with $form['#node']. You'll notice instead of Array, it says stdClass Object. This means we're working with an object, not an array. Let's ignore what the differences are right now, and just figure out how we manipulate that data.

Arrays are targetted with brackets. Objects are targetted with ->.

Homework: A few other useful PHP functions are var_dump() and var_export().

Using dpm()

The Devel module takes this a bit further and provides us with dpm(). This gives us output in a much more readable format, though the concept is the same.

With this, you can now use many of Drupal's great hooks to override various content-- take a look at my previous blog posts, Drupal Alters and Overrides: hook_form_alter and Drupal Alters and Overrides: hook_menu_alter.

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

Pages