background image

Content tagged with: Drupal 6.x

Eric's picture

I created a Drupal site to host my photography in CCK Imagefield nodes and used Lucene to enhance my search functionality. By default Drupal's search results are text-based so I decided to add some code to show image thumbnails in my search results. I checked out Drupal Lucene's hooks and decided to implement a hook_luceneapi_result_alter() function in my existing module.

<?php
function MYMODULE_luceneapi_result_alter(&$result, $module, $type = NULL) {
 
 
// check for node results
 
if ($type == 'node') {
 
   
// check node type
   
if ($result['node']->type == 'image') {
   
     
// define an imagecache image path for image thumbnail
     
$imagecache_path_thumbnail = file_directory_path() . '/imagecache/thumbnail' . str_replace(file_directory_path(),'',$result['node']->field_image[0]['filepath']);     
     
     
// define an imagecache image path for image (large)
     
$imagecache_path_large = file_directory_path() . '/imagecache/large' . str_replace(file_directory_path(),'',$result['node']->field_image[0]['filepath']);
   
     
// define theme_image() variables
     
$alt = check_plain($result['node']->title);
     
$title = check_plain($result['node']->title);
     
// add rel=lightbox to enable lightbox2 module
     
$attributes = array(
       
'rel' => 'lightbox',
      );
     
// let imagecache define the size
     
$getsize = FALSE;
     
// generate the image hml
     
$image_html = theme('image', $imagecache_path_thumbnail, $alt, $title, $attributes, $getsize);     
   
      if (
$image_html) {
               
       
// define lightbox link
       
$image_link = l(
         
$image_html,
         
$imagecache_path_large,
          array(
           
'html' => true,
           
'attributes' => array(
             
'rel' => 'lightbox',
            )
          )
        );

       
// add data to the result variable, passed by reference
       
$result['image_thumbnail'] = $image_link;
       
      }
   
    }
 
  }

}
?>

The above code adds additional data to my search results variables. I then implemented a hook_preprocess_search_result() function in my theme's template.php file to pass this data to the search-result.tpl.php template file.

<?php
function MYTHEME_preprocess_search_result(&$variables) {

 
// ...snip...

  // check for lucene node search results
 
if ($variables['type']=='luceneapi_node') {

   
// check for image
   
if ($variables['result']['image_thumbnail']) {   

     
// pass additional data to theme template file
     
$variables['image_thumbnail'] = $variables['result']['image_thumbnail'];

    }
   
  }

}
?>

And in my theme's search-result.tpl.php template file, I added the following PHP to show the new variable.

<div class="search-result <?php print $search_zebra; ?>">

  <?php if($image_thumbnail): ?>
    <?php print $image_thumbnail; ?>
  <?php endif; ?>

  <!-- ...snip... -->

I also added a few lines of CSS in my theme's style.css file to tidy up the layout.

.search-results.luceneapi_node-results .search-result {
  clear: both;
}

.search-results.luceneapi_node-results .search-result img {
  float: left;
  margin: 0px 20px 20px 0px;
}

The visual results can be seen here on my photo gallery.

Visual search results

Eric's picture

Drush is a great command line module for administering a Drupal site. It's core features are listed here. Check out the README.txt for usage and installation documentation.

Drush can be used to setup a base Drupal installation with a few quick commands, awesome. One of it's biggest time saving features is downloading all the contributed modules when setting up a new site. Here are a few commands I use to setup a new Drupal site based on feature sets. The following commands should be run in the root directory of your drupal installation.

# Download development modules and themes:
drush dl admin admin_menu coder devel devel_themer reroute_email simpletest views_bulk_operations --destination=sites/all/modules/contrib/ --uri=http://yourhostname.com

# Download common/essential modules:
drush dl cck views date wysiwyg pathauto token captcha recaptcha location emfield link jquery_ui webform htmlpurifier luceneapi vertical_tabs --destination=sites/all/modules/contrib/ --uri=http://yourhostname.com

# Download SEO modules:
drush dl google_analytics xmlsitemap globalredirect site_verify --destination=sites/all/modules/contrib/ --uri=http://yourhostname.com

