Drupal Tutorials

Creating a Template File Via a Form Element

If there is one thing I hate more than breath and martial arts (all kinds...), its writing copy within a php array. So for a recent project that required text-heavy forms, and a bunch of emails, I created an element that mimics php template. The usage and theme function are rather simple: (and rather stolen from phptemplate_render().

Drupal 6 AHAH forms: The easy way

Today, I was working with drupal 6's AHAH form elements. Initially, I was delighted at how well they worked. That delight turned to confusion once I realized that the form elements I had put in the menu callback of the #ahah['path'] was missing its name attribute. After doing a bit of research in how the poll module handled the formapi voodoo, I created a generalized function to aid in building AHAH callbacks. If there is a better way to do this, I wasn't able to find it.
<?php
// this is an example menu_callback that would be referenced by the #ahah['path'] property

Drupal CSS Coding Standards

On the #drupal IRC channel, Excallibur points out that there are no coding standards for CSS. I'd like to propose some straightforward ones.

Note that I am not intentionally omitting indentation within rules, but am having trouble with my code filter.

I. CSS is not Java.

This java-style of CSS does not make the code easier to read:

#rule1
{
  margin:0px;
}

It just adds an unnecessary space. Below is the correct way, which is consistent with core CSS.

#rule1 {
  margin:0px;
  padding:1em;
}

II. Two selectors = Two lines.

While the following code is more compact, it's also more difficult to scan.

#rule1, #rule2 {
  margin:0px;
  padding:1em;
}

The right way is separate lines.

#rule1,
#rule2 {
  margin:0px;
  padding:1em;
}

This small rule can make a big difference in complex themes (ever tried to debug some old civicspace themes?).

III. Single Line Rules

Single line rules are acceptable when there is only one selector and one property.

a {text-decoration:none;}
pre {font-size:1em;}

Can you think of any others? Disagree?

Stupid Simple Web Scraping with SimpleXML

The other day, I was tasked with building a data scraper. Having never built such a contraption, I naturally turned to the Internets for preexisting code. I was horrified with what I found.

The “free” PHP scripts (that’s “free” as in “free baby vomit”) were all infested with the worst sorts of newfangled regex, and PHP 4 era DOM traversing.

Making matters worse, the scripts didn’t offer much of an API, or interface for data mining – rather they provided a rigid, and worthless example – leaving their hapless users to mutilate whatever useful lines they could find, and create an even more horrid fraken-script.*

GOD OFFERED SIMPLEXML, AND IT WAS GOOD

It didn’t take me long to realize that PHP 5’s simpleXML was the answer. And indeed, after an hour of practice, simpleXML turned me into a scraping Ninja.

Below, is a very simple example [for drupal 6] that parses the drupal planet blogroll, and makes this neat little table out of it. Hopefully, you’ll find this method as easy, and useful as I did.

*Disclosure: I am not among the sadistic few that think Perl’s regular expressions are the greatest invention since sex. So you call simpleXML a crutch, and I’ll call you sick.

Enabling/Installing New Modules via Update.php: The Complete Solution

In our last episode of enabling new modules via update.php, Steve McKenzie pointed me to a better method: module_enable(). A quick test found, however, that it didn't run the install files, and didn't rebuild the module files cache. So after spending 5 minutes in system.module, I found all the missing pieces. The example update function below will install and enable the new module, as well as rebuild all the css, node type, and menu caches. In simple language, it does everything that happens when the modules admin page is submitted. Enjoy.

<?php
function example_update_1() {
 
$ret = array();

  // your array of modules you wish to enable and install in the update
 
$modules = array('some_module', 'some_other_module');
 
 
// You must rebuild the module cache for the system table to see the modules
 
module_rebuild_cache();
 
 
// enable modules first
 
module_enable($modules);
 
 
// now run their install files
 
drupal_install_modules($modules);

  // other magic functions that are only called when admin/build/modules form is submitted
 
menu_rebuild();
 
node_types_rebuild();
 
drupal_clear_css_cache();
 
 
// just a report for the install page -- otherwise this update will show up as "FAILED"
 
$ret[] = array('success' => true, 'query' => "enabled some module, and some other module");
  return
$ret;
}
?>

Enabling New Modules Via Update.php

UPDATE: There's a better way.

I work with 3 other developers, all of whom have their own local sandbox of our site. Since we're constantly adding new modules, I found a simple way to enable a new module via another module's .install file. That way, all we have to do is run update.php when we update our source tree.

