quicktabs_field_collection.module in QuickTabs Field Collection 7
Renders a field collection as QuickTabs.
File
quicktabs_field_collection.moduleView source
<?php
/**
* @file
* Renders a field collection as QuickTabs.
*/
/**
* Implements hook_permission().
*/
function quicktabs_field_collection_permission() {
return array(
'administer quicktabs_field_collection' => array(
'title' => t('Administer QuickTabs Field Collection'),
'description' => t('Configure advanced aspects of QuickTabs Field Collection'),
),
);
}
/**
* Implements hook_field_formatter_info().
*/
function quicktabs_field_collection_field_formatter_info() {
$formatters = array();
if (module_exists('field_collection')) {
$formatters['field_collection_quicktabs'] = array(
'label' => t('QuickTabs'),
'field types' => array(
'field_collection',
),
'description' => t('Displays a field collection as a QuickTabs instance'),
'settings' => array(
'tab_field' => NULL,
'content_options' => array(
'content_field' => NULL,
'content_view_mode' => 'field',
'content_field_striptags' => FALSE,
),
'classes' => '',
// Settings for the QuickTabs module that get passed into its API.
'quicktabs' => array(
'ajax' => FALSE,
'hide_empty_tabs' => TRUE,
'renderer' => 'quicktabs',
'style' => 'default',
'options' => array(
'ui_tabs' => array(
'history' => FALSE,
),
'accordion' => array(
'history' => FALSE,
'jquery_ui' => array(
'autoHeight' => TRUE,
'collapsible' => TRUE,
),
),
),
),
),
);
}
return $formatters;
}
/**
* Implements hook_field_formatter_settings_form().
*/
function quicktabs_field_collection_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
$options = array();
$field_collections = field_info_instances('field_collection_item', $field['field_name']);
foreach ($field_collections as $field_name => $field) {
$options[$field_name] = $field['label'] . ' (' . $field_name . ')';
}
$view_modes = array(
'field' => t('Field only'),
);
$entity_info = entity_get_info('field_collection_item');
foreach ($entity_info['view modes'] as $key => $info) {
$view_modes[$key] = $info['label'] . ' (' . $key . ')';
}
$element['tab_field'] = array(
'#type' => 'select',
'#title' => t('Label field'),
'#description' => t('The field collection field to use for the tab label.'),
'#required' => TRUE,
'#options' => $options,
'#default_value' => $settings['tab_field'],
);
$element['content_options'] = array(
'#type' => 'fieldset',
'#title' => t('Body'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
'#tree' => TRUE,
);
$element['content_options']['content_view_mode'] = array(
'#type' => 'select',
'#title' => t('View mode'),
'#description' => t('The field collection view mode to use for rendering. If the field option is selected then a field to display must be chosen.'),
'#required' => TRUE,
'#options' => $view_modes,
'#default_value' => $settings['content_options']['content_view_mode'],
'#attributes' => array(
'class' => array(
'qtfc-view-mode-select',
),
),
);
$element['content_options']['content_field'] = array(
'#type' => 'select',
'#title' => t('Field'),
'#description' => t('The field collection field to use for the tab body.'),
'#required' => FALSE,
'#options' => $options,
'#default_value' => $settings['content_options']['content_field'],
'#states' => array(
'enabled' => array(
'select.qtfc-view-mode-select' => array(
'value' => 'field',
),
),
),
'#element_validate' => array(
'quicktabs_field_collection_validate_content_field',
),
);
$element['content_options']['content_field_striptags'] = array(
'#type' => 'checkbox',
'#title' => t('Strip tags'),
'#description' => t("Strip all HTML tags from the value used for the tab's content."),
'#default_value' => $settings['content_options']['content_field_striptags'],
);
quicktabs_field_collection_get_quicktabs_options($element, $settings);
$element['classes'] = array(
'#type' => 'textfield',
'#title' => t('Custom Classes'),
'#description' => t('Provide a space delimited list of css classes to use.'),
'#default_value' => $settings['classes'],
);
return $element;
}
/**
* Helper function to add QuickTab settings fields to the field settings form.
*
* Taken from the QuickTab module and tweaked slightly to work within the field
* config form. If/when QuickTabs offers an API to pull in renderes and styles
* this function can be removed and the changes moved back into the normal
* settings form.
*
* @param array $element
* The settings form array.
*
* @param array $settings
* The current settings for the field.
*/
function quicktabs_field_collection_get_quicktabs_options(&$element, $settings) {
$element['quicktabs'] = array(
'#type' => 'fieldset',
'#title' => t('QuickTab settings'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#tree' => TRUE,
);
$element['quicktabs']['hide_empty_tabs'] = array(
'#type' => 'checkbox',
'#title' => t('Hide empty tabs'),
'#description' => t('Hide tabs where there is no content available.'),
'#default_value' => $settings['quicktabs']['hide_empty_tabs'],
);
ctools_include('plugins');
$renderers = ctools_get_plugins('quicktabs', 'renderers');
$renderer_options = array();
foreach ($renderers as $name => $info) {
if ($class = ctools_plugin_load_class('quicktabs', 'renderers', $name, 'handler')) {
// Add the renderer to the dropdown list of renderers
$renderer_options[$name] = $name;
// Get the renderer's options form elements
// PHP 5.2 doesn't support $class::staticMethod() syntax, so we have to
// use call_user_func_array() until PHP 5.3 is required.
$renderer_form_options[$name] = call_user_func_array(array(
$class,
'optionsForm',
), array(
$qt,
));
}
}
ksort($renderer_options);
$element['quicktabs']['renderer'] = array(
'#type' => 'select',
'#title' => t('Renderer'),
'#description' => t('Choose how to render the content.'),
'#options' => $renderer_options,
'#default_value' => $settings['quicktabs']['renderer'],
'#attributes' => array(
'class' => array(
'qtfc-renderer-select',
),
),
);
// Add the renderer options form elements to the form, to be shown only if the
// renderer in question is selected.
$element['quicktabs']['options'] = array(
'#tree' => TRUE,
);
foreach ($renderer_form_options as $renderer => $options) {
$defaults = !empty($settings['quicktabs']['options'][$renderer]) ? $settings['quicktabs']['options'][$renderer] : array();
foreach ($options as $key => &$option) {
$renderer_settings = isset($defaults[$key]) ? $defaults[$key] : NULL;
if (!empty($renderer_settings)) {
// Settings needs special handling in the case of nested form items.
$option = _quicktabs_field_collection_recurse_set_defaults($option, $renderer_settings);
}
$option['#states'] = array(
'visible' => array(
'select.qtfc-renderer-select' => array(
'value' => $renderer,
),
),
);
}
$element['quicktabs']['options'][$renderer] = $options;
}
if (module_exists('quicktabs_tabstyles')) {
$styles = module_invoke_all('quicktabs_tabstyles');
$style_options = array();
// The keys used for options must be valid html IDs.
foreach ($styles as $style) {
$style_options[$style] = $style;
}
ksort($style_options);
$element['quicktabs']['style'] = array(
'#type' => 'select',
'#title' => t('Style'),
'#description' => t('Choose the quicktab style.'),
'#options' => array(
'default' => t('Default style'),
) + array(
'nostyle' => t('No style'),
) + $style_options,
'#default_value' => $settings['quicktabs']['style'],
'#states' => array(
'visible' => array(
'select.qtfc-renderer-select' => array(
'value' => 'quicktabs',
),
),
),
);
}
}
/**
* Recursively set default settings for QuickTab renderers.
*
* @param array $option
* The form option to set #default_value on.
*
* @param mixed $setting
* A keyed array of options or the single option value to set.
*
* @return array
* The modified $option.
*/
function _quicktabs_field_collection_recurse_set_defaults($option, $setting) {
foreach (element_children($option) as $key) {
if (empty($setting[$key])) {
continue;
}
$option[$key] = _quicktabs_field_collection_recurse_set_defaults($option[$key], $setting[$key]);
/*
* Remove setting so we don't mistakenly put an array of child settings as
* the default value for a parent level form item.
*/
unset($setting[$key]);
}
if (!empty($setting)) {
$option['#default_value'] = $setting;
}
return $option;
}
/**
* Implements hook_field_formatter_settings_summary().
*/
function quicktabs_field_collection_field_formatter_settings_summary($field, $instance, $view_mode) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
$summary = array();
$summary[] = t('Tab field: @field-name', array(
'@field-name' => $settings['tab_field'],
));
if ('field' === $settings['content_options']['content_view_mode']) {
$summary[] = t('Content field: @field-name', array(
'@field-name' => $settings['content_options']['content_field'],
));
}
else {
$summary[] = t('Content view mode: @view-mode', array(
'@view-mode' => $settings['content_options']['content_view_mode'],
));
}
$summary[] = t('Strip tags in content: @yes-no', array(
'@yes-no' => !empty($settings['content_options']['content_field_striptags']) ? 'yes' : 'no',
));
if (!empty($settings['classes'])) {
$summary[] = t('Classes: @classes', array(
'@classes' => $settings['classes'],
));
}
$summary[] = t('Hide empty tabs: @yes-no', array(
'@yes-no' => !empty($settings['quicktabs']['hide_empty_tabs']) ? 'yes' : 'no',
));
$summary[] = t('QuickTab renderer: @qt-renderer', array(
'@qt-renderer' => $settings['quicktabs']['renderer'],
));
if (module_exists('quicktabs_tabstyles')) {
$summary[] = t('QuickTab style: @qt-style', array(
'@qt-style' => $settings['quicktabs']['style'],
));
}
return implode('<br />', $summary);
}
/**
* Implements hook_field_formatter_view().
*/
function quicktabs_field_collection_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
$settings = $display['settings'];
$theme_func = 'field_collection_quicktabs_formatter_' . $display['type'];
switch ($display['type']) {
case 'field_collection_quicktabs':
$new_element = array(
'#theme' => $theme_func,
'#settings' => $settings,
);
foreach ($items as $delta => $item) {
// Verify that there is something in the field collection befor trying to render it.
$entity = field_collection_field_get_entity($item);
if (!empty($entity)) {
$new_element['#items'][$item['value']] = $entity;
}
}
if (!empty($new_element['#items'])) {
$element[] = $new_element;
}
break;
}
return $element;
}
/**
* Implements hook_theme().
*/
function quicktabs_field_collection_theme($existing, $type, $theme, $path) {
return array(
'field_collection_quicktabs_formatter_field_collection_quicktabs' => array(
'variables' => array(
'items' => NULL,
'settings' => array(),
),
),
);
}
/**
* A theme function for displaying field collections as QuickTab instances.
*
* @param array $variables
* An array of the address and settings
*
* @return string
* The rendered HTML
*/
function theme_field_collection_quicktabs_formatter_field_collection_quicktabs($variables) {
$items = $variables['items'];
$defaults = quicktabs_field_collection_field_formatter_info();
$defaults = !empty($defaults['field_collection_quicktabs']['settings']) ? $defaults['field_collection_quicktabs']['settings'] : array();
$settings = array_merge($defaults, $variables['settings']);
if (empty($items)) {
return NULL;
}
$tabs = array();
$weight = 0;
foreach ($items as $collection_id => $collection) {
if (empty($collection)) {
continue;
}
$tabs[] = array_merge(_quicktabs_field_collection_get_tab_parts($collection, $settings), array(
'weight' => $weight++,
));
}
// AJAX is unsupported for this field formatter. Force disable.
$settings['quicktabs']['ajax'] = FALSE;
$renderer_settings = array();
// Adjust renderer options if available.
if (!empty($settings['quicktabs']['options'][$settings['quicktabs']['renderer']])) {
$settings['quicktabs']['options'] = $settings['quicktabs']['options'][$settings['quicktabs']['renderer']];
}
$qt = quicktabs_build_quicktabs('field_collection_quicktabs-' . $collection_id, $settings['quicktabs'], $tabs);
/*
* The class is added here instead of to the QT options so it wraps the entire
* QuickTabs output.
*/
if (!empty($qt['content']) && !empty($settings['classes'])) {
$settings['classes'] = explode(' ', $settings['classes']);
if (!isset($qt['content']['content']['#options']['attributes']['class'])) {
$qt['content']['content']['#options']['attributes']['class'] = array();
}
$qt_classes =& $qt['content']['content']['#options']['attributes']['class'];
if (!is_array($qt_classes)) {
$qt_classes = explode(' ', $qt_classes);
}
$qt_classes = array_merge($qt_classes, $settings['classes']);
}
return render($qt);
}
/**
* Retrieves the tab title and contents from a field collection entity.
*
* @param object $collection_entity
* The field collection entity to pull values from
*
* @return array
* An array with title and contents keys
*/
function _quicktabs_field_collection_get_tab_parts($collection_entity, $settings) {
$label_field_name = $settings['tab_field'];
// Retrieve the render array for the tab field.
$label_item = field_get_items('field_collection_item', $collection_entity, $label_field_name);
$label_value = field_view_value('field_collection_item', $collection_entity, $label_field_name, $label_item[0], 'default');
if ('field' === $settings['content_options']['content_view_mode']) {
$content_field_name = $settings['content_options']['content_field'];
// Retrieve the render array for the content field.
$content_value = field_view_field('field_collection_item', $collection_entity, $content_field_name, 'default');
}
else {
$content_value = entity_view('field_collection_item', array(
$collection_entity,
), $settings['content_options']['content_view_mode'], NULL, TRUE);
}
// Strip HTML tags from content if necessary.
$content = $settings['content_options']['content_field_striptags'] ? strip_tags(render($content_value)) : render($content_value);
return array(
'title' => decode_entities(render($label_value)),
'contents' => array(
'#markup' => $content,
),
);
}
/**
* Implements hook_help().
*/
function quicktabs_field_collection_help($path, $arg) {
switch ($path) {
case 'admin/help#quicktabs_field_collection':
$out = '';
$out .= '<p>' . t('The QTFC module is designed to let you use the QuickTabs module to render field collection entities.') . '</p>';
$out .= '<p>' . t('In order to use this module you must select and configure the QuickTabs formatter on any field collection display. The only required options are the source of the tab label and body.') . '</p>';
$out .= '<p>' . t('A text field as the source for the tab label is recommended. Any content used for the tab label will be run through <a href="@check-plain">check_plain()</a> before being displayed', array(
'@check-plain' => 'http://api.drupal.org/api/drupal/includes!bootstrap.inc/function/check_plain/7',
)) . '</p>';
$out .= '<p>' . t('The source of the body content can be any type of field. The module was designed with a long text field in mind, but it will render anything that makes use of the Drupal render API. This means you can get complex data to render by using a field collection with other fields as the source of the tab body. Combining this with <a href="@ds">Display Suite</a> increases the flexibility of what the tabbed content can look like.', array(
'@ds' => 'http://drupal.org/project/ds',
)) . '</p>';
$out .= '<p>' . t('Another option for body content is a view mode of the field collection. If this option is selected then the field option is disabled as they are mutually exclusive.') . '</p>';
return $out;
}
}
/**
* A field validate handler for the content field selection when the field view mode is chosen.
*/
function quicktabs_field_collection_validate_content_field($element, &$form_state, $form) {
$formatter_settings = $form_state['values']['fields'][$form_state['formatter_settings_edit']];
$formatter_settings = $formatter_settings['settings_edit_form']['settings'];
$is_field_view_mode = 'field' === $formatter_settings['content_options']['content_view_mode'];
if (empty($element['#value']) && $is_field_view_mode) {
form_error($element, t('A field must be chosen when the field view mode is selected.'));
}
}