# Download structural/building modules:
drush dl context features ctools panels --destination=sites/all/modules/contrib/ --uri=http://yourhostname.com

# Download image handling modules:
drush dl imageapi transliteration filefield mimedetect imagefield imagecache imagecache_actions --destination=sites/all/modules/contrib/ --uri=http://yourhostname.com

NOTE: the destination and uri flags on the drush command are optional, but I recommend using them. In recent Drupal development I stopped using sites/default in favor of sites/hostname.com, to ensure that if I ever decide to move the site into a multi-site configuration, I will not have overlapping sites/default/files directories.

You can even enable the downloaded modules from the command line by using the "drush en" command..

drush help en

Eric's picture

In this tutorial I'll show you how to upload an image using the Forms API, create a new node, and attach the image to the CCK (filefield/imagefield) field. I wrote this code to work with the modules I primarily use for image processing: cck, filefield, imageapi, imagecache, imagefield, mimedetect, and transliteration.

After I installed those modules, I created a new node type (admin/content/types/add) called "Image" and added a single imagefield field.

Image node fields

Next, I created a custom module with a hook_menu() implementation:

<?php
// NOTE: this variable is used through the code,
// so I thought it would be better to put it in a constant
define('IMAGE_UPLOAD_CONTAINER', 'image_upload');

/**
* Implements hook_menu()
*/
function helper_menu() {

 
// create a blank array of menu items
 
$items = array();
 
 
// define page callback for upload form
  // NOTE: you'll want to restrict permission better [see: access arguments]
 
$items['upload'] = array(
   
'title' => t('Upload'),
   
'description' => t('Upload'),
   
'page callback' => 'drupal_get_form',
   
'page arguments' => array('helper_page_callback_upload_form'),
   
'access arguments' => array('access content'),
   
'type' => MENU_CALLBACK,
  );
 
 
// return menu items
 
return $items;

}
?>

I defined the form function page callback:

<?php
/**
* Implements page callback for upload form
*/
function helper_page_callback_upload_form() {

 
// create an empty form array
 
$form = array();
 
 
// set the form encoding type
 
$form['#attributes']['enctype'] = "multipart/form-data";
 
 
// add a file upload file
 
$form[IMAGE_UPLOAD_CONTAINER] = array(
   
'#type' => 'file',
   
'#title' => t('Upload an image'),
  );
  
 
// add a submit button
 
$form['submit'] = array(
   
'#type' => 'submit',
   
'#value' => 'Submit',
  );
 
 
// return form array
 
return $form;

}
?>

This page callback function results in the following form:

Image node form

Then I added the form validation and submit handler functions:

<?php
/**
* Implements form validation handler
*/
function helper_page_callback_upload_form_validate($form, &$form_state) {

 
// if a file was uploaded, process it.
 
if (isset($_FILES['files']) && is_uploaded_file($_FILES['files']['tmp_name'][IMAGE_UPLOAD_CONTAINER])) {

   
// validate file extension
    // NOTE: you can ellaborate on this code and add additional validation
   
if ($_FILES['files']['type'][IMAGE_UPLOAD_CONTAINER] != 'image/jpeg') {
     
form_set_error(IMAGE_UPLOAD_CONTAINER, 'Invalid file extension.');
      return;
    }

   
// attempt to save the uploaded file
   
$file = file_save_upload(IMAGE_UPLOAD_CONTAINER, array(), file_directory_path());

   
// set error if file was not uploaded
   
if (!$file) {
     
form_set_error(IMAGE_UPLOAD_CONTAINER, 'Error uploading file.');
      return;
    }
      
   
// set files to form_state, to process when form is submitted
   
$form_state['storage'][IMAGE_UPLOAD_CONTAINER] = $file;
      
  }
  else {
   
// set error
   
form_set_error(IMAGE_UPLOAD_CONTAINER, 'Error uploading file.');
    return;  
  }

}

