Drupal 7 – Add page and section body classes

Add this snippet to the template.php file in the THEMENAME_preprocess_html() hook.

<?php
global $base_path;
list(,
$path) = explode($base_path, $_SERVER['REQUEST_URI'], 2);
list(
$path,) = explode('?', $path, 2);
$path = rtrim($path, '/');
// Construct the id name from the path, replacing slashes with dashes.
$body_id = str_replace('/', '-', $path);
// Construct the class name from the first part of the path only.
list($body_class,) = explode('/', $path, 2);
// $body_class = $body_class . ' not-front';
$body_id = 'page-'. $body_id;
$body_class = 'section-'. $body_class;
$vars['classes_array'][] = ' ' . $body_id . ' ' . $body_class;
?>
Leave a comment Tags:

Drupal 7 – Add width and height attributes to image styles (imagecache)

Image styles (imagecache) are now included in Drupal 7 core, however the width and height attributes are not added to the <img> elements (lame). Add the below code to your template.php file to add width and height attributes to images that use image styles.

<?php
function THEMENAME_image_style($variables) {
 
$style_name = $variables['style_name'];
 
$path = $variables['path'];

 
// theme_image() can only honor the $getsize parameter with local file paths.
  // The derivative image is not created until it has been requested so the file
  // may not yet exist, in this case we just fallback to the URL.
 
$style_path = image_style_path($style_name, $path);
  if (!
file_exists($style_path)) {
   
$style_path = image_style_url($style_name, $path);
  }
 
$variables['path'] = $style_path;

  if (
is_file($style_path)) {
    if (list(
$width, $height, $type, $attributes) = @getimagesize($style_path)) {
     
$variables['width'] = $width;
     
$variables['height'] = $height;
    }
  }
 
  return
theme('image', $variables);
}
?>
1 comment Tags:

Drupal 6 – Theme search results page using nids

This theme override will supply the nids of each search result. You are free to use the nids as you please! A very useful trick is to feed the nids (as arguments) to a view, then display the view results as your search results. Endless possibilities!

Note: this function goes in the template.php file in a custom theme

<?php
/**
* Theme the search results
*/
function THEMENAME_preprocess_search_results(&$vars){
   
$nids = array();
   
// cycle through each result
   
foreach($vars['results'] as $result){   
       
// get each nid   
       
$nids[] = $result['node']->nid;
    }
   
   
/**
     * You can now use the $nids array however you please!
     * I often feed the nids to a view for an
     * uber custom search results page as shown below
     */

    // add commas between each node
   
$nids = implode(',', $nids);

   
$output = views_embed_view('VIEWNAME', $nids);

   
// this variable will display the output on the search results page
   
$vars['search_results'] = $output;   
}
?>
Leave a comment Tags:

Drupal 6 – Ubercart – fix attribute option sort for product classes

I have noticed that modifying attribute option weights (sorting with the drag n drop table) is not reflected when attribute is displayed with product classes. This is because there is a separate table named uc_class_attribute_options that Ubercart does not update when changing the order.

Adding the below code using a custom module fixes this behavior

<?php
/**
* Implementation of hook_form_alter().
*/
function MODULENAME_form_alter(&$form, $form_state, $form_id){
    if(
$form_id == 'uc_attribute_options_form'){
       
$form['#submit'][] = 'MODULENAME_attribute_options_form_submit';
    }
}

/**
* Ubercart options do not update the ordering of the uc_class_attribute_options table - product classes will not
* see the proper ordering. This additional submit handler fixes that.
*/
function MODULENAME_attribute_options_form_submit($form, &$form_state){
    foreach (
$form_state['values']['options'] as $oid => $option) {
   
db_query("UPDATE {uc_class_attribute_options} SET ordering = %d WHERE oid = %d", $option['ordering'], $oid);
  }
}
?>
1 comment Tags: ,

Drupal 6 – Ubercart – Redirect the “Cancel” button on checkout

This method will override the core redirect to '/cart' when user clicks the "Cancel" button on checkout.

First you must change the #name attribute to a custom value. Then you must check for the $_POST value of that name. If it matches, implement a custom drupal_goto call.

