This is probably pretty basic, but I'm getting stuck. I have a custom search module that implements a block for doing an ajax search (not autocomplete, this does a real search and then displays the results on the same page). I'm trying to consolidate all of the pieces into the module itself, right now the theme's page-front.tpl.php has some markup for this that needs to go into the module.

I've implemented hook_block and now I'm trying to implement hook_theme with these functions:

function ajax_search_block($op, $delta = NULL, $edit = array()) {
  switch ($op) {
    case 'list':
      $blocks[0]['info'] = t('Ajax search form');
      $blocks[0]['cache'] = BLOCK_NO_CACHE;
      return $blocks;

    case 'view':
      $path = drupal_get_path('module', 'ajax_search');
      drupal_add_js($path .'/ajax_search.js');
      $block['content'] = drupal_get_form('search_block_form');
      $block['subject'] = t('Ajax Search');
      return $block;
    }
}

function ajax_search_theme() {
  return array(
    'ajax_search_block' => array(
      'template' => 'block-ajax_search',
      'arguments' => array('form' => NULL),
    ),
  );
}

I created a 'block-ajax_search.tpl.php' file in the module's directory, but it's not getting rendered. The devel themer tool still lists the actual used template as the theme's block.tpl.php. Any thoughts on what I'm missing?

Comments

mountaineer’s picture

The more I look around, I think the key is in the hook_block line?

$block['content'] = drupal_get_form('search_block_form');

That call maps to search-block-form.tpl.php in the core search module, right? I can override that in the theme, I know. But really, i want to wrap that in my own template.

What I've done is to implement block-ajax_search.tpl.php in my theme by copying the block.tpl.php file and adding markup. This works, but still struggling as to how to get that search form plus my extra markup inside a template file in the module itself.

mountaineer’s picture

Ok, so I understand the drupal_get_form call as well as hook_theme pretty well now. Independently, this is great, but not sure how to tie the two together so that the call to drupal_get_form renders my theme hook? In digging into the search module, I can't determine where the search_box() call is having the theme called.

function talkback_search_block($op, $delta = NULL, $edit = array()) {
  switch ($op) {
    case 'list':
      $blocks[0]['info'] = t('Talkback search form');
      $blocks[0]['cache'] = BLOCK_NO_CACHE;
      return $blocks;

    case 'view':
      $path = drupal_get_path('module', 'talkback_search');
      drupal_add_js($path .'/talkback_search.js');
      $block['content'] = drupal_get_form('talkback_search_block_form');
      //$block['content'] = theme('talkback_search_block_form');
      $block['subject'] = t('Talkback Search');
      return $block;
    }
}

function talkback_search_theme() {
  return array(
    'talkback_search_block_form' => array(
      'arguments' => array('form' => NULL),
      'template' => 'talkback_search-block-form',
    ),
  );
}

function talkback_search_forms() {
  $forms['talkback_search_block_form']= array(
    'callback' => 'search_box',
    'callback arguments' => array('talkback_search_block_form'),
  );
  return $forms;
}
mountaineer’s picture

I copied the template_preprocess function from search.module and it worked. Slowly getting the hang of this.

/**
 * Implementation of hook_block()
 */
function talkback_search_block($op, $delta = NULL, $edit = array()) {
  switch ($op) {
    case 'list':
      $blocks[0]['info'] = t('Talkback search form');
      // Not worth caching.
      $blocks[0]['cache'] = BLOCK_NO_CACHE;
      return $blocks;

    case 'view':
      $path = drupal_get_path('module', 'talkback_search');
      drupal_add_js($path .'/talkback_search.js');
      $block['content'] = drupal_get_form('talkback_search_block_form');
      $block['subject'] = t('Talkback Search');
      return $block;
    }
}

/**
 * Implementation of hook_theme()
 */
function talkback_search_theme() {
  return array(
    'talkback_search_block_form' => array(
      'arguments' => array('form' => NULL),
      'template' => 'talkback_search-block-form',
    ),
  );
}

/**
 * Implementation of hook_forms()
 */
function talkback_search_forms() {
  $forms['talkback_search_block_form']= array(
    'callback' => 'search_box',
    'callback arguments' => array('talkback_search_block_form'),
  );
  return $forms;
}

/**
 * Process variables for talkback_search-block-form.tpl.php.
 *
 * The $variables array contains the following arguments:
 * - $form
 *
 * @see talkback_search-block-form.tpl.php
 */
function template_preprocess_talkback_search_block_form(&$variables) {
  $variables['search'] = array();
  $hidden = array();
  // Provide variables named after form keys so themers can print each element independently.
  foreach (element_children($variables['form']) as $key) {
    $type = $variables['form'][$key]['#type'];
    if ($type == 'hidden' || $type == 'token') {
      $hidden[] = drupal_render($variables['form'][$key]);
    }
    else {
      $variables['search'][$key] = drupal_render($variables['form'][$key]);
    }
  }
  // Hidden form elements have no value to themers. No need for separation.
  $variables['search']['hidden'] = implode($hidden);
  // Collect all form elements to make it easier to print the whole form.
  $variables['search_form'] = implode($variables['search']);
}