Drupal Planet Posts

3 ways to prompt for user input in Drush

Drush is awesome. It makes Drupal development much easier. Not only that it comes already packed with a bunch of useful commands, but you can declare your own with great ease. So if you need to call some of your module's functionality from Drush, all you have to do is declare a simple command that integrates with it.

In this tutorial I am going to show you how to get user feeback for such a command. I do not refer to arguments or options in this case. But how you can ask for confirmation on whether or not the command should proceed as requested and how you can ask for a choice. Additionally we'll quickly look at how to get free text back from the user.

So let's dive in with an example command callback function called drush_module_name_example_command():

/**
 * Callback function for the example command
 */
function drush_module_name_example_command() {
  // Command code we will look at
  drush_print('Hello world!');
}

Confirmation

The first thing we'll look at is how to get the user to confirm the action. So in our case, we'll ask the user if they really want this string to be printed to the screen. Drush provides a great API for this:

if (drush_confirm('Are you sure you want \'Hello world\' printed to the screen?')) {
  drush_print('Hello world!');
}
else {
  drush_user_abort();
}

You'll notice 2 new functions. The drush_confirm() function prints a question to the screen with the intent of getting one of two answers back form the user: y or n. If the response is y, the function returns true which means our print statement proceeds. If the answer is n, the drush_user_abort() function gets called instead. This is the recommended way to stop executing a Drush command.

Select option

Now let's see how you can make the user choose an option from a list you provide. For our super Hello world use case, we will give the user the choice to select from a list who Drush should say hello to. It can be implemented like this:

$options = array(
 'world' => 'World',
 'univers' => 'Univers',
 'planet' => 'Planet',
);

$choice = drush_choice($options, dt('Who do you want to say hello to?'));

if ($choice) {
  drush_print(dt('Hello @choice!', array('@choice' => $options[$choice])));
}

So what happens above? First, we create an array to store the choices called $options. The array keys are the machine name and the values are the human friendly versions. Then, we call the drush_choice() function to which we pass 2 arguments: the $options array and the question we ask from the user.

When the command is run, this function is called and returns the machine name of the option the users chooses. Then we check if this value exists and print to the screen the concatenated string. We do use the human readable value by extracting it from the $options array using the key returned.

Free text values

A third type of user input is in the form of free text that you can ask the user to input. Of course the validation of this kind of input must be much stricter so as to not break your application somehow. But let's ask our user exactly who they want to say hello to.

$value = drush_prompt(dt('Who do you want to say hello to?'));

drush_print(dt('Hello @value!', array('@value' =>  $value)));

This one is very simple. When the command is run, the drush_prompt() function is called to which we pass a string of text to be displayed in the terminal. The return value is given by the user and we use that for concatenation. But do remember that this is example code only so if you do use this function, make sure you validate the user input properly.

Conclusion

So there you have it. Three different ways to get user input in the terminal using Drush. The first two are the most common ones I believe but it's good to know there is also the last one available in case we need it.

Drush safely!

Adding Facebook Open Graph tags to your Drupal site

In this article we are going to look at implementing the Facebook Open Graph (OG) tags on a Drupal site. It involves a bit of coding but nothing too major so bear with me. All the code we are going to write goes into the theme's template.php file so no need to to create a module for it. And if your theme does not yet have this file, go ahead and create it.

The purpose of this article is to demonstrate doing this in code (because its fun and you might need it depending on the logic you need to perform). Alternatively, of course, you can use the Metatag module for this.

Why use Open Graph tags?

I'm sure by now you know that people share pages on Facebook and you want your site to be shared as much as possible. You also know that a little teaser information is made available on Facebook when you share these pages (title, image, short description).

But have you ever noticed that with some sites, when you share pages on Facebook, or like/recommend them, some random, unintented image gets used in this teaser. Or the description is not correct, or even the title is not right. Facebook is quite good at picking the right elements to show there but sometimes it doesn't manage by default. And you can't expect the random user who shares your page to make adjustments to the text or title. So what do you do? You use Open Graph meta tags.

What are the Open Graph meta tags?

These are simple <meta> tags that you put in the head of your site to specify which elements should be used by Facebook for various purposes. For instance, you specify a link to an image and then Facebook knows exactly which image to use when building the teasers. The same goes with the title, description and many others.

The tag is quite simply structured. It contains a property attribute in which you specify what this tag is for and a content attribute where you specify what should be used for this property. Let's see an example for the title:

<meta property="og:title" content="This is the article title" />

Simple. You'll also notice that the property attribute value is preceeded by og:. This stands for Open Graph and Facebook will recognize it as such. Here are some examples for other more common OG tags:

<meta property="og:url" content="http://webomelette.com/article-url" />
<meta property="og:site_name" content="Web Omelette" />
<meta property="og:type" content="blog" />

The first one is the canonical URL for the page, the second is the site title and the third is the type of site.

But how do we add them to Drupal?