<?php
/**
* Implementation of hook_form_alter().
*/
function MODULENAME_form_alter(&$form, $form_state, $form_id){
   
// target the checkout form
   
if($form_id == 'uc_cart_checkout_form'){
       
// change the cancel button's #name to a custom value
       
$form['cancel']['#name'] = 'bx_cancel';
       
// check the $_POST value of your custom #name
       
if($_POST['bx_cancel'] == t('Cancel')){
           
// copied from Ubercart core
           
if (intval($_SESSION['cart_order']) > 0) {
               
uc_order_comment_save($_SESSION['cart_order'], 0, t('Customer cancelled this order from the checkout form.'));
              unset(
$_SESSION['cart_order']);
            }
           
// implement your custom redirect here
           
drupal_goto('<front>');
        }
    }   
}
?>
Leave a comment Tags: ,

Drupal 6 – Change a taxonomy listbox to a selectbox

This will change a scrolling listbox into a single selection drop-down selectbox. (Place in MODULENAME.module)

PS - change 1 to your vocabulary ID

<?php
$form
['taxonomy'][1]['#size'] = '';
$form['taxonomy'][1]['#multiple'] = 0;
?>
Leave a comment Tags:

Drupal 6 – Generate additional path alias when updating or adding a taxonomy term

This function generates an additional path alias when a new taxonomy term is created. It will also update the alias if the term is updated and delete the alias if the term is deleted.

In this example I am adding the alias 'taxonomy/term/%tid/articles' for every taxonomy term.

<?php
/**
* Implementation of hook_taxonomy().
*/
function MODULENAME_taxonomy($op, $type, $array = NULL){
    if((
$op == 'update' || $op == 'insert') && $type == 'term'){
       
       
// create an additional path alias of %path/articles
        // if alias does not exist, create new alias
       
if(db_result(db_query("SELECT COUNT(pid) FROM {url_alias} WHERE src = '%s'", 'taxonomy/term/' . $array['tid'] . '/articles')) == 0){
           
db_query("INSERT INTO {url_alias} (src, dst) VALUES ('%s', '%s')", 'taxonomy/term/' . $array['tid'] . '/articles', drupal_get_path_alias('taxonomy/term/' . $array['tid']) . '/articles');
       
// if alias exists, update the alias
       
}else{
           
db_query("UPDATE {url_alias} SET dst = '%s' WHERE src = '%s'", drupal_get_path_alias('taxonomy/term/' . $array['tid']) . '/articles', 'taxonomy/term/' . $array['tid'] . '/articles');
        }
       
    }else if(
$op == 'delete' && $type == 'term'){
       
// delete the alias
       
db_query("DELETE FROM {url_alias} WHERE src = '%s'", 'taxonomy/term/' . $array['tid'] . '/articles');
    }
}
?>
Leave a comment Tags:

Drupal 6 – Get latest Twitter feeds

This function accepts a Twitter account name, $user_id, and returns a list of the latest tweets.

Note: thanks to Chris Coyier!

<?php
/**
* Returns the latest Twitter statuses
*/
function MODULENAME_load_twitter($user_id){
   
// twitter url
   
$url = "http://twitter.com/statuses/user_timeline/$user_id.xml?count=10";
   
// convert to simple xml object
   
$xml = simplexml_load_file($url) or die("could not connect");
   
// start the markup
   
$output = '<ul>';
   
// cycle through each status
   
foreach($xml->status as $status){
       
// convert iso date to unix timestamp
       
$date = strtotime($status->created_at);
       
// format date
       
$date = date('n/j/Y', $date);
       
// get the status
       
$message = $status->text;
       
// convert any URL to a link
       
$regex = '/((https?|s?ftp|ssh)\:\/\/[^"\s\<\>]*[^.,;\'">\:\s\<\>\)\]\!])/';
       
$message = preg_replace_callback($regex, 'MODULENAME_twitter_match', $message);
       
       
// create markup
       
$output .= '<li><div class="twitter-date">' . $date . '</div>';
       
$output .= '<div class="twitter-status">' . $message . '</div></li>';
    }
   
// complete markup
   
$output .= '</ul>';
    return
$output;
}