Here's a simple example update function:

<?php

function some_enabled_module_update_1() {
 
$ret = array();
  switch (
$GLOBALS['db_type']) {
    case
'mysqli':
    case
'mysql':
     
//this function tells drupal to update its file directories, and insert records for any new modules it sees.
     
module_rebuild_cache();
     
$ret[] = update_sql("UPDATE {system} SET status = 1 WHERE name = 'some_completely_new_module'");
      break;
  }
  return
$ret;
}
;
?>

The major limitation of this method is that it doesn't run the new modules install file. I can live with that. It beats always bugging other developers to see if the build needs a new module enabled. I'm sure there's a workaround for that anyhow.

Drupal trick: Returning a themed menu tree with nothing more than the system path

I remember something a long time teacher said, "Nick, if you make a suit out of a gorrilla, the arms are too long." I forgot why that was relevent to the topic of theming menu trees.

Moving on, here's a nice little function I wrote to return a themed menu tree by path.

<?php
// will return all menu items under "administration".
print theme('menu_tree_by_path','admin');

// will return links to all node submission forms
print theme('menu_tree_by_path','node/add');

// return the correct menu array by path
function menu_get_mid_by_path($path) {
// oddly, menu_get_item accepts a path, but returns the parent id.

7 jQuery Plugins That Made Our Lives Easier at ON Networks

We, the developers of ON Networks released version 1.1 of our website this evening (its built off of drupal of course... if it weren't, than I would go sharing it with the planet, would i?). The notable improvements are ajax comments, tooltips for episodes, and a global navigation.

In celebration of this small milestone, I figured I'd reveal our favorite jQuery plugins that we're using. (note that our site's jQuery is 1.2.1... which is several versions ahead of the vanilla drupal core).

1. Cycle Plugin -- An early concept of our new homepage used this plugin. While that concept is dead, this plugin is very much alive in my head. Indeed, its one badass little jQuery plugin. For starters, it supports all the browsers I care about, offers tones of cool animations, and its syntax, and expected markup are bloody simple. Best of all, the author was a mind reader, and gave me all the options I needed, allowing me to use it without altering the plugin's source code.

The Key to Jquery Form Plugin + Drupal Formapi

Today I bring you an incomplete, yet stunningly easy solution to a problem that's been making want to set buildings on fire.

This problem was making drupal comments go AJAX by way of jquery's form plugin. I had all the good makings of a digg clone comment system, with reply forms dynamically inserting under replies (instead of going to another page). It was just the sans-pagerefresh comment submit thing that was missing.

Tragically, breaking the submit (necessary for ajax) also broke the ability for formapi to do its magic. Then, MerlinofChaos pointed out the 'obvious'approach on IRC.

Use drupal_execute to emulate form submission at a custom callback url. This approach can be applied to any form, so far as I can imagine. So I'm sharing it before I complete the much needed, and long desired ajax_comments.module (yes, it is really coming... solving this problem means I jumped over the last hurdle).

Here's the stripped down, proof of concept code: AJAX_COMMENTS.MODULE

Let Template.php Eat Static

 My arch-nemisis is overly complex logic in template.php and page.tpl.php files. It seems to me that when a drupal codebase becomes brittle and unmaintainable, the culprit is usually going to be hundreds of conditional lines of php code in a template file. You've probably seen code like this before:

THEMES/SPAGETTI_MONSTER/TEMPLATE.PHP

<?php

function spagetti_monster_page($content) {
 
// determine weather the page is a node view, or edit
 
switch(arg(0)) {
    case
'node':
      if (
is_numeric(arg(1)) && (!arg(2) || arg(2) == 'view')) {
       
$body_class = 'node_view';
      }
      else if (
arg(1) == 'add' || arg(2) == 'edit') {
       
$body_class = 'node_compose';
      }
     
// f#ck it, the clients will never look at these pages....
     
else {
       
$body_class = 'node_wtf';
      }
      break;
    case
'user'
      if (
is_numeric(arg(1)) && (!arg(2) || arg(2) == 'view')) {
       
$body_class = 'user_view';
      }
     
//.... and so on and so on and so on.....
     
break;
  }
}
?>

The dangers of this approach are something that cannot be explained: they must be felt first hand.

Switching args in a template.php or page.tpl.php file is like doing drugs (minus the laughs): lots of people have done it, survived, and even learned from it; but its an experience that is best avoided if you can help it. So lets see how to avoid it using static variables. (warning, you'll need to use a module).

Syndicate content