I wrote a while back an article on this site in which I looked at how you can add your own custom tags into the <head> of the site. And there we learned that we use the drupal_add_html_head() function inside of a preprocess one to achieve this.

So let's say that our Article nodes don't show up properly in the Facebook teasers and we would like to specify OG tags for the title, image and description. We will do this in the theme's template.php file inside of the template_preprocess_node() function:

function theme_name_preprocess_node(&$vars) {

}

Inside this function we get access to the node information being loaded and we can test to make sure we are adding our OG tags only to the pages that load these nodes:

// If the node is of type "article", add the OG tags
if ($vars['type'] == 'article') {
  // Inside this conditional, we define and add our OG tags
}

First, let's create the title tag, the simplest of them all. It will be represented by the node title:

$og_title = array(
  '#tag' => 'meta',
  '#attributes' => array(
    'property' => 'og:title',
    'content' => $vars['title'],
  ),
);

drupal_add_html_head($og_title, 'og_title');

If you remember from the other article, this is how we create a new meta tag in the site header. We define a renderable array that describes the tag (type and attributes) and we use the drupal_add_html_head() function to set it. Simple. Now if you clear the cache and go to an article page you'll notice in its source a new tag:

<meta property="og:title" content="The title of the article" />

This was simple. Let's see how we can extract the image URL and specify it inside a new tag for the image Facebook will use:

$img = field_get_items('node', $vars['node'], 'field_image');
$img_url = file_create_url($img[0]['uri']);

$og_image = array(
  '#tag' => 'meta',
  '#attributes' => array(
    'property' => 'og:image',
    'content' => $img_url,
  ),
);

drupal_add_html_head($og_image, 'og_image');

So what happens here? First, we use the field_get_items() function to retrieve the field called field_image from the loaded node. This will return an array of one or more images (depending on how the field is set up and how many images are in it).

Next, we use the image file URI inside the file_create_url() function to turn it into an absolute URL. Then, just like above, we create the renderable array with the og:image property and the image URL as the content. The result will be:

<meta property="og:image" content="http://your-site.com/sites/all/files/your-image.jpg" />

Finally, let's see how we can get a small chunk of our body field and use that as a description for Facebook:

$body_field  = field_view_field('node', $vars['node'], 'body', array('type' => 'text_plain'));

$og_description = array(
 '#tag' => 'meta',
 '#attributes' => array(
   'property' => 'og:description',
   'content' => text_summary($body_field[0]['#markup']),
 ),
);

drupal_add_html_head($og_description, 'og_description');    

Instead of using the same function as when we retrieved the image field earlier, we use field_view_field() in this case. The reason is that it already prepares the body for output and we can specify a text format to use. We want to use plain text to avoid printing all the HTML markup that is usually found in the body field.

Next, like above, we create our renderable array. Only this time, we also use the text_summary() function to trim the text down to a reasonable default of 600 words (the defaul teaser length on the site). If you want to specify a different length, you could pass it as the third argument, like so:

text_summary($body_field[0]['#markup'], NULL, 100),

This will trim it to 100 words. One thing I noticed about this function however is that it doesn't trim nicely. It will end the chunk in the middle of the sentence even if its API says it will try to find a sensible place. For this purpose it doesn't really matter because Facebook will trim it down anyway to a shorter version.

Conclusion

So there you have it. Now you can use the Open Graph meta tags on your Drupal site to let Facebook know about your content. It's a handy social helper that can greatly improve your social presence by making your site more appealing on Facebook.

10 things you should be doing on your Drupal site

This article comes as a continuation to the previous one in which I exemplified 5 things you should not do on or with your Drupal site. Today, however, I'll double up, take a more positive approach and go with 10 things you definitely should be doing. So let's begin.

Turn on caching and aggregation on production

When you develop locally you'll most likely disable css/js aggregation and turn off the caches. This makes it easier to quickly see changes as you make them and allows for a more efficient development. However, you have to make sure that these are turned back on when you move to the live site.

Drupal comes with a few powerful performance related settings that greatly improve the speed of your site. Page caching and compression for anonymous users is one of them. CSS/JS aggregation is another. And there are a bunch of contrib modules that enhance performance and I recommend you also look into those.

Disable development modules and functionality on production

If the previous point was about performance, this one is about security. There are various things you'll use locally while you develop or debug your Drupal site. The Devel module is something you'll probably enable and the error reporting will most likely be turned on so you can see what's going on.

This is all good and well but make sure that when you push your changes to the production site, these get turned off. Keeping the Devel module enabled on a live site is not indicated and can be a security risk. And although it constitutes security by obscurity, disabling the printing of errors to the screen is also important. Not to mention user friendly.

So either you create a checklist of things to do or automate these processes however you want. Drush will be a very good friend with this.

Use Drush for shell tasks like updating and installing modules

Speaking of Drush, any respectable Drupal developer will know how to use and will use Drush for one thing or another. It is a very helpful tool to run tasks related to Drupal from the command line. A Drupal shell basically.

I'm not even going to enumerate all the cool things you can do with it but I will refer you to a couple of articles I wrote before on how you can begin with Drush and some of the basic things you can use it for.

Keep regular backups of your production environment

The best backups are the ones you don't ever need. That being said, you'll need to keep regular backups of your site and server in order to revert if the worst should happen. There are many tools you can use for this (both manual and automated) but I'm not going to go into that right now. I will however share a story to scare you straight into opening your MySQL interface of choice and taking a database dump.

A while ago, I hosted a site for someone on a shared server from a random hosting company. One day I notice the site is down and in about 24 hours (of the site being down) I get an email. Someone hacked into their datacenter and deleted everything (both live servers and backup server). Apparently both were kept in the same place and their access was solely protected by the act of sending an email to the datacenter from the hosting company's email address asking for access...

The resolution was the following: no more data, ever, retrieved. Nobody got anything back. Luckily, I had backups and so should you. The moral of the story is obvious I think.

Find a good balance between contrib and custom

In the previous article I strongly advised against using too many contrib modules. I mean if the site is huge and needs them, it's fine. As long as they are accompanied with performance related enhancements to compensate for the load.

In this point I would like to stress the importance of finding a good balance between using contrib modules vs your own custom code. The rule of thumb is to use contrib modules as much as you can. This means do not write custom code that is already present in a module. This is because there are multiple people looking at that module and can spot problems, make updates and you'll be also better off.

That being said, you also have to be careful of (1) what modules you use and (2) what problem they solve. First of all, the module can be of bad quality or not performant, so you'll need to investigate a bit (how many people use it, how does the issue queue looks like, etc). Second of all, it can be an overkill. If you need a tiny piece of functionality offered by a module that does a bunch of other stuff you don't need, it's maybe time to think about whether or not you can implement that yourself. It's a judgement call depending on the case.

If you don't expect users to create accounts, disable this functionality

One of the things I kept forgetting and paid the price later was to disable the right for anonymous users to create user accounts on the site. By default on a fresh Drupal install, anonymous users can create accounts and you as an admin need to approve them. The problem is that if you forget, you can wake up in 6 months with a huge spam user list that you need to take care of.

This piece of advice concerns those who create new websites that don't need people creating accounts of course. If you require users to be able to create them themselves, make sure you implement some anti-spam techniques like Captcha, Mollom or Honeypot.

Employ Drupal coding and security standards

One of the important things that beginner Drupal developers need to learn is how to respect the Drupal coding and security standards in place.

The coding standards represent a particular way of writing, formatting and structuring code. Aside from syntactical rules, you also have readability rules and implementation rules (where and how should I use this function or hook).

The security standards represent the rules the respect of which ensures that you will write secure code. This means using helper functions and techniques that actually make Drupal a pretty secure system.

So make sure you got these down before attempting to write enterprise code for Drupal production sites.

Keep your code in Git

Using version control is a must with any web application. In this day and age you cannot write code without keeping it in some sort of versioning system like Git, Mercurial, or SVN. The Drupal community adopted Git and it's awesome. It's also one of the most popular ones out there.

If you want to develop Drupal modules, themes or contribute to existing ones or even core, you can't get around using Git. So make sure you start using it for all your projects if you don't already.

You can also use Git to deploy your code between environments. Keeping a central repository from which you can pull provides a fast and easy way to deploy code. This is of course if you're not already using some automated tool like Jenkins (that also integrates with Git by the way).

Update core regularly

It's recommended that you update your site when there are updates issued by the core maintainers, especially when they are security updates. Yes, it can take some time to perform these updates, but it's worth it.

Why? There is no getting around the fact that security updates need to be done. Once they are public, the vulnerabilities are as well. So if you haven't deleted the CHANGELOG.TXT file from your Drupal root (which you can do), potential attackers can find out the version of Drupal you are running. And the risk of exploiting those vulnerabilities increases. This is not to say that deleting the CHANGELOG.TXT file is enough and you shouldn't update.

Additionally, if you leave it for later, you'll end up having to do a big update across many version numbers which makes it much more difficult. It'll take much more time to do and the risk of breaking some functionality will increase as well.

So take the time regularly to do the updates, look at what is affected by them and test your site to make sure it won't break (locally!). If it does, fix the custom code (or update contrib) that no longer functions due to this. The problems should however be minimal with incremental updates.

Keep the modules in the right folders

There is a best practice in Drupal regarding the way you organise the modules on your site. We know that they must be kept in the sites/all/ folder but we can better organise them inside that as well.

Contrib modules need to go in a folder called contrib/ and custom modules in a folder custom/. Trust me, when you will have plenty of modules (of both types), finding them will be much easier.

Additionally, if you use the Features module, you should put all your features into a features/ folder. And if you patch any of the contrib modules, it's best if you move them from contrib/ to a folder called patched/. This way you have an overview of which modules you need to pay extra attention to when doing updates. After moving the module make sure you run a registry rebuild to update Drupal as well that the location has changed. With Drush this is easy: drush rr.

Conclusion

There you have them: 10 things I recommend you do on your Drupal site. Again, there are more of course, but here are 10 of my most important ones. By the way, do you know that saying: do as I say not as I do? :)

5 things you should not do on a Drupal site

In this article I am going to go over 5 things you should definitely not be doing on a Drupal site. In this venture I will try to avoid the "not not do" type of actions and focus only on what you should simply not do.

Do not hack core

I think this advice is quite straightforward and spread within the Drupal community. But it cannot be stressed enough. Drupal provides a myriad of ways you can avoid the temptation of modifying core files. And even if a particular problem you have seems that it can be solved so easily by hacking core, don't. Employ proper techniques of overriding that particular functionality.

Why? Well, good luck updating Drupal later on if you modify core files. Either you will override your changes which will effectively break your functionality or you will have to keep making those changes every time you update. Drupal 7 is already past 20 versions, so think about it. A, and a kitten dies every time someone hacks core.

Do not make updates on production

Speaking of updating Drupal core (or even contrib), I think it's important to know you should never perform the updates straight on the production environment. You never know what can break as a result of the new functionality core or contrib brings to the table or removes from your site.

In other words, make sure you test everything locally or on a specific environment you have for this kind of purpose. It's not a big deal, you set it up once and then can reuse it for all your other sites or projects. This goes of course also for any kind of development work you do - never first on production.

And since we are on updates, make sure you read what the nature of the update is - even if it's security. It doesn't hurt to know what functionality will be affected. And this way, you learn maybe some new things about Drupal.

Do not install all the modules in the world

When I was a beginner I was amazed by the plethora of modules available to extend core. So I installed and installed because maybe the functionality will be needed later on site. Drupal can do so much. Little did I know that this would virtually halt my site to a standstill. And turns out, most of that functionality was never even needed.

So my point is, make sure the modules you install are needed at the moment you install them. Try to gauge the quality of the code (there are various factors for that) and then test locally if it does the job for you. If yes, commit it to the repository and use it. If not, delete it, no point in cluttering your codebase or even worse, having it enabled and loaded by Drupal with every page request.

Do not commit your settings.php file

If you are storing the Drupal codebase in a Git repository, and you should, it sometimes happens that you commit the settings.php file. This means the credentials to accessing the database are stored in its history and difficult to remove.

Normally, this shouldn't' happen. Drupal comes with a .gitignore file that by default prevents the settings.php file from being considered relevant to the repo. And that's how it needs to stay. I've seen however cases in which this was not properly respected or the .gitignore file was changed (or removed) causing the the database credentials to be to be committed and available in plain text in the repository. So be careful.

Do not use the PHP Filter module

If you are running Drupal 7, you'll maybe know that there is this module called PHP Filter. Don't use it. Not only it represents a huge security risk if unauthorised users get to evaluate PHP with it, but you can also evaluate PHP with it!. Which is absurd.

There's a good reason why separation of concerns (logic from presentation) is to be desired in web applications. And god knows Drupal 7 falls short in many respects, but this is to the extreme. Putting PHP in with your content is the mother of all the you're doing it wrong. So just don't. Unless you have to. I'm kidding. Write a custom module to handle the functionality you'd need there and disable PHP Filter. But don't delete it because it's core (see my first point).

Conclusion

In this article I talked about 5 random things you should not be doing on or with your Drupal website. There are more of course, but these are - in my opinion - some of the important ones.

In the next one, I will take a more positive approach and give you some random tips on what you should be doing on your Drupal site. See you then.

Cool Module: Menu Token

In the previous article I showed you how you can add menu items with wildcards to your menus in custom modules. Since then, however, I've been shown a cool module that allows to do similar things through the UI: Menu token.

Menu token allows you to define menu items that include tokens (provided by the Token module). These tokens get replaced on page load depending on the context or whatever rule you set when you created the menu. So let's take a look at how it works.

To install it, go through the normal module installation procedure. With Drush, this is simple:

drush dl menu_token token && drush en menu_token token

You'll notice that we also install the Token module as it is needed.

Before anything, navigate to admin/config/menu_token and check/uncheck the relevant boxes. These are basically the available entity types exposed by Menu Token.

Next, go to your menu and add a new link. You'll notice a new checkbox saying Use tokens in title and in path. Check that box and you'll get all the options for the token in that menu link.

Example #1: Current User ID

Let's see how we can create a menu link that goes to the user page of the currently logged in user.

  1. Under Method for users, select User from context.
  2. Best to also check the box Remove token if replacement is not present to avoid problems if the token is not available on a given page
  3. Browse the available tokens and look for this one: [current-user:uid]. This is the token for the currently logged in user account ID.
  4. Add your menu title and for the path specify: user/[current-user:uid].
  5. Save