/**
* Regex callback that replaces any URL with a link
*/
function MODULENAME_twitter_match($url){
    return
'<a href="' . $url[0] . '" target="_blank">' . $url[0] .'</a>';
}
?>
Leave a comment Tags:

Drupal 6 – Get Facebook status for any public profile

Seems like every time I find a method that works Facebook goes and changes the API. However, this method seems pretty solid.

First, you must enable the developer app on your Facebook account and create an app with the URL of the site on which you will be using this code. From this app you will need:

  • App ID
  • App Secret

Second, download the Facebook PHP SDK: https://github.com/facebook/php-sdk/ and include facebook.php in your module.

This function accepts one argument, ($fbid is the user's Facebook ID) and returns an object containing the specified number of statuses along with other meta data. Simply dpm() the returned object to view details.

<?php
/**
* Returns the latest Facebook statuses
*/
function MODULENAME_load_fb($fbid){
   
// include the Facebook SDK
   
require(drupal_get_path('module', 'MODULENAME') . '/facebook.php');
   
// create a new Facebook object with custom app info
   
$facebook = new Facebook(array('appId' => 'YOUR_APP_ID', 'secret' => 'YOUR_SECRET_APP_ID'));
   
// get the user status
   
$status = $facebook->api('/' . $fbid . '/feed?limit=10');

    return
$status['data'];
}
?>
3 comments Tags:

Drupal 6 – Create a custom block that contains an entire block region

This snippet is very handy if you need to place an entire block region into a panel. I have used 'left' region for this demo, but feel free to change this to any region.

<?php
/**
* Implementation of hook_block().
*/
function MODULENAME_block($op = 'list', $delta = 0){
   
$block = array();   
    switch (
$op) {
        case
'list':
           
// left region
           
$block[0]['info'] = t('Block region - left');
            return
$block;           
           
        case
'view':           
            switch (
$delta) {
               
// left region
               
case 0:
                   
// get all blocks in left region
                   
$blocks_left = block_list('left');
                   
// cycle through each block
                   
foreach($blocks_left as $block_left){
                       
$output .= theme('block', $block_left);
                    }
                    break;
            }
           
// assign the markup
           
$block['content'] = $output;       
           
            return
$block;
    }
}
?>
Leave a comment Tags:

Drupal 6 – Create an XML playlist using CCK fields

The method below will allow you to add a custom submit handler to a node form, and create an XML playlist file from a "Tracks" CCK field. This method can easily be tweaked to suit many other needs.

First, add a custom submit handler to our "Band" content type node edit form:

<?php
/**
* Implementation of hook_form_alter().
*/
function MODULENAME_form_alter(&$form, $form_state, $form_id){
    if(
$form_id == 'band_node_form'){
       
$form['buttons']['submit']['#submit'][] = 'MODULENAME_band_submit';
    }
}
?>

Note our custom submit handler points to the function MODULENAME_band_submit. Create this function below your hook_form_alter function:

<?php
/**
* Submit handler for the Band node form
*/
function MODULENAME_band_submit($form, &$form_state){
   
// get the nid
   
$nid = $form_state['nid'];
   
// get all uploaded tracks
   
$tracks = $form_state['values']['field_band_track'];
   
// remove the button element
   
unset($tracks['field_band_track_add_more']);
   
   
// create a new array which will be sorted by track weight
   
$weights = array();
    foreach(
$tracks as $track){
       
$weights[] = $track['_weight'];
    }
   
// sort the weights in asc order
   
sort($weights);
   
   
// start the markup
   
$output = '<?xml version="1.0" encoding="utf-8"><playlist>';
   
// cycle through each weight
   
foreach($weights as $weight){
       
// cycle through each track and check to match the weight       
       
foreach($tracks as $track){
           
// if its a match, create the markup
           
if($track['_weight'] == $weight){
               
$output .= '<item><title>' . $track['data']['description'] . '</title><path>' . $track['filepath'] . '</path></item>';
                break;
            }
        }
    }
   
// finish the markup
   
$output .= '</playlist>';   
   
// create the playlist filepath
   
$filename = file_directory_path() . '/playlists/playlist' . $nid . '.xml';
   
// open or create the file
   
$file = fopen($filename, 'w');
   
// save the file
   
fwrite($file, $output);
   
// close the file
   
fclose($file);   
}
?>

As always, be sure to swap MODULENAME with your custom module name.

Note: due to syntax highlighting issues a "?" was omitted from the XML declaration line. Line should read: $output = '<?xml version="1.0" encoding="utf-8"?><playlist>';

Leave a comment Tags:

jQuery – Prevent queue buildup with hover and animations

Unless you add a stop() call on your hover events, animations will build up when the mouse moves in and out very rapidly. If you are using fadeIn() and fadeOut() the key is to use the stop() call WITH its two arguments set to true. Example:

$('.btn').hover(function() {
  $(this).find('.btn-inner').stop(true, true).fadeOut(200);
}, function() {
  $(this).find('.btn-inner').fadeIn(200);
});
1 comment Tags:

Drupal 6 – Return menu markup for a top level term with its children

Provide the top level term object ($parent_term) and this function will return the top level term as a linked h2 element, along with its immediate children as a linked menu.

<?php
/**
* Returns menu markup of a top level term and its children
*/
function MODULENAME_get_taxonomy_menu($parent_term){
   
// append the parent term as a title to the nav
   
$output = '<h2><a href="/' . drupal_get_path_alias('taxonomy/term/' . $parent_term->tid) . '">' . $parent_term->name . '</a></h2>';
   
// get all children of the parent term
   
$children = taxonomy_get_children($parent_term->tid);
    if(!empty(
$children)){
       
$links = array();
        foreach (
$children as $key => $child) {
           
// populate a links array with all children
           
$links['menu-' . $key] = array(
               
'title' => $child->name,
               
'href' => drupal_get_path_alias('taxonomy/term/' . $child->tid),
            );
        }
       
// append the children links markup
       
$output .= theme_links($links);
    }
   
    return
$output;
   
}
?>
Leave a comment Tags:

Drupal 6 – Get the top level term of a node from its path

Supply a node ID ($nid) and vocabulary ID ($vid) and this function will return the top level term object, derived from the node's alias. Note: the node's path alias must contain the term's path alias.

<?php
/**
* Returns the top level term of a node from its path
*/
function MODULENAME_get_parent_term_from_path($nid, $vid){
   
// get the node alias
   
$path = drupal_get_path_alias('node/' . $nid);
   
// get section of the path created from the taxonomy parent
   
$tax_path = substr($path, 0, strrpos($path, '/'));
   
// load the vocabulary tree
   
$tree = taxonomy_get_tree($vid);
   
// cycle through each term
   
foreach ($tree as $key => $term) {
       
// if the alias of the term matches the alias
       
if(drupal_get_path_alias('taxonomy/term/' . $term->tid) == $tax_path){
           
// if the matching term is not top level, use its parent
           
if($term->depth > 0){
                return
taxonomy_get_term($term->parents[0]);
            }
            return
$term;
        }
    }
}
?>
Leave a comment Tags:

Drupal 6 – Generate markup dividing a menu into equally populated columns

Supply the system menu name ($menu_name) and number of columns ($columns) and this function will return HTML markup which will divide the menu (with links) equally amongst the columns.

<?php
/**
* Generates markup equally populating a specified
* number of columns from a specified menu
*/
function MODULENAME_divide_menu($menu_name, $columns){
   
// get the menu tree array
   
$menu_tree = menu_tree_all_data($menu_name);
   
// determine when the column should end
   
$limit = ceil(count($menu_tree) / $columns);
   
// set some counters
   
$column_count = 1;
   
$loop_counter = 0;
   
// start the output
   
$output = '<div class="nav-col-1 nav-col">';
   
// loop through each menu item
   
foreach($menu_tree as $key => $item){
       
// append the link markup
       
$output .= l($item['link']['title'], $item['link']['link_path']);
       
// if cutoff is reached, start a new column
       
if($column_count < $columns && $loop_counter % $limit == $limit - 1){
           
$output .= '</div><div class="nav-col-' . ++$column_count . ' nav-col">';
           
$loop_counter = 0;
        }else{
           
$loop_counter++;
        }
    }
   
$output .= "</div>";
   
    return
$output;
}
?>
Leave a comment Tags: