finder_views.module

  1. finder
    1. 6.x-1.x
    2. 7.x-1.x

Version 1.1.2.56 (checked in on 2011/02/12 at 06:55:19 by danielb)

The finder views module.

Functions & methods

NameDescription
finder_views_finder_base_handlersImplements hook_finder_base_handlers().
finder_views_finder_fieldsImplements hook_finder_fields().
finder_views_finder_findImplements hook_finder_find().
finder_views_finder_gotoImplements hook_finder_goto().
finder_views_finder_resultImplements hook_finder_result().
finder_views_form_finder_admin_edit_alterImplements hook_form_FORM_ID_alter().
finder_views_form_finder_admin_element_edit_alterImplements hook_form_FORM_ID_alter().
finder_views_get_argsConvert finder arguments text field entry to an array of arguments.
finder_views_get_displaysGet an array of content types for use in select forms.
finder_views_get_element_argsGet element arguments.
finder_views_get_finder_argsGet finder arguments.
finder_views_get_viewsGet an array of content types for use in select forms.
finder_views_pathGet the raw link to an object given the table and id.
finder_views_themeImplements hook_theme().
finder_views_views_apiImplements hook_views_api().
finder_views_views_query_alterImplements hook_views_query_alter().
finder_view_get_relationshipsGet an array of relationships for use in admin screens.
theme_finder_views_resultsTheme the views finder results.
View source
<?php
// $Id: finder_views.module,v 1.1.2.56 2011/02/12 06:55:19 danielb Exp $

/**
 * @file
 * The finder views module.
 */

/**
 * Implements hook_views_api().
 *
 * @see hook_views_api()
 */
function finder_views_views_api() {
  return array(
    'api' => 3,
    'path' => finder_inc_path('finder_views'),
  );
}

/**
 * Implements hook_theme().
 *
 * @see hook_theme()
 */
function finder_views_theme() {
  return array(
    'finder_views_results' => array(
      'arguments' => array(
        'result' => NULL,
        'finder' => NULL,
        'form_state' => NULL,
      ),
    ),
  );
}

/**
 * Implements hook_finder_base_handlers().
 *
 * @see hook_finder_base_handlers()
 */