Now if you go somewhere your menu is visible, you'll notice a new link that leads to your user account page. Neat. We have't done anything that isn't already available in Drupal core, but still neat. The reason I'm saying this is that you can create a menu link with the path user/ that will lead the same place. But for illustrating the power of Menu Token, it's a good example.

Example #2: Current Node Type

Let's say you have a View that displays nodes of two different content types: Article and Basic Page. This View has a contextual filter to show nodes of the type article when the first parameter after the path to the view is article. And same for the Basic Page (with page being the machine name). The view path is nodes.

Let's create a menu link for the main menu that will link to this view and pass to the URL the content type of the currently viewed node.

  1. Under Method for nodes, select Node from context.
  2. Best to also check the box Remove token if replacement is not present to avoid problems if the token is not available on a given page
  3. Browse the available tokens and look for this one: [node:content-type:machine-name]. This is the token for the currently loaded node content type.
  4. Add you menu title and the following path: nodes/[node:content-type:machine-name]
  5. Save

Now if you navigate to an article page, you'll notice in your main menu a new link to the following path: nodes/article. If you go to a Basic page, it'll be nodes/page. And clicking on these will of course take you to your View page with the filtering applied.

Conclusion

These are a couple of simple examples of how you might use Menu Token. Of course you can use it in other situations depending on what you need and what tokens are available.

Hope this helps.

Adding menu items with wildcards to Drupal 7 menus

In this article I am going to share with you a quick tip on how to get your custom menu item into an actual menu on the site.

A problem I encountered when declaring a menu item using hook_menu() is that if the menu item contains a wildcard, it just won't go into the menu. You can easily specify a menu_name and if you have no wildcards, it will show up nicely in the menu you specified. If however, you need some wildcards, it won't.

I needed one such menu item (imagine that) to be placed in one of my menus on the site. After trying all sorts of things and failing miserably at them, I decided to go at it through a preprocessor function and declare my menu item there. So let me show you how I did it and maybe you can tell me some better, more correct, ways to do it.

First of all, I needed to see where my menu was being printed on the page (it was the Secondary Menu in fact). If you look at the Bartik theme in the page.tpl.php file, you'll notice the following block:

  <?php if ($secondary_menu): ?>
      <div id="secondary-menu" class="navigation">
        <?php print theme('links__system_secondary_menu', array(
         
'links' => $secondary_menu,
         
'attributes' => array(
           
'id' => 'secondary-menu-links',
           
'class' => array('links', 'inline', 'clearfix'),
          ),
         
'heading' => array(
           
'text' => t('Secondary menu'),
           
'level' => 'h2',
           
'class' => array('element-invisible'),
          ),
        ));
?>

      </div> <!-- /#secondary-menu -->
    <?php endif; ?>

This is basically where the Secondary Menu gets printed onto the page. And since it's in the page.tpl.php file, we can go ahead and write a preprocessor function for the page in the theme's template.php file. I always have the Devel module installed locally so I can debug variables, so if you are following along, make sure you do too.

function bartik_preprocess_page(&$vars) {
  dpm($vars);
}

You'll notice I am hacking the Bartik theme but I'm only doing this for education purposes in order to see what's behind the hood. It will not go into any website like this. And make sure that if you do this, you don't redeclare the same preprocess function in the same theme or you'll get an error.

Having said that, with the function above, I am debugging the variables array that goes into the page.tpl.php file to be displayed. And what do you know, one of the keys of this array is secondary_menu. Great. Inside we have a number of elements keyed by the class name that gets applied to each menu item when it gets printed. If we look inside each element, we can gather what we need to add to this array in order for it to display another menu item: a href (path to which the menu will link) and a title (the link title that will be displayed).

If you are using wildcards, you need to make sure though that when building the href, you have all the necessary information in this preprocess function to actually build it. I needed to current user ID so that was available (plus I could always take the user object from the global scope).

So to add an example menu item, you'd do something like this:

$vars['secondary_menu']['my_menu'] = array(
  'href' => 'path/you/want/' . $id,
  'title' => 'My dynamic menu item',
);

Please note that the $id is fictional and you have to gather it from somewhere if you want to include it in the URL. I was just giving an example. But if you refresh the page now, the Secondary Menu should include your new menu item.

Bonus

As a bonus, I'll show you how to add attributes to the item you include in the menu. If we wanted to add a button class to the menu link, instead of the above, we'd do this:

$vars['secondary_menu']['my_menu'] = array(
  'href' => 'path/you/want/' . $id,
  'title' => 'My dynamic menu item',
  'attributes' => array('class' => array('button')),
);

Notice the extra attributes key we pass along. There you can include also other attributes that will get processed by the core drupal_attributes() function.

