',
'variables' => array('fieldset_fields' => array()),
'template' => 'views-fieldsets-div',
'path' => $path,
),
'views_fieldsets_details' => array(
'views_fieldsets_label' => '
',
'variables' => array('fieldset_fields' => array(), 'legend' => ''),
'template' => 'views-fieldsets-details',
'path' => $path,
),
);
}
/**
* Implements hook_theme_registry_alter().
*/
function views_fieldsets_theme_registry_alter(&$registry) {
foreach ($registry as $hook => &$info) {
// Splice in our generic preprocessor for all fieldset types.
if (strpos($hook, 'views_fieldsets_') === 0 && isset($info['views_fieldsets_label'])) {
// It must come directly after 'template_preprocess', or first if that doesn't exist.
$index = array_search('template_preprocess', $info['preprocess functions']);
if ($index !== FALSE) {
array_splice($info['preprocess functions'], $index + 1, 0, '_template_preprocess_views_fieldsets');
}
else {
array_unshift($info['preprocess functions'], '_template_preprocess_views_fieldsets');
}
}
unset($info);
}
}
/**
* Find all eligible fieldset theme hooks.
*/
function _views_fieldsets_types() {
$registry = theme_get_registry();
$types = array();
foreach ($registry as $hook => $info) {
if (strpos($hook, 'views_fieldsets_') === 0 && isset($info['views_fieldsets_label'])) {
$types[substr($hook, 16)] = $info['views_fieldsets_label'];
}
}
return $types;
}
/**
* Implements template_preprocess_views_view_table().
*
* Preprocessor for Views' row style template.
*/
function views_fieldsets_preprocess_views_view_table(&$vars) {
$view = $vars['view'];
$display_handler = $view->display_handler;
$fields = $display_handler->get_option('fields');
$tmp_vars = $vars;
$tmp_vars['options']['default_field_elements'] = TRUE;
foreach ($view->result as $index => $row) {
$view->row_index = $index;
template_preprocess_views_view_fields($tmp_vars);
$vars['field_fields'][$index] = $tmp_vars['fields'];
}
$fieldsets = views_fieldsets_field_options_to_fieldsets_1d($fields);
if ($fieldsets && array_filter($fieldsets)) {
// Fix separators.
$last_in_fieldset = FALSE;
foreach ($vars['fields'] as $id => $object) {
$in_fieldset = views_fieldsets_field_is_in_fieldset($id, $display_handler);
if (!empty($object->separator) && !$in_fieldset && $last_in_fieldset) {
$object->separator = '';
}
$last_in_fieldset = $in_fieldset;
}
// Add collapse.js for actual fieldsets.
drupal_add_js('misc/collapse.js');
drupal_add_js('misc/form.js');
$hierarchy = views_fieldsets_hierarchy_info($display_handler, $fieldsets);
$vars['hierarchy'] = $hierarchy;
// Remove fieldsetted fields' header.
foreach (array_filter($fieldsets) as $field_name => $fieldset_name) {
unset($vars['header'][$field_name]);
}
foreach ($vars['rows'] as $index => $row) {
$view->row_index = $index;
$new_row = array();
foreach ($hierarchy['tree'] as $field_name => $info_field) {
if (isset($vars['fields'][$field_name])) {
if (views_fieldsets_field_is_fieldset($field_name, $display_handler)) {
$sub_vars = $vars;
// Fake vars.
$sub_vars['fields'][$field_name] = (object) array(
'handler' => $view->display_handler->handlers['field'][$field_name],
'label' => $view->display_handler->handlers['field'][$field_name]->options['label'],
);
$sub_vars['fieldset_field'] = $field_name;
// Saving current row index.
$sub_vars['row_index'] = $index;
// Recursive render of fieldsets.
$new_row[$field_name] = _views_fieldsets_render__table($info_field, $sub_vars);
}
else {
// Render single field.
if (isset($row[$field_name])) {
$new_row[$field_name] = $row[$field_name];
}
}
}
}
// Save new, rendered, flat row into old row.
$vars['rows'][$index] = $new_row;
}
}
}
/**
* Helper function to render fieldsets recursively for table row style.
*/
function _views_fieldsets_render__table($fields, $vars) {
// Set default values.
$view = $vars['view'];
$display_handler = $view->display_handler;
$views_field = $view->field[$vars['fieldset_field']];
$views_field_options = $views_field->options;
$hide_empty = !empty($display_handler->default_display->options['style_options']['info'][$vars['fieldset_field']]['empty_column']);
$content = array();
foreach ($fields->children as $child_field_name => $child_info) {
if ($views_field = $vars['field_fields'][$vars['row_index']][$child_field_name]) {
if (views_fieldsets_field_is_fieldset($child_field_name, $display_handler)) {
$sub_vars = $vars;
// Fake vars.
$sub_vars['fields'][$child_field_name] = (object) array(
'handler' => $view->display_handler->handlers['field'][$child_field_name],
'label' => $view->display_handler->handlers['field'][$child_field_name]->options['label'],
);
$sub_vars['fieldset_field'] = $child_field_name;
$content[$child_field_name] = $views_field;
$content[$child_field_name]->content = _views_fieldsets_render__table($child_info, $sub_vars);
$views_field->label_html = $views_field->wrapper_prefix = $views_field->wrapper_suffix = '';
}
else {
// Default behaviour to render field.
$content[$child_field_name] = $views_field;
}
}
}
// Checking if we need to hide fieldset.
$is_empty = TRUE;
foreach ($content as $field) {
if (!empty($field->content)) {
$is_empty = FALSE;
break;
}
}
if (!$is_empty || !$hide_empty) {
$vars['fieldset_fields'] = $content;
$html_tag = $views_field_options['fieldset']['type'];
unset($vars['theme_hook_suggestion'], $vars['theme_hook_suggestions']);
$theme_hook_suggestions = views_theme_functions('views_fieldsets_' . $html_tag, $vars['view'], $display_handler->display);
$output = theme($theme_hook_suggestions, $vars);
$output .= "\n";
}
else {
$output = '';
}
return $output;
}
/**
* Implements template_preprocess_views_view_fields().
*
* Preprocessor for Views' row style template.
*/
function views_fieldsets_preprocess_views_view_fields(&$vars) {
$view = $vars['view'];
$display_handler = $view->display_handler;
$fields = $display_handler->get_option('fields');
$fieldsets = views_fieldsets_field_options_to_fieldsets_1d($fields);
if ($fieldsets && array_filter($fieldsets)) {
// Fix separators.
$last_in_fieldset = FALSE;
foreach ($vars['fields'] as $id => $object) {
$in_fieldset = views_fieldsets_field_is_in_fieldset($id, $display_handler);
if (!empty($object->separator) && !$in_fieldset && $last_in_fieldset) {
$object->separator = '';
}
$last_in_fieldset = $in_fieldset;
}
// Add collapse.js for actual fieldsets.
drupal_add_js('misc/collapse.js');
drupal_add_js('misc/form.js');
$hierarchy = views_fieldsets_hierarchy_info($display_handler, $fieldsets);
$vars['hierarchy'] = $hierarchy;
$new_fields = array();
foreach ($hierarchy['tree'] as $field_name => $info_field) {
if (isset($vars['fields'][$field_name])) {
$views_field = $vars['fields'][$field_name];
if (views_fieldsets_field_is_fieldset($field_name, $display_handler)) {
// Save fieldset field name for next recursion.
$sub_vars = $vars;
$sub_vars['fieldset_field'] = $field_name;
// Render fieldset + children.
$content = views_fieldsets_render__simple($info_field->children, $sub_vars);
$views_field->content = $content;
$views_field->label_html = $views_field->wrapper_prefix = $views_field->wrapper_suffix = '';
$new_fields[$field_name] = $views_field;
}
else {
// Render single field.
$new_fields[$field_name] = $views_field;
}
}
}
$vars['fields'] = $new_fields;
}
}
/**
* Helper to render fieldsets.
*
* @see views_fieldsets_preprocess_views_view_fields__2().
*/
function views_fieldsets_render__simple($fields, $vars) {
$display_handler = $vars['view']->display_handler;
$views_field = $vars['view']->field[$vars['fieldset_field']];
$views_field_options = $views_field->options;
$hide_empty = !empty($views_field->options['hide_empty']);
$content = array();
foreach ($fields as $field_name => $info_field) {
if (isset($vars['fields'][$field_name])) {
$views_field = $vars['fields'][$field_name];
if (views_fieldsets_field_is_fieldset($field_name, $display_handler)) {
// Prep children & fieldset field options/settings.
$sub_fields = !empty($info_field->children) ? $info_field->children : array();
$sub_vars = $vars;
$sub_vars['fieldset_field'] = $field_name;
// Render fieldset + children.
$views_field->is_fieldset = TRUE;
$views_field->wrapper_prefix = '';
$views_field->label_html = '';
$views_field->content = views_fieldsets_render__simple($sub_fields, $sub_vars);
$views_field->wrapper_suffix = '';
}
else {
// Render single field.
$views_field->is_fieldset = FALSE;
}
$content[$field_name] = $views_field;
}
}
$is_empty = TRUE;
foreach ($content as $field) {
if (!$field->is_fieldset || !empty($field->content)) {
$is_empty = FALSE;
break;
}
}
if (!$is_empty || !$hide_empty) {
$vars['fieldset_fields'] = $content;
$html_tag = $views_field_options['fieldset']['type'];
unset($vars['theme_hook_suggestion'], $vars['theme_hook_suggestions']);
$theme_hook_suggestions = views_theme_functions('views_fieldsets_' . $html_tag, $vars['view'], $display_handler->display);
$output = theme($theme_hook_suggestions, $vars);
$output .= "\n";
}
else {
$output = '';
}
return $output;
}
/**
* Default preprocessor for all views_fieldsets_TYPE tpls.
*/
function _template_preprocess_views_fieldsets(&$vars) {
$view = $vars['view'];
$hierarchy = $vars['hierarchy'];
$fieldset_field = $vars['fieldset_field'];
$views_field = $vars['fields'][$fieldset_field];
$views_field_options = $views_field->handler->options;
// CSS classes.
$classes = $views_field->handler->tokenize_value($views_field_options['fieldset']['classes'], $view->row_index);
$classes_array = array_filter(explode(' ', $classes));
if (!$classes_array) {
$classes_array[] = drupal_strtolower(drupal_clean_css_identifier($views_field->label));
}
$classes_array[] = 'views-fieldset';
if (!empty($views_field_options['fieldset']['collapsible'])) {
$classes_array[] = 'collapsible';
}
if (!empty($views_field_options['fieldset']['collapsed'])) {
$classes_array[] = 'collapsed';
}
$vars['classes_array'] = $classes_array;
// Fieldset legend.
if (!empty($views_field_options['alter']['alter_text']) && !empty($views_field_options['alter']['text'])) {
$vars['legend'] = $views_field->content;
}
else {
$vars['legend'] = $views_field->label;
}
$vars['legend'] = t($vars['legend'], array(), array('context' => 'views_fieldsets'));
// Attributes?
$vars['attributes_array'] = array(
'data-module' => 'views_fieldsets',
);
if (!empty($views_field_options['fieldset']['id'])) {
$id = $views_field_options['fieldset']['id'];
$id = $views_field->handler->tokenize_value($id, $view->row_index);
$vars['attributes_array']['id'] = drupal_html_id($id);
}
}
/**
* Implements hook_form_FORM_ID_alter() for views_ui_edit_form().
*/
function views_fieldsets_form_views_ui_edit_form_alter($form, $form_state) {
drupal_add_css(drupal_get_path('module', 'views_fieldsets') . '/css/views_fieldsets.css');
}
/**
* Implements hook_form_views_ui_edit_display_form_alter().
*/
function views_fieldsets_form_views_ui_edit_display_form_alter(&$form, &$form_state) {
$view = $form_state['view'];
if ($form_state['section'] == 'analyze-theme') {
$funcs = array();
foreach (array('fieldset', 'div', 'details') as $tag) {
$theme_hook_suggestions = views_theme_functions('views_fieldsets_' . $tag, $view, $view->display_handler->display);
$funcs[] = $view->display_handler->option_link(t('Views fieldsets @tag', array('@tag' => '<' . $tag . '>')), 'analyze-theme-fieldsets-' . $tag) . ': ' . $view->display_handler->format_themes($theme_hook_suggestions);
}
$html = theme('item_list', array('items' => $funcs));
$form['options']['analysis']['#markup'] .= $html;
}
}
/**
* Helper to make a nice 1D fieldsets array from fields' settings.
*/
function views_fieldsets_field_options_to_fieldsets_1d($fields) {
// Create empty 1D array with `field` => `parent`.
$fieldsets = $fields ? array_combine(array_keys($fields), array_fill(0, count($fields), '')) : array();
// Fill `parent` values by iterating through all fields (only the Views Fieldset fields matter).
foreach ($fields as $field_name => $field) {
if (isset($field['children'])) {
foreach ($field['children'] as $child_field_name) {
$fieldsets[$child_field_name] = $field_name;
}
}
}
return $fieldsets;
}
/**
* Implements hook_views_ui_display_tab_alter().
*/
function views_fieldsets_views_ui_display_tab_alter(&$build, $view, $display_id) {
$display_handler = &$view->display[$display_id]->handler;
$fields = $display_handler->get_option('fields');
$fieldsets = views_fieldsets_field_options_to_fieldsets_1d($fields);
$hierarchy = views_fieldsets_hierarchy_info($display_handler, $fieldsets);
foreach (element_children($build['details']['columns']['first']['fields']['fields']) as $field_name) {
$field = &$build['details']['columns']['first']['fields']['fields'][$field_name];
$field_is_fieldset = views_fieldsets_field_is_fieldset($field_name, $display_handler);
if ($field_is_fieldset) {
$field['#class'][] = 'views-fieldset';
}
if (isset($hierarchy['fields'][$field_name])) {
$field['#class'][] = 'views-fieldset-depth-' . $hierarchy['fields'][$field_name]->info->depth;
}
unset($field);
}
}
/**
* Helper to ...
*
* Establishes whether a field is a Views Fieldsets field BY ITS NAME.
*
* Deprecated since 2012-06-27.
*/
function views_fieldsets_name_is_fieldset($field_name) {
return 0 < preg_match('/^fieldset(_\d+)?$/', $field_name);
}
/**
* Helper to ...
*
* Establishes whether a field is a Views Fieldsets field BY ITS TYPE.
*/
function views_fieldsets_field_is_fieldset($field_name, $display_handler) {
$handler = $display_handler->get_handler('field', $field_name);
return $handler instanceof views_fieldsets_fieldset_field_handler;
}
/**
* Helper to ...
*
* Establishes whether a field is IN a Views Fieldsets field.
*/
function views_fieldsets_field_is_in_fieldset($field_name, $display_handler) {
if (empty($display_handler->_fieldsets)) {
$display_handler->_fieldsets = array_filter($display_handler->handlers['field'], function ($handler) {
return $handler instanceof views_fieldsets_fieldset_field_handler;
});
}
foreach ($display_handler->_fieldsets as $fieldset) {
if (in_array($field_name, $fieldset->options['children'])) {
return TRUE;
}
}
return FALSE;
}
/**
* Helper to ...
*/
function views_fieldsets_hierarchy_total_weights_set(&$hierarchy, &$fields, &$weight) {
foreach ($hierarchy as $field_name => $field) {
$field->info->total_weight = $weight++;
$fields[$field_name] = $field;
if (isset($field->children)) {
views_fieldsets_hierarchy_total_weights_set($field->children, $fields, $weight);
}
}
}
/**
* Helper to ...
*/
function views_fieldsets_hierarchy_total_weights(&$hierarchy, &$fields = array(), &$weight = 0) {
views_fieldsets_hierarchy_total_weights_set($hierarchy, $fields, $weight);
}
/**
* Helper to ...
*/
function views_fieldsets_hierarchy_info($display_handler, $fieldsets, $get_parent = '', $depth = 0) {
$hierarchy = array();
foreach ($fieldsets as $field_name => $parent) {
if ($get_parent == $parent) {
$hierarchy[$field_name] = (object) array(
'info' => (object) array(
'fieldset_weight' => count($hierarchy),
'total_weight' => 0,
'depth' => $depth,
'parent' => $parent ? $parent : '',
),
);
if (views_fieldsets_field_is_fieldset($field_name, $display_handler)) {
$hierarchy[$field_name]->children = views_fieldsets_hierarchy_info($display_handler, $fieldsets, $field_name, $depth + 1);
}
}
}
if (!$depth) {
$fields = array();
$weight = 0;
views_fieldsets_hierarchy_total_weights($hierarchy, $fields, $weight);
return array(
'total_weights' => array_keys($fields),
'fields' => $fields,
'tree' => $hierarchy,
);
}
return $hierarchy;
}
/**
* Implements hook_form_FORM_ID_alter() for views_ui_rearrange_form().
*/
function views_fieldsets_form_views_ui_rearrange_form_alter(&$form, &$form_state, $form_id = 'views_ui_rearrange_form') {
$actions = array_filter(explode('/', $form['#action']));
if (!isset($form['fields']) || 'field' != end($actions)) {
return;
}
$view = $form_state['view'];
$display_handler = $view->display_handler;
$fields = $display_handler->get_option('fields');
$fieldsets = views_fieldsets_field_options_to_fieldsets_1d($fields);
$hierarchy = views_fieldsets_hierarchy_info($display_handler, $fieldsets);
$fields = $hierarchy['fields'];
// Add tabledrag related elements
foreach (element_children($form['fields']) as $field_name) {
if (views_fieldsets_field_is_fieldset($field_name, $display_handler)) {
$form['fields'][$field_name]['name']['#markup'] = '' . $form['fields'][$field_name]['name']['#markup'] . '';
}
$form['fields'][$field_name]['weight']['#size'] = 3;
$form['fields'][$field_name]['field_name'] = array(
'#type' => 'hidden',
'#value' => $field_name,
'#attributes' => array('class' => array('field-name')),
);
$form['fields'][$field_name]['hierarchy'] = array(
'#type' => 'hidden',
'#default_value' => !empty($fields[$field_name]->info->parent) ? $fields[$field_name]->info->parent : '',
'#attributes' => array('class' => array('hierarchy')),
'#size' => 5,
);
$form['fields'][$field_name]['depth'] = array(
'#type' => 'hidden',
'#default_value' => !empty($fields[$field_name]->info->depth) ? $fields[$field_name]->info->depth : '',
'#attributes' => array('class' => array('depth')),
'#size' => 5,
);
}
// To add TableDrag and visual specialties.
$form['#theme'] = 'views_fieldsets_rearrange_form';
// To be used in the theme function (for views_fieldsets_field_is_fieldset()).
$form['#display_handler'] = $display_handler;
array_unshift($form['buttons']['submit']['#submit'], 'views_fieldsets_rearrange_form_submit');
}
/**
* Submit handler for views_ui_rearrange_form().
*/
function views_fieldsets_rearrange_form_submit($form, &$form_state) {
$values = &$form_state['values'];
$view = $form_state['view'];
$display_handler = $view->display_handler;
$fields = $display_handler->get_option('fields');
// Sort input by (hierarchical) weight.
uasort($values, 'drupal_sort_weight');
// Create simple hierarchy (field => parent) from sorted input.
$fieldsets = array();
foreach ($values as $field_name => $stuff) {
if (isset($fields[$field_name])) {
$fieldsets[$field_name] = $stuff['hierarchy'];
}
}
// Create advanced hierarchy from sorted simple hierarchy.
$fieldsets = views_fieldsets_hierarchy_info($display_handler, $fieldsets);
// Sort fields the Views way (no indentations/parents/relationships).
// Why? For Views' actual submit handler (which is the one after this one).
foreach ($fieldsets['total_weights'] as $weight => $field_name) {
$values[$field_name]['weight'] = $weight;
}
// Create simple hierarchy from new sort (sorted the Views way, with parents).
foreach ($fieldsets['fields'] as $field_name => $field) {
// $hierarchy[$field_name] = $fields[$field_name]['views_fieldsets_parent'] = $field->info->parent;
// And create hierarchy per Views Fieldset field.
if (views_fieldsets_field_is_fieldset($field_name, $display_handler)) {
$fields[$field_name]['children'] = !empty($field->children) ? array_keys($field->children) : array();
}
}
$display_handler->set_option('fields', $fields);
}
/**
* Theme function for views_fieldsets_rearrange_form.
*/
function theme_views_fieldsets_rearrange_form($variables) {
$form = $variables['form'];
$display_handler = $form['#display_handler'];
$rows = array();
foreach (element_children($form['fields']) as $id) {
if (isset($form['fields'][$id]['name'])) {
$field_name = $form['fields'][$id]['field_name']['#value'];
$depth = $form['fields'][$id]['depth']['#default_value'];
$indentation = $depth > 0 ? theme('indentation', array('size' => $depth)) : '';
$row = array();
$row[] =
$indentation .
drupal_render($form['fields'][$id]['name']) .
drupal_render($form['fields'][$id]['hierarchy']) .
drupal_render($form['fields'][$id]['depth']) .
drupal_render($form['fields'][$id]['field_name']);
$form['fields'][$id]['weight']['#attributes']['class'] = array('weight');
$row[] = drupal_render($form['fields'][$id]['weight']);
$row[] = drupal_render($form['fields'][$id]['removed']) . l('' . t('Remove') . '', 'javascript:void()', array(
'attributes' => array(
'id' => 'views-remove-link-' . $id,
'class' => array(
'views-hidden',
'views-button-remove',
'views-remove-link',
),
'alt' => t('Remove this item'),
'title' => t('Remove this item'),
),
'html' => TRUE,
));
$classes = array('draggable');
if (!views_fieldsets_field_is_fieldset($field_name, $display_handler)) {
$classes[] = 'tabledrag-leaf';
}
$rows[] = array(
'data' => $row,
'class' => $classes,
'id' => 'views-row-' . $id,
);
}
}
if (empty($rows)) {
$rows[] = array(
array(
'data' => t('No fields available.'),
'colspan' => '2',
),
);
}
$header = array('', t('Weight'), t('Remove'));
$output = drupal_render($form['override']);
$output .= '';
$output .= theme('table', array(
'header' => $header,
'rows' => $rows,
'attributes' => array('id' => 'arrange'),
));
$output .= '
';
$output .= drupal_render_children($form);
drupal_add_tabledrag('arrange', 'match', 'parent', 'hierarchy', 'hierarchy', 'field-name', FALSE);
drupal_add_tabledrag('arrange', 'depth', 'group', 'depth', NULL, NULL, FALSE);
drupal_add_tabledrag('arrange', 'order', 'sibling', 'weight');
return $output;
}
/**
* Implements hook_views_api().
*/
function views_fieldsets_views_api() {
return array(
'version' => 3,
'path' => drupal_get_path('module', 'views_fieldsets') . '/includes',
);
}