diff --git a/css/ds.admin.css b/css/ds.admin.css index e69de29..2316da9 100644 --- a/css/ds.admin.css +++ b/css/ds.admin.css @@ -0,0 +1,19 @@ + +/** + * @file + * Administration CSS for Display Suite. + */ + +.extra-field-settings { + display: none; + width: 600px; + z-index: 1000; + border: 1px solid #000; + padding: 5px; + background-color: #efefef; +} + +.extra-fs-group div.form-item { + float: left; + width: 130px; +} \ No newline at end of file diff --git a/ds.api.php b/ds.api.php index 5c86272..6992a02 100644 --- a/ds.api.php +++ b/ds.api.php @@ -276,6 +276,23 @@ function hook_ds_fields_info_alter(&$fields, $entity_type) { } /** + * Define theme functions for fields. + * + * This only is necessary when you're using the field settings + * plugin which comes with the DS extras module. This function + * will call the theming functions directly, not through + * theme('function', $variables); A function gets 2 parameters, + * the $variables and $config which are the configuration options + * for the current field: theme_ds_field_custom($variables, $config); + * + * @return $field_theme_functions + * A collection of field theming functions. + */ +function hook_ds_field_theme_functions_info() { + return array('theme_field' => t('Theme field')); +} + +/** * Creates a summary for the field format configuration summary. * * As soon as you have hook_ds_fields and one of the fields @@ -316,10 +333,10 @@ function hook_ds_field_settings_form($field) { } /** - * Alter the layout settings just before they get saved. + * Modify the layout settings just before they get saved. * * @param $record - * The record just before they get saved into the database. + * The record just before it gets saved into the database. * @param $form_state * The form_state values. */ @@ -328,6 +345,20 @@ function hook_ds_layout_settings_alter($record, $form_state) { } /** + * Modify the field settings before they get saved. + * + * @param $field_settings + * A collection of field settings which keys are fields. + * @param $form + * The current form which is submitted. + * @param $form_state + * The form state with all its values. + */ +function hook_ds_field_settings_alter(&$field_settings, $form, $form_state) { + $field_settings['title']['region'] = 'left'; +} + +/** * Define layouts from code. * * @return $layouts diff --git a/ds.field_ui.inc b/ds.field_ui.inc index 1913ca1..957cda9 100644 --- a/ds.field_ui.inc +++ b/ds.field_ui.inc @@ -256,19 +256,8 @@ function ds_field_ui_layouts_save($form, &$form_state) { foreach ($fields as $key => $field) { - // Ignore the Field group module and the region to block plugin. - if ($key == '_add_new_group' || $key == '_add_new_block_region') { - continue; - } - - // If the field is in hidden region, do not save. Check if the - // field has a type key which means it's from Field API and - // we need to reset that type to 'hidden' so it doesn't get - // fired by Field API in the frontend. - if ($field['region'] == 'hidden') { - if (isset($field['type'])) { - $form_state['values']['fields'][$key]['type'] = 'hidden'; - } + // Make sure we need to save anything for this field. + if (_ds_field_valid($key, $field, $form_state)) { continue; } @@ -361,6 +350,9 @@ function ds_field_ui_fields_save($form, &$form_state) { $field_settings[$field] = $settings; } + // Allow other modules to modify the field settings before they get saved. + drupal_alter('ds_field_settings', $field_settings, $form, $form_state); + // Save the record. if (!empty($field_settings)) { $record = new stdClass; @@ -615,9 +607,10 @@ function _ds_field_ui_fields($entity_type, $bundle, $view_mode, &$form, &$form_s return; } - // Get the fields. + // Get the fields and put them on the form. $fields = ds_get_fields($entity_type, FALSE); $field_settings = ds_get_field_settings($entity_type, $bundle, $view_mode); + $form['#field_settings'] = $field_settings; $table = &$form['fields']; $form['#ds_fields'] = array(); @@ -781,31 +774,54 @@ function _ds_field_ui_fields($entity_type, $bundle, $view_mode, &$form, &$form_s } /** - * Return styles. + * Utility function to check if we need to save anything for this field. + */ +function _ds_field_valid($key, $field, &$form_state) { + $continue = FALSE; + + // Ignore the Field group module and the region to block plugin. + if ($key == '_add_new_group' || $key == '_add_new_block_region') { + $continue = TRUE; + } + + // If the field is in hidden region, do not save. Check if the + // field has a type key which means it's from Field API and + // we need to reset that type to 'hidden' so it doesn't get + // fired by Field API in the frontend. + if ($field['region'] == 'hidden') { + if (isset($field['type'])) { + $form_state['values']['fields'][$key]['type'] = 'hidden'; + } + $continue = TRUE; + } + + return $continue; +} + +/** + * Utility function to return styles. */ -function _ds_styles() { - static $run = FALSE; +function _ds_styles($name = 'ds_styles_regions') { static $styles = array(); - if (!$run) { - $region_styles = trim(variable_get('ds_styles_regions', '')); - if (!empty($region_styles)) { - $styles[''] = t('None'); - $region_styles = explode("\n", $region_styles); - foreach ($region_styles as $key => $value) { + if (!isset($styles[$name])) { + $styles[$name] = array(); + $custom_styles = trim(variable_get($name, '')); + if (!empty($custom_styles)) { + $styles[$name][''] = t('None'); + $custom_styles = explode("\n", $custom_styles); + foreach ($custom_styles as $key => $value) { $classes = explode("|", $value); $key = trim($classes[0]); - $name = isset($classes[1]) ? trim($classes[1]) : $key; - $styles[$key] = $name; + $friendly_name = isset($classes[1]) ? trim($classes[1]) : $key; + $styles[$name][$key] = $friendly_name; } } - $run = TRUE; } - return $styles; + return $styles[$name]; } - /** * Utility function to sort a multidimensional array by a value in a sub-array. * diff --git a/ds.module b/ds.module index fea027d..2320ea6 100644 --- a/ds.module +++ b/ds.module @@ -2,7 +2,7 @@ /** * @file - * Core functions for the Display Suite module. + * Display Suite core functions. */ /** @@ -419,6 +419,11 @@ function ds_field_attach_view_alter(&$build, $context) { foreach ($field_values as $key => $field) { + // Ignore if this field is not a DS field. + if (!isset($fields[$key])) { + continue; + } + $field = $fields[$key]; $field['formatter'] = $field_values[$key]['format']; @@ -437,6 +442,7 @@ function ds_field_attach_view_alter(&$build, $context) { '#field_name' => $key, '#bundle' => $bundle, '#entity_type' => $entity_type, + '#view_mode' => $view_mode, '#access' => TRUE, '#items' => array( 0 => array( diff --git a/ds.registry.inc b/ds.registry.inc index 2509fe9..d6c9239 100644 --- a/ds.registry.inc +++ b/ds.registry.inc @@ -24,7 +24,7 @@ function _ds_menu() { // Custom styles. $items['admin/structure/ds/styles'] = array( 'title' => 'Styles', - 'description' => 'Define classes which you can use as classes for regions.', + 'description' => 'Define classes which you can use as classes on regions.', 'page callback' => 'drupal_get_form', 'page arguments' => array('ds_styles_form'), 'file' => 'ds.styles.inc', diff --git a/ds.views.inc b/ds.views.inc index 4acc830..e963c83 100644 --- a/ds.views.inc +++ b/ds.views.inc @@ -18,7 +18,7 @@ function ds_views_plugins() { 'help' => t('Display the entity with the Display suite module.'), 'handler' => 'views_plugin_ds_entity_view', 'path' => $path . '/views', - 'base' => array('node', 'comment', 'users', 'apachesolr', 'taxonomy_term_data'), + 'base' => array('node', 'comment', 'users', 'apachesolr', 'taxonomy_term_data'), 'theme' => 'ds_row_entity', 'uses options' => TRUE, 'type' => 'normal', diff --git a/js/ds.js b/js/ds.js index 0db51ca..bde6d10 100644 --- a/js/ds.js +++ b/js/ds.js @@ -1,6 +1,38 @@ (function($) { +Drupal.DisplaySuite = Drupal.DisplaySuite || {}; +Drupal.DisplaySuite.fieldopened = ''; + +/** + * Field settings. + */ +Drupal.behaviors.settingsToggle = { + attach: function (context) { + // remove click from link + $('.fs-link').click(function(e) { + e.preventDefault(); + }); + + // Add click event to field settings link. + $('.fs-link').click(function(){ + var settings = $(this).siblings('.extra-field-settings'); + if (Drupal.DisplaySuite.fieldopened != '' && Drupal.DisplaySuite.fieldopened != settings.attr('id')) { + $('#' + Drupal.DisplaySuite.fieldopened).hide(); + } + + if (settings.is(':visible')) { + settings.hide(); + } + else { + settings.slideDown('normal'); + } + // Store the opened setting. + Drupal.DisplaySuite.fieldopened = settings.attr('id'); + }); + } +}; + /** * Row handlers for the 'Manage display' screen. */ diff --git a/modules/ds_extras/ds_extras.admin.inc b/modules/ds_extras/ds_extras.admin.inc index 657ab8c..23ce401 100644 --- a/modules/ds_extras/ds_extras.admin.inc +++ b/modules/ds_extras/ds_extras.admin.inc @@ -1,13 +1,49 @@ 'fieldset', + '#title' => t('Field settings'), + ); + + $form['fs']['ds_extras_field_settings'] = array( + '#type' => 'checkbox', + '#title' => t('Enable'), + '#description' => t('Toggle this checkbox to enable the "Field settings" functionality. With this feature, you can change properties per field: classes, label and wrappers.'), + '#default_value' => variable_get('ds_extras_field_settings', FALSE), + ); + + $form['fs']['ds_extras_field_settings_default'] = array( + '#type' => 'fieldset', + '#title' => t('Default field template'), + '#states' => array( + 'invisible' => array( + 'input[name="ds_extras_field_settings"]' => array('checked' => FALSE), + ), + ), + ); + + $theme_functions = module_invoke_all('ds_field_theme_functions_info'); + unset($theme_functions['theme_ds_field_custom']); + $form['fs']['ds_extras_field_settings_default']['ef-default'] = array( + '#type' => 'select', + '#options' => $theme_functions, + '#default_value' => variable_get('ef-default', 'theme_field'), + '#description' => t('Select the default field template for every field. You can override this per field on the "Manage display" screens, where you also will be able to change all wrappers.
Default will output the field as defined in Drupal Core, Reset will strip all wrappers.
You can create your own custom field templates which need to be defined with hook_ds_field_theme_functions_info(). See ds.api.php for an example.'), + ); + $form['switch'] = array( '#type' => 'fieldset', - '#title' => t('Custom view modes per node'), + '#title' => t('Node switch view modes'), ); $form['switch']['ds_extras_switch_view_mode'] = array( @@ -80,11 +116,324 @@ function ds_extras_settings($form) { * Submit callback: Extras settings screen. */ function ds_extras_settings_submit($form, &$form_state) { - // Clear fields cache. cache_clear_all('ds_fields', 'cache'); - // Clear module_implements cache and rebuild menu. cache_clear_all('entity_info:', 'cache', TRUE); cache_clear_all('theme_registry:', 'cache', TRUE); cache_clear_all('module_implements', 'cache_bootstrap'); menu_rebuild(); } + +/** + * Alter Manage display screen. + */ +function ds_extras_field_ui_alter(&$form, &$form_state) { + + // Field settings. + if (variable_get('ds_extras_field_settings', FALSE) && isset($form['#ds_layout'])) { + + $field_settings = $form['#field_settings']; + $functions = module_invoke_all('ds_field_theme_functions_info'); + $default_field_function = variable_get('ef-default', 'theme_field'); + + $i = 1; + foreach (element_children($form['fields']) as $key) { + + $form['fields'][$key]['format']['ef'] = array( + '#prefix' => '' . t('Output settings') . '
', + '#suffix' => '
', + ); + $i++; + + $field_function = isset($field_settings[$key]['ef']['func']) ? $field_settings[$key]['ef']['func'] : $default_field_function; + + // Functions. + $form['fields'][$key]['format']['ef']['function'] = array( + '#type' => 'select', + '#options' => $functions, + '#title' => t('Field template'), + '#default_value' => $field_function, + '#attributes' => array( + 'class' => array('ds-extras-field-template'), + ), + ); + + // Wrappers and label. + $wrappers = array( + 'lb' => array( + 'title' => t('Label'), + 'states' => array( + 'invisible' => array( + 'select[name="fields[' . $key . '][label]"]' => array('value' => 'hidden'), + ), + ), + ), + 'ow' => array('title' => t('Wrapper')), + 'fis' => array('title' => t('Field items')), + 'fi' => array('title' => t('Field item')), + ); + foreach ($wrappers as $wrapper_key => $value) { + $form['fields'][$key]['format']['ef'][$wrapper_key] = array( + '#type' => 'checkbox', + '#title' => $value['title'], + '#prefix' => '
', + '#default_value' => isset($field_settings[$key]['ef'][$wrapper_key]) ? TRUE : FALSE, + '#description' => t('Toggle to enable'), + ); + if (isset($value['states'])) { + $form['fields'][$key]['format']['ef'][$wrapper_key]['#states'] = $value['states']; + } + $form['fields'][$key]['format']['ef'][$wrapper_key . '-el'] = array( + '#type' => 'textfield', + '#title' => t('Element'), + '#size' => '10', + '#description' => t('E.g. div, span, h2 etc.'), + '#default_value' => isset($field_settings[$key]['ef'][$wrapper_key . '-el']) ? $field_settings[$key]['ef'][$wrapper_key . '-el'] : '', + ); + if (isset($value['states'])) { + $form['fields'][$key]['format']['ef'][$wrapper_key . '-el']['#states'] = $value['states']; + } + $classes = array( + 'field-name-' . strtr($key, '_', '-'), + ); + $form['fields'][$key]['format']['ef'][$wrapper_key . '-cl'] = array( + '#type' => 'textfield', + '#title' => t('Classes'), + '#size' => '10', + '#suffix' => '
', + '#default_value' => isset($field_settings[$key]['ef'][$wrapper_key . '-cl']) ? $field_settings[$key]['ef'][$wrapper_key . '-cl'] : '', + '#description' => t('Classes: !classes', array('!classes' => implode(', ', $classes))), + ); + if (isset($value['states'])) { + $form['fields'][$key]['format']['ef'][$wrapper_key . '-cl']['#states'] = $value['states']; + } + } + + // Another label. + unset($form['fields'][$key]['format']['ef']['lb']['#description']); + $form['fields'][$key]['format']['ef']['lb']['#type'] = 'textfield'; + $form['fields'][$key]['format']['ef']['lb']['#size'] = '10'; + $form['fields'][$key]['format']['ef']['lb']['#default_value'] = isset($field_settings[$key]['ef']['lb']) ? $field_settings[$key]['ef']['lb'] : ''; + } + } + + // Views displays. + if (variable_get('ds_extras_vd', FALSE)) { + // Add an additional submit callback. + $form['#submit'] = array_merge(array('ds_extras_vd_field_ui_submit'), $form['#submit']); + } + + // Hide page title functionality, currently only works on node. + if (isset($form['#ds_layout']) && $form['#entity_type'] == 'node' && ($form['#view_mode'] == 'full' || variable_get('ds_extras_switch_view_mode', FALSE)) && variable_get('ds_extras_hide_page_title', FALSE)) { + $form['additional_settings']['ds_layouts']['ds_hide_page_title'] = array( + '#type' => 'checkbox', + '#title' => t('Hide page title'), + '#default_value' => isset($form['#ds_layout']->settings['hide_page_title']) ? $form['#ds_layout']->settings['hide_page_title'] : FALSE, + '#description' => t('Hide the page title on the page view of this node. Note that this setting will only work when this view mode is used as the full page layout of a node.'), + '#weight' => 100, + ); + } + + // Region to block only fires if there is a layout and we're working on the + // a view mode which is not equal to default. + if (isset($form['#ds_layout']) && $form['#view_mode'] != 'default' && variable_get('ds_extras_region_to_block', FALSE)) { + + $layout = $form['#ds_layout']; + + // Get the entity_type, bundle and view mode. + $entity_type = $form['#entity_type']; + $bundle = $form['#bundle']; + $view_mode = $form['#view_mode']; + + $region_blocks_options = array(); + $region_blocks = variable_get('ds_extras_region_blocks', array()); + foreach ($region_blocks as $key => $block) { + if ($block['info'] == "{$entity_type}_{$bundle}_{$view_mode}") { + $region_blocks_options[$key] = t('Remove') . ' ' . $block['title']; + } + } + + $form['additional_settings']['region_to_block'] = array( + '#type' => 'fieldset', + '#title' => t('Block regions'), + '#description' => t('Create additional regions in this layout which will be exposed as blocks.') + ); + + $form['additional_settings']['region_to_block']['new_block_region'] = array( + '#type' => 'textfield', + '#title' => t('Region name'), + '#description' => t('Enter a name to create a new region.'), + ); + $form['additional_settings']['region_to_block']['new_block_region_key'] = array( + '#title' => t('Machine name'), + '#type' => 'machine_name', + '#default_value' => '', + '#maxlength' => 32, + '#required' => FALSE, + '#description' => t('The machine-readable name of this block region. This name must contain only lowercase letters and underscores. This name must be unique.'), + '#disabled' => FALSE, + '#machine_name' => array( + 'exists' => 'ds_extras_region_to_block_unique', + 'source' => array('additional_settings', 'region_to_block', 'new_block_region'), + ), + ); + + if (!empty($region_blocks_options)) { + $form['additional_settings']['region_to_block']['remove_block_region'] = array( + '#type' => 'checkboxes', + '#title' => t('Existing block regions'), + '#options' => $region_blocks_options, + '#description' => t('Toggle regions you want to remove. Make sure no fields are attached in that region anymore or you will not see them anymore.'), + ); + } + + $form['#submit'][] = 'ds_extras_block_submit'; + } +} + +/** + * Implements hook_ds_layout_region_alter(). + */ +function ds_extras_ds_layout_region_alter($context, &$region_info) { + + $region_blocks = variable_get('ds_extras_region_blocks', array()); + // Bail out if region_blocks is empty or we are working on default view mode. + if (empty($region_blocks) || $context['view_mode'] == 'default') { + return; + } + + $entity_type = $context['entity_type']; + $bundle = $context['bundle']; + $view_mode = $context['view_mode']; + + foreach ($region_blocks as $block_key => $block) { + + if ($block['info'] == "{$entity_type}_{$bundle}_{$view_mode}") { + $region_info['region_options'][$block_key] = $block['title']; + $region_info['table_regions'][$block_key] = array( + 'title' => check_plain($block['title']), + 'message' => t('No fields are displayed in this region'), + ); + } + } +} + +/** + * Implements hook_ds_field_settings_alter(). + */ +function ds_extras_ds_field_settings_alter(&$field_settings, $form, &$form_state) { + + $fields = $form_state['values']['fields']; + $default_field_function = variable_get('ef-default', 'theme_field'); + $wrappers = array( + 'ow' => t('Wrapper'), + 'fis' => t('Field items'), + 'fi' => t('Field item') + ); + + foreach ($fields as $key => $field) { + + // Make sure we need to save anything for this field. + if (_ds_field_valid($key, $field, $form_state)) { + continue; + } + + // Get the values. + $values = $fields[$key]['format']['ef']; + + // Label. + if (isset($fields[$key]['label']) && $fields[$key]['label'] != 'hidden') { + if (!empty($values['lb'])) { + $field_settings[$key]['ef']['lb'] = $values['lb']; + } + if (!(empty($values['lb-el']))) { + $field_settings[$key]['ef']['lb-el'] = check_plain($values['lb-el']); + } + if (!(empty($values['lb-cl']))) { + $field_settings[$key]['ef']['lb-cl'] = check_plain($values['lb-cl']); + } + } + + // Theme output function. + $function = $values['function']; + if ($function != $default_field_function) { + $field_settings[$key]['ef']['func'] = $function; + } + + // Custom field configuration. + if ($function == 'theme_ds_field_custom') { + foreach ($wrappers as $wrapper_key => $title) { + if ($values[$wrapper_key]) { + // Enable. + $field_settings[$key]['ef'][$wrapper_key] = TRUE; + // Element. + $field_settings[$key]['ef'][$wrapper_key . '-el'] = !(empty($values[$wrapper_key . '-el'])) ? check_plain($values[$wrapper_key . '-el']) : 'div'; + // Classess. + $field_settings[$key]['ef'][$wrapper_key . '-cl'] = !(empty($values[$wrapper_key . '-cl'])) ? check_plain($values[$wrapper_key . '-cl']) : ''; + } + } + } + } +} + +/** + * Submit callback after Field UI submission of a views display. + */ +function ds_extras_vd_field_ui_submit($form, &$form_state) { + // Add the 'type' key to the extra title key so we can ditch the notice. + $form_state['values']['fields']['title']['type'] = 'hidden'; +} + +/** + * Submit callback: manage block regions. + */ +function ds_extras_block_submit($form, &$form_state) { + + // Create new region. + if (!empty($form_state['values']['additional_settings']['region_to_block']['new_block_region'])) { + + // Get the entity_type, bundle and view mode. + $entity_type = $form['#entity_type']; + $bundle = $form['#bundle']; + $view_mode = $form['#view_mode']; + + $block = array( + 'title' => $form_state['values']['additional_settings']['region_to_block']['new_block_region'], + 'info' => "{$entity_type}_{$bundle}_{$view_mode}", + ); + + $block_key = $form_state['values']['additional_settings']['region_to_block']['new_block_region_key']; + $region_blocks = variable_get('ds_extras_region_blocks', array()); + $region_blocks[$block_key] = $block; + variable_set('ds_extras_region_blocks', $region_blocks); + } + + // Remove a region. + if (isset($form_state['values']['additional_settings']['region_to_block']['remove_block_region'])) { + $variable_set = FALSE; + $region_blocks = variable_get('ds_extras_region_blocks', array()); + $remove = $form_state['values']['additional_settings']['region_to_block']['remove_block_region']; + foreach ($remove as $key => $value) { + if ($key === $value) { + $variable_set = TRUE; + db_delete('block') + ->condition('delta', $key) + ->condition('module', 'ds_extras') + ->execute(); + unset($region_blocks[$key]); + } + } + + if ($variable_set) { + variable_set('ds_extras_region_blocks', $region_blocks); + } + } +} + +/** + * Return unique region to block. + */ +function ds_extras_region_to_block_unique($name) { + $region_blocks = variable_get('ds_extras_region_blocks', array()); + $value = strtr($name, array('-' => '_')); + return isset($region_blocks[$value]) ? TRUE : FALSE; +} diff --git a/modules/ds_extras/ds_extras.info b/modules/ds_extras/ds_extras.info index 0a60a1b..045f6b6 100644 --- a/modules/ds_extras/ds_extras.info +++ b/modules/ds_extras/ds_extras.info @@ -1,6 +1,6 @@ name = "Extras" -description = "Contains additional features: switching view modes on a per node basis, hide page title, exposing regions as blocks, fivestar and views displays." +description = "Contains additional features: field output settings, switching view modes on a per node basis, hide page title, exposing regions as blocks, fivestar and views displays." core = "7.x" package = "Display suite" dependencies[] = ds -configure = admin/structure/ds/extras +configure = admin/structure/ds/extras \ No newline at end of file diff --git a/modules/ds_extras/ds_extras.install b/modules/ds_extras/ds_extras.install index a37f20d..eae6e4c 100644 --- a/modules/ds_extras/ds_extras.install +++ b/modules/ds_extras/ds_extras.install @@ -76,6 +76,7 @@ function ds_extras_uninstall() { variable_del('ds_extras_vd'); variable_del('ds_extras_fivestar'); variable_del('ds_extras_hide_page_title'); + variable_del('ds_extras_field_settings'); db_drop_field('node_revision', 'ds_switch'); // Remove fivestar variables. diff --git a/modules/ds_extras/ds_extras.module b/modules/ds_extras/ds_extras.module index 6fff040..c3c9ece 100644 --- a/modules/ds_extras/ds_extras.module +++ b/modules/ds_extras/ds_extras.module @@ -2,7 +2,7 @@ /** * @file - * Display Suite extras. + * Display Suite extras main functions. */ /** @@ -47,6 +47,11 @@ function ds_extras_theme_registry_alter(&$theme_registry) { if (variable_get('ds_extras_hide_page_title', FALSE)) { $theme_registry['page']['process functions'][] = 'ds_extras_process_page_title'; } + + // Change the default field theming function. + if (variable_get('ds_extras_field_settings', FALSE)) { + $theme_registry['field']['function'] = 'theme_ds_field'; + } } /** @@ -57,6 +62,15 @@ function ds_extras_module_implements_alter(&$implementations, $hook) { // Because it's possible to turn on/off features for DS extras, // we'll unset hooks here if necessary which otherwhise do nothing at all. + // Disable the field settings feature. + $fs_hooks = array( + 'ds_field_settings_alter', + 'ds_field_theme_functions_info', + ); + if (!variable_get('ds_extras_field_settings', FALSE) && in_array($hook, $fs_hooks)) { + unset($implementations['ds_extras']); + } + // Disable the region to block feature. $region_hooks = array( 'ds_layout_region_alter', @@ -110,79 +124,8 @@ function ds_extras_module_implements_alter(&$implementations, $hook) { * Implements hook_form_FORM_ID_alter(). */ function ds_extras_form_field_ui_display_overview_form_alter(&$form, &$form_state) { - - // Views displays. - if (variable_get('ds_extras_vd', FALSE)) { - // Add an additional submit callback. - $form['#submit'] = array_merge(array('ds_extras_vd_field_ui_submit'), $form['#submit']); - } - - // Hide page title functionality, currently only works on node. - if (isset($form['#ds_layout']) && $form['#entity_type'] == 'node' && ($form['#view_mode'] == 'full' || variable_get('ds_extras_switch_view_mode', FALSE)) && variable_get('ds_extras_hide_page_title', FALSE)) { - $form['additional_settings']['ds_layouts']['ds_hide_page_title'] = array( - '#type' => 'checkbox', - '#title' => t('Hide page title'), - '#default_value' => isset($form['#ds_layout']->settings['hide_page_title']) ? $form['#ds_layout']->settings['hide_page_title'] : FALSE, - '#description' => t('Hide the page title on the page view of this node. Note that this setting will only work when this view mode is used as the full page layout of a node.'), - '#weight' => 100, - ); - } - - // Region to block only fires if there is a layout and we're working on the - // a view mode which is not equal to default. - if (isset($form['#ds_layout']) && $form['#view_mode'] != 'default' && variable_get('ds_extras_region_to_block', FALSE)) { - - $layout = $form['#ds_layout']; - - // Get the entity_type, bundle and view mode. - $entity_type = $form['#entity_type']; - $bundle = $form['#bundle']; - $view_mode = $form['#view_mode']; - - $region_blocks_options = array(); - $region_blocks = variable_get('ds_extras_region_blocks', array()); - foreach ($region_blocks as $key => $block) { - if ($block['info'] == "{$entity_type}_{$bundle}_{$view_mode}") { - $region_blocks_options[$key] = t('Remove') . ' ' . $block['title']; - } - } - - $form['additional_settings']['region_to_block'] = array( - '#type' => 'fieldset', - '#title' => t('Block regions'), - '#description' => t('Create additional regions in this layout which will be exposed as blocks.') - ); - - $form['additional_settings']['region_to_block']['new_block_region'] = array( - '#type' => 'textfield', - '#title' => t('Region name'), - '#description' => t('Enter a name to create a new region.'), - ); - $form['additional_settings']['region_to_block']['new_block_region_key'] = array( - '#title' => t('Machine name'), - '#type' => 'machine_name', - '#default_value' => '', - '#maxlength' => 32, - '#required' => FALSE, - '#description' => t('The machine-readable name of this block region. This name must contain only lowercase letters and underscores. This name must be unique.'), - '#disabled' => FALSE, - '#machine_name' => array( - 'exists' => 'ds_extras_region_to_block_unique', - 'source' => array('additional_settings', 'region_to_block', 'new_block_region'), - ), - ); - - if (!empty($region_blocks_options)) { - $form['additional_settings']['region_to_block']['remove_block_region'] = array( - '#type' => 'checkboxes', - '#title' => t('Existing block regions'), - '#options' => $region_blocks_options, - '#description' => t('Toggle regions you want to remove. Make sure no fields are attached in that region anymore or you will not see them anymore.'), - ); - } - - $form['#submit'][] = 'ds_extras_block_submit'; - } + form_load_include($form_state, 'inc', 'ds_extras', 'ds_extras.admin'); + ds_extras_field_ui_alter($form, $form_state); } /** @@ -221,7 +164,144 @@ function ds_extras_field_attach_view_alter(&$build, $context) { } /** - * Helper funtion to return the view mode for the current entity. + * Implements hook_ds_field_theme_functions_info(). + */ +function ds_extras_ds_field_theme_functions_info() { + return array( + 'theme_field' => t('Default'), + 'theme_ds_field_reset' => t('Reset'), + 'theme_ds_field_custom' => t('Custom'), + ); +} + +/** + * Overriden function of theme_field(). + * + * This function is replaced in ds_extras_theme_registry_alter() + * for every field. By default theme_field() is called directly. + */ +function theme_ds_field($variables) { + + $config = array(); + static $field_settings = array(); + if (!isset($field_settings[$variables['element']['#entity_type']][$variables['element']['#bundle']][$variables['element']['#view_mode']])) { + $field_settings[$variables['element']['#entity_type']][$variables['element']['#bundle']][$variables['element']['#view_mode']] = ds_get_field_settings($variables['element']['#entity_type'], $variables['element']['#bundle'], $variables['element']['#view_mode']); + } + + // Check if this field has custom output settings. + $field_name = $variables['element']['#field_name']; + if (isset($field_settings[$variables['element']['#entity_type']][$variables['element']['#bundle']][$variables['element']['#view_mode']][$field_name]['ef'])) { + $config = $field_settings[$variables['element']['#entity_type']][$variables['element']['#bundle']][$variables['element']['#view_mode']][$field_name]['ef']; + } + + // Alter the label if configured. + if (!$variables['label_hidden']) { + if (isset($config['lb'])) { + $variables['label'] = t(check_plain($config['lb'])); + } + } + + // Call the field output function. + // We're not babysitting here, the function must exist. + if (isset($config['func'])) { + return $config['func']($variables, $config); + } + + // Default field function. + $default_field_function = variable_get('ef-default', 'theme_field'); + return $default_field_function($variables, $config); +} + +/** + * Reset all HTML for the field. + */ +function theme_ds_field_reset($variables, $config) { + $output = ''; + + // Render the label. + if (!$variables['label_hidden']) { + $output .= '
' . $variables['label'] . ': 
'; + } + + // Render the items. + foreach ($variables['items'] as $delta => $item) { + $output .= drupal_render($item); + } + + return $output; +} + +/** + * Custom output all HTML for the field. + */ +function theme_ds_field_custom($variables, $config) { + $output = ''; + + // Render the label if it's not hidden + if (!$variables['label_hidden']) { + if (isset($config['lb-el'])) { + if (!empty($config['lb-cl'])) { + $class = ' class="field-label-' . $variables['element']['#label_display'] . ' ' . $config['lb-cl'] . '"'; + } + else { + $class = ' class="field-label-' . $variables['element']['#label_display'] . '"'; + } + $output .= '<' . $config['lb-el'] . $class . '>' . $variables['label'] . ': '; + } + else { + $output .= '
' . $variables['label'] . ': 
'; + } + } + + // Field items wrapper + if (isset($config['fis'])) { + $fis_wrapper = $config['fis-el']; + $class = (!empty($config['fis-cl'])) ? ' class="' . $config['fis-cl'] . '"' : ''; + $output .= '<' . $fis_wrapper . $class . '>'; + } + + // Field item wrapper. + if (isset($config['fi'])) { + $fi_wrapper = $config['fi-el']; + } + + // Render items. + foreach ($variables['items'] as $delta => $item) { + // Field item wrapper. + if (isset($config['fi'])) { + $classes = 'field-item ' . ($delta % 2 ? 'odd' : 'even'); + if (!empty($config['fi-cl'])) { + $classes .= ' ' . $config['fi-cl']; + } + $output .= '<' . $fi_wrapper . ' class="' . $classes . '">'; + } + + // Render field content. + $output .= drupal_render($item); + + // Closing field item wrapper. + if (isset($config['fi'])) { + $output .= ''; + } + } + + // Closing field items wrapper. + if (isset($config['fis'])) { + $output .= ''; + } + + // Outer wrapper. + if (isset($config['ow'])) { + $ow_wrapper = $config['ow-el']; + $class = (!empty($config['ow-cl'])) ? ' class="' . $config['ow-cl'] . '"' : ''; + $output = '<' . $ow_wrapper . $class . '>' . $output . ''; + } + + return $output; +} + +/** + * Utility funtion to return the view mode for the current entity. * * The drupal_static is called in ds_extras_node_show to set * the current view mode. Through this technique, the hide page @@ -283,7 +363,7 @@ function ds_extras_fivestar_submit($form, $form_state) { } /** - * Implementation of hook_fivestar_access(). + * Implements hook_fivestar_access(). */ function ds_extras_fivestar_access($type, $id, $tag, $uid) { $node = node_load($id); @@ -400,7 +480,7 @@ function ds_extras_form_node_form_alter(&$form, $form_state, $form_id) { '#title' => t('View mode'), '#options' => $options, '#default_value' => isset($node->ds_switch) ? $node->ds_switch : '', - '#description' => t('Switch to a different view mode to display the default full page view of this node.'), + '#description' => t('Switch to a different view mode to display the full page view of this node.'), '#weight' => -1, ); } @@ -443,89 +523,6 @@ function ds_extras_block_view($delta = '') { } /** - * Implements hook_ds_layout_region_alter(). - */ -function ds_extras_ds_layout_region_alter($context, &$region_info) { - - $region_blocks = variable_get('ds_extras_region_blocks', array()); - // Bail out if region_blocks is empty or we are working on default view mode. - if (empty($region_blocks) || $context['view_mode'] == 'default') { - return; - } - - $entity_type = $context['entity_type']; - $bundle = $context['bundle']; - $view_mode = $context['view_mode']; - - foreach ($region_blocks as $block_key => $block) { - - if ($block['info'] == "{$entity_type}_{$bundle}_{$view_mode}") { - $region_info['region_options'][$block_key] = $block['title']; - $region_info['table_regions'][$block_key] = array( - 'title' => check_plain($block['title']), - 'message' => t('No fields are displayed in this region'), - ); - } - } - -} - -/** - * Return unique region to block. - */ -function ds_extras_region_to_block_unique($name) { - $region_blocks = variable_get('ds_extras_region_blocks', array()); - $value = strtr($name, array('-' => '_')); - return isset($region_blocks[$value]) ? TRUE : FALSE; -} - -/** - * Submit callback: manage block regions. - */ -function ds_extras_block_submit($form, &$form_state) { - - // Create new region. - if (!empty($form_state['values']['additional_settings']['region_to_block']['new_block_region'])) { - - // Get the entity_type, bundle and view mode. - $entity_type = $form['#entity_type']; - $bundle = $form['#bundle']; - $view_mode = $form['#view_mode']; - - $block = array( - 'title' => $form_state['values']['additional_settings']['region_to_block']['new_block_region'], - 'info' => "{$entity_type}_{$bundle}_{$view_mode}", - ); - - $block_key = $form_state['values']['additional_settings']['region_to_block']['new_block_region_key']; - $region_blocks = variable_get('ds_extras_region_blocks', array()); - $region_blocks[$block_key] = $block; - variable_set('ds_extras_region_blocks', $region_blocks); - } - - // Remove a region. - if (isset($form_state['values']['additional_settings']['region_to_block']['remove_block_region'])) { - $variable_set = FALSE; - $region_blocks = variable_get('ds_extras_region_blocks', array()); - $remove = $form_state['values']['additional_settings']['region_to_block']['remove_block_region']; - foreach ($remove as $key => $value) { - if ($key === $value) { - $variable_set = TRUE; - db_delete('block') - ->condition('delta', $key) - ->condition('module', 'ds_extras') - ->execute(); - unset($region_blocks[$key]); - } - } - - if ($variable_set) { - variable_set('ds_extras_region_blocks', $region_blocks); - } - } -} - -/** * Implements hook_ctools_plugin_api(). */ function ds_extras_ctools_plugin_api($owner, $api) { @@ -566,14 +563,6 @@ function ds_extras_entity_info() { } /** - * Submit callback after Field UI submission of a views display. - */ -function ds_extras_vd_field_ui_submit($form, &$form_state) { - // Add the 'type' key to the extra title key so we can ditch the notice. - $form_state['values']['fields']['title']['type'] = 'hidden'; -} - -/** * Implements hook_field_extra_fields(). */ function ds_extras_field_extra_fields() { @@ -628,9 +617,6 @@ function ds_extras_preprocess_view_layout(&$variables) { /** * Function used for theming the views title, user name etc. Note that * this is a function so it can't be overridden by a phptemplate function. - * - * @param $field - * The field array. */ function ds_vd_render_title_field($field) { $output = ''; @@ -638,7 +624,7 @@ function ds_vd_render_title_field($field) { $tag = $formatter[2]; $output = '<' . $tag . '>' . check_plain($field['entity']->get_title()) . ''; - // Views is a special case here, we'll put it back in + // Views is a special case, we stack title on the entity. $field['entity']->preprocess_fields[] = 'title'; $field['entity']->ds_vd['title'] = $output; } diff --git a/tests/ds.entities.test b/tests/ds.entities.test index b8ae788..483ed1c 100644 --- a/tests/ds.entities.test +++ b/tests/ds.entities.test @@ -16,12 +16,18 @@ class dsNodeTests extends dsBaseTest { public static function getInfo() { return array( 'name' => t('Node display'), - 'description' => t('Tests for display of nodes.'), + 'description' => t('Tests for display of nodes and fields.'), 'group' => t('Display suite'), ); } - function testDSNodeEntity() { + /** + * Utility function to setup for all kinds of tests. + * + * @param $label + * How the body label must be set. + */ + function entitiesTestSetup($label = 'above') { // Create a node. $settings = array('type' => 'article'); @@ -54,9 +60,43 @@ class dsNodeTests extends dsBaseTest { 'fields[php_field][region]' => 'left', 'fields[body][region]' => 'right', 'fields[links][region]' => 'footer', + 'fields[body][label]' => $label, ); $this->dsConfigureUI($fields); + return $node; + } + + /** + * Utility function to clear field settings. + */ + function entitiesClearFieldSettings() { + db_query('TRUNCATE {ds_field_settings}'); + cache_clear_all('ds_fields', 'cache'); + cache_clear_all('ds_field_settings', 'cache'); + } + + /** + * Set the label. + */ + function entitiesSetLabel($label, $text = '') { + // Configure fields. + $edit = array( + 'fields[body][label]' => $label, + ); + if (!empty($text)) { + $edit['fields[body][format][ef][lb]'] = $text; + } + $this->dsConfigureUI($edit); + } + + /** + * Test basic node display fields. + */ + function testDSNodeEntity() { + + $node = $this->entitiesTestSetup(); + // Look at node and verify token and block field. $this->drupalGet('node/' . $node->nid); $this->assertRaw('view-mode-full', 'Template file found (in full view mode)'); @@ -148,4 +188,290 @@ class dsNodeTests extends dsBaseTest { $this->assertNoRaw('

'. $node->title . '

'); } -} + + /** + * Tests on field settings. + */ + function testDSFieldSettings() { + + // Get a node. + $node = $this->entitiesTestSetup('hidden'); + $body_field = $node->body[$node->language][0]['value']; + + // ------------------------- + // Default theming function. + // ------------------------- + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("

" . $body_field . "

+
"); + + $this->entitiesSetLabel('above'); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
Body: 

" . $body_field . "

+
"); + + $this->entitiesSetLabel('above', 'My body'); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
My body: 

" . $body_field . "

+
"); + + $this->entitiesSetLabel('hidden'); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("

" . $body_field . "

+
"); + $this->entitiesClearFieldSettings(); + + // ----------------------- + // Reset theming function. + // ----------------------- + $edit = array( + 'ef-default' => 'theme_ds_field_reset', + ); + $this->drupalPost('admin/structure/ds/extras', $edit, t('Save configuration')); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

"); + + $this->entitiesSetLabel('above'); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+
Body: 

" . $body_field . "

"); + + $this->entitiesSetLabel('inline'); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+
Body: 

" . $body_field . "

"); + + $this->entitiesSetLabel('above', 'My body'); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+
My body: 

" . $body_field . "

"); + + $this->entitiesSetLabel('inline', 'My body'); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+
My body: 

" . $body_field . "

"); + + $this->entitiesSetLabel('hidden'); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

"); + $this->entitiesClearFieldSettings(); + + // ---------------------- + // Custom field function. + // ---------------------- + + // With outer wrapper. + $edit = array( + 'fields[body][format][ef][function]' => 'theme_ds_field_custom', + 'fields[body][format][ef][ow]' => '1', + 'fields[body][format][ef][ow-el]' => 'div' + ); + $this->dsConfigureUI($edit); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

+
"); + + // With outer div wrapper and class. + $edit = array( + 'fields[body][format][ef][ow]' => '1', + 'fields[body][format][ef][ow-el]' => 'div', + 'fields[body][format][ef][ow-cl]' => 'ow-class' + ); + $this->dsConfigureUI($edit); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

+
"); + + // With outer span wrapper and class. + $edit = array( + 'fields[body][format][ef][ow]' => '1', + 'fields[body][format][ef][ow-el]' => 'span', + 'fields[body][format][ef][ow-cl]' => 'ow-class-2' + ); + $this->dsConfigureUI($edit); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

+
"); + + // Clear field settings. + $this->entitiesClearFieldSettings(); + + // With outer wrapper and field items wrapper. + $edit = array( + 'fields[body][format][ef][function]' => 'theme_ds_field_custom', + 'fields[body][format][ef][ow]' => '1', + 'fields[body][format][ef][ow-el]' => 'div', + 'fields[body][format][ef][fis]' => '1', + 'fields[body][format][ef][fis-el]' => 'div' + ); + $this->dsConfigureUI($edit); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

+
"); + + // With outer wrapper and field items div wrapper with class. + $edit = array( + 'fields[body][format][ef][ow]' => '1', + 'fields[body][format][ef][ow-el]' => 'div', + 'fields[body][format][ef][ow-el]' => 'div', + 'fields[body][format][ef][fis]' => '1', + 'fields[body][format][ef][fis-el]' => 'div', + 'fields[body][format][ef][fis-cl]' => 'fi-class' + ); + $this->dsConfigureUI($edit); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

+
"); + + // With outer wrapper and field items span wrapper and class. + $edit = array( + 'fields[body][format][ef][ow]' => '1', + 'fields[body][format][ef][ow-el]' => 'div', + 'fields[body][format][ef][fis]' => '1', + 'fields[body][format][ef][fis-el]' => 'span', + 'fields[body][format][ef][fis-cl]' => 'fi-class' + ); + $this->dsConfigureUI($edit); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

+
"); + + // With outer wrapper class and field items span wrapper and class. + $edit = array( + 'fields[body][format][ef][ow]' => '1', + 'fields[body][format][ef][ow-el]' => 'div', + 'fields[body][format][ef][ow-cl]' => 'ow-class', + 'fields[body][format][ef][fis]' => '1', + 'fields[body][format][ef][fis-el]' => 'span', + 'fields[body][format][ef][fis-cl]' => 'fi-class' + ); + $this->dsConfigureUI($edit); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

+
"); + + // With outer wrapper span class and field items span wrapper and class. + $edit = array( + 'fields[body][format][ef][ow]' => '1', + 'fields[body][format][ef][ow-el]' => 'span', + 'fields[body][format][ef][ow-cl]' => 'ow-class', + 'fields[body][format][ef][fis]' => '1', + 'fields[body][format][ef][fis-el]' => 'span', + 'fields[body][format][ef][fis-cl]' => 'fi-class-2' + ); + $this->dsConfigureUI($edit); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

+
"); + + // Clear field settings. + $this->entitiesClearFieldSettings(); + + // With field item div wrapper. + $edit = array( + 'fields[body][format][ef][function]' => 'theme_ds_field_custom', + 'fields[body][format][ef][fi]' => '1', + ); + $this->dsConfigureUI($edit); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

+
"); + + // With field item span wrapper. + $edit = array( + 'fields[body][format][ef][fi]' => '1', + 'fields[body][format][ef][fi-el]' => 'span', + ); + $this->dsConfigureUI($edit); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

+
"); + + // With field item span wrapper and class. + $edit = array( + 'fields[body][format][ef][fi]' => '1', + 'fields[body][format][ef][fi-el]' => 'span', + 'fields[body][format][ef][fi-cl]' => 'fi-class', + ); + $this->dsConfigureUI($edit); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

+
"); + + // With fis and fi. + $edit = array( + 'fields[body][format][ef][fis]' => '1', + 'fields[body][format][ef][fis-el]' => 'div', + 'fields[body][format][ef][fis-cl]' => 'fi-class-2', + 'fields[body][format][ef][fi]' => '1', + 'fields[body][format][ef][fi-el]' => 'div', + 'fields[body][format][ef][fi-cl]' => 'fi-class', + ); + $this->dsConfigureUI($edit); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

+
"); + // With all + $edit = array( + 'fields[body][format][ef][ow]' => '1', + 'fields[body][format][ef][ow-el]' => 'div', + 'fields[body][format][ef][ow-cl]' => 'ow-class', + 'fields[body][format][ef][fis]' => '1', + 'fields[body][format][ef][fis-el]' => 'div', + 'fields[body][format][ef][fis-cl]' => 'fi-class-2', + 'fields[body][format][ef][fi]' => '1', + 'fields[body][format][ef][fi-el]' => 'span', + 'fields[body][format][ef][fi-cl]' => 'fi-class', + ); + $this->dsConfigureUI($edit); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

+
"); + + // Label tests with custom function. + $this->entitiesSetLabel('above'); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+
Body: 

" . $body_field . "

+
"); + + $this->entitiesSetLabel('inline'); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+
Body: 

" . $body_field . "

+
"); + + $this->entitiesSetLabel('above', 'My body'); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+
My body: 

" . $body_field . "

+
"); + + $this->entitiesSetLabel('inline', 'My body'); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+
My body: 

" . $body_field . "

+
"); + + $this->entitiesSetLabel('hidden'); + $this->drupalGet('node/' . $node->nid); + $this->assertRaw("
+

" . $body_field . "

+
"); + } +} \ No newline at end of file diff --git a/tests/ds_test.module b/tests/ds_test.module index edd2829..14ac5fb 100644 --- a/tests/ds_test.module +++ b/tests/ds_test.module @@ -12,6 +12,7 @@ function ds_test_install() { variable_set('ds_extras_region_to_block', TRUE); variable_set('ds_extras_switch_view_mode', TRUE); variable_set('ds_extras_hide_page_title', TRUE); + variable_set('ds_extras_field_settings', TRUE); } /** diff --git a/views/views_plugin_ds_entity_view.inc b/views/views_plugin_ds_entity_view.inc index 13788be..e56bae8 100644 --- a/views/views_plugin_ds_entity_view.inc +++ b/views/views_plugin_ds_entity_view.inc @@ -142,7 +142,7 @@ class views_plugin_ds_entity_view extends views_plugin_row { $form['grouping_fieldset']['group_field_function'] = array( '#type' => 'textfield', '#title' => 'Heading function', - '#description' => t('The value of the field can be in a very raw format (eg, date created). Enter a custom function which you can use to format that value. The value and the object will be passed into that function eg. custom_function($raw_value, $object);'), + '#description' => check_plain(t('The value of the field can be in a very raw format (eg, date created). Enter a custom function which you can use to format that value. The value and the object will be passed into that function eg. custom_function($raw_value, $object);')), '#default_value' => isset($this->options['grouping_fieldset']['group_field_function']) ? $this->options['grouping_fieldset']['group_field_function'] : '', ); }