You can use this same technique to add classes to existing menu items as well, not necessarily new ones you are adding. A little theming lesson as well, similar to how we added classes to form elements in the article on theming forms.

Caveat

There is one problem with this approach, reason for which I kept trying to do it properly using hook_menu().

Since you are adding the menu item through the template preprocess function, it will only be displayed in the Secondary Menu of the page.tpl.php file that prints it out.

Let's say you have a block.tpl.php that for some reason needs to print out this menu as well. In this case, your new menu item won't show up. You'll have to include it in the preprocess function of the block.tpl.php as well (for e.g. bartik_preprocess_block()) the same way we did above.

6 tips for new Drupal developers

Being a Drupal developer can be very fun. But if you are going to be one, there are a number of things you should take into account. Aside, of course, from knowing how to actually develop stuff in Drupal. So I thought I’d share with you some things I learned along the way. If you have any other advice for novices in the world of Drupal, feel free to comment on this article.

Learn very well the backoffice of Drupal

I think this is pretty obvious. One of the most important things before doing any developing work in Drupal is to first know your way around the admin. That is, to be able to configure a core website and to be familiar with the more popular contrib modules (such as Views, Panels etc).

With the risk of sounding a bit absurd, you cannot start writing Drupal modules if you don’t know how to install and enable one, right? But don’t worry, it’s fun to play around and there are a lot of great resources out there to help you.

Learn PHP (for Drupal)

Drupal is built in PHP. This means you cannot develop any module or proper theme without knowing PHP. The good news, however, is that it’s awesome to learn and most of the time you’ll have fun with it. I myself learned PHP along the way from various online sources and in a self-teaching kind of way.

First of all, I advise you to get familiar both with functional and object oriented PHP. Initially, you won’t deal too much with objects in Drupal, but you will see later the benefit of knowing how this style of programming works. Second of all, you must familiarise yourself with PHP also from a Drupal perspective. It’s important to know the system of hooks, preprocess functions, etc that are typical to this type of application. And here the drupal.org API reference page will be your best friend - bookmark it to your forehead.

Get familiar with the standards - coding, security, commenting

There are three main standards I’d say you need to get familiar with as soon as you start developing in Drupal. First of all, you need to write secure code. It’s important that your module does not open the site up to XSS or SQL injection vulnerabilities (among others). Second of all, you need to write quality code that is consistent with the Drupal framework. This is important for cleanliness and the good functioning of the project. Third of all, you need to comment your code so that other developers can easily read and understand what you are trying to achieve.

Join the community

The Drupal community is very rich in terms of skilled and friendly developers and Drupal enthusiasts. You should learn who they are and try to engage with them - trust me, you’ll have so much to learn.

The Drupal community has many virtual representations. For instance, there is the Drupal Planet blog aggregator where many Drupal related blogs are included - a great resource for keeping up to date with blog posts on the subject. The IRC chat, the Drupal stackexchange and the drupal.org forum (plus individual issue queues) are the places you go with problems you encounter. Then there are plenty of events, local groups, cons, camps and what have you that are great places to network and meet face to face with fellow Drupalers.

Tutorialize yourself

As you know, the process of (self-)learning online revolves around reading a bunch of tutorials, watching videos, scouring various forum topics etc. Well, it’s no different for learning Drupal. There are many websites out there that offer great written and video content, both for free and against payment. I do not want to mention any names because it would not be fair to those I do not include. If you follow me on Twitter you’ll get a lot of resources like that.

Use social media to stay informed

I don’t need to tell you about the importance of using social media for promoting your company or product. But what some people don’t understand is that social media is also great for keeping informed about stuff. I am active on Twitter (and a bit on Google+) and I have to tell you, it’s a goldmine for staying up to date with the world of Drupal. So I definitely recommend it.

You can obviously follow the #drupal hashtag on Twitter or even the @Drupal account, join the expanding Drupal community on Google+ or like the Drupal page on Facebook. And remember what I said about the community people - many of them are also active on social media.

Conclusion

Above you have some of the more common things you need to look out for if you are interested in getting more involved with Drupal and you are a beginner. You who already has some experience on the matter, have anything else to add?

How to alter the Webform submission information before being saved into the database

In this article we are going to look at a cool Webform api function that allows us to interfere with the submissions being saved to the database. Interfere sounds like a negative thing but because the Webform module is so awesome, we can perform all sorts of operations on the submitted data before saving it.

Among the many API functions the Webform module comes with, a cool one is hook_webform_submission_presave() and that's what we will look at in this article. This function gets called whenever a user submits a form but before the submission gets saved. And we have available as parameters the $node object and the $submission object that contains the data and that can be altered (passed by reference).

Use case

Why would you need it? To illustrate how you can use it, I am going to show you what I needed, followed by how I implemented it with hook_webform_submission_presave().

My user accounts had some fields on it (first and last name) and all users on the site were invited to submit once a particular webform. And since I already have their first and last names in the $user object, I wasn't going to ask them to provide them again in the webform. And yes, I needed the webform submission to contain the names.

