Last updated June 11, 2010. Created on June 11, 2010.
Edited by NancyDru. Log in to edit this page.

We needed to create a way to handle our RSS feeds differently than a standard teaser display. After going through several iterations of hook_nodeapi code, which were all less than we wanted, we decided to look at using the standard Drupal filter ("input format") system. Since check_markup takes a filter format id as its second parameter, this just might be the easier way out.

Coding up a custom filter is not a big deal; there's a good example in the API. So we did that, and it turned out to be much smaller than the nodeapi code because it didn't need to check for all kinds of different situations.

We then set up the full input format manually and tested. Everything was great. ...Except... [Isn't there always an "except?"] We have three tiers of systems to go through to get this stuff live. None of us were keen on creating the input format again so many times; it's a manual process, so prone to errors.

So the obvious answer is to do it programmatically. So we searched on DO and couldn't find any documentation on how to do this. Oh, well, time to re-invent the wheel... So here's the code we came up with; we hope it gives someone else a jump start.

  // First we want a complete list of roles, because we want everyone to have access to this.
  $roles = array();
  $result = db_query("SELECT rid FROM {role}");
  while ($r = db_fetch_array($result)) {
    $roles[] = $r['rid'];
  // Build an array for writing.
  $format = array('name' => 'test_format', 'roles' => ',' . implode(',', $roles), 'cache' => 0);
  // Use drupal_write_record because we don't want duplicates.
  drupal_write_record('filter_formats', $format);
  // Save this format id.
  $filter = $format['format'];
  // Make sure it worked. If not, quit now.
  if (!$filter) {
    drupal_set_message(t('Oops, looks like this might be a duplicate filter?'), 'error');

  // Okay, so far, so good. Now we make a list of the filters we want to use.
  // This is array(module, delta); The weight is determined by the order listed.
  $list = array(
    array('nancys_filter', 0),  // Section remover
    array('filter', 2),  // URL filter
    array('filter', 0),  // HTML filter
    array('nancys_filter', 1),  // Word fixer
    array('filter', 1),  // Line break converter
    array('filter', 3),  // HTML corrector
    array('pathologic', 0), // Pathologic
  // Okie, dokie. Now all we have to do is run through that array and write it to the db.
  foreach ($list as $weight => $r) {
    $row = array('format' => $filter, 'module' => $r[0], 'delta' => $r[1], 'weight' => $weight);
    drupal_write_record('filters', $row);
  // And finally...
  // Create a default list of HTML tags for the HTML filter to use.
  variable_set("allowed_html_$filter", '<a> <abbr> <acronym> <address> <b> <bdo> <big> <blockquote> <br> <caption> <cite> <code> <col> <colgroup> <dd> <del> <dfn> <div> <dl> <dt> <em> <h1> <h2> <h3> <h4> <h5> <h6> <hr> <i> <ins> <kbd> <li> <ol> <p> <pre> <q> <samp> <small> <span> <strong> <sub> <sup> <table> <tbody> <td> <tfoot> <th> <thead> <tr> <tt> <ul> <var>'); 

Looking for support? Visit the forums, or join #drupal-support in IRC.


wiifm’s picture

If so, can you provide a download link? This would benefit me greatly. Thanks for your hard work


NancyDru’s picture

It is part of a custom module that my customer needed, but it is not a contributed module. You can either put this into your own module or create a PHP-page to put it in.

joejoejoew’s picture

Thanks, I'm just about to do this myself. If you're interested, take a look at how the core php module does the same thing:

It looks like he php module doesn't implement hook_uninstall.

NancyDru’s picture

The code that defines the filter is very similar, but I go into build the whole input format, that's where the difference is.

Hook_uninstall is not mandatory; however, it should be there in this case. Why don't you open a core issue requesting one?

joejoejoew’s picture

php_install creates the input format as well. It does the same thing as your example.

I was trying to point out that all of this code could go in a hook_install implemenation, and, in that case, should also implement hook_uninstall.

TechNikh’s picture

For drupal7

$format_exists = (bool) db_query_range('SELECT 1 FROM {filter_format} WHERE name = :name', 0, 1, array(':name' => 'PHP code'))->fetchField();
  // Add a PHP code text format, if it does not exist. Do this only for the
  // first install (or if the format has been manually deleted) as there is no
  // reliable method to identify the format in an uninstall hook or in
  // subsequent clean installs.
  if (!$format_exists) {
    $php_format = array(
      'format' => 'php_code',
      'name' => 'PHP code',
      // 'Plain text' format is installed with a weight of 10 by default. Use a
      // higher weight here to ensure that this format will not be the default
      // format for anyone.
      'weight' => 11,
      'filters' => array(
        // Enable the PHP evaluator filter.
        'php_code' => array(
          'weight' => 0,
          'status' => 1,
    $php_format = (object) $php_format;

    drupal_set_message(t('A <a href="@php-code">PHP code</a> text format has been created.', array('@php-code' => url('admin/config/content/formats/' . $php_format->format))));


In 30 seconds set up Automated Visual testing of your website. Zero coding.
Ever dreamed of styling your view, We have a solution for you.