You are here

finder.admin.inc in Finder 7

Same filename and directory in other branches
  1. 6 includes/finder.admin.inc

The finder admin screens.

File

includes/finder.admin.inc
View source
<?php

// $Id: finder.admin.inc,v 1.1.2.50 2011/02/12 06:55:18 danielb Exp $

/**
 * @file
 * The finder admin screens.
 */

/**
 * Admin finder list page.
 */
function finder_admin_list() {
  $output = array();
  $finders = finder_load_multiple();
  if (empty($finders)) {
    $output[]['#markup'] = t('There are currently no finders configured.');
  }
  else {
    foreach ((array) $finders as $finder) {

      // allow modules to change the finder here
      finder_invoke_finderapi($finder, 'finder_admin_list');
      if (!isset($finder->settings['programmatic']) || !$finder->settings['programmatic']) {
        $rows = array();
        $rows[] = array(
          array(
            'data' => '<strong>' . check_plain($finder->title) . '</strong>',
            'class' => 'finder-title',
          ),
          array(
            'data' => l(t('Edit'), 'admin/structure/finder/' . $finder->finder_id . '/edit') . ' | ' . l(t('Delete'), 'admin/structure/finder/' . $finder->finder_id . '/delete'),
            'class' => 'finder-ops',
            'align' => 'right',
          ),
        );
        $rows[] = array(
          array(
            'data' => '
              <div class="type">' . t('Type') . '<span class="finder-colon">:</span> <span>' . t($finder->base_handler['#title']) . '</span></div>
              <div class="path">' . t('Path') . '<span class="finder-colon">:</span> <span>' . l($finder->path, $finder->path) . '</span></div>
              ',
            'class' => 'finder-summary',
          ),
          array(
            'data' => '<div class="description">' . check_markup($finder->description) . '</div>',
            'class' => 'finder-desc description',
          ),
        );
        $output[] = array(
          '#theme' => 'table',
          '#rows' => $rows,
          '#attributes' => array(
            'class' => 'finder-table finder-' . $finder->finder_id,
          ),
        );
      }
    }
  }
  $output[] = drupal_get_form('finder_admin_add_form');
  return $output;
}

/**
 * Admin finder add form.
 */
function finder_admin_add_form($form, &$form_state) {
  $form['base'] = array(
    '#type' => 'select',
    '#title' => t('Add a new finder'),
    '#default_value' => '',
    '#options' => finder_admin_get_base_options(),
    '#description' => t('Choose what kind of finder to create.'),
    '#required' => TRUE,
  );
  $form['actions'] = array(
    '#type' => 'actions',
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Add finder'),
  );
  return $form;
}

/**
 * Submit function for admin finder add form.
 */
function finder_admin_add_form_submit($form, &$form_state) {
  $values =& $form_state['values'];
  $finder = (object) array(
    'base' => $values['base'],
  );
  finder_save($finder);
  $finder->title = t('Finder !1', array(
    '!1' => $finder->finder_id,
  ));
  $finder->path = 'finder/' . $finder->finder_id;
  finder_save($finder);
  drupal_set_message(t('A finder was added.  Configure the finder and add elements below.'));
  menu_rebuild();
  drupal_goto('admin/structure/finder/' . $finder->finder_id . '/edit');
}

/**
 * Admin finder edit page.
 */