Implementation

The first thing I did was create 2 hidden fields on the webform for the first and last names. Users filling in the info wouldn't even realize they are there. Next, I implemented the hook:

/**
* Implements hook_webform_submission_presave().
*/

function my_module_webform_submission_presave($node, &$submission) {
  // Get the submission user object.
  $user = user_load($submission->uid);

  // Check if $user does have the first name filled.
  if (!empty($user->field_first_name)) {
    $first_name = $user->field_first_name['und'][0]['value'];
    // Add the $user first name to the submission data.
    $submission->data[4]['value'][0] = $first_name;
  }

  // Same as above but for the last name.
  if (!empty($user->field_last_name)) {
    $last_name = $user->field_last_name['und'][0]['value'];
    $submission->data[5]['value'][0] = $last_name;
  }

}

As you can see from my comments, the first thing I do is retrieve the $user object of the submission author. Next, I check if the relevant fields are set (to make sure no errors are thrown if there is a user without any names), and assign them to the data array in the $submission object. However, as you can see, I hardcoded the webform component id when doing this assignment:

$submission-&gt;data[4]['value'][0] = $first_name;
$submission-&gt;data[5]['value'][0] = $last_name;

This means I looked them up before and am sure they will not change (i.e. get deleted and/or recreated). It's probably not the bestest of solutions but if you are certain of the webform you created, you can do it like this. Another approach would be to iterate through all the components in the data array and check for the machine name of the field and do the assignment based on that. So you have plenty of options.

Additionally, you'll notice that I do not use the $node object at all which means that this hook will do its job on all webforms. This is because I only have one webform on the site (and I'm certain I'll only have one). But that's why the $node object is there, so you can check against and condition your logic to certain nodes that meet various criteria. The choices are many.

Conclusion

In this article we've looked at using this awesome hook provided by the Webform module: hook_webform_submission_presave(). You can do a lot of stuff with it. We've seen only how to add aditional information to the submission but you can also alter the passing submission values. So keep in mind there's this nifty function you can use when you're building your webforms.

How to batch assign taxonomy terms to nodes using Views Bulk Operations

In this article I am going to show you a quick trick that will allow you to assign taxonomy terms to a lot of nodes all at once. For this we will use Views and Views Bulk Operations and will require no coding whatsoever. So let's begin.

First off, make sure you have the 2 modules installed. Drush will quickly take care of that for you if you don't have them yet:

drush dl ctools views vbo && drush en ctools views views_ui vbo

Now, the next thing we need to do is create a View page that displays the content (nodes, users, etc) you'd like to operate on in bulk (in our case, add taxonomy terms to). Make sure it uses fields and for start, the title field will be enough. For filtering, use whatever you need to filter the View to show only the content you want and sorting doesn't really matter.

Next up, add a new field of the type: Bulk operations: Content. This will provide next to the node title a checkbox for you to select that node to be part of the bulk operation.

To configure this field, make sure you check the boxes Modify entity values and Show available tokens followed by selecting the values of which field you'd like changed (in our case the taxonomy term reference field). In the screenshot below, you can see my selection for the Tags field of the Article node (I am going with a node view displaying articles).

Now you can save the View and navigate to its page. In the image below you can see my example. A table formatted view with the checkbox and the Article node title to its right. And the VBO operations above it.

Now, let's say I want to apply a taxonomy term to all these nodes. I can select them all (either manually or using the top-most checkbox dedicated for selecting all rows at once), choose my operation (Modify entity values) and click Execute. And this is then my next screen:

I have an autocomplete widget (like the default Article content type Tags field referencing taxonomy terms) where I can select one or more terms I'd like applied to all those nodes. I also have an option to ensure that existing values do not get overriden, by checking the respective checkbox. And lastly, I have some tokens available to use (because of the Tokens module).

Once I select my terms and press Next, I get an overview of how many nodes are going to be affected by this change (as you can see below). And that's basically it.

One thing to keep in mind here. If you are adding a non already existing taxonomy term, VBO will create that term as many times as the number of nodes being processed. So you'll end up with a bunch of terms with the same title. Probably not something you either expect or want. I therefore recommend you create your term before and then apply it to the content.

Hope this helps!

How to theme forms and add custom classes wherever we want in Drupal 7

In this article we are going to talk about theming forms. What exactly about it? Since theming forms can be a huge topic, I will stick to inserting your own custom classes wherever you can in a given form.

Have you ever needed a form element to have some special class you could target in your css? Or even yet, have you ever used a css framework like Bootstrap that tells you: ok, you need the form element to have class X in order to pick up these nice styles? Well, it can be a bit tricky to find exactly where you need to go, hook into what, override what theme function etc.

So in this tutorial I'm going to show you how to get your classes into 5 different form "places":

  • the <form> tag itself
  • the submit button
  • the element input itself
  • the form element wrapper <div>
  • the element label

