array('label' => 'View Reference'),
);
}
/**
* Implementation of hook_field_settings().
*/
function viewfield_field_settings($op, $field) {
switch ($op) {
/* These are off until we need them
case 'form':
return $form;
case 'save':
return array(); */
case 'database columns':
$columns = array(
'vname' => array('type' => 'char', 'length' => 32),
'vargs' => array('type' => 'varchar', 'not null' => false, 'default' => "''", 'sortable' => TRUE, 'length' => 255),
);
return $columns;
/*
case 'filters':
return array(
'default' => array(
'list' => '_viewfield_filter_handler',
'list-type' => 'list',
'operator' => 'views_handler_operator_or',
'value-type' => 'array',
'extra' => array('field' => $field),
),
); */
}
}
/**
* Implementation of hook_field_formatter_info().
*/
function viewfield_field_formatter_info() {
$formatters = array(
'default' => array(
'label' => 'Entire view (using default style)',
'field types' => array('viewfield'),
),
'count' => array(
'label' => 'Count of items in view',
'field types' => array('viewfield'),
),
);
include_once(drupal_get_path('module', 'views') .'/views_cache.inc');
$plugins = _views_get_style_plugins();
foreach ($plugins as $type => $details) {
$formatters[$type] = array(
'label' => $details['name'],
'field types' => array('viewfield')
);
}
return $formatters;
}
/**
* Implementation of hook_field_formatter().
*/
function viewfield_field_formatter($field, $item, $formatter, $node) {
// these are Eaton's tests for his normal, defaults, content type wide settings stuff
//$v = ($field['configurability'] == 'none') ? $field['vname'] : $item['vname'];
//$a = ($field['configurability'] == 'none') ? $field['vargs'] : $item['vargs'];
// using the $v, $a convention in case I uncomment the above lines.
$v = $item['vname'];
$a = $item['vargs'];
if (!empty($v)) {
// XXX this probably not multi-select safe...
global $user;
$view = views_get_view($v);
/* -- TODO uncomment when token doesn't cause recursion issues
if (module_exists('token')) {
$translated_args = token_replace_multiple($a, array('node' => $node));
}
else {
$translated_args = strtr($a, array('%nid' => $node->nid, '%author' => $node->uid, '%viewer' => $user->uid));
}
*/
$translated_args = strtr($a, array('%nid' => $node->nid, '%author' => $node->uid, '%viewer' => $user->uid));
$args = explode(',', $translated_args);
if ($formatter != 'default' && $formatter != 'count') {
$view->page_type = $formatter;
}
// need to prevent recusive views and node building, but don't need to do it on new node previews
if ($node->nid) {
_viewfield_nodestack_push($node->nid);
}
switch ($formatter) {
default:
if ($view->use_pager) {
// fix for multiple pagers
global $pager_total;
static $viewfield_pager_elements = array();
$key = $node->nid . '-' . $field['field_name'] . '-' . $view->name; // set a unique key for the view in the current node
if (!isset($viewfield_pager_elements[$key])) {
// set the viewfield pager element to the max + 1
$max1 = is_array($pager_total) ? @max(array_values($pager_total)) : 1;
// without this fix below i get an error with php4
$av = array_values($viewfield_pager_elements);
$max2 = $av ? max($av) : 0;
//$max2 = @max(array_values($viewfield_pager_elements));
$viewfield_pager_elements[$key] = @max($max1, $max2) + 1;
}
$use_pager = $viewfield_pager_elements[$key];
}
else {
$use_pager = 0;
}
$output = views_build_view('embed', $view, $args, $use_pager, $view->nodes_per_page);
break;
case 'count':
// TODO use the the new 'queries' $op instead
$results = views_build_view('items', $view, $args);
$count = count($results['items']);
$output = $count;
break;
}
// this node is "safe" again
if ($node->nid) {
_viewfield_nodestack_pop();
}
return $output;
}
}
/**
* Implementation of hook_widget_info().
*/
function viewfield_widget_info() {
return array(
'viewfield_select' => array(
'label' => 'Select List',
'field types' => array('viewfield'),
), /*
'viewfield_autocomplete' => array(
'label' => 'Autocomplete View Field',
'field types' => array('viewfield'),
), */
);
}
/**
* Implementation of hook_widget().
*/
function viewfield_widget($op, &$node, $field, &$node_field) {
switch ($op) {
case 'prepare form values':
$node_field_transposed = content_transpose_array_rows_cols($node_field);
$node_field['default vnames'] = $node_field_transposed['vname'];
break;
case 'form':
$form = array();
$options = _viewfield_potential_references($field);
$form[$field['field_name']] = array('#tree' => TRUE);
$form[$field['field_name']]['vnames'] = array(
'#type' => 'select',
'#title' => t($field['widget']['label']),
'#default_value' => $node_field['default vnames'],
'#multiple' => $field['multiple'],
'#options' => $options,
'#required' => $field['required'],
'#description' => $field['widget']['description'],
);
$form[$field['field_name']]['vargs'] = array(
'#type' => 'textfield',
'#title' => 'arguments',
'#default_value' => $node_field[0]['vargs'], // all views share args (for now ...)
'#required' => false,
'#description' => t('Provide a comma separated list of arguments to pass to the view. These arguments will be passed to EACH selected view.'),
);
// TODO: token support right now a bit hacked on ... needs better integration
// ev. checkbox to enable/disable use of token-module here
/* -- TODO uncomment when token works
if (module_exists('token')) {
$form[$field['field_name']]['vargs']['#description'] .= '
'.
t('Use the syntax [token] if you want to insert a replacement pattern.');
$form[$field['field_name']]['token_help'] = array(
'#title' => t('Replacement patterns'),
'#type' => 'fieldset',
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$form[$field['field_name']]['token_help']['help'] = array(
'#value' => theme('token_help', 'node'),
);
} else {
$form[$field['field_name']]['vargs']['#description'] .= '
' . t('You may use %nid for the node id of the current node. %author for the node author and %viewer for user viewing the node.');
}
*/ $form[$field['field_name']]['vargs']['#description'] .= '
' . t('You may use %nid for the node id of the current node. %author for the node author and %viewer for user viewing the node.');
return $form;
case 'process form values':
if ($field['multiple']) {
$items = $node_field['vnames'];
foreach($items as $item) {
$node_field[] = array (
'vname' => $item,
'vargs' => $node_field['vargs'],
);
}
}
else {
$node_field[0]['vname'] = $node_field['vnames'];
$node_field[0]['vargs'] = $node_field['vargs'];
}
// Remove the widget's data representation so it isn't saved.
unset($node_field['vnames']);
unset($node_field['vargs']);
}
}
/*** Private functions ***/
/**
* Prepare a list of views for selection.
*/
function _viewfield_potential_references($field) {
$options = array();
// add a null option for non-required fields
if (!$field['required'] && !$field['multiple']) {
$options[0] = '<' . t('None') . '>';
}
include_once(drupal_get_path('module', 'views') . '/views_cache.inc');
$default_views = _views_get_default_views();
$res = db_query("SELECT name FROM {view_view} ORDER BY name");
while ($view = db_fetch_object($res)) {
$options[$view->name] = $view->name;
}
if(is_array($default_views)) {
foreach($default_views as $key => $view) {
$options[$key] = $view->name;
}
}
return $options;
}
/**
* Functions for manipulating a global stack of nids. This prevents us from recursively
* building a node, with a view, with the node, with the view.... etc
*/
function _viewfield_nodestack_push($nid) {
global $viewfield_stack;
if (!isset($viewfield_stack)) {
$_GLOBAL['viewfield_stack'] = array();
global $viewfield_stack;
}
$viewfield_stack[] = $nid;
}
function _viewfield_nodestack_pop() {
global $viewfield_stack;
return array_pop($viewfield_stack);
}
/**
* Implementation of hook_db_rewrite_sql
*
* Prevent views from loading the node containing the view.
*/
function viewfield_db_rewrite_sql($query, $primary_table, $primary_field, $args) {
global $viewfield_stack;
if (!empty($viewfield_stack)) {
if ($primary_field == 'nid') {
$return['where'] = "$primary_table.nid NOT IN (" . implode(',', $viewfield_stack). ')';
return $return;
}
}
}