function finder_admin_edit($form, &$form_state, $finder) {

  // allow modules to change the finder here
  finder_invoke_finderapi($finder, 'finder_admin_edit', $form, $form_state);
  $form_state['storage']['finder'] = $finder;

  // build the form
  $form['#tree'] = TRUE;
  $form['finder_id'] = array(
    '#type' => 'value',
    '#value' => $finder->finder_id ? $finder->finder_id : 'add',
    '#weight' => 0,
  );
  $form['links'] = array(
    '#finder' => $finder,
    '#theme' => 'finder_admin_links',
    '#weight' => 0,
  );
  $form['base'] = array(
    '#type' => 'select',
    '#title' => t('Finder type'),
    '#default_value' => $finder->base,
    '#options' => finder_admin_get_base_options(),
    '#description' => t('You cannot change this.'),
    '#required' => TRUE,
    '#disabled' => TRUE,
    '#weight' => 5,
  );
  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Title'),
    '#default_value' => $finder->title,
    '#size' => 40,
    '#maxlength' => 255,
    '#required' => TRUE,
    '#weight' => 10,
  );
  $form['description'] = array(
    '#type' => 'textfield',
    '#title' => t('Description'),
    '#default_value' => $finder->description,
    '#size' => 80,
    '#description' => t('This will appear on the finder administration page.'),
    '#weight' => 20,
  );
  $form['path'] = array(
    '#type' => 'textfield',
    '#title' => t('Path'),
    '#default_value' => $finder->path,
    '#description' => t('Finder needs a URL path for some functionality.  No leading or trailing slash.'),
    '#size' => 30,
    '#maxlength' => 128,
    '#required' => TRUE,
    '#weight' => 40,
  );
  $form['block'] = array(
    '#type' => 'checkbox',
    '#title' => t('Provide block'),
    '#default_value' => $finder->block,
    '#weight' => 50,
    '#description' => t('Create a block for the finder form.'),
  );
  $form['settings'] = array(
    '#weight' => 60,
  );
  $form['settings']['form_on_page'] = array(
    '#type' => 'checkbox',
    '#title' => t('Form on page'),
    '#default_value' => $finder->settings['form_on_page'],
    '#weight' => 10,
    '#description' => t('Put a finder form on the path given above.'),
  );
  $form['settings']['form'] = array(
    '#type' => 'fieldset',
    '#title' => t('Form'),
    '#weight' => 100,
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $form['settings']['form']['prefix'] = array(
    '#type' => 'text_format',
    '#base_type' => 'textarea',
    '#format' => isset($finder->settings['form']['prefix']['format']) ? $finder->settings['form']['prefix']['format'] : NULL,
    '#title' => t('Prefix'),
    '#default_value' => isset($finder->settings['form']['prefix']['value']) ? $finder->settings['form']['prefix']['value'] : '',
    '#weight' => 10,
    '#description' => t('Displayed before the form.'),
  );
  $form['settings']['form']['suffix'] = array(
    '#type' => 'text_format',
    '#base_type' => 'textarea',
    '#format' => isset($finder->settings['form']['suffix']['format']) ? $finder->settings['form']['suffix']['format'] : NULL,
    '#title' => t('Suffix'),
    '#default_value' => isset($finder->settings['form']['suffix']['value']) ? $finder->settings['form']['suffix']['value'] : '',
    '#weight' => 20,
    '#description' => t('Displayed after the form.'),
  );
  $form['settings']['form']['button_text'] = array(
    '#type' => 'textfield',
    '#title' => t('Button text'),
    '#default_value' => isset($finder->settings['form']['button_text']) ? $finder->settings['form']['button_text'] : t('Find'),
    '#weight' => 100,
    '#description' => t('Text to display on the submit button.'),
  );
  $form['settings']['form']['go_text'] = array(
    '#type' => 'textfield',
    '#title' => t('Go text'),
    '#default_value' => isset($finder->settings['form']['go_text']) ? $finder->settings['form']['go_text'] : t('Go'),
    '#weight' => 120,
    '#description' => t('Text to display on the go button. Only used with <em>redirect to result</em> "go" button option under <em>Advanced</em>.'),
  );
  $form['settings']['advanced'] = array(
    '#type' => 'fieldset',
    '#title' => t('Advanced'),
    '#weight' => 200,
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $form['settings']['advanced']['no_results'] = array(
    '#type' => 'fieldset',
    '#title' => t('No results output'),
    '#weight' => 5,
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $variables = array(
    'keywords' => t('An array keyed by the Finder element ID, containing structured data about submitted keywords.'),
    'form_state' => t('The Forms API form state array.'),
    'finder' => t('Object containing data about this finder.'),
  );
  $form['settings']['advanced']['no_results']['no_results'] = finder_php_setting(array(
    '#type' => 'textarea',
    '#title' => t('No results output'),
    '#default_value' => isset($finder->settings['advanced']['no_results']['no_results']) ? $finder->settings['advanced']['no_results']['no_results'] : t('There are no results to display'),
    '#weight' => 5,
    '#rows' => 1,
    '#description' => t('
        You can use a mixture of text and PHP code to print or return the
        output when there are no results.  PHP must be enclosed in PHP tags.
        This can also be used to make context-aware redirects.'),
  ), array(
    'keywords' => t('An array keyed by the Finder element ID, containing structured data about submitted keywords.'),
    'form_state' => t('The Forms API form state array.'),
    'finder' => t('Object containing data about this finder.'),
  ));
  $form['settings']['advanced']['filter'] = array(
    '#type' => 'checkbox',
    '#title' => t('Show results on results page even before the form has been completed'),
    '#default_value' => isset($finder->settings['advanced']['filter']) ? $finder->settings['advanced']['filter'] : 0,
    '#weight' => 10,
    '#description' => t('Allows this finder to behave more as a filter.'),
  );
  $form['settings']['advanced']['validate_empty'] = array(
    '#type' => 'checkbox',
    '#title' => t('Validate empty submission'),
    '#default_value' => isset($finder->settings['advanced']['validate_empty']) ? $finder->settings['advanced']['validate_empty'] : 0,
    '#weight' => 15,
    '#description' => t('Prevent submission where all elements have empty values.'),
  );
  $form['settings']['advanced']['submission'] = array(
    '#type' => 'checkbox',
    '#title' => t('Use submit button'),
    '#default_value' => isset($finder->settings['advanced']['submission']) ? $finder->settings['advanced']['submission'] : 1,
    '#weight' => 20,
    '#description' => t('Gives the finder a submit button.'),
  );
  $form['settings']['advanced']['ajax'] = array(
    '#type' => 'checkbox',
    '#title' => t('Use Ajax on submit button'),
    '#default_value' => isset($finder->settings['advanced']['ajax']) ? $finder->settings['advanced']['ajax'] : 0,
    '#weight' => 30,
    '#description' => t('Dynamically update the form and results using Ajax instead of loading a whole new page.'),
  );
  $form['settings']['advanced']['ajax_effect'] = array(
    '#type' => 'radios',
    '#title' => t('Ajax effect'),
    '#default_value' => isset($finder->settings['advanced']['ajax_effect']) ? $finder->settings['advanced']['ajax_effect'] : 'none',
    '#weight' => 32,
    '#description' => t('If using Ajax, this will be the transition effect when the update occurs.'),
    '#options' => array(
      'none' => t('None'),
      'fade' => t('Fade'),
      'slide' => t('Slide'),
    ),
  );
  $form['settings']['advanced']['ajax_remote'] = array(
    '#type' => 'checkbox',
    '#title' => t('Ajax block is remote control'),
    '#default_value' => isset($finder->settings['advanced']['ajax_remote']) ? $finder->settings['advanced']['ajax_remote'] : 0,
    '#weight' => 34,
    '#description' => t('If Ajax is being used in a finder block that happens to be on the finder page, make the finder block act as a remote control for the finder page.'),
  );
  $form['settings']['advanced']['element_combination'] = array(
    '#type' => 'radios',
    '#title' => t('Multiple element result combination'),
    '#default_value' => isset($finder->settings['advanced']['element_combination']) ? $finder->settings['advanced']['element_combination'] : 0,
    '#weight' => 40,
    '#description' => t('With multiple elements, how should the results of each element be combined on the results page?'),
    '#options' => array(
      0 => t('<em>Conjunction</em> - Match <em>all</em> elements using the AND operator.'),
      1 => t('<em>Disjunction</em> - Match <em>any</em> element using the OR operator.'),
    ),
  );
  $form['settings']['advanced']['pager'] = array(
    '#type' => 'textfield',
    '#title' => t('Pager'),
    '#default_value' => isset($finder->settings['advanced']['pager']) ? $finder->settings['advanced']['pager'] : '10',
    '#description' => t('Number of items to show per results page.  Set to 0 to disable pager.'),
    '#size' => 5,
    '#maxlength' => 8,
    '#weight' => 50,
  );
  $form['settings']['advanced']['goto'] = array(
    '#type' => 'radios',
    '#title' => t('Redirect to result'),
    '#default_value' => $finder->settings['advanced']['goto'] ? $finder->settings['advanced']['goto'] : '',
    '#weight' => 80,
    '#options' => array(
      '' => t('Never redirect to result, always use results page.'),
      'best' => t('Redirect to the only result, or show results page if there are multiple results.'),
      'always' => t('Always redirect to the first result.'),
      'go' => t('Use a seperate "go" button for the first result, otherwise use results page.'),
    ),
  );
  $form['settings']['advanced']['hide_args'] = array(
    '#type' => 'checkbox',
    '#title' => t('Hide URL arguments on results page'),
    '#default_value' => isset($finder->settings['advanced']['hide_args']) ? $finder->settings['advanced']['hide_args'] : 0,
    '#weight' => 160,
    '#description' => t("Use the user's session to store submitted values across multiple pages.  Also creates a token for multipage results to identify the stored submission"),
  );
  $form['settings']['advanced']['arg_sep'] = array(
    '#type' => 'textfield',
    '#title' => t('Multiple value URL arguments separator'),
    '#default_value' => isset($finder->settings['advanced']['arg_sep']) ? $finder->settings['advanced']['arg_sep'] : ',',
    '#weight' => 170,
    '#description' => t('Must contain at least one character other than \' \', \'/\', \'_\', and \'-\'.  If this string exists within a keyword, the keyword will be automatically enclosed in double quotes to prevent parsing issues.'),
    '#size' => 5,
    '#required' => TRUE,
  );
  $form['settings']['advanced']['empty_symbol'] = array(
    '#type' => 'textfield',
    '#title' => t('Empty value URL arguments symbol'),
    '#default_value' => isset($finder->settings['advanced']['empty_symbol']) ? $finder->settings['advanced']['empty_symbol'] : '',
    '#weight' => 172,
    '#description' => t('Leave blank for default symbol (a space).  You may need to set this to some other symbol or text if you are getting "forbidden" errors on results pages.  Must contain at least one character other than \' \', \'/\', \'_\', and \'-\'.'),
    '#size' => 5,
    '#required' => FALSE,
  );
  $form['settings']['advanced']['show_links'] = array(
    '#type' => 'checkbox',
    '#title' => t('Show finder links'),
    '#default_value' => isset($finder->settings['advanced']['show_links']) ? $finder->settings['advanced']['show_links'] : 1,
    '#weight' => 180,
    '#description' => t('Show the <em>finder links</em>.'),
  );
  $form['settings']['advanced']['show_admin_links'] = array(
    '#type' => 'checkbox',
    '#title' => t('Show finder admin links'),
    '#default_value' => isset($finder->settings['advanced']['show_admin_links']) ? $finder->settings['advanced']['show_admin_links'] : 1,
    '#weight' => 182,
    '#description' => t('Show the <em>finder admin links</em>.'),
  );
  $form['settings']['advanced']['cache_finder_find'] = array(
    '#type' => 'textfield',
    '#title' => t('Cache duration of options and results'),
    '#default_value' => isset($finder->settings['advanced']['cache_finder_find']) ? $finder->settings['advanced']['cache_finder_find'] : '0',
    '#weight' => 190,
    '#description' => t('Set to 0 to disable.'),
    '#size' => 5,
    '#required' => TRUE,
    '#field_suffix' => t('minutes'),
  );
  if (!empty($finder->elements)) {
    $form['elements'] = array(
      '#title' => t('Elements'),
      '#weight' => 2000,
      '#theme' => 'finder_admin_edit_elements_table',
    );
    foreach ($finder->elements as $key => $value) {
      if (empty($value->settings['choices']['field'])) {
        drupal_set_message(t("Finder element %title is not configured.", array(
          '%title' => $value->title,
        )), 'error');
      }
      $element_output = '<div class="finder-element">';
      $element_output .= '<div class="finder-element-title"><strong>' . check_plain($value->title) . '</strong></div>';
      $element_output .= '<div class="finder-element-element">' . t('Element') . '<span class="finder-colon">:</span> <span>' . $value->element_handler['#title'] . '</span></div>';
      $element_output .= '</div>';
      $form['elements'][$value->finder_element_id]['value']['#markup'] = $element_output;
      $form['elements'][$value->finder_element_id]['ops']['#markup'] = l(t('Edit'), 'admin/structure/finder/' . $finder->finder_id . '/' . $value->finder_element_id) . ' | ' . l(t('Delete'), 'admin/structure/finder/' . $finder->finder_id . '/' . $value->finder_element_id . '/delete');
      $form['elements'][$value->finder_element_id]['weight'] = array(
        '#type' => 'weight',
        '#delta' => count($finder->elements),
        '#default_value' => $key,
      );
    }
    $form['elements']['#form'] = $form['elements'];
  }
  else {
    $form['no_elements'] = array(
      '#markup' => '
        <div id="edit-no-elements-wrapper" class="form-item">
        <label for="edit-path">' . t('Elements') . '<span class="finder-colon">:</span></label>' . t('There are currently no elements configured for this finder.') . '</div>
      ',
      '#weight' => 100,
    );
  }
  $form['add_element'] = array(
    '#type' => 'select',
    '#title' => t('Add element'),
    '#default_value' => '',
    '#options' => finder_admin_get_element_options(),
    '#description' => t('Choose the form element to use and press %save_button.', array(
      '%save_button' => t('Save finder'),
    )),
    '#weight' => 10000,
  );
  $form['actions'] = array(
    '#type' => 'actions',
    '#weight' => 10040,
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save finder'),
  );
  $form['actions']['delete'] = array(
    '#type' => 'submit',
    '#value' => t('Delete finder'),
  );
  $form['actions']['cancel'] = array(
    '#markup' => l(t('Cancel'), 'admin/structure/finder'),
  );
  return $form;
}

/**
 * Validate function for admin finder add/edit page.
 */
function finder_admin_edit_validate($form, &$form_state) {
  $values =& $form_state['values'];
  $arg_sep = preg_replace("/[\\/\\-\\_\\s]/", "", $values['settings']['advanced']['arg_sep']);
  if (!$arg_sep) {
    form_set_error('arg_sep', t('Multiple value URL arguments separator must contain at least one character that is not a space ( ), forward-slash (/), hyphen (-), or underscore (_).'));
  }
  if (!empty($values['settings']['advanced']['empty_symbol'])) {
    $empty_symbol = preg_replace("/[\\/\\-\\_\\s]/", "", $values['settings']['advanced']['empty_symbol']);
    if (!$empty_symbol) {
      form_set_error('arg_sep', t('Empty value URL arguments symbol must contain at least one character that is not a space ( ), forward-slash (/), hyphen (-), or underscore (_).'));
    }
    if ($arg_sep == $empty_symbol) {
      form_set_error('empty_symbol', t('The "empty value URL arguments symbol" should not be the same as the "multiple value URL arguments separator".'));
    }
  }
}

/**
 * Submit function for admin finder add/edit page.
 */
function finder_admin_edit_submit($form, &$form_state) {
  $values =& $form_state['values'];
  if ($form_state['clicked_button']['#id'] == 'edit-actions-delete') {
    drupal_goto('admin/structure/finder/' . $values['finder_id'] . '/delete');
  }
  else {
    $finder = (object) array(
      'finder_id' => $values['finder_id'],
      'base' => $values['base'],
      'title' => $values['title'],
      'description' => $values['description'],
      'path' => $values['path'],
      'block' => $values['block'],
      'settings' => $values['settings'],
    );
    finder_save($finder);
    if (isset($values['elements']) && is_array($values['elements'])) {
      foreach ($values['elements'] as $finder_element_id => $value) {
        $finder_element = (object) array(
          'finder_element_id' => $finder_element_id,
          'weight' => $value['weight'],
        );
        finder_element_save($finder_element);
      }
    }
    drupal_set_message(t('The %ft finder was saved.', array(
      '%ft' => $finder->title,
    )));
    menu_rebuild();

    // Clear the finder_find caches for this finder.
    if ($finder->settings['advanced']['cache_finder_find']) {
      $finder = finder_load($finder->finder_id);
      if (!empty($finder->elements)) {
        cache_clear_all('f' . $finder->finder_id . '|', 'cache_finder_find', TRUE);
        foreach ($finder->elements as $element) {
          cache_clear_all('e' . $element->finder_element_id . '|', 'cache_finder_find', TRUE);
        }
        drupal_set_message(t('Cache for the %ft finder was reset.', array(
          '%ft' => $finder->title,
        )));
      }
    }
    if ($values['add_element']) {
      $finder_element = (object) array(
        'finder_id' => $values['finder_id'],
        'element' => $values['add_element'],
      );
      finder_element_save($finder_element);
      $finder_element->title = t('Finder element !1', array(
        '!1' => $finder_element->finder_element_id,
      ));
      finder_element_save($finder_element);
      drupal_set_message(t('A finder element was added.  Configure the element below.'));
      drupal_goto('admin/structure/finder/' . $values['finder_id'] . '/' . $finder_element->finder_element_id);
    }
    else {
      drupal_goto('admin/structure/finder/' . $values['finder_id'] . '/edit/');
    }
  }
}

/**
 * Admin finder delete page.
 */
function finder_admin_delete($form, &$form_state, $finder) {

  // allow modules to change the finder here
  finder_invoke_finderapi($finder, 'finder_admin_delete');
  $form_state['storage']['finder'] = $finder;

  // build the form
  $form['#tree'] = TRUE;
  $form['finder_id'] = array(
    '#type' => 'value',
    '#value' => $finder->finder_id,
  );
  return confirm_form($form, t('Are you sure you want to delete the %ft finder?', array(
    '%ft' => $finder->title,
  )), isset($_GET['destination']) ? $_GET['destination'] : 'admin/structure/finder', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
}

/**
 * Submit function for admin finder delete page.
 */
function finder_admin_delete_submit($form, &$form_state) {
  $finder_id =& $form_state['values']['finder_id'];
  finder_delete($finder_id);
  menu_rebuild();
  drupal_goto('admin/structure/finder');
}

/**
 * Admin finder element add/edit page.
 * Must have a Finder object at this point.
 */
function finder_admin_element_edit($form, &$form_state, $finder, $finder_element_id) {
  $element =& finder_element($finder, $finder_element_id);

  // allow modules to change the element here
  finder_invoke_finderapi($element, 'finder_admin_element_edit', $form, $form_state);
  $module =& $finder->base_handler['#module'];
  $fields = module_invoke($module, 'finder_fields', $finder, $finder_element_id);
  $form_state['storage']['finder'] = $finder;
  $form_state['storage']['finder_element_id'] = $finder_element_id;
  $form_state['storage']['finder_element_defaults'] = $element;
  $form['#tree'] = TRUE;
  $form['finder_id'] = array(
    '#type' => 'value',
    '#value' => $finder->finder_id,
    '#weight' => 0,
  );
  $form['finder_element_id'] = array(
    '#type' => 'value',
    '#value' => $finder_element_id,
    '#weight' => 2,
  );
  $form['element'] = array(
    '#type' => 'select',
    '#title' => t('Element'),
    '#default_value' => $element->element ? $element->element : '',
    '#options' => finder_admin_get_element_options(),
    '#description' => t('The form element to use.'),
    '#required' => TRUE,
    '#weight' => 10,
  );
  $form['title'] = array(
    '#type' => 'textfield',
    '#title' => t('Title'),
    '#default_value' => $element->title ? $element->title : '',
    '#size' => 40,
    '#maxlength' => 255,
    '#required' => TRUE,
    '#weight' => 20,
    '#description' => t('The label on the form element.'),
  );
  $form['settings'] = array(
    '#weight' => 30,
  );
  $form['settings']['form'] = array(
    '#type' => 'fieldset',
    '#title' => t('Form element'),
    '#weight' => 0,
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $form['settings']['form']['description'] = array(
    '#type' => 'textfield',
    '#title' => t('Description'),
    '#default_value' => isset($element->settings['form']['description']) ? $element->settings['form']['description'] : '',
    '#weight' => 10,
    '#description' => t('The description or help message to display with the form element.'),
  );
  $form['settings']['form']['prefix'] = array(
    '#type' => 'text_format',
    '#base_type' => 'textarea',
    '#format' => isset($element->settings['form']['prefix']['format']) ? $element->settings['form']['prefix']['format'] : NULL,
    '#title' => t('Prefix'),
    '#default_value' => isset($element->settings['form']['prefix']['value']) ? $element->settings['form']['prefix']['value'] : '',
    '#weight' => 20,
    '#description' => t('Displayed before the form element.'),
  );
  $form['settings']['form']['suffix'] = array(
    '#type' => 'text_format',
    '#base_type' => 'textarea',
    '#format' => isset($element->settings['form']['suffix']['format']) ? $element->settings['form']['suffix']['format'] : NULL,
    '#title' => t('Suffix'),
    '#default_value' => isset($element->settings['form']['suffix']['value']) ? $element->settings['form']['suffix']['value'] : '',
    '#weight' => 30,
    '#description' => t('Displayed after the form element.'),
  );
  $form['settings']['form']['default_value'] = array(
    '#type' => 'textfield',
    '#title' => t('Default value'),
    '#default_value' => isset($element->settings['form']['default_value']) ? $element->settings['form']['default_value'] : '',
    '#weight' => 40,
    '#description' => t('Default value of the form element.'),
  );
  $form['settings']['form']['required'] = array(
    '#type' => 'checkbox',
    '#title' => t('Required'),
    '#default_value' => isset($element->settings['form']['required']) ? $element->settings['form']['required'] : 0,
    '#weight' => 50,
    '#description' => t('Enforce user input in this field.'),
  );
  $form['settings']['choices'] = array(
    '#type' => 'fieldset',
    '#title' => t('Possible choices'),
    '#weight' => 60,
    '#collapsible' => TRUE,
    '#collapsed' => FALSE,
  );
  if ($fields) {
    $form['settings']['choices']['field'] = array(
      '#type' => 'select',
      '#title' => t('Finder field'),
      '#default_value' => $element->settings['choices']['field'],
      '#options' => $fields,
      '#description' => t('This is the field that will be searched on (filtered).  If you pick multiple fields; performance will be affected.  This field will also be displayed in choices lists (if applicable), however often the raw values of this field are unacceptable for human readability, you can overcome this with PHP by using a computed field, using rewrite options below (if applicable), or through theming.'),
      '#weight' => 20,
      '#required' => TRUE,
      '#multiple' => TRUE,
      '#size' => min(12, count($fields) + 1),
    );
  }
  else {
    $form['settings']['choices']['no_field'] = array(
      '#markup' => t("<em>There are currently no fields to choose from.</em>"),
      '#weight' => 20,
    );
  }
  $form['settings']['choices']['sort'] = array(
    '#type' => 'checkbox',
    '#title' => t('Sort options'),
    '#default_value' => isset($element->settings['choices']['sort']) ? $element->settings['choices']['sort'] : 0,
    '#weight' => 100,
    '#description' => t('Will put the list into order for easier scanning.'),
  );
  $form['settings']['advanced'] = array(
    '#type' => 'fieldset',
    '#title' => t('Submitted values'),
    '#weight' => 500,
    '#collapsible' => TRUE,
    '#collapsed' => TRUE,
  );
  $form['settings']['advanced']['delimit'] = array(
    '#type' => 'textfield',
    '#title' => t('Treat delimited values as separate keywords upon submission'),
    '#default_value' => isset($element->settings['advanced']['delimit']) ? $element->settings['advanced']['delimit'] : '',
    '#weight' => 10,
    '#description' => t('For example, if you type a space here, the submitted value will be expanded into a value for each word.  Leave empty to disable this feature.'),
  );
  $form['settings']['advanced']['field_combination'] = array(
    '#type' => 'radios',
    '#title' => t('Multiple field result combination'),
    '#default_value' => isset($element->settings['advanced']['field_combination']) ? $element->settings['advanced']['field_combination'] : 0,
    '#weight' => 20,
    '#description' => t('With multiple fields being select above, how should the fields be combined when calculating results?'),
    '#options' => array(
      // I know these choices are in a different order than on the finder admin
      // page, but that's because the first option is the more appropriate
      // default in both cases.
      0 => t('<em>Disjunction</em> - Match <em>any</em> field using the OR operator.'),
      1 => t('<em>Conjunction</em> - Match <em>all</em> fields using the AND operator.'),
    ),
  );
  $form['settings']['advanced']['value_combination'] = array(
    '#type' => 'radios',
    '#title' => t('Multiple value result combination'),
    '#default_value' => isset($element->settings['advanced']['value_combination']) ? $element->settings['advanced']['value_combination'] : 0,
    '#weight' => 25,
    '#description' => t('With multiple submitted values for this element, how should the values be combined when calculating results?'),
    '#options' => array(
      // I know these choices are in a different order than on the finder admin
      // page, but that's because the first option is the more appropriate
      // default in both cases.
      0 => t('<em>Disjunction</em> - Match <em>any</em> value using the OR operator.'),
      1 => t('<em>Conjunction</em> - Match <em>all</em> values using the AND operator.'),
    ),
  );
  $form['settings']['advanced']['nesting_order'] = array(
    '#type' => 'radios',
    '#title' => t('Multiple field/value nesting order'),
    '#default_value' => isset($element->settings['advanced']['nesting_order']) ? $element->settings['advanced']['nesting_order'] : 0,
    '#weight' => 30,
    '#description' => t('With multiple values or fields, how should fields and values be matched together?  This is difficult to explain.  Suppose you have an element that selects two fields and a user submits two values (X and Y), the first option here will do matching like this: <em>(field_1 matches X; field_2 matches X), (field_1 matches Y; field_2 matches Y)</em> whereas the second will do it like this: <em>(field_1 matches X, field_1 matches Y); (field_2 matches X, field_2 matches Y)</em>.  The semicolons represent <em>multiple field result combination</em>, the commas represent <em>multiple value result combination</em>, and the word <em>matches</em> refers to the <em>result matching</em> option below.  So simple.'),
    '#options' => array(
      0 => t('Match multiple fields for each value first, then combine the results of multiple values. (recommended)'),
      1 => t('Match multiple values for each field first, then combine the results of multiple fields.'),
    ),
  );
  $operators = finder_condition_args();
  foreach ($operators as $k => $v) {
    $operators[$k] = finder_condition_args_label($v, t('results'), t('submitted values'));
  }
  $form['settings']['advanced']['match'] = array(
    '#type' => 'radios',
    '#title' => t('Result matching'),
    '#default_value' => isset($element->settings['advanced']['match']) ? $element->settings['advanced']['match'] : 'e',
    '#options' => $operators,
    '#weight' => 60,
    '#description' => t('<em>Equals</em> is the most common result matching method. <a href="!url">Configure custom matching</a>.', array(
      '!url' => url('admin/structure/finder/custom_matching'),
    )),
  );
  $form['actions'] = array(
    '#type' => 'actions',
    '#weight' => 100,
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save finder element'),
  );
  $form['actions']['delete'] = array(
    '#type' => 'submit',
    '#value' => t('Delete finder element'),
  );
  $form['actions']['cancel'] = array(
    '#markup' => l(t('Cancel'), 'admin/structure/finder/' . $finder->finder_id . '/' . $finder_element_id),
  );
  return $form;
}

/**
 * Submit function for admin finder add/edit page.
 */
function finder_admin_element_edit_submit($form, &$form_state) {
  $values =& $form_state['values'];
  if ($form_state['clicked_button']['#id'] == 'edit-actions-delete') {
    drupal_goto('admin/structure/finder/' . $values['finder_id'] . '/' . $values['finder_element_id'] . '/delete');
  }
  else {
    $finder_element = (object) array(
      'finder_element_id' => $values['finder_element_id'],
      'finder_id' => $values['finder_id'],
      'element' => $values['element'],
      'title' => $values['title'],
      'weight' => isset($values['weight']) ? $values['weight'] : NULL,
      'settings' => $values['settings'],
    );
    finder_element_save($finder_element);
    drupal_set_message(t('The finder element was saved.'));
    drupal_goto('admin/structure/finder/' . $values['finder_id'] . '/edit');
  }
}

/**
 * Admin finder delete page
 */
function finder_admin_element_delete($form, &$form_state, $finder, $finder_element_id) {
  $element =& finder_element($finder, $finder_element_id);

  // allow modules to change the element here
  finder_invoke_finderapi($element, 'finder_admin_element_delete');
  $form['#tree'] = TRUE;
  $form['finder_element_id'] = array(
    '#type' => 'value',
    '#value' => $finder_element_id,
  );
  $form['finder_id'] = array(
    '#type' => 'value',
    '#value' => $finder->finder_id,
  );
  return confirm_form($form, t('Are you sure you want to delete the finder element %fet ?', array(
    '%fet' => $element->title,
  )), isset($_GET['destination']) ? $_GET['destination'] : 'admin/structure/finder/' . $finder->finder_id . '/edit', t('This action cannot be undone.'), t('Delete'), t('Cancel'));
}

/**
 * Submit function for admin finder delete page.
 */
function finder_admin_element_delete_submit($form, &$form_state) {
  $finder_element_id =& $form_state['values']['finder_element_id'];
  $finder_id =& $form_state['values']['finder_id'];
  finder_element_delete($finder_element_id);
  drupal_goto('admin/structure/finder/' . $finder_id . '/edit');
}

/**
 * Get base handlers and convert to options array.
 */
function finder_admin_get_base_options() {
  $bases = finder_base_handlers();
  $base_options = array(
    '' => t('- Select a finder type -'),
  );
  if (!empty($bases)) {
    foreach ($bases as $base_key => $base_data) {
      $base_options[$base_key] = $base_data['#title'];
    }
  }
  else {
    drupal_set_message(t('Error: You must activate a finder base handler module such as Finder Views or Finder Node to begin.'), 'error');
    return array(
      '' => t('- No finder types to choose from -'),
    );
  }
  return $base_options;
}

/**
 * Get element handlers and convert to options array.
 */
function finder_admin_get_element_options() {
  $elements = finder_element_handlers();
  $element_options = array(
    '' => t('- Select an element type -'),
  );
  if (!empty($elements)) {
    foreach ($elements as $element_key => $element_data) {
      $element_options[$element_key] = t($element_data['#title']);
    }
  }
  else {
    drupal_set_message(t('Error: You must activate a finder element handler module such as Finder Autocomplete or Finder Optionwidgets to begin.'), 'error');
    return array(
      '' => t('- No element types to choose from -'),
    );
  }
  return $element_options;
}

/**
 * Admin finder import page.
 */
function finder_admin_import() {
  global $user;
  if (isset($_POST['finder_code']) && !empty($_POST['finder_code'])) {
    $finder_code = trim($_POST['finder_code']);
    $import = finder_import($finder_code);
    if (is_array($import)) {
      foreach ($import as $finder) {
        finder_invoke_finderapi($finder, 'finder_import');

        // Handle custom matching.
        finder_admin_import_custom_matching($import);
        $new_finder = finder_clone($finder);
        drupal_set_message(t('Imported !finder', array(
          '!finder' => l($new_finder->title, 'admin/structure/finder/' . $new_finder->finder_id . '/edit'),
        )));
      }
      drupal_goto('admin/structure/finder');
    }
    else {
      finder_invoke_finderapi($import, 'finder_import');

      // Handle custom matching.
      finder_admin_import_custom_matching($import);
      $new_finder = finder_clone($import);
      drupal_set_message(t('Imported !finder', array(
        '!finder' => l($new_finder->title, 'admin/structure/finder/' . $new_finder->finder_id . '/edit'),
      )));
      drupal_goto('admin/structure/finder/' . $new_finder->finder_id . '/edit');
    }
  }
  return drupal_get_form('finder_admin_import_form');
}

/**
 * Admin finder import form.
 */
function finder_admin_import_form($form, &$form_state) {
  $form['#prefix'] = t('<p>You may import a finder by copy-and-pasting the results of an exported finder. </p>');
  $form['finder_code'] = array(
    '#type' => 'textarea',
    '#title' => t('Finder code'),
    '#default_value' => '',
    '#required' => TRUE,
    '#rows' => 30,
    '#description' => t('Paste the finder code here.'),
  );
  $form['#redirect'] = FALSE;
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Import'),
  );
  return $form;
}

/**
 * Admin finder export page.
 *
 * Set $return_code to TRUE to not return form but the code instead.
 */
function finder_admin_export($original_finder, $return_code = FALSE) {
  $finder = clone $original_finder;
  drupal_set_title(t('Export of !title', array(
    '!title' => check_plain($finder->title),
  )));

  // Handle custom matching.
  finder_admin_export_custom_matching($finder);
  finder_invoke_finderapi($finder, 'finder_export');
  $finder_code = finder_export($finder);
  return $return_code ? $finder_code : drupal_get_form('finder_admin_export_form', $finder_code);
}

/**
 * Admin finder export form.
 */
function finder_admin_export_form($form, &$form_state, $code) {
  $form['export'] = array(
    '#type' => 'textarea',
    '#title' => t('Finder code'),
    '#default_value' => $code,
    '#rows' => 30,
    '#description' => t('Copy this code and then on the site you want to import to, go to the "Finder import" link on the finder admin page, and paste it in there.'),
    '#attributes' => array(
      'style' => 'width: 97%;',
    ),
  );
  return $form;
}

/**
 * Finder admin custom matching configuration page.
 */
function finder_admin_custom_matching($form, &$form_state) {
  $form['#tree'] = TRUE;

  // This page is styled.
  $form['#attributes']['class'][] = 'finder-custom-matching';
  drupal_add_css(drupal_get_path('module', 'finder') . '/finder.css');
  $form['intro']['#markup'] = '<p>' . t('This page allows you to configure custom matching methods for use in finder configuration.  Presented here for reference are the default matching methods built into finder.  At the bottom of the page you will find two blank rows where you can create new matching methods.  To remove a custom row, delete the name and save the form.') . '</p>';

  // Add the default rows.
  $default_matching = finder_condition_args_default();
  foreach ($default_matching as $k => $v) {
    finder_admin_custom_matching_entry($form, $k, $v, TRUE);
  }

  // Add the configured custom rows.
  $custom_matching = variable_get('finder_custom_matching', array());
  foreach ($custom_matching as $k => $v) {
    finder_admin_custom_matching_entry($form, $k, $v, FALSE);
  }

  // Add two more rows.
  $more = array();
  $custom = 0;
  while (count($more) < 2) {
    if (!isset($custom_matching['c' . $custom])) {
      $more['c' . $custom] = array();
    }
    $custom++;
  }
  foreach ($more as $k => $v) {
    finder_admin_custom_matching_entry($form, $k, $v, FALSE);
  }
  $form['actions'] = array(
    '#type' => 'actions',
  );
  $form['actions']['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Save custom matching'),
  );
  return $form;
}

/**
 * Build the form for a single entry.
 *
 * @param &$form
 *  Reference to the form array to add the form to.
 * @param $key
 *  The key of the match entry.
 * @param $value
 *  The value of the match entry.
 * @param $default
 *  Boolean indicating whether this is a default entry (vs. custom).
 */
function finder_admin_custom_matching_entry(&$form, $key, $value, $default) {
  $form[$key] = array(
    '#type' => 'fieldset',
  );
  $form[$key]['name'] = array(
    '#type' => 'textfield',
    '#title' => t('Name'),
    '#default_value' => isset($value['name']) ? $value['name'] : '',
    '#size' => 20,
    '#maxlength' => 128,
    '#disabled' => $default,
    '#field_suffix' => isset($value['name']) ? '<small class="finder-condition-machine-name"> (' . t('Machine name') . ': ' . $key . ')</small>' : '',
    '#description' => $default ? '' : (isset($value['name']) ? t('Clear name to delete row.') : t('Enter name to create row.')),
  );
  $form[$key]['description'] = array(
    '#type' => 'textfield',
    '#title' => t('Description'),
    '#default_value' => isset($value['description']) ? $value['description'] : '',
    '#size' => 60,
    '#maxlength' => 512,
    '#disabled' => $default,
    '#description' => $default ? '' : t('Explain, in these terms, how <em>!matches</em> relates to <em>!keywords</em>.'),
  );
  $form[$key]['operator'] = array(
    '#type' => 'textfield',
    '#title' => t('Operator'),
    '#default_value' => isset($value['operator']) ? $value['operator'] : '',
    '#size' => ($x = isset($value['operator']) ? min(drupal_strlen($value['operator']), 30) : 5) ? $x : 1,
    '#maxlength' => 512,
    '#field_prefix' => "'" . t('field') . "'",
    '#disabled' => $default,
    '#prefix' => '<div class="finder-condition"><span class="finder-condition-operator">',
    '#suffix' => '</span>',
  );
  $form[$key]['value_prefix'] = array(
    '#type' => 'textfield',
    '#title' => t('Prefix'),
    '#default_value' => isset($value['value_prefix']) ? $value['value_prefix'] : '',
    '#size' => ($x = isset($value['value_prefix']) ? min(drupal_strlen($value['value_prefix']), 30) : 3) ? $x : 1,
    '#maxlength' => 512,
    '#field_suffix' => t('value'),
    '#disabled' => $default,
    '#prefix' => '<span class="finder-condition-value-prefix">',
    '#suffix' => '</span>',
  );
  $form[$key]['value_suffix'] = array(
    '#type' => 'textfield',
    '#title' => t('Suffix'),
    '#default_value' => isset($value['value_suffix']) ? $value['value_suffix'] : '',
    '#size' => ($x = isset($value['value_suffix']) ? min(drupal_strlen($value['value_suffix']), 30) : 3) ? $x : 1,
    '#maxlength' => 512,
    '#disabled' => $default,
    '#prefix' => '<span class="finder-condition-value-suffix">',
    '#suffix' => '</span></div>',
  );
}

/**
 * Submit function for finder admin custom matching configuration page.
 */
function finder_admin_custom_matching_submit($form, &$form_state) {
  $values = $form_state['values'];
  unset($values['actions']);
  $defaults = array_keys(finder_condition_args_default());
  foreach ($defaults as $key) {
    if (isset($values[$key])) {
      unset($values[$key]);
    }
  }
  $custom_matching = array();
  foreach ($values as $key => $value) {
    if (is_array($value) && isset($value['name']) && !empty($value['name'])) {
      $custom_matching[$key] = $value;
    }
  }
  variable_set('finder_custom_matching', $custom_matching);
}

/**
 * Handle custom matching in imports.
 */
function finder_admin_import_custom_matching(&$finder) {

  // Handle custom matching.
  $custom_matching = variable_get('finder_custom_matching', array());
  foreach ($finder->elements as $feid => &$element) {
    $match =& $element->settings['advanced']['match'];
    if (is_array($match)) {
      $match_data = reset($match);
      $found_key = FALSE;
      foreach ($custom_matching as $custom_key => $custom_match) {
        if ($custom_match['operator'] == $match_data['operator'] && $custom_match['value_prefix'] == $match_data['value_prefix'] && $custom_match['value_suffix'] == $match_data['value_suffix']) {
          $found_key = $custom_key;
        }
      }
      if ($found_key) {
        $match = $found_key;
      }
      else {
        $new = NULL;
        $custom = 0;
        while (is_null($new)) {
          if (!isset($custom_matching['c' . $custom])) {
            $new = array(
              'c' . $custom,
            );
            break;
          }
          $custom++;
        }
        $custom_matching[$new] = $custom_match;
        $match = $new;
      }
    }
  }
  variable_set('finder_custom_matching', $custom_matching);
}

/**
 * Handle custom matching in exports.
 */
function finder_admin_export_custom_matching(&$finder) {

  // Change how match method is stored to support custom matching.
  $custom_matching = variable_get('finder_custom_matching', array());
  foreach ($finder->elements as $feid => &$element) {
    $match = $element->settings['advanced']['match'];
    if (isset($custom_matching[$match])) {
      $element->settings['advanced']['match'] = array(
        $match => $custom_matching[$match],
      );
    }
  }
}

Functions

Namesort descending Description
finder_admin_add_form Admin finder add form.
finder_admin_add_form_submit Submit function for admin finder add form.
finder_admin_custom_matching Finder admin custom matching configuration page.
finder_admin_custom_matching_entry Build the form for a single entry.
finder_admin_custom_matching_submit Submit function for finder admin custom matching configuration page.
finder_admin_delete Admin finder delete page.
finder_admin_delete_submit Submit function for admin finder delete page.
finder_admin_edit Admin finder edit page.
finder_admin_edit_submit Submit function for admin finder add/edit page.
finder_admin_edit_validate Validate function for admin finder add/edit page.
finder_admin_element_delete Admin finder delete page
finder_admin_element_delete_submit Submit function for admin finder delete page.
finder_admin_element_edit Admin finder element add/edit page. Must have a Finder object at this point.
finder_admin_element_edit_submit Submit function for admin finder add/edit page.
finder_admin_export Admin finder export page.
finder_admin_export_custom_matching Handle custom matching in exports.
finder_admin_export_form Admin finder export form.
finder_admin_get_base_options Get base handlers and convert to options array.
finder_admin_get_element_options Get element handlers and convert to options array.
finder_admin_import Admin finder import page.
finder_admin_import_custom_matching Handle custom matching in imports.
finder_admin_import_form Admin finder import form.
finder_admin_list Admin finder list page.