Before we go further, this tutorial assumes you are already familiar with Drupal hooks and know how to implement one at the basic level. We are going to talk about form_alter hooks a lot which means that you can use more than one for the job: for instance hook_form_alter() or hook_form_FORM-ID_alter(), whichever best suits your need. You can read more about hooks in this section.

1. The form tag: <form>

If you want to add your class to a form tag you can do so inside of a form_alter hook. Once you are targeting the form(s) you want, you'll need to add some information to the $form array that gets passed through the hook:

$form['#attributes']['class'][] = 'your-class';

What happens here? The $form variable is a renderable array that also takes #attributes. There can be many types of attributes, one being class. This is as well an array so we make sure we add another item to the class array.

How do you know all this? When I debug the $form variable with the Devel module, I see no #attributes array in there at all...

WeIl, if you look at theme_form() itself - which is the Drupal core theme in charge of rendering forms - you'll notice that the #attributes array exists and gets transformed into HTML attributes by the drupal_attributes() core function. So, whatever you put in there will be transformed into attributes.

2. The form submit button

Adding a class to the submit button - the input element rather - is similar to adding one to the <form> tag but a bit tricker.

One thing you can do is override the entire theme_button() function in your theme and add your class there. Not really recommended if all you are doing is adding a class because you are copying all that code just to add a couple of more words. For more complex operations, you can do that.

Instead, you can use the same form_alter hook as before, and insert it there. We'll look at a couple of different forms to notice the difference between how you might approach this.

First of all, you can have a custom form that you declared yourself in the module. In this case, all you have to do is specify the #attributes when declaring the submit button. Something like this:

  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
    '#attributes' => array(
      'class' => array(
        'your-custom-class' 
      ),
    ),
  );

If the form however is declared by another module and you don't - nor you should - want to hack it, you can use the form_alter hook of your choice. Considering that this is the form submit button declaration (so no classes defined in the #attributes array originally):

  $form['my_submit'] = array(
    '#type' => 'submit',
    '#value' => t('Next'),
  );

In the form alter you can add the following line:

$form['my_submit']['#attributes']['class'][] = 'my-custom-class';

Where my_submit is the machine name of the submit button. This will have the same effect.

Now let's take the Search block form as an example and say you want to add the class to the Search button. In your $form array, you'll notice an actions array. Looking this up in the Form API reference, you'll see that this is in fact a wrapper around one or multiple form buttons. So going inside that, we can find the submit button. So to add a class to that button, we do something like this:

$form['actions']['submit']['#attributes']['class'][] = 'your-custom-class';

So it's basically about finding out where the submit button is in the $form array. And since the actions form element is defined as a renderable array as well, you can add a class to that too:

$form['actions']['#attributes']['class'][] = 'your-custom-class';

So now the class is on the wrapper <div> of one or multiple buttons in the form.

3. Form elements

Similar to the form buttons, to add classes to form elements (the actual input, select, etc fields), you need to find them in the $form array of your form_alter hook and then add to the #attributes array. So to take the same Search block form, we can add our custom class like so:

$form['search_block_form']['#attributes']['class'][] = 'your-custom-class';

Easy peasy. And same as above, if you are the one declaring the form, you can just add the #attributes array with the class right there.

4. Form element wrapper <div>

When I say form element wrapper <div>, I mean the <div> surrounding the form element itself and the label. So how do we add our custom class to this? If you try with the form_alter hook as before, you won't be able because the form elements are rendered using their own custom theme implementation of theme_form_element(). And I've found that using the preprocess hook for that theme function does not pass the class to the wrapping <div> (as I thought it should).

So then what we can do is override the theme function itself - in our custom theme of course - and add the class there. Just copy the theme implementation from the API page into your theme template.php file and change its name from theme_form_element() to your_theme_name_form_element(). Then perform inside it any additional checks to make sure you only target the class name addition to the elements you want. The important thing then is to add the class into this array:

$attributes['class'] = array('form-item');

You can see below it all sorts of checks to add further classes that have some sort of meaning for the form element. You can insert yours in there somewhere.

5. Form element label

Adding your own class to the label is similar to what we did in the previous point: you have to override the right theme function. In this case it is theme_form_element_label().

Here though, you have to be careful. The $attributes['class'] array into which we've been putting classes is no longer an array but a simple string. So you need to avoid wiping out any other classes that Drupal might want to add to the label in various circumstances. So right before the function returns the output, add something like this:

$attributes['class'] .= ' my-custom-class';

This way you are appending to any class string that may come before. For some reason, the $attributes['class'] is not an array here. I don't know. Maybe you figured out why and there is a better way of doing this.

Conclusion

In this article we've seen what we need to do to add our own custom css classes to Drupal 7 forms. It's not a walk in the park but it's not so difficult either. One thing you can be sure of though is that it takes a lot of trial and error until you get everything right.