/**
* Implements form submit handler
*/
function helper_page_callback_upload_form_submit($form, &$form_state) {
 
 
// create new node object
 
$new_node = (object) array(
   
'type' => 'image',
   
'uid' => $GLOBALS['user']->uid,
   
'name' => $GLOBALS['user']->name,
   
'title' => t('YOUR NODE TITLE'),
   
'status' => 1,
   
'field_image' => array(
      (array)
$form_state['storage'][IMAGE_UPLOAD_CONTAINER],
    ),
  );
   
 
// save node
 
node_save($new_node);
 
 
// clear form storage, to allow form to submit
 
$form_state['storage'] = array();
 
 
// redirect user, set message, etc!

}
?>

After using the form to upload an image, the following node was created:

New image node

Eric's picture

In this tutorial, I'll show a way to pass PHP/Drupal variables to javascript using drupal_add_js(), and a way you can debug javascript variables using the FireBug console.

I'll start by creating a hook_menu() implementation to establish a page callback:

<?php
function helper_menu() {

 
$items = array();
 
 
$items['js-vars'] = array(
   
'title' => t('Javascript Variables'),
   
'description' => t('Javascript Variables'),
   
'page callback' => 'helper_page_callback_js_vars',
   
'access arguments' => array('access content'),
   
'type' => MENU_CALLBACK,   
  );
 
  return
$items;

}
?>

Next, I'll define the page callback:

<?php
function helper_page_callback_js_vars() {

 
// include module javascript file
 
drupal_add_js(drupal_get_path('module','helper') . '/js/helper.js');

 
// define variables you'd like to pass to the DOM
 
$js_vars = array(
   
'js_vars' => array(
     
'message' => t('Hello @username', array('@username' => $GLOBALS['user']->name)),
     
'an_array' => array(
       
'color' => t('red'),
       
'name' => t('Eric'),
      ),
    ),
  );
 
 
// pass variables to javascript
 
drupal_add_js($js_vars, 'setting');
 
 
// generate some page output
 
return "TEST";

}
?>

And here is the contents of the javascript include file I stuck in my module directory:

$(document).ready(function(){

  // debug variables directly in FireBug
  console.debug(Drupal.settings.js_vars);
 
  // popup mesage passed from Drupal
  alert(Drupal.settings.js_vars.message);
 
});

When viewing this page in a browser, you'll see the following. The javascript popup window is using variables passed directly from a Drupal/PHP array:
javascript popup

The console.debug() javascript method was used to send data directly to the FireBug console. If you open FireBug, you'll see the following:
FireBug Console

If you click on the Object shown, you can drill into the variables further:
FireBug Console

Eric's picture

In this tutorial, I'll show you how you can create a table with re-sortable column headers and pagination from custom SQL. I strongly recommend you attempt to implement this functionality using the Views module first :)

<?php
/**
* Implements hook_menu()
*/
function helper_menu() {

 
$items = array();
 
 
$items['pager-test'] = array(
   
'title' => t('Pager Test'),
   
'description' => t('Pager Test'),
   
'page callback' => 'helper_page_callback_pager_test',
   
'access arguments' => array('access content'),
   
'type' => MENU_CALLBACK,
  );
 
  return
$items;

}

/**
* Implements page callback for pager-test url
*/
function helper_page_callback_pager_test() {

 
// define number of results per page
 
$number_results = 10;

 
// define a list of columns to select
 
$columns = array(
   
'nid' => t('ID'),
   
'type' => t('Type'),
   
'title' => t('Title'),
  );

 
// define sql to fetch results
 
$sql = "select %s from {node} where status = 1";

 
// define sql to fetch number of results
 
$sql_count = "select count(*) from {node} where status = 1";

 
// create resort header from column list
 
$header = array();
  foreach (
$columns as $key => $value) {
   
$header[] = array(
     
'data' => $value,
     
'field' => $key,
    );
  }
 
 
// add tablesort to SQL
 
$sql .= tablesort_sql($header);

 
// execute query
 
$resource = pager_query($sql, $number_results, 0, $sql_count, implode(', ', array_keys($columns)));

 
// fetch results
 
$results = array();
  while (
$row = db_fetch_array($resource)) {
   
$results[] = $row
  }

 
// define variable to contain page callback output
 
$output = "";
 
 
// create table html
 
$output .= theme('table', $header, $results);
 
 
// create pager html
 
$output .= theme('pager', NULL, $number_results, 0);

  return
$output;

}
?>

The above code results in the following table:

Pager Test