Drupal Planet Posts

PHP: Using the usort / uasort functions

Have you ever had to sort an array in PHP? There are a bunch of functions available, the most common being sort(). This function does a default sorting of the values in your array. So if you have numbers or want to do alphabetical sorting, sort() will get the job done.

But what if you require a more complex sorting logic? Let's say you have an array of names that need to be sorted in a specific order. I don't know, because your client says so. Let me show you how.

Let's say your DB returns a list of names in an array:

$names = array("Christian", "Daniel", "Adrian");

And your client says they need to be arranged in the following order: Adrian, Christian, Daniel. You can use the usort() function together with a comparator function you write yourself. How does this system work?

As a second argument of the usort() function, we pass in the name of our custom comparator function. The way this gets processed is that all the values in the array that needs sorting are passed to this function 2 at the time (usually you'll see them as $a and $b). This is done to determine which one takes precedence over which. The comparator has to return 0 if the 2 values are considered equal, a negative integer if the first value is less than the second value or a positive integer if the second value is less than the first. What less means is up to you to determine. So let's put this in practice with our example:

function _name_comparer($a, $b) {
    $correct_order = array("Adrian", "Christian", "Daniel");

    $a_key = array_search($a, $correct_order);
    $b_key = array_search($b, $correct_order);

    if ($a_key == $b_key) {
        return 0;
    }

    return ($a_key < $b_key) ? -1 : 1;
}

usort($names, "_name_comparer");

So what happens in my comparator function? First, I create an array that contains the proper order of the names. This means that each value has an integer key that can be easily compared (and that I store in the $a_key and $b_key variables). After comparing these, I return 0, a negative or positive integer. The result is that the $names array gets resorted in the order they appear in the $correct_order local variable I created. And that's it.

If the $names variable is associative and you need to maintain the keys as they were, you can use the uasort() function:

$names = array(
    "christian" => "Christian", 
    "daniel" => "Daniel", 
    "adrian" => "Adrian",
);
usort($names, "_name_comparer");

The comparator function can stay the same, but the uasort() function will take into account and maintain the index association of your values.

And that's it. Hope this helps.

Drupal 8 Dependency Injection, Service Container And All That Jazz

With the move from a mostly procedural to a mostly OOP based architecture in Drupal 8, many Drupal developers have been introduced to new concepts we don't fully understand. I myself was terrified of notions such as dependency injection and service container, making me worry about the future of my Drupal development.

So I took it to Symfony (from where many components have been borrowed) and then Drupal 8 alpha releases and turns out it's not a big deal. All you need in order to understand them is to know basic OOP principles. Check out Larry Garfield's timeless introductory article to Object Oriented Programming on Drupal Watchdog for a good start.

In this article I am going to talk a bit about what dependency injection is and why one would use a container for managing these dependencies. In Symfony and Drupal 8 this is called a service container (because we refer to these global objects as services). Then, we will take a look at how these are applied in Drupal 8. Briefly, because you don't need much to understand them.

So what is dependency injection?

Take the following simple class:

class Car {

  protected $engine;

  public function __construct() {
    $this->engine = new Engine();
  }

  /* ... */

}

When you instantiate a new class Car you go like this:

$car = new Car();

And now you have an object handler ($car) that has an $engine property containing the handler of another object. But what if this car class needs to work with another engine? You'd have to extend the class and overwrite its constructor for each new car with a different engine. Does that make sense? No.

Now consider the following:

class Car {

  protected $engine;

  public function __construct($engine) {
    $this->engine = $engine;
  }

  /* ... */

}

To instantiate an object of this class, you go like this:

$engine = new Engine();
$car = new Car($engine);

Much better. So now if you need to create another car using another engine, you can do so easily without caring about the Car class too much since it is supposedly equipped to work with all the engines in your application.

$turbo = new TurboEngine();
$car2 = new Car($turbo);

And that is dependency injection. The Car class depends on an engine to run (dooh), so we inject one into its constructor which then does what it needs to do. Rather than hardcoding the engine into the Car class which would not make the engine swappable. Such constructor injections are the most common but you'll also find other types such as the setter injection by which we would pass in the engine through a setter method.

So what is this container business?

So far we've seen a very simple class example. But imagine (rightfully) that the Car has many other potentially swappable components (dependencies), like a type of gear shift, breaks or wheels. You have to manually instantiate all these dependent objects just so you can pass them to the one you actually need. This is what the container is for, to do all that for you.

Basically it works like this. You first register with the container your classes and their dependencies. And then at various points of your application, you can access the container and request an instance of a particular class (or service as we call them in Symfony and Drupal 8). The container instantiates an object of that class as well as one of each of its dependencies, then returns you that service object. But what is the difference between services that we usually access through the container and other PHP classes?

A very good definition that makes this distinction comes from the Symfony book:

As a rule, a PHP object is a service if it is used globally in your application. A single Mailer service is used globally to send email messages whereas the many Message objects that it delivers are not services. Similarly, a Product object is not a service, but an object that persists Product objects to a database is a service.

Understanding how the container works under the hood is I believe not crucial for using it. It's enough to know how to register classes and how to access them later. There are multiple ways to register services but in Drupal 8 we use YAML files. In Symfony, you can use directly PHP, YAML or even XML. To know more about how to do this in Drupal 8, check out this documentation page. Accessing the services in Drupal 8, on the other hand, is done in one of two ways: statically and using, yet again, dependency injection.

Statically, it's very simple. We use the global \Drupal namespace to access its service() method that returns the service with the name we pass to it.

$service = \Drupal::service('my service');

This approach is mostly used for when we need a service in our .module files where we are still working with procedural code. If we are in a class (such as a form, controller, entity, etc), we should always inject the service as a dependency to the class. Since I covered it elsewhere and the Drupal documentation mentioned provides a good starting point, I won't go into the exact steps you need to take in order to inject dependent services into your Drupal 8 classes. However, you can check out my introductory series on Drupal 8 module development, on Sitepoint.com, where I covered the process of creating services and injecting them as dependencies (in the third part, published soon if not already).

Conclusion

So there you go. Dependency injection is a very simple concept that has to do with the practice of decoupling functionality between classes. By passing dependencies to objects we can isolate their purpose and easily swap them with others. Additionally, it make is much easier to unit test the classes individually by passing mock objects.

The service container is basically there to manage some classes when things get overwhelming. That is, when the number grows and the number of their dependencies also increases. It keeps track of what a certain service needs before getting instantiated, does it for you and all you have to do is access the container to request that service.

Hope its clear.

4 tools you should definitely use for Drupal development

Developing Drupal sites can be quite a challenge and adventure. And this comes from those who call themselves Drupal developers. Men and women of PHP who work with other frameworks and applications most likely find it even more cumbersome to understand. However, Drupal is fostered by a big community of enthusiastic people who love it, myself included. But in all honesty, the more you work with it, the more you develop this love/hate relationship with all the quirks of Drupal development.

But one thing is certain, and this is applicable to other areas of web development as well: the tools you use for the job can make a big difference in the experience you have. And Drupal makes no exception. I mean, remember when we were writing PHP in Notepad and that one missing semicolon added 2 hours of debugging that day?

In this article I would like to share with you 4 tools that I use for Drupal development. I heavily rely on them to minimise frustration, increase productivity and lower development time. And I can guarantee you that if you are serious about Drupal development and you are not using them, you are missing out. But if you are, kudos, do share some of your experiences that further demonstrate their power.

So here we are, I guess in order of complexity, the 4 tools in my belt when I run vagrant up to spin up a project on my local environment. I will say a few words about each, but I can't go into all of their features. That's for you to explore after I give you a taste of what they can offer.

Devel and Search Krumo modules

Devel is the most used Drupal development module built for aiding with debugging code, generating content and all sorts of other dev tasks. Search Krumo is yet another cool module that plugs into it in order to give us a hand with navigating through huge array structures. And if you know Drupal 7, it is all about big arrays.

These modules are probably the first solution for debugging variables in Drupal. Using Devel's dsm(), dpm(), and krumo() functions in your code you can print out arrays, objects and whatever you need for a great overview of what you have in scope at that moment of execution. And they are not the only ones...

Another great use for the Devel module is content generation. It has a series of submodules that can generate nodes, taxonomy terms, users and more. Sometimes you need 500 nodes on the site to test something out. Additionally, you can use it to execute PHP code in the Drupal environment, switch between users on the site and other awesome functionality. So it's a must have on any Drupal development environment.

Drush

Drush is an awesome command line tool for Drupal that speeds up many tasks. Some people call it the swiss army knife of Drupal and you can't really argue the opposite.

Drush allows you to perform a host of Drupal tasks from the command line. You can download and enable/disable/uninstall/update modules or Drupal core and all sorts of other helpful jobs. This great list of core commands can give you an overview of what you can do with Drush. And if you are looking for some help with setting Drush up on your server, you can read this article I wrote on the subject.

Another great thing about Drush is that aside from all the awesome core commands, you can declare your own. This way, you can expose some of your custom functionality to the command line. This goes behind development and can help with maintenance or even production jobs that need to run with cron. So it truly is versatile.

A good IDE like PHPStorm

I mentioned before the good ol' times (not really) when Notepad was the editor of choice for many developers. Luckily nowadays we don't have to suffer through that as we can use IDEs for coding. I myself use PHPStorm and is of great help.

An IDE can speed up your development time by preventing code mistakes, highlighting syntax for great readability, code hinting for classes and functions in your project and many others. And with Drupal, all of these are important. Since Drupal 7 is mostly procedural you need to be aware of many functions and parameters. The IDE great reduces the time you spend online researching these APIs. And not to mention the integrations you can create with these API documentation resources.

Another great use of IDEs (which for me is the most important) is debugging. Integrating PHPStorm with XDebug on my local server really changed things around. But more on that in the next point.

Xdebug

As great as the Devel module is for printing out variables to the screen, it does not come close to Xdebug when we talk about debugging. After setting it up, all you have to do is place a breakpoint in your code and load your site page. The execution stops at the breakpoint (that was hopefully supposed to be executed) and you have access to a wealth of contextual information. You get all the global and scope variables that you can navigate through, a great callstack of what functions/methods have been triggered so far and many others.

Another cool feature is that you can play forward the execution line by line and jump inside of to be called functions to see where the code is heading. This is great for debugging where your code fails, at which point does that exception get thrown, or why that variable is null. So I do recommend checking it out.

Conclusion

And there you have it: 4 tools you can start using today to make you Drupal development experience more efficient. Using Drush and the Devel module are really only specifically for Drupal, but the use of a good IDE and XDebug is applicable to all other PHP projects as well. And I can guarantee you they are all worth using.

How to use Drush Make in your daily routine

This is a guest post from Kate Marshalkina, a Russian Drupal developer who works for Licel LLC. Enjoy the read and check out some of her other work.

Drush Make is well-known as an advanced tool for Drupal distribution building. But it also can be very useful for those who have never dealt with distributions. One great example is applying patches like a boss.

In this article I’ll show you how I use Drush Make to automate some of my routine tasks and help me to discover great Drupal stuff.

Drush Make commands

Drush Make includes 2 commands which are already built in Drush itself:

  1. make — Turns a .makefile into a Drupal codebase.
  2. make-generate — Generates a .makefile from the current Drupal site.

Both commands are related to a .makefile — flat text file with Drush Make instructions. You can read more about .makefile syntax here.

But for now, let's go deeper and see Drush Make in action.

Rebuild your development environment

How often do you install a new and clean Drupal site for development, testing or demonstration purposes? Additionally to Drupal core, developers usually have a predefined list of favorite modules like Administration Menu, Views or something more special. With Drush Make you can automate this process greatly by combining all the projects you need into one file and lettting Drush Make build it for you.

Here is an example .makefile for a multilingual testing site:

; Drush Make API version.
api = 2
; Drupal core.
core = 7.x

;Common modules.
projects[admin_menu][subdir] = "contrib"
projects[ctools][subdir] = "contrib"
projects[token][subdir] = "contrib"
projects[views][subdir] = "contrib"

; Development modules.
projects[devel][subdir] = "development"

; Multilingual modules.
projects[fallback_language_negotation][subdir] = "contrib"
projects[variable][subdir] = "contrib"
projects[i18n][subdir] = "contrib"
projects[i18nviews][subdir] = "contrib"

; Load some translations.
translations[] = de
translations[] = ru

This file can be saved locally (in ~/.drush/make-files/d7_i18n.make for example) or hosted on a remote server like GitHub.

To use it, let’s run the make command to prepare our custom build on our server (in /var/www/drupal_test.local for example):

$ drush make d7_i18n.make /var/www/drupal_test.local

The first run can be quite long, but the next time Drush will take most of projects from its cache.

As a result, the latest Drupal core, contrib modules and translations from the .makefile will be downloaded and placed in appropriate folders. Now you can go to your site's URL and run the install.php or run the installation process directly with Drush:

$ drush si --db-url="mysql://user:password@localhost/databasename" --site-name="Drupal Multilingual"

Additionally, you can also generate a tarball from the .makefile with --tar option:

$ drush make d7_i18n.make drupal_multilingual --tar

Add to that a couple of features (based on Features module) and you’ll end up with your own distro.

Download dependencies

Have you ever noticed that some contrib modules provide .make or .make.example file? These usually contain a list of specific external libraries (like the jQuery Colorbox plugin for the Colorbox module). These file can be built inside existing Drupal codebases using the --no-core flag. As an example, let’s say you want to download the Chosen module:

$ drush dl chosen
Project chosen (7.x-2.0-beta4) downloaded to sites/all/modules/contrib/chosen.

$ drush make sites/all/modules/contrib/chosen/chosen.make.example --no-core
chosen downloaded from https://github.com/harvesthq/chosen/releases/download/v1.1.0/chosen_v1.1.0.zip

In this case, the proper jQuery plugin was downloaded and unzipped into the proper directory inside the libraries/ folder. Isn’t that handy?

Module developers, please, add a .make.example file into your Drupal.org projects if you are using any external libraries. Instead of building custom Drush commands like chosen-plugin, we can use Drush Make. Just compare 117 lines to 7.

Generate makefile from existing site

You can easily share a custom Drupal build with Drush Make. First run generate-makefile command from Drupal root to generate a skeleton:

$ drush generate-makefile drupal_custom_build.make

The generated file drupal_custom_build.make will contain instructions for all enabled projects with specific versions. If a project has .git folder, Drush Make will automatically set appropriate properties:

projects[redirect][type] = "module"
projects[redirect][download][type] = "git"
projects[redirect][download][url] = "http://git.drupal.org/project/redirect.git"
projects[redirect][download][branch] = "7.x-1.x"
projects[redirect][download][revision] = "0b7b8dc2d58cb277874d87c91c45f0a361e148f7"

This file still needs a quick manual review. For example, you can add patch references. In my project, 2 patches are applied to the Redirect module:

projects[redirect][patch][] = "https://drupal.org/files/issues/redirect-global-905914-145.patch"
projects[redirect][patch][] = "https://drupal.org/files/issues/redirect.circular-loops.1796596-146.patch"

The resulting .makefile may be very useful if you want to share your working environment with a colleague or to provide definitive info for troubleshooting.

Bonus! Explore Drupal world!

Finally, the Drush Make file itself is a good read for discovering new cool contrib projects. Check out well-tested Commerce Kickstart or OpenScholar .makefiles with plenty of interesting projects inside.

I hope this article will help you use Drush more widely, to automate some of your tasks or to even build your first distribution!

About the Author

Kate is a passionate web developer from Russia who fell in love with Drupal in 2011.

She cares about multilingual stuff, usability and performance.

 

Connect with Kate:
Twitter | drupal.org | Google +

New features for Block Inject

I've worked recently on some new features for my contrib module Block Inject and I thought I'd share with you what's new.

Based on some feature requests from the community, I've implemented two new things that make this module more flexible. They are available in the 7.x-1.2alpha5 release onwards.

Theming

First, the injected region is now wrapped in a <div> with some default classes on it for easy styling. I've also created an alter hook for this so you can add easily your own classes there depending on the $node object the region is injected in.

An example implementation of this hook:

function hook_block_inject_attributes_alter($attributes) {
  if ($attributes['node']->type == 'article') {
    $attributes['attributes']['class'][] = 'article-block-inject';
  }
}

The $attributes parameter is an array with two values: the node object and another attributes array that gets transformed into HTML attributes by the drupal_attributes() function.

Site building

The second new feature of the module is the possibility to specify default paragraph offsets for an inject region depending on some conditions related to the node body field.

For example, when creating the inject region you can set it so that the region gets injected 5 paragraphs lower than the middle if the total number of paragraphs is over 20. Or move the region higher by 2 paragraphs if the total number of paragraphs equals 6.

Feel free to check it out and let me know what you think.

Sending HTML Emails with Webform in Drupal 7

Have you ever wondered how you can include HTML markup in the emails you send with Webform? Out of the box, you cannot. But I am going to show you a simple way to achieve this using the Mime Mail module and some simple theming. Additionally, I will show you how to control which webforms should send HTML emails and which should not.

First though, make sure you install and enable the Mime Mail and Mail System modules (the latter is a dependency of the former). With Drush, all you have to do is use this command:

drush en mimemail -y

It will take care of all you need to do. If you commit the module to your repo, don't forget that the Mail System module also gets downloaded, so make sure you include it as well.

Next, edit your theme's template.php file and paste this block of code (explained after):

function your_theme_webform_mail_headers($variables) {

  $headers = array();

  $headers = array(
    'Content-Type'  => 'text/html; charset=UTF-8; format=flowed; delsp=yes',
    'X-Mailer'      => 'Drupal Webform (PHP/'. phpversion() .')',
  );

  return $headers;

}

Make sure you change your_theme with the name of your theme. So what happens here? We override the theme_webform_mail_headers() declared by the Webform module. We do this in order to add a content type to the mail headers, and set it to HTML. And that's pretty much it.

If you now clear your caches and test a webform, you'll see that you can add anchor tags and other basic HTML tags.

One problem you might run into though is that all your webforms are now sending emails in HTML format - a result only partially desired. You'll notice that the default email that you send no longer provides any spacing and all the text gets put on one line - as HTML in fact.

So what you can do is make a selection of webforms for which you'll want HTML emails. A handy way of doing this is by adding a field to your webform content type that will be used to swith HTML emails on/off for a given node. So to illustrate this, let's say we added a new field to the relevant content type called HTML Emails (with the machine name: field_html_email). This field is a boolean type (a single checkbox basically) with the values of 1 for on and 0 for off.

It follows to adapt the theme override above and replace it with something like this:

function your_theme_webform_mail_headers($variables) {

  $headers = array(
    'X-Mailer' => 'Drupal Webform (PHP/' . phpversion() . ')',
  );

  // Get the HTML Email field
  $html_email_field = field_get_items('node', $variables['node'], 'field_html_email');

  // Check if this webform node needs to send HTML emails
  if (!empty($html_email_field)) {
    $html = $html_email_field[0]['value'] == 1 ? TRUE : FALSE;
  }

  if ($html === TRUE) {
    $headers['Content-Type'] = 'text/html; charset=UTF-8; format=flowed; delsp=yes';
  }

  return $headers;
} 

If you consult the documentation for this theme function, you'll know that the $variables parameter contains also the node object which uses Webform to send the email. So we basically check for the value of our field and if it is 1, we add the HTML information to the mail headers. Otherwise, we return the $headers array containing the value it does by default (essentially making no changes).

You can now clear the caches and test it out. Edit a node of the respective content type and check the box. You'll see that it now sends HTML emails. However, if you uncheck the box, it will fallback to the default format that comes with the Webform module.

Hope this helps.

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.