finder_views.module in Finder 7
Same filename and directory in other branches
The finder views module.
File
modules/finder_views/finder_views.moduleView 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(
'variables' => array(
'results' => 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().'),
'#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' => isset($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/<?php print "term_x/term_y";
?>/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/<?php print "term_x/term_y";
?>/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();
$views_fields = views_fetch_fields(array_keys($base_tables), 'filter');
$options = array();
foreach ($views_fields as $k => $v) {
$options[$v['group']][$k] = $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);
}
// Temporary hack - rather than doing this, the functions calling finder_find() should set this up?
// or maybe this func should handle the whole thing? i.e. creating the dummy keywords for choices.
// See #1270150.
if (is_null($keywords[$feid])) {
$keywords[$feid][] = NULL;
}
/*
This code is removed because of #1270150.
// 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', array(
'results' => $results,
'finder' => $finder,
'form_state' => $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)) {
if (!empty($view->finder_ids)) {
$alias = $query
->ensure_table($view->base_table);
$query
->add_where(NULL, $alias . '.' . $view->base_field, $view->finder_ids, 'IN');
}
else {
$query
->add_where_expression(NULL, '1=0');
}
}
}
/**
* 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;
break;
case 'users':
$path = 'user/' . $id;
break;
case 'term_data':
$path = 'taxonomy/term/' . $id;
break;
case 'node_revisions':
$revision = node_load(NULL, $id);
$path = 'node/' . $revision->nid . '/revisions/' . $id . '/view';
break;
case 'files':
$path = file_load($id)->uri;
break;
}
drupal_alter('finder_views_path', $path, $table, $id);
return $path;
}
/**
* Theme the views finder results.
*
* @param $variables
* 'results' - An array of result objects.
* 'finder' - The finder object.
* 'form_state' - The Forms API form state.
*/
function theme_finder_views_results($variables) {
extract($variables);
$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;
}