'viewreference autocomplete', 'page callback' => 'viewreference_autocomplete', 'page arguments' => array(2, 3), 'access callback' => 'viewreference_autocomplete_access', 'access arguments' => array(2, 3), 'type' => MENU_CALLBACK, ); return $items; } /** * Implements hook_theme(). */ function viewreference_theme() { return array( 'viewreference_display_title' => array( 'variables' => array( 'view' => NULL, 'view_name' => NULL, 'display_key' => NULL, 'append_id' => FALSE, ), ), 'viewreference_formatter_default' => array( 'variables' => array('element' => NULL), ), 'viewreference_formatter_full' => array( 'variables' => array('element' => NULL), ), 'viewreference_formatter_plain' => array( 'variables' => array('element' => NULL), ), 'viewreference_formatter_link' => array( 'variables' => array('element' => NULL), ), 'viewreference_formatter_path' => array( 'variables' => array('element' => NULL), ), ); } /** * Implements hook_field_info(). */ function viewreference_field_info() { $field_info = array( 'viewreference' => array( 'label' => t('View reference'), 'description' => t('Reference a views display from the views module.'), 'settings' => array( 'referenceable_views' => array(), 'referenceable_tags' => array( 'allow' => '', 'deny' => '', ), 'arguments' => array( 'dsv_arguments' => 0, 'php_arguments' => 0, 'delimiter' => '/', 'rows' => 1, 'label' => '!field_label ' . t('arguments'), ), 'append_id' => 0, 'skip_default' => 1, 'skip_empty' => 0, ), 'default_widget' => 'viewreference_autocomplete', 'default_formatter' => 'viewreference_default', ), ); return $field_info; } /** * Implements hook_field_schema(). */ function viewreference_field_schema($field) { $columns = array( 'view_id' => array( 'type' => 'varchar', 'length' => '255', 'default' => NULL, 'not null' => FALSE, ), 'arguments' => array( 'type' => 'text', 'size' => 'big', ), ); return array( 'columns' => $columns, 'indexes' => array('view_id' => array('view_id')), ); } /** * Implements hook_field_settings_form(). */ function viewreference_field_settings_form($field, $instance, $has_data) { $settings = $field['settings']; $form = array(); $form['referenceable_views'] = array( '#type' => 'checkboxes', '#title' => t('Views that can be referenced'), '#description' => t('Select the Views that can be referenced. If no Views are selected here, and tags are not entered below, then all the Views will be available.'), '#multiple' => TRUE, '#default_value' => is_array($settings['referenceable_views']) ? $settings['referenceable_views'] : array(), '#options' => viewreference_get_views($settings['append_id']), // This call doesn't supply $settings, so they aren't filtered. ); $form['referenceable_tags'] = array( '#type' => 'fieldset', '#title' => t('Views tags that can be referenced'), '#collapsible' => TRUE, '#collapsed' => (!empty($settings['referenceable_tags']['allow']) || !empty($settings['referenceable_tags']['deny'])) ? FALSE : TRUE, '#description' => t('Optionally you can allow views by tags here instead of, or in addition to, using Views that can be referenced, then other Views will be excluded. You can also deny views by tags, and if Views that can be referenced and the Allow list are left blank all other Views will be available.'), ); $form['referenceable_tags']['allow'] = array( '#type' => 'textfield', '#title' => t('Allow list'), '#default_value' => !empty($settings['referenceable_tags']['allow']) ? $settings['referenceable_tags']['allow'] : '', '#size' => 128, '#maxlength' => 512, '#description' => t('Enter a comma delimited list of tags to include.'), ); $form['referenceable_tags']['deny'] = array( '#type' => 'textfield', '#title' => t('Deny list'), '#default_value' => !empty($settings['referenceable_tags']['deny']) ? $settings['referenceable_tags']['deny'] : '', '#size' => 128, '#maxlength' => 512, '#description' => t('Enter a comma delimited list of tags to exclude.'), ); $form['arguments'] = array( '#type' => 'fieldset', '#title' => t('Contextual filter arguments'), '#collapsible' => TRUE, '#collapsed' => ($settings['arguments']['dsv_arguments'] || $settings['arguments']['php_arguments']) ? FALSE : TRUE, '#description' => t('Enabling the following options will provide an input field for passing arguments (aka contextual filters) to the View.'), ); $form['arguments']['dsv_arguments'] = array( '#type' => 'checkbox', '#title' => t('Allow delimiter seperated values.'), '#default_value' => isset($settings['arguments']['dsv_arguments']) ? $settings['arguments']['dsv_arguments'] : 0, '#description' => t('Users can provide a list of arguments seperated by a delimiter. e.g: term_1/term_2'), ); $form['arguments']['php_arguments'] = array( '#type' => 'checkbox', '#title' => t('Allow PHP code.'), '#default_value' => isset($settings['arguments']['php_arguments']) ? $settings['arguments']['php_arguments'] : 0, '#description' => t('Users can insert PHP code to generate the list of arguments. e.g: term_1/<?php print "term_x/term_y"; ?>/term_2') . '
' . t('Note: The users must have the use PHP for settings permission.'), '#disabled' => !user_access('use PHP for settings'), ); $form['arguments']['delimiter'] = array( '#type' => 'textfield', '#title' => t('Delimiter'), '#default_value' => !empty($settings['arguments']['delimiter']) ? $settings['arguments']['delimiter'] : '/', '#size' => 3, '#maxlength' => 30, '#required' => TRUE, ); $row_range = range(0, 10); unset($row_range[0]); $form['arguments']['rows'] = array( '#type' => 'select', '#title' => t('Number of rows in argument field'), '#default_value' => isset($settings['arguments']['rows']) ? $settings['arguments']['rows'] : 1, '#options' => $row_range, '#description' => t('Set as 1 for textfield, or larger values for textarea (may be easier to write PHP with a textarea)'), '#required' => TRUE, ); $form['arguments']['label'] = array( '#type' => 'textfield', '#title' => t('Label for arguments field'), '#default_value' => isset($settings['arguments']['label']) ? $settings['arguments']['label'] : '!field_label ' . t('arguments'), '#description' => t('Use !field_label to insert the field label.'), ); $form['append_id'] = array( '#type' => 'checkbox', '#title' => t('Append unique ID in lists.'), '#default_value' => isset($settings['append_id']) ? $settings['append_id'] : 0, '#description' => t('It is possible for Views displays to have the same title, this option will append [view:view_display_n] in lists used by this field to disambiguate the options.'), ); $form['skip_default'] = array( '#type' => 'checkbox', '#title' => t('Exclude the master (default) display from lists.'), '#default_value' => isset($settings['skip_default']) ? $settings['skip_default'] : 1, ); $form['skip_empty'] = array( '#type' => 'checkbox', '#title' => t('Do not output view if no rows are detected'), '#default_value' => isset($settings['skip_empty']) ? $settings['skip_empty'] : 0, ); $form['skip_disabled'] = array( '#type' => 'checkbox', '#title' => t('Do not allow selection of disabled views'), '#default_value' => isset($settings['skip_disabled']) ? $settings['skip_disabled'] : 0, ); $form['sort_views'] = array( '#type' => 'checkbox', '#title' => t('Sort the views by title'), '#default_value' => isset($settings['sort_views']) ? $settings['sort_views'] : 1, ); return $form; } /** * Implements hook_field_validate(). */ function viewreference_field_validate($entity_type, $entity, $field, $instance, $langcode, $items, &$errors) { $views = viewreference_get_views($field['settings']['append_id'], $field['settings']); foreach ($items as $delta => $item) { if (is_array($item)) { if (!empty($item['view_id'])) { if (!in_array($item['view_id'], array_keys($views))) { $errors[$field['field_name']][$langcode][$delta][] = array( 'error' => 'invalid_view', 'message' => t("%name: This view can't be referenced.", array('%name' => $instance['label'])), ); } } } } } /** * Implements hook_field_is_empty(). */ function viewreference_field_is_empty($item, $field) { return empty($item['view_id']); } /** * Implements hook_field_formatter_info(). */ function viewreference_field_formatter_info() { $ret = array( 'viewreference_default' => array( 'label' => t('Default (view)'), 'description' => t('Display the referenced view.'), 'field types' => array('viewreference'), ), 'viewreference_full' => array( 'label' => t('Full (title and view)'), 'description' => t('Display the referenced view with a title.'), 'field types' => array('viewreference'), ), 'viewreference_plain' => array( 'label' => t('Title (no link)'), 'description' => t('Display the title of the referenced view.'), 'field types' => array('viewreference'), ), 'viewreference_link' => array( 'label' => t('Title (link)'), 'description' => t('Display the title of the referenced view as a link (if possible).'), 'field types' => array('viewreference'), ), 'viewreference_path' => array( 'label' => t('Path'), 'description' => t('Display the path of the referenced view (if possible).'), 'field types' => array('viewreference'), ), ); return $ret; } /** * Implements hook_field_formatter_view(). */ function viewreference_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) { $element = array(); $formatter = str_replace('viewreference_', '', $display['type']); foreach ($items as $delta => $item) { $element[$delta] = array( '#theme' => 'viewreference_formatter_' . $formatter, '#element' => array( 'entity_type' => &$entity_type, 'entity' => &$entity, 'field' => &$field, 'instance' => &$instance, 'langcode' => &$langcode, 'item' => $item, 'display' => &$display, ), ); $element[$delta]['#element']['view'] = viewreference_get_view($element[$delta]['#element']); if (!$element[$delta]['#element']['view']) { unset($element[$delta]); } } return $element; } /** * Value callback for a viewreference_autocomplete element. */ function viewreference_autocomplete_value($element, $input = FALSE, $form_state) { if ($input === FALSE) { $field_key = $element['#columns'][0]; $args_key = $element['#columns'][1]; if (!empty($element['#default_value'][$field_key])) { $field_name = $element['#field_name']; $field = field_info_field($field_name); $settings = $field['settings']; $settings['referenceable_views'] = array($element['#default_value'][$field_key]); $views = viewreference_get_views(TRUE, $settings); $value = $views[$element['#default_value'][$field_key]]; return array($field_key => $value, $args_key => $element['#default_value'][$args_key]); } return array($field_key => NULL, $args_key => $element['#default_value'][$args_key]); } } /** * Validation callback for a viewreference_autocomplete element. */ function viewreference_autocomplete_validate($element, &$form_state, $form) { $field = field_widget_field($element, $form_state); $value = $element['#value']; $new_value = NULL; if (!empty($value)) { $regex = '/' // Start of string . '(.*).*?' // Any non-greedy . '(\\[)' // [ . '((?:[a-z][a-z0-9_]*))' // Variable 1 . '(:)' // : . '((?:[a-z][a-z0-9_]*))' // Variable 2 . '(\\])' // ] . '/is'; // End of string preg_match($regex, $value, $matches); if (!empty($matches)) { $new_value = $matches[3] . ':' . $matches[5]; $allowed = viewreference_get_views(FALSE, $field['settings']); if (!isset($allowed[$new_value])) { form_error( $element, t( '%name: View display %value cannot be referenced.', array( '%name' => $element['#title'], '%value' => $new_value, ) ) ); } } else { form_error( $element, t( '%name: The value %value is in an unexpected format. Expecting: %format', array( '%name' => $element['#title'], '%value' => $value, '%format' => 'View title [view:display_n]', ) ) ); } } form_set_value($element, $new_value, $form_state); } /** * Implements hook_field_widget_error(). */ function viewreference_field_widget_error($element, $error, $form, &$form_state) { form_error($element['view_id'], $error['message']); } /** * Menu access callback for the autocomplete path. * * Check for both 'edit' and 'view' access in the unlikely event * a user has edit but not view access. */ function viewreference_autocomplete_access($entity_type, $field_name) { return user_access('access content') && ($field = field_info_field($field_name)) && field_access('view', $field, $entity_type) && field_access('edit', $field, $entity_type); } /** * Menu callback for the autocomplete results. */ function viewreference_autocomplete($bundle_name, $field_name, $string = '') { // If the request has a '/' in the search text, then the menu system will have // split it into multiple arguments, recover the intended $string. $args = func_get_args(); // Shift off the $bundle_name argument. array_shift($args); // Shift off the $field_name argument. array_shift($args); $string = implode('/', $args); $field = field_info_field($field_name); $settings = $field['settings']; $matches = viewreference_get_views($settings['append_id'], $settings, FALSE, $string, FALSE, TRUE); drupal_json_output($matches); } /** * Implements hook_options_list(). */ function viewreference_options_list($field) { $references = viewreference_get_views($field['settings']['append_id'], $field['settings']); $options = array(); foreach ($references as $key => $value) { $options[$key] = $value['rendered']; } return $options; } /** * Create a display title for a view display. */ function viewreference_views_display_title($view_name, $view, $display) { // Build the display title. if (isset($view->display[$display]->display_options['title'])) { // This view display has a nice title, let's use that. return $view->display[$display]->display_options['title']; } elseif (isset($view->display['default']->display_options['title'])) { // This view display inherits it's title from the default display. return $view->display['default']->display_options['title']; } else { // This view display does not have a title configured, we have to construct a title. return ucfirst($view_name) . ' ' . strtolower($view->display[$display]->display_title); } } /** * Get an array of data and rendered HTML items that are useful in theming the * formatter output. * * @param $element * An array of parameters used in viewing the element. * @param $params * An array of special features needed to be built: * 'embed' - The $view->preview() of the view display * 'title' - The display title of the view display * 'link' - A link to the view display, or the title if link not available. * 'path' - The path to the view display, or the title if path not available. * 'contextual' - The contextual links. * @return * The array of useful data about the view. */ function viewreference_get_view($element, $params = array()) { if (!empty($element['item']['view_id'])) { if (!empty($element['view'])) { $view = $element['view']; } if (empty($view['view']) || empty($view['display']) || empty($view['name'])) { $view_id_parts = explode(':', $element['item']['view_id']); $view['name'] = $view_id_parts[0]; $view['display'] = $view_id_parts[1]; $view['view'] = views_get_view($view['name']); } if ($view['view'] && $view['view']->access($view['display'])) { // Save $_GET['q'] so it can be restored before returning from this function. //$q = $_GET['q']; if (empty($view['embed']) && (in_array('embed', $params) || !empty($element['field']['settings']['skip_empty']))) { $view['args'] = viewreference_get_element_args($element); //if (!empty($view['args'])) { // $_GET['q'] .= '/' . implode('/', $view['args']); //} $view['embed'] = $view['view']->preview($view['display'], $view['args']); // If the view is empty and the viewreference field is configured with // "skip empty views" enabled, skip outputting the view. if (!empty($element['field']['settings']['skip_empty']) && empty($view['view']->result)) { // Restore $_GET['q'] before skipping the view. //$_GET['q'] = $q; return FALSE; } } if ((in_array('title', $params) && empty($view['title'])) || (in_array('link', $params) && empty($view['link']))) { $view['display_key'] = $view['display']; $view['title'] = theme('viewreference_display_title', $view); if (in_array('link', $params) && empty($view['link'])) { $disabled = isset($view['view']->disabled) ? $view['view']->disabled: FALSE; if (isset($view['view']->display[$view['display']]->display_options['path']) && !$disabled) { $view['args'] = isset($view['args']) ? $view['args'] : viewreference_get_element_args($element); $view['url_args'] = implode('/', $view['args']); $view['path'] = $view['view']->display[$view['display']]->display_options['path']; if ($view['url_args']) { $view['path'] .= '/' . $view['url_args']; } $view['link'] = l($view['title'], $view['view']->get_url($view['args'], $view['path'])); } else { $view['link'] = $view['title']; } } } if (in_array('contextual', $params) && empty($view['contextual'])) { $view['contextual'] = ''; if (module_exists('contextual')) { $contextual = contextual_element_info(); views_add_contextual_links($contextual['contextual_links'], 'special_block_-exp', $view['view'], $view['display']); if (!empty($contextual['contextual_links']['#contextual_links'])) { $view['contextual'] = drupal_render($contextual['contextual_links']); } } } //$_GET['q'] = $q; return $view; } } } /** * Theme function for 'default' viewreference field formatter. */ function theme_viewreference_formatter_default($variables) { $element = &$variables['element']; $output = ''; if ($view = viewreference_get_view($element, array('contextual', 'embed'))) { $output .= ''; } return $output; } /** * Theme function for 'full' viewreference field formatter. */ function theme_viewreference_formatter_full($variables) { $element = &$variables['element']; $output = ''; if ($view = viewreference_get_view($element, array('contextual', 'title', 'embed'))) { $output .= ''; } return $output; } /** * Theme function for 'plain' viewreference field formatter. */ function theme_viewreference_formatter_plain($variables) { $element = &$variables['element']; $output = ''; if ($view = viewreference_get_view($element, array('title'))) { $output .= $view['title']; } return $output; } /** * Theme function for 'link' viewreference field formatter. */ function theme_viewreference_formatter_link($variables) { $element = &$variables['element']; $output = ''; if ($view = viewreference_get_view($element, array('link'))) { $output .= $view['link']; } return $output; } /** * Theme function for 'path' viewreference field formatter. */ function theme_viewreference_formatter_path($variables) { $element = &$variables['element']; $output = ''; if ($view = viewreference_get_view($element, array('link'))) { $output .= isset($view['path']) ? $view['path'] : $view['link']; } return $output; } /** * Get an array of views. * * @param bool $append_id * Whether to append the id to the returned display names. * @param array $settings * The settings of the field. * @param bool $full * If TRUE will return all the data, rather than just the title. * @param string $string * String to match against the title to filter results by. * @param bool $exact_string * If TRUE the $string parameter must match exactly. * @param bool $long_key * If TRUE will key array by the title and ID, not just the ID. * * @return mixed[] * The array of views. The array value type depends on the parameters. */ function viewreference_get_views($append_id = FALSE, $settings = NULL, $full = FALSE, $string = '', $exact_string = FALSE, $long_key = FALSE) { /** @var views_display[] $views_displays */ $views_displays = _viewreference_get_applicable_views_displays($settings); return _viewreference_extract_views_displays($settings, $views_displays, $append_id, $full, $string, $exact_string, $long_key); } /** * @param array $settings * If applying filters, the settings of the field. * * @return array[] * An array where the keys are views machine names, and each value is an array * of the format array($view, $applicable_displays), where the first element * is a view, and the second element is an array of views displays. */ function _viewreference_get_applicable_views_displays($settings) { $loaded_views = views_get_all_views(); // Prepare filters. if (!empty($settings['referenceable_views'])) { $filters['ids'] = array_filter($settings['referenceable_views']); } if (!empty($settings['referenceable_tags']['allow'])) { $filters['allow_tags'] = array_map('trim', explode(',', $settings['referenceable_tags']['allow'])); } if (!empty($settings['referenceable_tags']['deny'])) { $filters['deny_tags'] = array_map('trim', explode(',', $settings['referenceable_tags']['deny'])); } $applicable_views_displays = array(); foreach ((array)$loaded_views as $view_name => $view) { // Limit views to active views if (!empty($settings['skip_disabled']) && $view->disabled) { continue; } // Prepare this view's tags. $tags = array_map('trim', explode(',', $view->tag)); // Determine if there are allow tags $has_allow_tag = FALSE; if (!empty($tags) && !empty($filters['allow_tags'])) { foreach ($tags as $tag) { if (in_array($tag, $filters['allow_tags'])) { $has_allow_tag = TRUE; break; } } } // Determine if there are deny tags $has_deny_tag = FALSE; if (!empty($tags) && !empty($filters['deny_tags'])) { foreach ($tags as $tag) { if (in_array($tag, $filters['deny_tags'])) { $has_deny_tag = TRUE; break; } } } // Skip the entire view, if there is a deny tag. if ($has_deny_tag) { continue; } $allow_all = $has_allow_tag || (empty($filters['ids']) && empty($filters['allow_tags'])); $applicable_displays = array(); foreach ((array)$view->display as $display_key => $display) { // Skip this one if it's a 'default' view and we're skipping defaults. if ($display_key === 'default' && $settings['skip_default']) { continue; } if ($allow_all) { $applicable_displays[$display_key] = $display; continue; } // Skip this one if it's not 'allowed'. $id = $view_name . ':' . $display_key; if (!empty($filters['ids']) && in_array($id, $filters['ids'])) { $applicable_displays[$display_key] = $display; } } if (!empty($applicable_displays)) { $applicable_views_displays[$view_name] = array($view, $applicable_displays); } } return $applicable_views_displays; } /** * Get an array of views. * * @param array $settings * The settings of the field. * @param views_display[] $views_displays * @param bool $append_id * Whether to append the id to the returned display names. * @param bool $full * If TRUE will return all the data, rather than just the title. * @param string $string * String to match against the title to filter results by. * @param bool $exact_string * If TRUE the $string parameter must match exactly. * @param bool $long_key * If TRUE will key array by the title and ID, not just the ID. * * @return mixed[] * The array of views. */ function _viewreference_extract_views_displays($settings, $views_displays, $append_id = FALSE, $full = FALSE, $string = '', $exact_string = FALSE, $long_key = FALSE) { $views = array(); foreach ($views_displays as $view_name => $view_and_displays) { list($view, $view_displays) = $view_and_displays; /** @var views_display $display */ foreach ($view_displays as $display_key => $display) { $id = $view_name . ':' . $display_key; // Get display title. $theme_vars = array( 'view' => $view, 'view_name' => $view_name, 'display_key' => $display_key, 'append_id' => $append_id, ); $display_title = theme('viewreference_display_title', $theme_vars); // Determine whether and what to return. $key = $long_key ? $display_title . ($append_id ? '' : ' [' . $id . ']') : $id; if ($string) { if (!$exact_string && (stripos($display_title, $string) !== FALSE || stripos($key, $string) !== FALSE)) { $views[$key] = $full ? $display : $display_title; } elseif ($display_title == $string) { $views[$key] = $full ? $display : $display_title; } } else { $views[$key] = $full ? $display : $display_title; } } } if (!empty($settings['sort_views'])) { asort($views); } return $views; } /** * Theme the display title for this view display. * * @param $variables An array of arguments that will be extracted to the following variables: * $view - The view object. * $view_name - The name of the view. * $display_key - The name of the display to use. * $append_id - Boolean indicating whether to append a unique id. * @return * The display title of this views display. */ function theme_viewreference_display_title($variables) { // Get variables passed to theme function. $variables['view']->set_display($variables['display_key']); $display_title = $variables['view']->display_handler->options['title']; if (!$display_title) { // No title, we have to construct a title. $display_title = ucfirst($variables['view_name']) . ' ' . strtolower($variables['view']->display[$variables['display_key']]->display_title); } if (isset($variables['view']->display[$variables['display_key']]->display_title)) { $display_title .= ' - ' . $variables['view']->display[$variables['display_key']]->display_title; } if ($variables['append_id']) { // Append ID for disambiguation in forms (views displays can have the same title). $display_title .= ' [' . $variables['view_name'] . ':' . $variables['display_key'] . ']'; } return $display_title; } /** * Convert arguments text field entry to an array of arguments. */ function viewreference_get_element_args($element) { $string = &$element['item']['arguments']; $field = &$element['field']; $settings = $field['settings']; $delimiter = &$settings['arguments']['delimiter']; $dsv_arguments = &$settings['arguments']['dsv_arguments']; $php_arguments = &$settings['arguments']['php_arguments']; $arguments = ''; $args = array(); if ($php_arguments) { $last_edit_user = user_load($element['entity']->revision_uid); if (user_access('use PHP for settings', $last_edit_user)) { $variables = array( $element['entity_type'] => $element['entity'], ); $arguments = viewreference_eval($string, $variables); } else { $arguments = $string; } } elseif ($dsv_arguments) { $arguments = $string; } if ($arguments) { $args = explode($delimiter, $arguments); foreach ($args as $k => $v) { $args[$k] = check_plain(trim($v)); } } // Allow modules to easily supply their own views arguments. drupal_alter('viewreference_args', $args, $element); return $args; } /** * A version of php_eval() that allows passing of variables. */ function viewreference_eval($code, $variables = array()) { global $theme_path, $theme_info, $conf; // Store current theme path. $old_theme_path = $theme_path; // Restore theme_path to the theme, as long as drupal_eval() executes, // so code evaluted will not see the caller module as the current theme. // If theme info is not initialized get the path from theme_default. if (!isset($theme_info)) { $theme_path = drupal_get_path('theme', $conf['theme_default']); } else { $theme_path = dirname($theme_info->filename); } foreach ((array)$variables as $key => $value) { $$key = $value; } ob_start(); print eval('?>' . $code); $output = ob_get_contents(); ob_end_clean(); // Recover original theme path. $theme_path = $old_theme_path; return $output; } /** * Implements hook_field_widget_info(). */ function viewreference_field_widget_info() { return array( 'viewreference_select' => array( 'label' => t('Select list'), 'description' => t('Display the list of referenceable views as a select list.'), 'field types' => array('viewreference'), 'behaviors' => array( 'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'default value' => FIELD_BEHAVIOR_DEFAULT, ), ), 'viewreference_autocomplete' => array( 'label' => t('Autocomplete text field'), 'description' => t('Display the list of referenceable views as a textfield with autocomplete behaviour.'), 'field types' => array('viewreference'), 'behaviors' => array( 'multiple values' => FIELD_BEHAVIOR_DEFAULT, 'default value' => FIELD_BEHAVIOR_DEFAULT, ), ), ); } /** * Implements hook_field_widget_form(). */ function viewreference_field_widget_form(&$form, &$form_state, $field, $instance, $langcode, $items, $delta, $element) { switch ($instance['widget']['type']) { case 'viewreference_select': $element += array( '#type' => 'viewreference_select', '#default_value' => isset($items[$delta]) ? $items[$delta] : NULL, ); break; case 'viewreference_autocomplete': $element += array( '#type' => 'viewreference_autocomplete', '#default_value' => isset($items[$delta]) ? $items[$delta] : NULL, '#value_callback' => 'viewreference_autocomplete_value', ); break; } return $element; } /** * Implements hook_element_info(). */ function viewreference_element_info() { return array( 'viewreference_select' => array( '#input' => TRUE, '#columns' => array('view_id', 'arguments'), '#delta' => 0, '#process' => array('viewreference_select_process'), ), 'viewreference_autocomplete' => array( '#input' => TRUE, '#columns' => array('view_id', 'arguments'), '#delta' => 0, '#process' => array('viewreference_autocomplete_process'), '#autocomplete_path' => FALSE, ), ); } /** * Process callback for a viewreference_select element. * * @see viewreference_element_info(). */ function viewreference_select_process($element, $form_state, $form) { $field_name = $element['#field_name']; $language = $element['#language']; $field = field_widget_field($element, $form_state); $instance = field_widget_instance($element, $form_state); $settings = $field['settings']; $options = _viewreference_select_widget_options($settings); if (!$instance['required']) { $options = array(0 => '<'. t('none') .'>') + $options; } $element[$element['#columns'][0]] = array( '#type' => 'select', '#multiple' => 0, '#options' => $options, '#default_value' => isset($element['#value'][$element['#columns'][0]]) ? $element['#value'][$element['#columns'][0]] : '', '#field_name' => $field_name, '#delta' => $element['#delta'], '#columns' => $element['#columns'], '#title' => $element['#title'], '#required' => $instance['required'], '#description' => isset($instance['description']) ? $instance['description'] : NULL, ); if ($settings['arguments']['dsv_arguments'] || $settings['arguments']['php_arguments']) { $element[$element['#columns'][1]] = array( '#type' => ($settings['arguments']['rows'] == 1 ? 'textfield' : 'textarea'), '#default_value' => isset($element['#value'][$element['#columns'][1]]) ? $element['#value'][$element['#columns'][1]] : '', '#title' => isset($settings['arguments']['label']) ? str_replace('!field_label', $instance['label'], check_plain($settings['arguments']['label'])) : $instance['label'] . ' ' . t('arguments'), '#rows' => $settings['arguments']['rows'], '#language' => $language, '#delta' => $element['#delta'], '#columns' => $element['#columns'], ); } return $element; } /** * @return array[] */ function _viewreference_select_widget_options($settings) { $options = array(); foreach (_viewreference_get_applicable_views_displays($settings) as $view_key => $view_and_displays) { list($view, $view_displays) = $view_and_displays; $view_optgroup_key = $view_key; $view_title = $view->get_title(); if (!empty($view_title)) { $view_optgroup_key .= ' (' . $view_title . ')'; } foreach ($view_displays as $display_key => $display) { $option_key = $view_key . ':' . $display_key; $option_title = $display_key; if (!empty($display->display_title)) { $option_title .= ' (' . $display->display_title . ')'; } $options[$view_optgroup_key][$option_key] = $option_title; } ksort($options[$view_optgroup_key]); } ksort($options); return $options; } /** * Process callback for a viewreference_autocomplete element. * * @see viewreference_element_info(). */ function viewreference_autocomplete_process($element, $form_state, $form) { $field_parents = $element['#field_parents']; $field_name = $element['#field_name']; $language = $element['#language']; $field_state = field_form_get_state($field_parents, $field_name, $language, $form_state); $field = $field_state['field']; $instance = $field_state['instance']; $bundle = $instance['bundle']; $settings = $field['settings']; $element[$element['#columns'][0]] = array( '#type' => 'textfield', '#default_value' => isset($element['#value'][$element['#columns'][0]]) ? $element['#value'][$element['#columns'][0]] : '', '#autocomplete_path' => 'viewreference/autocomplete/'. $bundle . '/' . $field_name, '#element_validate' => array('viewreference_autocomplete_validate'), '#field_name' => $field_name, '#language' => $language, '#delta' => $element['#delta'], '#columns' => $element['#columns'], '#title' => $element['#title'], '#required' => $element['#required'], '#description' => isset($element['#description']) ? $element['#description'] : '', ); if ($settings['arguments']['dsv_arguments'] || $settings['arguments']['php_arguments']) { $element[$element['#columns'][1]] = array( '#type' => ($settings['arguments']['rows'] == 1 ? 'textfield' : 'textarea'), '#default_value' => isset($element['#value'][$element['#columns'][1]]) ? $element['#value'][$element['#columns'][1]] : '', '#title' => $instance['label'] . ' ' . t('arguments'), '#rows' => $settings['arguments']['rows'], '#delta' => $element['#delta'], '#columns' => $element['#columns'], '#required' => $element['#required'], '#description' => isset($element['#description']) ? $element['#description'] : '', ); } return $element; }