views:

859

answers:

1

I'm trying to create a custom search but getting stuck. What I want is to have a dropdownbox so the user can choose where to search in. These options can mean 1 or more content types.

So if he chooses options A, then the search will look in node-type P,Q,R. But he may not give those results, but only the uid's which will be then themed to gather specific data for that user.

To make it a little bit clearer, Suppose I want to llok for people. The what I'm searching in is 2 content profile types. But ofcourse you dont want to display those as a result, but a nice picture of the user and some data.

I started with creating a form with a textfield and the dropdown box. Then, in the submit handler, i created the keys and redirected to another pages with those keys as a tail. This page has been defined in the menu hook, just like how search does it.

After that I want to call hook_view to do the actual search by calling node_search, and give back the results.

Unfortunately, it goes wrong. When i click the Search button, it gives me a 404.

But am I on the right track? Is this the way to create a custom search?

Thx for your help.

Here's the code for some clarity:

<?php
// $Id$

/*
 * @file
 * Searches on Project, Person, Portfolio or Group.
 */

/**
 * returns an array of menu items
 * @return array of menu items
 */
function vm_search_menu() {

  $subjects = _vm_search_get_subjects();
  foreach ($subjects as $name => $description) {
    $items['zoek/'. $name .'/%menu_tail'] = array(
      'page callback' => 'vm_search_view',
      'page arguments' => array($name),
      'type' => MENU_LOCAL_TASK,
    );
  }
  return $items;
}


/**
 * create a block to put the form into.
 * @param $op
 * @param $delta
 * @param $edit
 * @return mixed
 */
function vm_search_block($op = 'list', $delta = 0, $edit = array()) {
  switch ($op) {
    case 'list':
      $blocks[0]['info'] = t('Algemene zoek');
      return $blocks;
    case 'view':
        if (0 == $delta) {
          $block['subject'] = t('');
          $block['content'] = drupal_get_form('vm_search_general_form');
        }
      return $block;
    }
}

/**
  * Define the form.
  */
function vm_search_general_form() {
  $subjects = _vm_search_get_subjects();
  foreach ($subjects as $key => $subject) {
    $options[$key] = $subject['desc'];
  }

    $form['subjects'] = array(
     '#type' => 'select',
    '#options' => $options,
    '#required' => TRUE,
    );
  $form['keys'] = array(
    '#type' => 'textfield',
    '#required' => TRUE,
  );
   $form['submit'] = array(
      '#type' => 'submit',
      '#value' => t('Zoek'),
   );
   return $form;
}


function vm_search_general_form_submit($form, &$form_state) {
  $subjects = _vm_search_get_subjects();
  $keys = $form_state['values']['keys']; //the search keys
  //the content types to search in
  $keys .= ' type:' . implode(',', $subjects[$form_state['values']['subjects']]['types']);



  //redirect to the page, where vm_search_view will handle the actual search
  $form_state['redirect'] = 'zoek/'. $form_state['values']['subjects'] .'/'. $keys;
}


/**
 * Menu callback; presents the search results.
 */
function vm_search_view($type = 'node') {
  // Search form submits with POST but redirects to GET. This way we can keep
  // the search query URL clean as a whistle:
  // search/type/keyword+keyword
  if (!isset($_POST['form_id'])) {
    if ($type == '') {
      // Note: search/node can not be a default tab because it would take on the
      // path of its parent (search). It would prevent remembering keywords when
      // switching tabs. This is why we drupal_goto to it from the parent instead.
      drupal_goto($front_page);
    }

    $keys = search_get_keys();
    // Only perform search if there is non-whitespace search term:
    $results = '';
    if (trim($keys)) {
      // Log the search keys:
      watchdog('vm_search', '%keys (@type).', array('%keys' => $keys, '@type' => $type));

      // Collect the search results:
      $results = node_search('search', $type);

      if ($results) {
        $results = theme('box', t('Zoek resultaten'), $results);
      }
      else {
        $results = theme('box', t('Je zoek heeft geen resultaten opgeleverd.'));
      }
    }
  }
  return $results;
}


/**
 * returns array where to look for
 * @return array
 */
function _vm_search_get_subjects() {
  $subjects['opdracht'] =
    array('desc' => t('Opdracht'),
          'types' => array('project')
          );
  $subjects['persoon'] =
     array('desc' => t('Persoon'),
          'types' => array('types_specialisatie', 'smaak_en_interesses')
          );
  $subjects['groep'] =
    array('desc' => t('Groep'),
        'types' => array('Villamedia_groep')
        );
  $subjects['portfolio'] =
    array('desc' => t('Portfolio'),
          'types' => array('artikel')
          );
   return $subjects;
}
A: 

To be honest, I haven't seen many people implement hook_search. Most just use Views, or, for advanced things, something like Faceted Search.

Did you consider using either for your current project? Why didn't it work?

Eli Krupitsky
I did, and I use views for other customized searches, but it's bad for performance. Faceted Search I have yet to discover.
Dr. Hfuhruhurr
It's pretty nice - as is the whole faceted search concept. If you're worried about performance, you could also look at Search Lucene or Apache Solr.
Eli Krupitsky
Btw, faceted search also hooks into views, so you can use views to display search result.
Eli Krupitsky