function finder_views_finder_base_handlers() {
  return array(
    'views' => array(
      '#title' => t('Views finder'),
      '#module' => 'finder_views',
    ),
  );
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * @see hook_form_FORM_ID_alter()
 */
function finder_views_form_finder_admin_edit_alter(&$form, $form_state) {
  $finder = &$form_state['storage']['finder'];
  if ($finder->base == 'views') {
    $form['settings']['advanced']['pager']['#description'] .=
      ' ' . t('For the results pager to work properly, ensure your Views display has "Items per page" set to "unlimited".');
    $form['settings']['views'] = array(
      '#type' => 'fieldset',
      '#title' => t('Views'),
      '#weight' => 80,
      '#collapsible' => TRUE,
      '#collapsed' => FALSE,
    );
    if ($views = finder_views_get_views()) {
      $form['settings']['views']['view'] = array(
        '#type' => 'select',
        '#title' => t('Find items from this view'),
        '#default_value' => $finder->settings['views']['view'] ? $finder->settings['views']['view'] : '',
        '#options' => $views,
        '#required' => TRUE,
        '#weight' => 10,
      );

      $form['settings']['views']['displays'] = array(
        '#type' => 'fieldset',
        '#title' => t('Views displays'),
        '#weight' => 20,
        '#collapsible' => TRUE,
        '#collapsed' => TRUE,
        '#description' => t('Leaving these set to "Defaults" is perfectly suitable in most cases.'),
      );

      $displays = finder_views_get_displays($finder->settings['views']['view']);

      $form['settings']['views']['displays']['query'] = array(
        '#type' => 'select',
        '#title' => t('Query display'),
        '#default_value' => $finder->settings['views']['displays']['query'] ? $finder->settings['views']['displays']['query'] : 'default',
        '#options' => $displays,
        '#required' => TRUE,
        '#weight' => 10,
        '#description' => t('Allows you to use a specific display to calculate results, you can use this to add sort/filter settings via Views that do not affect the element choices.'),
      );

      $form['settings']['views']['displays']['output'] = array(
        '#type' => 'select',
        '#title' => t('Output display'),
        '#default_value' => $finder->settings['views']['displays']['output'] ? $finder->settings['views']['displays']['output'] : 'default',
        '#options' => $displays,
        '#required' => TRUE,
        '#weight' => 20,
        '#description' => t('Allows you to use a specific display to output the results page, you can use this to change output settings via Views that do not affect the element choices.'),
      );

      if (count($displays) === 1) {
        $form['settings']['views']['displays']['query']['#disabled'] = TRUE;
        $form['settings']['views']['displays']['output']['#disabled'] = TRUE;
      }

      $form['settings']['views']['results'] = array(
        '#type' => 'radios',
        '#title' => t('Results page'),
        '#default_value' => $finder->settings['views']['results'] ? $finder->settings['views']['results'] : 0,
        '#weight' => 40,
        '#description' => t('"Output display" is configured under the "Views displays" fieldset above.  Custom results page can be themed using theme_finder_views_results($results, $finder, $form_state).'),
        '#options' => array(
          0 => t('Build results page from "Output display".'),
          1 => t('Build custom results page.'),
        ),
      );
      $relationships = finder_view_get_relationships($finder);
      if (!empty($relationships)) {
        $form['settings']['views']['relationships'] = array(
          '#type' => 'fieldset',
          '#title' => t('Relationships'),
          '#weight' => 70,
          '#collapsible' => TRUE,
          '#collapsed' => TRUE,
          '#description' => t('If any fields in your finder rely on relationships, here is where you inform finder of this.'),
        );
        $fields = finder_views_finder_fields($finder, 0);
        foreach ($relationships as $rel_key => $rel_label) {
          $form['settings']['views']['relationships'][$rel_key] = array(
            '#type' => 'select',
            '#title' => $rel_label,
            '#default_value' => $finder->settings['views']['relationships'][$rel_key] ? $finder->settings['views']['relationships'][$rel_key] : array(),
            '#options' => $fields,
            '#multiple' => TRUE,
            '#size' => min(count($fields) + 1, 20),
            '#description' => t('Select the fields that use the relationship %rel.  You do not need to select fields that are not used in this finder.', array('%rel' => $rel_label)),
          );
        }
      }
      $form['settings']['views']['views_args'] = array(
        '#type' => 'fieldset',
        '#title' => t('Views arguments'),
        '#weight' => 80,
        '#collapsible' => TRUE,
        '#collapsed' => TRUE,
        '#description' => t('Restrict results using arguments.  These arguments will not apply to element choices - use with caution.'),
      );
      $form['settings']['views']['views_args']['args'] = finder_php_setting(
        array(
          '#type' => 'textarea',
          '#default_value' => isset($finder->settings['views']['views_args']['args']) ? $finder->settings['views']['views_args']['args'] : '',
          '#title' => t('Arguments'),
          '#rows' => 1,
          '#description' => t('
            You can provide a list of arguments seperated by a delimiter.
            e.g: <em>term_1/term_2</em>.<br />Or insert PHP code to generate the
            list of arguments. e.g: <em>term_1/&lt;?php print "term_x/term_y";
            ?&gt;/term_2</em>.'),
        ),
        array(
          'finder' => t('Object containing data about this finder.'),
        )
      );
      $form['settings']['views']['views_args']['delimiter'] = array(
        '#type' => 'textfield',
        '#default_value' => isset($finder->settings['views']['views_args']['delimiter']) ? $finder->settings['views']['views_args']['delimiter'] : '/',
        '#title' => t('Delimiter'),
        '#size' => 5,
        '#maxlength' => 10,
        '#description' => t('This is the character used to split multiple arguments above.'),
        '#required' => TRUE,
      );
      $form['settings']['views']['empty_text'] = array(
        '#type' => 'checkbox',
        '#title' => t('Show view display when there are no results'),
        '#default_value' => $finder->settings['views']['empty_text'],
        '#weight' => 50,
        '#description' => t("Use the view display's empty text instead of finder's no results output."),
      );
    }
    else {
      $form['settings']['views']['no_view'] = array(
        '#value' => t("<em>There are currently no views to choose from.</em>"),
        '#weight' => 10,
      );
    }
  }
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * @see hook_form_FORM_ID_alter()
 */
function finder_views_form_finder_admin_element_edit_alter(&$form, $form_state) {
  $finder = &$form_state['storage']['finder'];
  if ($finder->base == 'views') {
    $element = &$form_state['storage']['finder_element_defaults'];
    unset($form['settings']['choices']['sort']);

    $form['settings']['choices']['displays'] = array(
      '#type' => 'fieldset',
      '#title' => t('Views displays'),
      '#weight' => 270,
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#description' => t('Leaving this set to "Defaults" is perfectly suitable for most cases.'),
    );

    $displays = finder_views_get_displays($finder->settings['views']['view']);

    $form['settings']['choices']['displays']['query'] = array(
      '#type' => 'select',
      '#title' => t('Query display'),
      '#default_value' => $element->settings['choices']['displays']['query'] ? $element->settings['choices']['displays']['query'] : 'default',
      '#options' => $displays,
      '#required' => TRUE,
      '#weight' => 10,
      '#description' => t('
          Allows you to use a specific display to calculate the choices list,
          you can use this to add sort/filter settings via Views that do not
          affect other elements or the results.'),
    );

    $form['settings']['choices']['views'] = array(
      '#type' => 'fieldset',
      '#title' => t('Views arguments'),
      '#weight' => 280,
      '#collapsible' => TRUE,
      '#collapsed' => TRUE,
      '#description' => t('Restrict possible choices using arguments.  These arguments will not apply to the results - use with caution.'),
    );

    $form['settings']['choices']['views']['args'] = finder_php_setting(
      array(
        '#type' => 'textarea',
        '#default_value' => isset($element->settings['choices']['views']['args']) ? $element->settings['choices']['views']['args'] : '',
        '#title' => t('Arguments'),
        '#rows' => 1,
        '#description' => t('
          You can provide a list of arguments seperated by a delimiter.
          e.g: <em>term_1/term_2</em>.<br />Or insert PHP code to generate the
          list of arguments. e.g: <em>term_1/&lt;?php print "term_x/term_y";
          ?&gt;/term_2</em>. (Variables available: $finder_element)'),
      ),
      array(
        'finder' => t('Object containing data about this finder.'),
      )
    );
    $form['settings']['choices']['views']['delimiter'] = array(
      '#type' => 'textfield',
      '#default_value' => isset($element->settings['choices']['views']['delimiter']) ? $element->settings['choices']['views']['delimiter'] : '/',
      '#title' => t('Delimiter'),
      '#size' => 5,
      '#maxlength' => 10,
      '#description' => t('This is the character used to split multiple arguments above.'),
      '#required' => TRUE,
    );
  }
}

/**
 * Implements hook_finder_fields().
 *
 * @see hook_finder_fields()
 */
function finder_views_finder_fields($finder, $finder_element_id) {
  if ($view = views_get_view($finder->settings['views']['view'])) {
    views_include('admin');
    $display = $view->add_display('finder_views');
    $view->set_display($display);
    $base_tables = $view->get_base_tables();
    $options = views_fetch_fields(array_keys($base_tables), 'field');
    foreach ($options as $k => $v) {
      $options[$k] = $v['group'] . ': ' . $v['title'];
    }
    return $options;
  }
  return FALSE;
}

/**
 * Get an array of content types for use in select forms.
 */
function finder_views_get_views() {
  $views = array('' => ' - ' . t('Select a view') . ' - ');
  $all_views = views_get_all_views();
  if (!empty($all_views)) {
    foreach ($all_views as $view) {
      if ($view->type == 'Default') {
        $views[t('Default Views')][$view->name] = $view->name;
      }
      else {
        $views[t('Existing Views')][$view->name] = $view->name;
      }
    }
    return $views;
  }
  return FALSE;
}

/**
 * Get an array of content types for use in select forms.
 */
function finder_views_get_displays($view_name = NULL) {
  if (!$view_name) {
    return array('default' => t('Defaults'));
  }
  $options = array();
  $all_views = views_get_all_views();
  $view = $all_views[$view_name];
  foreach ($view->display as $key => $display) {
    $options[$key] = $display->display_title . ' (' . $key . ')';
  }
  return $options;
}

/**
 * Get an array of relationships for use in admin screens.
 */
function finder_view_get_relationships($finder) {
  if ($view = views_get_view($finder->settings['views']['view'])) {
    $options = array();
    $display = $finder->settings['views']['displays']['query'] ? $finder->settings['views']['displays']['query'] : 'default';
    if (isset($view->display[$display]->display_options['relationships'])) {
      foreach ($view->display[$display]->display_options['relationships'] as $rel_key => $rel) {
        $options[$rel_key] = $rel['label'];
      }
    }
    return $options;
  }
  return FALSE;
}

/**
 * Implements hook_finder_find().
 *
 * @see hook_finder_find()
 */
function finder_views_finder_find($finder, $finder_element_id, $keywords, $mode, $match, $pager) {

  $options = array();
  $view_name = &$finder->settings['views']['view'];

  if ($view = views_get_view($view_name)) {

    $view_args = array();

    // We add a display, and let it derive from the 'default' display.
    $display = $view->add_display('finder_views');

    // Change the display options based on 'query display' setting.
    if ($mode == 'results' && $finder->settings['views']['displays']['query']) {
      $custom_display = &$finder->settings['views']['displays']['query'];
    }
    elseif ($mode == 'choices' && $fe = &finder_element($finder, $finder_element_id)
            && $fe->settings['choices']['displays']['query']) {
      $custom_display = &$fe->settings['choices']['displays']['query'];
    }

    if (isset($custom_display) && $custom_display != 'default') {
      $view->display[$display]->display_options = $view->display[$custom_display]->display_options;
    }

    // Activate the display
    $view->set_display($display);

    // For choices, remove all the currently added fields.
    // This prevents problems with the 'group by' clauses.
    if ($mode == 'choices') {
      // Get a list of currently added fields.
      $fields = $view->get_items('field', $display);
      foreach ($fields as $key => $field) {
        $view->set_item($display, 'field', $field['id'], NULL);
        unset($fields[$key]);
      }
    }

    $view->display_handler->set_option('style_plugin', 'finder_views_php_array_finder');

    $view->display_handler->set_option('row_plugin', 'fields');

    $field_info = array();

    foreach ($keywords as $feid => $keyword_array) {

      if ($mode == 'choices' && $feid == $finder_element_id) {
        $element = &finder_element($finder, $feid);

        // Select the 'choices' field.
        $element_fields = &$element->settings['choices']['field'];
        foreach ($element_fields as $key => $field) {
          $field_info[$feid][$key] = finder_split_field($field);
          $field_alias = finder_field_alias($feid, $field_info[$feid][$key]['table'], $field_info[$feid][$key]['field']);
          $view->add_item($display, 'field', $field_info[$feid][$key]['table'], $field_info[$feid][$key]['field'], array(), $field_alias);
          $groups[] = $field_alias;
        }
        // Add element args for 'choices'.
        $view_args = finder_views_get_element_args($element);

      }

      // Remove empty keyword strings.
      $keywords[$feid] = array_filter((array)$keywords[$feid], 'finder_empty_keyword');
      // Remove blank keyword array.
      if (empty($keywords[$feid])) {
        unset($keywords[$feid]);
      }

    }

    $options = array(
      'finder' => $finder,
      'finder_element_id' => $finder_element_id,
      'keywords' => $keywords,
      'mode' => $mode,
      'match' => $match,
      'groups' => isset($groups) ? $groups : array(),
    );

    $view->display_handler->set_option('finder_views_options', $options);

    // Save $field_info into the view, so we can use it in the display and style plugins.
    $view->display_handler->set_option('finder_views_field_info', $field_info);

    // Limit result set size.
    if (isset($pager)) {
      $view->display_handler->set_option('use_pager', TRUE);
      $view->display_handler->set_option('items_per_page', $pager);
      $pager_element = ($mode == 'results') ? 0 : 'finder_choices_'. $finder_element_id;
      $view->display_handler->set_option('pager_element', $pager_element);
    }

    if ($mode == 'results') {
      $view_args = finder_views_get_finder_args($finder);
      // Limit result for redirect.
      if (isset($finder->go) && $finder->go) {
        $view->display_handler->set_option('use_pager', TRUE);
        $view->display_handler->set_option('items_per_page', 1);
        $view->display_handler->set_option('pager_element', 0);
      }
    }

    // Make sure the query is not cached
    $view->is_cacheable = FALSE;

    $view->build($display);

    $result = $view->execute_display($display, $view_args);

  }
  else {
    $result = FALSE;
  }

  return $result;

}

/**
 * Implements hook_finder_result().
 *
 * @see hook_finder_result()
 */
function finder_views_finder_result($finder, $keywords, $results, $form_state) {
  $output = '';
  if ($results || $finder->settings['views']['empty_text']) {
    if ($finder->settings['views']['results']) {
      $output .= theme('finder_views_results', $results, $finder, $form_state);
    }
    else {
      $args = array();
      $view = views_get_view($finder->settings['views']['view']);

      $display_id = 'default';
      if ($finder->settings['views']['displays']['output']) {
        $display_id = $finder->settings['views']['displays']['output'];
      }
      $view->set_display($display_id);
      $view->set_arguments($args);
      $view->is_cacheable = FALSE;

      $view->display_handler->set_option('use_pager', 0);

      // compile ids so that finder_views_views_query_alter() knows what to do
      $ids = array();
      foreach ($results as $result) {
        $ids[] = $result->{$result->base_field};
      }
      $view->finder_ids = $ids;
      $view->preview();
      $output .= $view->render($display_id);
    }
  }
  return $output;
}

/**
 * Implements hook_views_query_alter().
 *
 * @see hook_views_query_alter()
 */
function finder_views_views_query_alter($view, &$query) {
  if (isset($view->finder_ids)) {
    $alias = $query->ensure_table($view->base_table);
    $query->add_where(NULL, $alias .'.'. $view->base_field .' IN ('. db_placeholders($view->finder_ids) .')', $view->finder_ids);
  }
}

/**
 * Implements hook_finder_goto().
 *
 * @see hook_finder_goto()
 */
function finder_views_finder_goto($finder, $result) {
  $id = &$result->{$result->base_field};
  $path = finder_views_path($result->base_table, $id);
  if ($path) {
    if ($result->base_table == 'files') {
      file_download($path);
    }
    drupal_goto($path);
  }
}

/**
 * Get the raw link to an object given the table and id.
 *
 * You would think Drupal or Views would provide this feature? :(
 *
 * @param $table
 *   Base table for this type of object.
 * @param $id
 *   The value of the primary key for this record.
 * @return
 *   A raw path that can be put into url() or l() that can be used to link to
 *   or redirect to the object.
 */
function finder_views_path($table, $id) {
  switch ($table) {
    case 'node':
      $path = 'node/' . $id;
    case 'users':
      $path = 'user/' . $id;
    case 'term_data':
      $path = 'taxonomy/term/' . $id;
    case 'node_revisions':
      $revision = node_load(NULL, $id);
      $path = 'node/' . $revision->nid . '/revisions/' . $id . '/view';
    case 'files':
      $query = 'SELECT filepath FROM {files} f WHERE f.fid = %d';
      $file = db_fetch_object(db_query($query, $id));
      $path = $file->filepath;
  }
  drupal_alter('finder_views_path', $path, $table, $id);
  return $path;
}

/**
 * Theme the views finder results.
 *
 * @param $results
 *   An array of result objects.
 * @param $finder
 *   The finder object.
 * @param $form_state
 *   The Forms API form state.
 */
function theme_finder_views_results($results, $finder, $form_state) {
  $output = '';

  foreach ($results as $key => $result) {

    // Open the results wrapper
    $output .= '<div id="finder-views-result-' . $key . '" class="finder-views-result">';

    // Output the identity of this result object
    $id = &$result->{$result->base_field};
    $path = finder_views_path($result->base_table, $id);
    $id_output = $path ? l($id, $path) : $id;
    $identity = $result->base_table . ', ' . $result->base_field . ': ' . $id_output;
    $output .= '<div class="identity">' . $identity . '</div>';

    // Output a list of finder element titles and the submitted keywords.
    if (!empty($result->field_names)) {
      $keywords = array();
      foreach ($result->field_names as $finder_element_id => $element_fields) {
        $element = &finder_element($finder, $finder_element_id);
        $element_output = '<span class="element-title">'. $element->title .': </span>';
        $element_values = array();
        foreach ($element_fields as $field_name) {
          if (!empty($result->$field_name)) {
            $element_values[] = $result->$field_name;
          }
        }
        $element_output .= implode(', ', $element_values);
        $keywords[] = $element_output;
      }
      $output .= '<div class="keywords">'. implode('<br>', $keywords) .'</div>';
    }

    // Close the results wrapper
    $output .= '</div>';

  }
  return $output;
}

/**
 * Get element arguments.
 *
 * @param $element
 *   The finder element object.
 * @return
 *   The array of views arguments.
 */
function finder_views_get_element_args($element) {
  $variables = array(
    'finder_element' => $element,
  );
  $string = &$element->settings['choices']['views']['args'];
  $delimiter = &$element->settings['choices']['views']['delimiter'];
  return finder_views_get_args($string, $delimiter, $variables);
}

/**
 * Get finder arguments.
 *
 * @param $element
 *   The finder element object.
 * @return
 *   The array of views arguments.
 */
function finder_views_get_finder_args($finder) {
  $variables = array(
    'finder' => $finder,
  );
  $string = &$finder->settings['views']['views_args']['args'];
  $delimiter = &$finder->settings['views']['views_args']['delimiter'];
  return finder_views_get_args($string, $delimiter, $variables);
}

/**
 * Convert finder arguments text field entry to an array of arguments.
 *
 * @param $string
 *   The typed string of arguments, can include PHP code.
 * @param $delimiter
 *   The string by which arguments in $string are delimited.
 * @param $variables
 *   Any variables that should be available to any PHP provided in the input.
 * @return
 *   The array of views arguments.
 */
function finder_views_get_args($string, $delimiter, $variables) {
  $args = array();
  $arguments = finder_eval($string, $variables);
  if ($arguments) {
    $args = explode($delimiter, $arguments);
    foreach ($args as $k => $v) {
      $args[$k] = trim($v);
    }
  }
  return $args;
}

Post new comment

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.

More information about formatting options

Type the characters you see in this picture. (verify using audio)
Type the characters you see in the picture above; if you can't read them, submit the form and a new image will be generated. Not case sensitive.