array(
// Should be "View", but that would translate into "view" (show) for many
// languages due to missing string translation contexts.
'label' => t('Views'),
'description' => t('Displays a selected view in a node.'),
'callbacks' => array(
'tables' => CONTENT_CALLBACK_NONE,
'arguments' => CONTENT_CALLBACK_NONE,
),
),
);
}
/**
* Implementation of hook_field_settings().
*/
function viewfield_field_settings($op, $field) {
switch ($op) {
case 'form':
$form['allowed_views'] = array(
'#type' => 'checkboxes',
'#title' => t('Allowed values'),
'#default_value' => is_array($field['allowed_views']) ? $field['allowed_views'] : array(),
'#options' => drupal_map_assoc(array_keys(views_get_all_views())),
'#description' => t('Only selected views will be available for content authors. Leave empty to allow all.'),
);
return $form;
case 'validate':
if ($field['force_default'] && $field['multiple']) {
form_set_error('multiple', t('Multiple views are not supported if force default is enabled.'));
}
break;
case 'save':
return array(
'allowed_views',
);
case 'database columns':
return array(
// Views requires at least 96 chars for the view name and display, plus
// we need 1 for our delimiter. Round up to a common value of 128.
'vname' => array('type' => 'varchar', 'not null' => FALSE, 'length' => 128),
'vargs' => array('type' => 'varchar', 'not null' => FALSE, 'length' => 255),
);
}
}
/**
* Implementation of hook_field().
*/
function viewfield_field($op, &$node, $field, &$items, $teaser, $page) {
switch ($op) {
case 'presave':
foreach ($items as $delta => $item) {
if (empty($item['vname'])) {
unset($items[$delta]);
}
}
break;
case 'sanitize':
// Replace field values with widget defaults when force_default is set.
if ($field['widget']['force_default']) {
$items = $field['widget']['default_value'];
}
break;
}
}
/**
* Implementation of hook_content_is_empty().
*/
function viewfield_content_is_empty($item, $field) {
return empty($item['vname']);
}
/**
* Implementation of hook_field_formatter_info().
*/
function viewfield_field_formatter_info() {
return array(
'default' => array(
'label' => t('Default'),
'field types' => array('viewfield')
),
);
}
/**
* Return a themed view avoiding viewfield recursion.
*/
function theme_viewfield_formatter_default($element) {
// $_viewfield_stack keeps a record of the current node to prevent infinite
// recursion during the view rendering process.
global $_viewfield_stack;
$node = $element['#node'];
if (!empty($element['#item']['vname']) && !isset($_viewfield_stack[$node->nid])) {
// Push id of current node unless it's a new node being previewed.
if ($node->nid) {
$_viewfield_stack[$node->nid] = $node->nid;
}
list($view_name, $display) = explode('|', $element['#item']['vname'], 2);
$view_args = _viewfield_get_view_args($element['#item']['vargs'], $element['#node']);
// Render the view like Views would do.
// @see views_embed_view()
$view = views_get_view($view_name);
if ($view && $view->access($display)) {
// Override the view's path to the current path. Otherwise, exposed views
// filters would submit to the front page.
$view->override_path = $_GET['q'];
$output = $view->preview($display, $view_args);
}
// This node is "safe" again.
if ($node->nid) {
unset($_viewfield_stack[$node->nid]);
}
// Only return an actual view result to not break empty value behavior.
if (isset($output)) {
return $output;
}
}
}
/**
* Implementation of hook_widget_info().
*/
function viewfield_widget_info() {
return array(
'viewfield_select' => array(
'label' => 'Select List',
'field types' => array('viewfield'),
'multiple_values' => CONTENT_HANDLE_CORE,
'callbacks' => array(
'default value' => CONTENT_CALLBACK_DEFAULT,
),
),
);
}
/**
* Implementation of hook_widget_settings().
*/
function viewfield_widget_settings($op, $widget) {
switch ($op) {
case 'form':
$form['force_default'] = array(
'#type' => 'checkbox',
'#title' => t('Always use default value'),
'#default_value' => $widget['force_default'],
'#description' => t('Hides this field in forms and forces the default value defined below.'),
);
return $form;
case 'save':
return array(
'force_default',
);
}
}
/**
* Implementation of hook_widget().
*/
function viewfield_widget(&$form, &$form_state, $field, $items, $delta = 0) {
$element = array(
'#type' => $field['widget']['type'],
'#default_value' => isset($items[$delta]) ? $items[$delta] : NULL,
);
return $element;
}
/**
* Implementation of FAPI hook_elements().
*/
function viewfield_elements() {
return array(
'viewfield_select' => array(
'#input' => TRUE,
'#columns' => array('vname', 'vargs'),
'#delta' => 0,
'#process' => array('viewfield_select_process'),
),
);
}
function viewfield_select_process($element, $edit, $form_state, $form) {
// This form is used for both the default value field in the admin as well as
// the node edit form, so we have to make sure we show the default value field
// always.
$is_field_settings_form = !isset($form['#node']);
$field = isset($form['#field_info'][$element['#field_name']]) ? $form['#field_info'][$element['#field_name']] : NULL;
$element['#field'] = $field;
// Display the form to let the user pick a view.
$options = _viewfield_potential_references($field, $element['#delta']);
$element['vname'] = array(
'#type' => 'select',
'#title' => $element['#title'],
'#options' => $options,
'#default_value' => isset($element['#default_value']['vname']) ? $element['#default_value']['vname'] : NULL,
'#required' => $element['#required'],
'#access' => $is_field_settings_form || !$field['widget']['force_default'],
'#description' => $element['#description'],
);
// If there is only one option, only show arguments.
if (count($options) == 1 && !$is_field_settings_form) {
list($key, $label) = each($options);
$element['vname']['#access'] = FALSE;
$element['vname']['#default_value'] = $key;
}
$element['vargs'] = array(
'#type' => 'textfield',
'#title' => !isset($label) ? t('Arguments') : t('%field (@value) arguments', array(
'%field' => $field['widget']['label'],
'@value' => $label,
)),
'#default_value' => isset($element['#default_value']['vargs']) ? $element['#default_value']['vargs'] : NULL,
'#access' => $is_field_settings_form || !$field['widget']['force_default'],
'#description' => t('A comma separated list of arguments to pass to the selected view. Wrap arguments containing commas in double quotes. Replace double quotes in arguments with two double quotes.'),
);
$token_description = t('Available tokens: %nid for the id of the current node; %author for the node author; %viewer for the viewing user');
if (module_exists('token')) {
$element['vargs']['#description'] .=
'
' . $token_description . '; ' . t('or any token from the placeholder token list.')
. '
' . t('Note: Using placeholder tokens in combination with the %fields row style may negatively affect site performance.', array('%fields' => t('Fields')));
// Only show token help for first value or in field settings form.
if ($element['#delta'] == 0 && ($is_field_settings_form || !$field['widget']['force_default'])) {
$element['token_help'] = array(
'#type' => 'fieldset',
'#title' => t('Placeholder tokens'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$element['token_help']['tokens'] = array(
'#value' => theme('token_help', 'node'),
);
}
}
else {
$element['vargs']['#description'] .= '
' . $token_description . '.';
}
return $element;
}
/**
* Prepare a list of views for selection.
*/
function _viewfield_potential_references($field, $delta = 0) {
$options = array();
if (isset($field['allowed_views']) && is_array($field['allowed_views'])) {
$field['allowed_views'] = array_filter($field['allowed_views']);
}
if (empty($field['allowed_views'])) {
$field['allowed_views'] = array_keys(views_get_all_views());
}
foreach ($field['allowed_views'] as $view_name) {
// Check for deleted views saved in allowed_views.
if ($view = views_get_view($view_name)) {
foreach ($view->display as $display) {
$options[$view->name .'|'. $display->id] = $view->name .' - '. $display->display_title;
}
}
}
// Add a '0' option for non-required or subsequent values of multiple fields.
if (empty($field['required']) || ($field['multiple'] && $delta > 0)) {
array_unshift($options, '<'. t('none') .'>');
}
return $options;
}
/**
* Implementation of hook_theme().
*/
function viewfield_theme() {
return array(
'viewfield_select' => array(
'arguments' => array('element' => NULL),
),
'viewfield_formatter_default' => array(
'arguments' => array('element' => NULL),
),
);
}
/**
* Add CSS to force help text to wrap correctly on node edit form.
*/
function theme_viewfield_select($element) {
if (!empty($element['#children'])) {
$field = $element['#field'];
if ($field['multiple'] && $element['#delta'] == 0) {
// This is needed only for multiple viewfields.
drupal_add_css(drupal_get_path('module', 'viewfield') .'/viewfield.css');
}
return '